Update authentication method

This commit is contained in:
2023-11-18 18:20:29 +11:00
parent 9d9ffc9122
commit 3b3ad66ba3
24 changed files with 273 additions and 25 deletions

View File

@@ -0,0 +1,15 @@
module Admin
module Actions
module Sessions
class Create < Action
include Deps["commands.sessions.create"]
def handle(req, res)
create.(email: req.params[:email])
res.redirect_to "/admin"
end
end
end
end
end

View File

@@ -0,0 +1,13 @@
module Admin
module Actions
module Sessions
class New < Action
include Deps["views.sessions.new"]
def handle(req, res)
res.render new
end
end
end
end
end

View File

@@ -0,0 +1,18 @@
module Admin
module Actions
module Sessions
class Validate < Action
include Deps["commands.sessions.validate"]
def handle(req, res)
user_id = validate.(token: req.params[:token])
session = req.env["rack.session"]
session[:user_id] = user_id
res.redirect_to "/admin"
end
end
end
end
end

View File

@@ -0,0 +1,48 @@
require "mail"
module Admin
module Commands
module Sessions
class Create
include Deps[
"repos.login_tokens_repo",
"repos.user_repo"
]
def call(email:)
app_settings = Admin::Container["settings"]
user = user_repo.by_email(email: email)
return unless user
login_tokens_repo.delete_all
token = login_tokens_repo.create(user_id: user.id, token: SecureRandom.uuid)
Mail.defaults do
delivery_method :smtp, {
address: app_settings.smtp_server,
port: 587,
authentication: "plain",
openssl_verify_mode: "peer",
enable_starttls_auto: true
}
end
Mail.delivery_method.settings[:user_name] = app_settings.smtp_username
Mail.delivery_method.settings[:password] = app_settings.smtp_password
mail = Mail.new do
subject "Login to #{app_settings.site_name}"
body "#{app_settings.micropub_site_url}/admin/login/#{token.token}"
end
mail[:to] = email
mail[:from] = app_settings.from_email
mail.deliver
end
end
end
end
end

View File

@@ -0,0 +1,17 @@
module Admin
module Commands
module Sessions
class Validate
include Deps["repos.login_tokens_repo"]
def call(token:)
user_id = login_tokens_repo.by_token(token: token).user_id
if user_id
login_tokens_repo.delete_all
user_id
end
end
end
end
end
end

View File

@@ -1,16 +1,12 @@
require "adamantium/middleware/authenticate"
module Adamantium
class AuthenticatedAdminAction
def self.call(action:)
auth_proc = -> (id) { Admin::Container["repos.user_repo"].exists(id) }
action_proc = ->(env) { Admin::Container["actions.#{action}"].call(env) }
if Hanami.app.settings.basic_auth_username && Hanami.app.settings.basic_auth_password
Rack::Auth::Basic.new(action_proc) do |username, password|
username == Hanami.app.settings.basic_auth_username &&
password == Hanami.app.settings.basic_auth_password
end
else
Rack::Auth::Basic.new(action_proc) { |_username, _password| true }
end
Adamantium::Middleware::Authenticate.new(action_proc, auth_proc)
end
end
end

View File

@@ -11,6 +11,10 @@ module Admin
get "/", to: Auth.call(action: "index")
get "/login", to: "sessions.new"
get "/login/:token", to: "sessions.validate"
post "/sessions/create", to: "sessions.create"
get "/pages", to: Auth.call(action: "pages.index")
get "/pages/new", to: Auth.call(action: "pages.new")
get "/pages/:slug/edit", to: Auth.call(action: "pages.edit")

View File

@@ -0,0 +1,15 @@
module Admin
module Repos
class LoginTokensRepo < Adamantium::Repo[:login_tokens]
commands :create
def by_token(token:)
login_tokens.where(token: token).one
end
def delete_all
login_tokens.delete
end
end
end
end

View File

@@ -0,0 +1,17 @@
module Admin
module Repos
class UserRepo < Adamantium::Repo[:users]
commands :create
def exists(id)
!!users
.where(id: id)
.one
end
def by_email(email:)
users.where(email: email).one
end
end
end
end

View File

@@ -0,0 +1,24 @@
html
head
meta charest="utf-8"
meta name="viewport" content="width=device-width, initial-scale=1.0"
meta name="theme-color" content="rgb(37, 99, 235)"
title Admin // Daniel Nitsikopoulos
= stylesheet_tag "app"
link rel="icon" type="image/x-icon" href="/assets/favicon.ico"
body class="bg-white dark:bg-black selection:bg-blue-100 selection:text-blue-900 dark:selection:bg-blue-600 dark:selection:text-blue-100"
main class="pb-8 px-4 pt-4 md:pt-8"
header class="mb-12 max-w-screen-md mx-auto"
div class="flex items-center mb-8 md:mb-12 text-lg md:text-xl text-gray-400 dark:text-gray-600"
div class="flex-none mx-auto md:flex-auto md:mx-0"
div class="h-card flex items-center"
img class="u-photo w-6 h6 md:w-10 md:h-10 rounded-full mr-1.5" src="/assets/memoji.png"
a href="/" rel="me" class="u-url u-uid"
h1 class="p-name uppercase text-sm md:text-sm text-gray-400 dark:text-gray-400" = Hanami.app.settings.site_name
== yield

View File

@@ -0,0 +1,7 @@
div class="max-w-prose mx-auto prose dark:prose-invert"
form action="/admin/sessions/create" method="POST"
div class="mb-2"
label for="email" class="mr-2" Email
input type="email" id="email" name="email" class="border"
div class="mb-2"
button Login

View File

@@ -0,0 +1,9 @@
module Admin
module Views
module Sessions
class New < Admin::View
config.layout = "minimal"
end
end
end
end