Skip to content

Commit d431dc6

Browse files
recreate admin account
1 parent b0be921 commit d431dc6

9 files changed

Lines changed: 178 additions & 68 deletions

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,7 @@ gem "faker", "~> 3.5", group: :development
9393
gem "inline_svg", "~> 1.10"
9494

9595
gem "csv", "~> 3.3"
96+
97+
gem "rotp", "~> 6.3"
98+
99+
gem "rqrcode", "~> 3.1"

Gemfile.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ GEM
103103
xpath (~> 3.2)
104104
childprocess (5.1.0)
105105
logger (~> 1.5)
106+
chunky_png (1.4.0)
106107
concurrent-ruby (1.3.5)
107108
connection_pool (2.5.4)
108109
crass (1.0.6)
@@ -421,6 +422,11 @@ GEM
421422
roda (~> 3.76)
422423
rodauth (~> 2.36)
423424
rodauth-model (~> 0.2)
425+
rotp (6.3.0)
426+
rqrcode (3.1.0)
427+
chunky_png (~> 1.0)
428+
rqrcode_core (~> 2.0)
429+
rqrcode_core (2.0.0)
424430
rubocop (1.75.8)
425431
json (~> 2.3)
426432
language_server-protocol (~> 3.17.0.2)
@@ -595,6 +601,8 @@ DEPENDENCIES
595601
rails (~> 8.0.1)
596602
rodauth-omniauth (~> 0.6.0)
597603
rodauth-rails (~> 2.0)
604+
rotp (~> 6.3)
605+
rqrcode (~> 3.1)
598606
selenium-webdriver
599607
sequel-activerecord_connection (~> 2.0)
600608
solid_cable

app/mailers/rodauth_mailer.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,11 @@ def reset_password(name, account_id, key)
1616
end
1717

1818
def verify_login_change(name, account_id, key)
19-
@rodauth = rodauth(name, account_id) {
20-
@verify_login_change_key_value = key
21-
}
19+
@rodauth = rodauth(name, account_id) { @verify_login_change_key_value = key }
2220
@account = @rodauth.rails_account
2321
@new_email = @account.login_change_key.login
2422

25-
mail to: @new_email,
26-
subject: @rodauth.email_subject_prefix + @rodauth.verify_login_change_email_subject
23+
mail to: @new_email, subject: @rodauth.email_subject_prefix + @rodauth.verify_login_change_email_subject
2724
end
2825

2926
def change_password_notify(name, account_id)

app/models/admin.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,29 @@
1313
#
1414
class Admin < ResourceRecord
1515
include Rodauth::Rails.model(:admin)
16+
# add concerns above.
17+
18+
# add model configurations above.
19+
20+
# add belongs_to associations above.
21+
22+
# add has_one associations above.
23+
24+
# add has_many associations above.
25+
26+
# add attachments above.
27+
28+
# add scopes above.
29+
1630
validates :email, presence: true
31+
# add validations above.
32+
33+
# add callbacks above.
34+
35+
# add delegations above.
1736

1837
enum :status, unverified: 1, verified: 2, closed: 3
38+
# add misc attribute macros above.
39+
40+
# add methods above.
1941
end

app/rodauth/admin_rodauth_plugin.rb

Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,26 @@ class AdminRodauthPlugin < RodauthPlugin
1212
# http://rodauth.jeremyevans.net/documentation.html
1313

1414
# List of authentication features that are loaded.
15-
enable(
16-
:login,
17-
:remember,
18-
:logout,
19-
# :create_account,
20-
# :verify_account,
21-
# :verify_account_grace_period,
22-
:reset_password,
23-
:reset_password_notify,
24-
# :change_login,
25-
# :verify_login_change,
26-
:change_password,
27-
:change_password_notify,
28-
:case_insensitive_login,
29-
:internal_request
30-
)
15+
enable :login, :remember, :logout, :create_account, :verify_account, :close_account, :reset_password, :reset_password_notify, :password_grace_period, :change_password, :otp, :recovery_codes, :lockout, :active_sessions, :audit_logging, :internal_request
3116

3217
# ==> General
3318

3419
# Prevent rodauth from introspecting the database if we are not using UUIDs
3520
convert_token_id_to_integer? { Admin.columns_hash["id"].type == :integer }
3621

3722
# Change prefix of table and foreign key column names from default "account"
23+
account_lockouts_table :admin_lockouts
24+
account_login_failures_table :admin_login_failures
3825
accounts_table :admins
26+
active_sessions_account_id_column :admin_id
27+
active_sessions_table :admin_active_session_keys
28+
audit_logging_account_id_column :admin_id
29+
audit_logging_table :admin_authentication_audit_logs
30+
otp_keys_table :admin_otp_keys
31+
recovery_codes_table :admin_recovery_codes
3932
remember_table :admin_remember_keys
4033
reset_password_table :admin_password_reset_keys
41-
# verify_account_table :admin_verification_keys
42-
# verify_login_change_table :admin_login_change_keys
34+
verify_account_table :admin_verification_keys
4335

4436
# The secret key used for hashing public-facing tokens for various features.
4537
# Defaults to Rails `secret_key_base`, but you can use your own secret key.
@@ -66,7 +58,7 @@ class AdminRodauthPlugin < RodauthPlugin
6658

6759
# Redirect back to originally requested location after authentication.
6860
login_return_to_requested_location? true
69-
# two_factor_auth_return_to_requested_location? true # if using MFA
61+
two_factor_auth_return_to_requested_location? true
7062

7163
# Autologin the user after they have reset their password.
7264
# reset_password_autologin? true
@@ -81,41 +73,26 @@ class AdminRodauthPlugin < RodauthPlugin
8173
# Requires the JSON feature
8274
# only_json? false
8375

76+
# Only ask for password after asking for the login
77+
use_multi_phase_login? true
78+
8479
# ==> Emails
8580
# Use a custom mailer for delivering authentication emails.
8681

87-
# create_reset_password_email do
88-
# Rodauth::AdminMailer.reset_password(
89-
# self.class.configuration_name,
90-
# account_id, reset_password_key_value
91-
# )
92-
# end
93-
94-
# create_verify_account_email do
95-
# Rodauth::AdminMailer.verify_account(
96-
# self.class.configuration_name,
97-
# account_id, verify_account_key_value
98-
# )
99-
# end
100-
101-
# create_verify_login_change_email do |_login|
102-
# Rodauth::AdminMailer.verify_login_change(
103-
# self.class.configuration_name,
104-
# account_id, verify_login_change_key_value
105-
# )
106-
# end
82+
create_reset_password_email do
83+
Rodauth::AdminMailer.reset_password(self.class.configuration_name, account_id, reset_password_key_value)
84+
end
10785

108-
create_password_changed_email do
109-
Rodauth::AdminMailer.change_password_notify(
110-
self.class.configuration_name, account_id
111-
)
86+
create_verify_account_email do
87+
Rodauth::AdminMailer.verify_account(self.class.configuration_name, account_id, verify_account_key_value)
11288
end
11389

11490
create_reset_password_notify_email do
115-
Rodauth::AdminMailer.reset_password_notify(
116-
self.class.configuration_name,
117-
account_id
118-
)
91+
Rodauth::AdminMailer.reset_password_notify(self.class.configuration_name, account_id)
92+
end
93+
94+
create_unlock_account_email do
95+
Rodauth::AdminMailer.unlock_account(self.class.configuration_name, account_id, unlock_account_key_value)
11996
end
12097

12198
send_email do |email|
@@ -131,6 +108,7 @@ class AdminRodauthPlugin < RodauthPlugin
131108
# flash_error_key :error # default is :alert
132109

133110
# Override default flash messages.
111+
two_factor_not_setup_error_flash "You need to setup two factor authentication"
134112
# create_account_notice_flash "Your account has been created. Please verify your account by visiting the confirmation link sent to your email address."
135113
# require_login_error_flash "Login is required for accessing this page"
136114
# login_notice_flash nil
@@ -180,6 +158,11 @@ class AdminRodauthPlugin < RodauthPlugin
180158

181159
# ==> Hooks
182160

161+
# Prevent using the web to sign up.
162+
before_create_account_route do
163+
request.halt unless internal_request?
164+
end
165+
183166
# Validate custom fields in the create account form.
184167
# before_create_account do
185168
# throw_error_status(422, "name", "must be present") if param("name").empty?
@@ -190,28 +173,28 @@ class AdminRodauthPlugin < RodauthPlugin
190173
# Profile.create!(account_id: account_id, name: param("name"))
191174
# end
192175

193-
# # Do additional cleanup after the account is closed.
194-
# # after_close_account do
195-
# # Profile.find_by!(account_id: account_id).destroy
196-
# # end
197-
# create_account_route "register"
176+
# Do additional cleanup after the account is closed.
177+
# after_close_account do
178+
# Profile.find_by!(account_id: account_id).destroy
179+
# end
198180

199181
# ==> Redirects
200182

201-
# # Redirect to home after login.
202-
# create_account_redirect "/admin_dashboard"
183+
# Redirect to home after login.
184+
create_account_redirect "/admin_dashboard"
203185

204186
# Redirect to home after login.
205187
login_redirect "/admin_dashboard"
206188

207189
# Redirect to home page after logout.
208-
logout_redirect "/"
190+
logout_redirect "/admin_dashboard"
209191

210-
# # Redirect to wherever login redirects to after account verification.
211-
# verify_account_redirect { login_redirect }
192+
# Redirect to wherever login redirects to after account verification.
193+
verify_account_redirect { login_redirect }
212194

213195
# Redirect to login page after password reset.
214196
reset_password_redirect { login_path }
197+
215198
# ==> Deadlines
216199
# Change default deadlines for some actions.
217200
# verify_account_grace_period 3.days.to_i
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<% unless rodauth(:admin).login_form_footer_links.empty? %>
2+
<ul>
3+
<% rodauth(:admin).login_form_footer_links.sort.each do |_, link, text| %>
4+
<% next if rodauth(:admin).try(:create_account_path) == link %>
5+
<li><%= link_to text, link, class: "text-primary-600 rounded-sm text-sm hover:underline hover:text-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 dark:text-primary-300 dark:hover:text-primary-400 dark:focus-visible:ring-2 dark:focus-visible:ring-primary-300" %></li>
6+
<% end %>
7+
</ul>
8+
<% end %>

db/migrate/20250116233733_create_rodauth_admin_base_remember_verify_account_reset_password_verify_login_change.rb

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,52 @@ def change
3333
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
3434
end
3535

36-
# Used by the verify login change feature
37-
create_table :admin_login_change_keys, id: false do |t|
36+
# Used by the otp feature
37+
create_table :admin_otp_keys, id: false do |t|
38+
t.bigint :id, primary_key: true
39+
t.foreign_key :admins, column: :id
40+
t.string :key, null: false
41+
t.integer :num_failures, null: false, default: 0
42+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
43+
end
44+
45+
# Used by the recovery codes feature
46+
create_table :admin_recovery_codes, primary_key: [:id, :code] do |t|
47+
t.bigint :id
48+
t.foreign_key :admins, column: :id
49+
t.string :code
50+
end
51+
52+
# Used by the lockout feature
53+
create_table :admin_login_failures, id: false do |t|
54+
t.bigint :id, primary_key: true
55+
t.foreign_key :admins, column: :id
56+
t.integer :number, null: false, default: 1
57+
end
58+
create_table :admin_lockouts, id: false do |t|
3859
t.bigint :id, primary_key: true
3960
t.foreign_key :admins, column: :id
4061
t.string :key, null: false
41-
t.string :login, null: false
4262
t.datetime :deadline, null: false
63+
t.datetime :email_last_sent
64+
end
65+
66+
# Used by the active sessions feature
67+
create_table :admin_active_session_keys, primary_key: [:admin_id, :session_id] do |t|
68+
t.references :admin, foreign_key: true
69+
t.string :session_id
70+
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
71+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
72+
end
73+
74+
# Used by the audit logging feature
75+
create_table :admin_authentication_audit_logs do |t|
76+
t.references :admin, foreign_key: true, null: false
77+
t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
78+
t.text :message, null: false
79+
t.json :metadata
80+
t.index [:admin_id, :at], name: "audit_admin_admin_id_at_idx"
81+
t.index :at, name: "audit_admin_at_idx"
4382
end
4483
end
4584
end

db/schema.rb

Lines changed: 41 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/tasks/rodauth_admin.rake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace :rodauth do
2+
desc "Create a admin account"
3+
task admin: :environment do
4+
require "tty-prompt"
5+
6+
prompt = TTY::Prompt.new
7+
email = ENV["EMAIL"] || prompt.ask("Email:", required: true)
8+
9+
RodauthApp.rodauth(:admin).create_account(login: email)
10+
end
11+
end

0 commit comments

Comments
 (0)