rodauth-rails 1.14.0 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -41
  3. data/lib/generators/rodauth/install_generator.rb +6 -22
  4. data/lib/generators/rodauth/mailer/email_auth.erb +6 -0
  5. data/lib/generators/rodauth/mailer/otp_disabled.erb +6 -0
  6. data/lib/generators/rodauth/mailer/otp_locked_out.erb +6 -0
  7. data/lib/generators/rodauth/mailer/otp_setup.erb +6 -0
  8. data/lib/generators/rodauth/mailer/otp_unlock_failed.erb +6 -0
  9. data/lib/generators/rodauth/mailer/otp_unlocked.erb +6 -0
  10. data/lib/generators/rodauth/mailer/password_changed.erb +6 -0
  11. data/lib/generators/rodauth/mailer/reset_password.erb +6 -0
  12. data/lib/generators/rodauth/mailer/reset_password_notify.erb +6 -0
  13. data/lib/generators/rodauth/mailer/unlock_account.erb +6 -0
  14. data/lib/generators/rodauth/mailer/verify_account.erb +6 -0
  15. data/lib/generators/rodauth/mailer/verify_login_change.erb +7 -0
  16. data/lib/generators/rodauth/mailer/webauthn_authenticator_added.erb +6 -0
  17. data/lib/generators/rodauth/mailer/webauthn_authenticator_removed.erb +6 -0
  18. data/lib/generators/rodauth/mailer_generator.rb +126 -0
  19. data/lib/generators/rodauth/migration/active_record/audit_logging.erb +2 -2
  20. data/lib/generators/rodauth/migration/active_record/jwt_refresh.erb +0 -1
  21. data/lib/generators/rodauth/migration/active_record/otp_unlock.erb +7 -0
  22. data/lib/generators/rodauth/migration/sequel/audit_logging.erb +2 -2
  23. data/lib/generators/rodauth/migration/sequel/jwt_refresh.erb +1 -1
  24. data/lib/generators/rodauth/migration/sequel/otp_unlock.erb +6 -0
  25. data/lib/generators/rodauth/migration_generator.rb +3 -3
  26. data/lib/generators/rodauth/templates/INSTRUCTIONS +8 -2
  27. data/lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb.tt +18 -2
  28. data/lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +4 -50
  29. data/lib/generators/rodauth/templates/app/misc/rodauth_main.rb.tt +5 -26
  30. data/lib/generators/rodauth/templates/app/models/account.rb.tt +1 -1
  31. data/lib/generators/rodauth/templates/app/views/rodauth/otp_unlock.html.erb +21 -0
  32. data/lib/generators/rodauth/templates/app/views/rodauth/otp_unlock_not_available.html.erb +5 -0
  33. data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/otp_unlock.html.erb +22 -0
  34. data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/otp_unlock_not_available.html.erb +14 -0
  35. data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +1 -0
  36. data/lib/generators/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +1 -0
  37. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/otp_disabled.text.erb +2 -0
  38. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/otp_locked_out.text.erb +9 -0
  39. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/otp_setup.text.erb +2 -0
  40. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/otp_unlock_failed.text.erb +8 -0
  41. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/otp_unlocked.text.erb +2 -0
  42. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/webauthn_authenticator_added.text.erb +3 -0
  43. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/webauthn_authenticator_removed.text.erb +3 -0
  44. data/lib/generators/rodauth/views_generator.rb +2 -1
  45. data/lib/rodauth/rails/feature/base.rb +2 -1
  46. data/lib/rodauth/rails/feature/instrumentation.rb +12 -6
  47. data/lib/rodauth/rails/feature/internal_request.rb +16 -6
  48. data/lib/rodauth/rails/version.rb +1 -1
  49. data/lib/rodauth/rails.rb +1 -1
  50. data/rodauth-rails.gemspec +4 -4
  51. metadata +35 -8
  52. data/CHANGELOG.md +0 -568
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a85a9d6a32ae95b8508024caebfa807fae2ab58841bfe2d8d2d6d382f3f336b2
4
- data.tar.gz: bae2d174023325da77e494431246c5b4269e803be35157c084b5e35cc084c090
3
+ metadata.gz: 12ac51c0ef57f053d8bdc843eef7a846554defb7e37403b9ccf2ab83bd52fb6b
4
+ data.tar.gz: 5854a05239bfbb92f2b0aecc5c0e9dd1de22388d364afc6f4fe601e4900c54c5
5
5
  SHA512:
6
- metadata.gz: 20ff48cdfa007d82233bd5e46bb09b31b6b1dc0ffa4669303b5c7bec19c3fdb36cda03b38ce36199eb4241433e4f2c118dd729544bda62a7b3c949c6af313a5e
7
- data.tar.gz: 7930be938efaa027572fd487067b925eafc286e5f356db1781e0892cf62d30f2aef72ac4a1b854b17fee07679d38975c5fe29a15509dbf180e88bc973ba3457e
6
+ metadata.gz: bbf3d3cc5f453756a8a52a73409de3134569aa12908be81a505e637b0a05f890735a9589df237fb1e7f2f9687a5df2ac6821586d0e4cd52995d9efd3b0989e46
7
+ data.tar.gz: 6c1725dc4b64c498a6d840aba77c61c273df112bb712610b8342ebded946c7dfdb7a4e7fe33ffac69303ff8020223902040a66ebb58d6cd7247a085ceebdd448
data/README.md CHANGED
@@ -68,7 +68,7 @@ $ rails generate rodauth:install
68
68
 
69
69
  This generator will create a Rodauth app and configuration with common
70
70
  authentication features enabled, a database migration with tables required by
71
- those features, a mailer with default templates, and a few other files.
71
+ those features, and a few other files.
72
72
 
73
73
  Feel free to remove any features you don't need, along with their corresponding
74
74
  tables. Afterwards, run the migration:
@@ -77,14 +77,6 @@ tables. Afterwards, run the migration:
77
77
  $ rails db:migrate
78
78
  ```
79
79
 
80
- For your mailer to be able to generate email links, you'll need to set up
81
- default URL options in each environment. Here is a possible configuration for
82
- `config/environments/development.rb`:
83
-
84
- ```rb
85
- config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
86
- ```
87
-
88
80
  ### Install options
89
81
 
90
82
  The install generator will use the `accounts` table by default. You can specify a different table name:
@@ -254,7 +246,7 @@ end
254
246
  ```rb
255
247
  class RodauthController < ApplicationController
256
248
  before_action :verify_captcha, only: :login, if: -> { request.post? } # executes before Rodauth endpoints
257
- rescue_from("MyApp::SomeError") { |exception| ... } # rescues around Rodauth endpoints
249
+ rescue_from("SomeError") { |exception| ... } # rescues around Rodauth endpoints
258
250
  end
259
251
  ```
260
252
 
@@ -316,42 +308,41 @@ $ rails generate rodauth:views webauthn two_factor_base --name admin
316
308
 
317
309
  ## Mailer
318
310
 
319
- The install generator will create `RodauthMailer` with default email templates,
320
- and configure Rodauth features that send emails as part of the authentication
321
- flow to use it.
311
+ When you're ready to modify the default email templates and safely deliver them
312
+ in a background job, you can run the following command to generate the mailer
313
+ integration:
322
314
 
323
- ```rb
324
- # app/mailers/rodauth_mailer.rb
325
- class RodauthMailer < ApplicationMailer
326
- def verify_account(account_id, key) ... end
327
- def reset_password(account_id, key) ... end
328
- def verify_login_change(account_id, key) ... end
329
- def password_changed(account_id) ... end
330
- # def email_auth(account_id, key) ... end
331
- # def unlock_account(account_id, key) ... end
332
- end
315
+ ```sh
316
+ $ rails generate rodauth:mailer
333
317
  ```
318
+
319
+ This will create a `RodauthMailer`, email templates, and necessary Rodauth
320
+ configuration for the features you have enabled. For email links to work, you
321
+ need to have `config.action_mailer.default_url_options` set for each
322
+ environment.
323
+
334
324
  ```rb
335
- # app/misc/rodauth_main.rb
336
- class RodauthMain < Rodauth::Rails::Auth
337
- configure do
338
- create_reset_password_email { RodauthMailer.reset_password(account_id, reset_password_key_value) }
339
- create_verify_account_email { RodauthMailer.verify_account(account_id, verify_account_key_value) }
340
- create_verify_login_change_email { |_login| RodauthMailer.verify_login_change(account_id, verify_login_change_key_value) }
341
- create_password_changed_email { RodauthMailer.password_changed(account_id) }
342
- # create_email_auth_email { RodauthMailer.email_auth(account_id, email_auth_key_value) }
343
- # create_unlock_account_email { RodauthMailer.unlock_account(account_id, unlock_account_key_value) }
344
- send_email do |email|
345
- # queue email delivery on the mailer after the transaction commits
346
- db.after_commit { email.deliver_later }
347
- end
348
- end
349
- end
325
+ # config/environments/development.rb
326
+ config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
327
+ ```
328
+
329
+ The generator accepts various options:
330
+
331
+ ```sh
332
+ # generate mailer integration for specified features
333
+ $ rails generate rodauth:mailer email_auth lockout webauthn_modify_email
334
+
335
+ # generate mailer integration for all Rodauth features
336
+ $ rails generate rodauth:mailer --all
337
+
338
+ # specify different Rodauth configuration to select enabled features
339
+ $ rails generate rodauth:mailer --name admin
350
340
  ```
351
341
 
352
- This configuration calls `#deliver_later`, which uses Active Job to deliver
353
- emails in a background job. If you want to send emails synchronously, you can
354
- modify the configuration to call `#deliver_now` instead.
342
+ Note that the generated Rodauth configuration calls `#deliver_later`, which
343
+ uses Active Job to deliver emails in a background job. If you want to deliver
344
+ emails synchronously, you can modify the configuration to call `#deliver_now`
345
+ instead.
355
346
 
356
347
  If you're using a background processing library without an Active Job adapter,
357
348
  or a 3rd-party service for sending transactional emails, see [this wiki
@@ -535,6 +526,14 @@ Rodauth::Rails.rodauth(session: { two_factor_auth_setup: true })
535
526
  Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
536
527
  ```
537
528
 
529
+ You can override default URL options ad-hoc by modifying `#rails_url_options`:
530
+
531
+ ```rb
532
+ rodauth.base_url #=> "https://example.com"
533
+ rodauth.rails_url_options[:host] = "subdomain.example.com"
534
+ rodauth.base_url #=> "https://subdomain.example.com"
535
+ ```
536
+
538
537
  ### Using as a library
539
538
 
540
539
  Rodauth offers a [`Rodauth.lib`][library] method for when you want to use it as a library (via [internal requests][internal_request]), as opposed to having it route requests. This gem provides a `Rodauth::Rails.lib` counterpart that does the same but with Rails integration:
@@ -633,6 +632,7 @@ The `rails` feature rodauth-rails loads provides the following configuration met
633
632
  | `rails_controller_instance` | Instance of the controller with the request env context. |
634
633
  | `rails_controller` | Controller class to use for rendering and CSRF protection. |
635
634
  | `rails_account_model` | Model class connected with the accounts table. |
635
+ | `rails_url_options` | Options used for generating URLs outside of a request (defaults to `config.action_mailer.default_url_options`) |
636
636
 
637
637
  ```rb
638
638
  class RodauthMain < Rodauth::Rails::Auth
@@ -13,15 +13,6 @@ module Rodauth
13
13
  "sqlserver" => RUBY_ENGINE == "jruby" ? "mssql" : "tinytds",
14
14
  }
15
15
 
16
- MAILER_VIEWS = %w[
17
- email_auth
18
- password_changed
19
- reset_password
20
- unlock_account
21
- verify_account
22
- verify_login_change
23
- ]
24
-
25
16
  source_root "#{__dir__}/templates"
26
17
  namespace "rodauth:install"
27
18
 
@@ -55,16 +46,6 @@ module Rodauth
55
46
  template "app/models/account.rb", "app/models/#{table_prefix}.rb"
56
47
  end
57
48
 
58
- def create_mailer
59
- return unless defined?(ActionMailer)
60
-
61
- template "app/mailers/rodauth_mailer.rb"
62
-
63
- MAILER_VIEWS.each do |view|
64
- copy_file "app/views/rodauth_mailer/#{view}.text.erb"
65
- end
66
- end
67
-
68
49
  def create_fixtures
69
50
  generator_options = ::Rails.configuration.generators.options
70
51
  if generator_options[:test_unit][:fixture] && generator_options[:test_unit][:fixture_replacement].nil?
@@ -101,9 +82,12 @@ module Rodauth
101
82
  options[:argon2]
102
83
  end
103
84
 
104
- def sequel_activerecord_integration?
105
- defined?(ActiveRecord::Railtie) &&
106
- (!defined?(Sequel) || Sequel::DATABASES.empty?)
85
+ def activerecord?
86
+ defined?(ActiveRecord::Railtie)
87
+ end
88
+
89
+ def sequel?
90
+ defined?(Sequel) && Sequel::DATABASES.any?
107
91
  end
108
92
 
109
93
  def session_store?
@@ -0,0 +1,6 @@
1
+ def email_auth(name, account_id, key)
2
+ @rodauth = rodauth(name, account_id) { @email_auth_key_value = key }
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.email_auth_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def otp_disabled(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.otp_disabled_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def otp_locked_out(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.otp_locked_out_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def otp_setup(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.otp_setup_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def otp_unlock_failed(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.otp_unlock_failed_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def otp_unlocked(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.otp_unlocked_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def password_changed(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.password_changed_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def reset_password(name, account_id, key)
2
+ @rodauth = rodauth(name, account_id) { @reset_password_key_value = key }
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def reset_password_notify(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_notify_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def unlock_account(name, account_id, key)
2
+ @rodauth = rodauth(name, account_id) { @unlock_account_key_value = key }
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.unlock_account_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def verify_account(name, account_id, key)
2
+ @rodauth = rodauth(name, account_id) { @verify_account_key_value = key }
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.verify_account_email_subject
6
+ end
@@ -0,0 +1,7 @@
1
+ def verify_login_change(name, account_id, key)
2
+ @rodauth = rodauth(name, account_id) { @verify_login_change_key_value = key }
3
+ @account = @rodauth.rails_account
4
+ @new_email = @account.login_change_key.login
5
+
6
+ mail to: @new_email, subject: @rodauth.email_subject_prefix + @rodauth.verify_login_change_email_subject
7
+ end
@@ -0,0 +1,6 @@
1
+ def webauthn_authenticator_added(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.webauthn_authenticator_added_email_subject
6
+ end
@@ -0,0 +1,6 @@
1
+ def webauthn_authenticator_removed(name, account_id)
2
+ @rodauth = rodauth(name, account_id)
3
+ @account = @rodauth.rails_account
4
+
5
+ mail subject: @rodauth.email_subject_prefix + @rodauth.webauthn_authenticator_removed_email_subject
6
+ end
@@ -0,0 +1,126 @@
1
+ require "rails/generators/base"
2
+
3
+ module Rodauth
4
+ module Rails
5
+ module Generators
6
+ class MailerGenerator < ::Rails::Generators::Base
7
+ source_root "#{__dir__}/templates"
8
+ namespace "rodauth:mailer"
9
+
10
+ argument :selected_features, optional: true, type: :array,
11
+ desc: "Rodauth features to generate mailer integration for (verify_account, verify_login_change, reset_password etc.)"
12
+
13
+ class_option :all, aliases: "-a", type: :boolean,
14
+ desc: "Generates mailer integration for all Rodauth features",
15
+ default: false
16
+
17
+ class_option :name, aliases: "-n", type: :string,
18
+ desc: "The configuration name for which to generate mailer configuration",
19
+ default: nil
20
+
21
+ EMAILS = {
22
+ verify_account: %w[verify_account],
23
+ reset_password: %w[reset_password],
24
+ verify_login_change: %w[verify_login_change],
25
+ email_auth: %w[email_auth],
26
+ lockout: %w[unlock_account],
27
+ reset_password_notify: %w[reset_password_notify],
28
+ change_password_notify: %w[password_changed],
29
+ otp_modify_email: %w[otp_setup otp_disabled],
30
+ otp_lockout_email: %w[otp_locked_out otp_unlocked otp_unlock_failed],
31
+ webauthn_modify_email: %w[webauthn_authenticator_added webauthn_authenticator_removed],
32
+ }
33
+
34
+ TOKENS = %w[reset_password verify_account verify_login_change email_auth unlock_account]
35
+
36
+ def copy_mailer_views
37
+ return unless validate_features
38
+
39
+ emails.each do |email|
40
+ copy_file "app/views/rodauth_mailer/#{email}.text.erb"
41
+ end
42
+ end
43
+
44
+ def copy_mailer
45
+ return unless validate_features
46
+
47
+ if File.exist?("#{destination_root}/app/mailers/rodauth_mailer.rb") && options.fetch(:skip, true) && !options[:force] && behavior == :invoke
48
+ say "\nCopy the following lines into your Rodauth mailer:\n\n#{mailer_content}"
49
+ else
50
+ template "app/mailers/rodauth_mailer.rb"
51
+ end
52
+ end
53
+
54
+ def show_configuration
55
+ return unless behavior == :invoke && validate_features
56
+
57
+ say "\nCopy the following lines into your Rodauth configuration:\n\n#{configuration_content}"
58
+ end
59
+
60
+ private
61
+
62
+ def mailer_content
63
+ emails
64
+ .map { |email| File.read("#{__dir__}/mailer/#{email}.erb") }
65
+ .map { |content| erb_eval(content) }
66
+ .join("\n")
67
+ .indent(2)
68
+ end
69
+
70
+ def configuration_content
71
+ emails
72
+ .map { |email| configuration_chunk(email) }
73
+ .join
74
+ .indent(2)
75
+ end
76
+
77
+ def configuration_chunk(email)
78
+ <<~RUBY
79
+ create_#{email}_email do#{" |_login|" if email == "verify_login_change"}
80
+ RodauthMailer.#{email}(self.class.configuration_name, account_id#{", #{email}_key_value" if TOKENS.include?(email)})
81
+ end
82
+ RUBY
83
+ end
84
+
85
+ def erb_eval(content)
86
+ if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
87
+ ERB.new(content, trim_mode: "-").result(binding)
88
+ else
89
+ ERB.new(content, 0, "-").result(binding)
90
+ end
91
+ end
92
+
93
+ def emails
94
+ features.flat_map { |feature| EMAILS.fetch(feature) }
95
+ end
96
+
97
+ def validate_features
98
+ if (features - EMAILS.keys).any?
99
+ say "No available email template for feature(s): #{(features - EMAILS.keys).join(", ")}", :error
100
+ false
101
+ else
102
+ true
103
+ end
104
+ end
105
+
106
+ def features
107
+ if options[:all]
108
+ EMAILS.keys
109
+ elsif selected_features
110
+ selected_features.map(&:to_sym)
111
+ else
112
+ rodauth_configuration.features & EMAILS.keys
113
+ end
114
+ end
115
+
116
+ def rodauth_configuration
117
+ Rodauth::Rails.app.rodauth!(configuration_name)
118
+ end
119
+
120
+ def configuration_name
121
+ options[:name]&.to_sym
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -11,6 +11,6 @@ create_table :<%= table_prefix %>_authentication_audit_logs<%= primary_key_type
11
11
  <% else -%>
12
12
  t.string :metadata
13
13
  <% end -%>
14
- t.index [:<%= table_prefix %>_id, :at], name: "audit_<%= table_prefix %>_at_idx"
15
- t.index :at, name: "audit_at_idx"
14
+ t.index [:<%= table_prefix %>_id, :at]
15
+ t.index :at
16
16
  end
@@ -3,5 +3,4 @@ create_table :<%= table_prefix %>_jwt_refresh_keys<%= primary_key_type %> do |t|
3
3
  t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
4
4
  t.string :key, null: false
5
5
  t.datetime :deadline, null: false
6
- t.index :<%= table_prefix %>_id, name: "<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx"
7
6
  end
@@ -0,0 +1,7 @@
1
+ # Used by the otp_unlock feature
2
+ create_table :<%= table_prefix %>_otp_unlocks, id: false do |t|
3
+ t.<%= primary_key_type(nil) %> :id, primary_key: true
4
+ t.foreign_key :<%= table_prefix.pluralize %>, column: :id
5
+ t.integer :num_successes, null: false, default: 1
6
+ t.datetime :next_auth_attempt_after, null: false, default: -> { "<%= current_timestamp %>" }
7
+ end
@@ -12,6 +12,6 @@ create_table :<%= table_prefix %>_authentication_audit_logs do
12
12
  <% else -%>
13
13
  String :metadata
14
14
  <% end -%>
15
- index [:<%= table_prefix %>_id, :at], name: :audit_<%= table_prefix %>_at_idx
16
- index :at, name: :audit_at_idx
15
+ index [:<%= table_prefix %>_id, :at]
16
+ index :at
17
17
  end
@@ -4,5 +4,5 @@ create_table :<%= table_prefix %>_jwt_refresh_keys do
4
4
  foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, null: false, type: :Bignum
5
5
  String :key, null: false
6
6
  DateTime :deadline, null: false
7
- index :<%= table_prefix %>_id, name: :<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx
7
+ index :<%= table_prefix %>_id
8
8
  end
@@ -0,0 +1,6 @@
1
+ # Used by the otp_unlock feature
2
+ create_table :<%= table_prefix %>_otp_unlocks do
3
+ foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
4
+ Integer :num_successes, null: false, default: 1
5
+ Time :next_auth_attempt_after, null: false, default: Sequel::CURRENT_TIMESTAMP
6
+ end
@@ -20,12 +20,12 @@ module Rodauth
20
20
  desc: "Name of the generated migration file"
21
21
 
22
22
  def create_rodauth_migration
23
- validate_features or return
23
+ return unless validate_features
24
24
 
25
25
  migration_template "db/migrate/create_rodauth.rb", File.join(db_migrate_path, "#{migration_name}.rb")
26
26
  end
27
27
 
28
- def show_instructions
28
+ def show_configuration
29
29
  # skip if called from install generator, it already adds configuration
30
30
  return if current_command_chain.include?(:generate_rodauth_migration)
31
31
  return unless options[:prefix] && behavior == :invoke
@@ -36,7 +36,7 @@ module Rodauth
36
36
  .join("\n")
37
37
  .indent(2)
38
38
 
39
- say "\nAdd the following to your Rodauth configuration:\n\n#{configuration}"
39
+ say "\nCopy the following lines into your Rodauth configuration:\n\n#{configuration}"
40
40
  end
41
41
 
42
42
  private
@@ -39,7 +39,7 @@ Depending on your application's configuration some manual setup may be required:
39
39
  ...
40
40
  </head>
41
41
 
42
- * Not required *
42
+ * Not required *
43
43
 
44
44
  5. You can copy Rodauth views (for customization) to your app by running:
45
45
 
@@ -47,6 +47,12 @@ Depending on your application's configuration some manual setup may be required:
47
47
 
48
48
  rails g rodauth:views --css=tailwind # tailwind views (requires @tailwindcss/forms plugin)
49
49
 
50
- * Not required *
50
+ * Not required *
51
+
52
+ 6. You can generate email templates and mailer integration by running:
53
+
54
+ rails g rodauth:mailer
55
+
56
+ * Not required *
51
57
 
52
58
  ===============================================================================
@@ -1,4 +1,20 @@
1
1
  class RodauthController < ApplicationController
2
- # used by Rodauth for rendering views, CSRF protection, and running any
3
- # registered action callbacks and rescue_from handlers
2
+ # Used by Rodauth for rendering views, CSRF protection, running any
3
+ # registered action callbacks and rescue handlers, instrumentation etc.
4
+
5
+ # Controller callbacks and rescue handlers will run around Rodauth endpoints.
6
+ # before_action :verify_captcha, only: :login, if: -> { request.post? }
7
+ # rescue_from("SomeError") { |exception| ... }
8
+
9
+ # Layout can be changed for all Rodauth pages or only certain pages.
10
+ # layout "authentication"
11
+ # layout -> do
12
+ # case rodauth.current_route
13
+ # when :login, :create_account, :verify_account, :verify_account_resend,
14
+ # :reset_password, :reset_password_request
15
+ # "authentication"
16
+ # else
17
+ # "application"
18
+ # end
19
+ # end
4
20
  end
@@ -1,61 +1,15 @@
1
1
  class RodauthMailer < ApplicationMailer
2
2
  default to: -> { @rodauth.email_to }, from: -> { @rodauth.email_from }
3
3
 
4
- def verify_account(name, account_id, key)
5
- @rodauth = rodauth(name, account_id) { @verify_account_key_value = key }
6
- @account = @rodauth.rails_account
7
-
8
- mail subject: @rodauth.email_subject_prefix + @rodauth.verify_account_email_subject
9
- end
10
-
11
- def reset_password(name, account_id, key)
12
- @rodauth = rodauth(name, account_id) { @reset_password_key_value = key }
13
- @account = @rodauth.rails_account
14
-
15
- mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_email_subject
16
- end
17
-
18
- def verify_login_change(name, account_id, key)
19
- @rodauth = rodauth(name, account_id) { @verify_login_change_key_value = key }
20
- @account = @rodauth.rails_account
21
- @new_email = @account.login_change_key.login
22
-
23
- mail to: @new_email, subject: @rodauth.email_subject_prefix + @rodauth.verify_login_change_email_subject
24
- end
25
-
26
- def password_changed(name, account_id)
27
- @rodauth = rodauth(name, account_id)
28
- @account = @rodauth.rails_account
29
-
30
- mail subject: @rodauth.email_subject_prefix + @rodauth.password_changed_email_subject
31
- end
32
-
33
- # def reset_password_notify(name, account_id)
34
- # @rodauth = rodauth(name, account_id)
35
- # @account = @rodauth.rails_account
36
-
37
- # mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_notify_email_subject
38
- # end
39
-
40
- # def email_auth(name, account_id, key)
41
- # @rodauth = rodauth(name, account_id) { @email_auth_key_value = key }
42
- # @account = @rodauth.rails_account
43
-
44
- # mail subject: @rodauth.email_subject_prefix + @rodauth.email_auth_email_subject
45
- # end
46
-
47
- # def unlock_account(name, account_id, key)
48
- # @rodauth = rodauth(name, account_id) { @unlock_account_key_value = key }
49
- # @account = @rodauth.rails_account
50
-
51
- # mail subject: @rodauth.email_subject_prefix + @rodauth.unlock_account_email_subject
52
- # end
4
+ <%= mailer_content -%>
53
5
 
54
6
  private
55
7
 
8
+ # Default URL options are inherited from Action Mailer, but you can override them
9
+ # ad-hoc by modifying the `rodauth.rails_url_options` hash.
56
10
  def rodauth(name, account_id, &block)
57
11
  instance = RodauthApp.rodauth(name).allocate
58
- instance.instance_eval { @account = account_ds(account_id).first! }
12
+ instance.account_from_id(account_id)
59
13
  instance.instance_eval(&block) if block
60
14
  instance
61
15
  end