rodauth-rails 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +10 -18
- data/lib/generators/rodauth/install_generator.rb +1 -1
- data/lib/generators/rodauth/migration/active_record/active_sessions.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/audit_logging.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/email_auth.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/otp.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/password_expiration.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/reset_password.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/sms_codes.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/verify_account.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/webauthn.erb +1 -1
- data/lib/generators/rodauth/migration_generator.rb +2 -22
- data/lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +7 -7
- data/lib/generators/rodauth/templates/app/misc/rodauth_main.rb.tt +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/_login_form.html.erb +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
- data/lib/generators/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
- data/lib/generators/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +1 -1
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb.tt +1 -1
- data/lib/generators/rodauth/views_generator.rb +3 -12
- data/lib/rodauth/rails/app.rb +7 -9
- data/lib/rodauth/rails/feature/base.rb +5 -29
- data/lib/rodauth/rails/feature/render.rb +1 -1
- data/lib/rodauth/rails/railtie.rb +2 -6
- data/lib/rodauth/rails/version.rb +1 -1
- data/lib/rodauth/rails.rb +0 -10
- data/rodauth-rails.gemspec +2 -2
- metadata +9 -9
- data/lib/generators/rodauth/templates/app/views/rodauth/_login_form_header.html.erb +0 -3
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form_header.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f73ab003a11054b2534802c0de9224c867b7a173d8d553888918fa792ee3da4
|
4
|
+
data.tar.gz: 07136b1748df5970d5d263d5d9439596c3c2e083ccd88269ab7145a8cd73fefc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc8c1a0ef2cd7d9c49f9fed9dd6423e92ec4112ddaa65b5a8fa63134f35d5fa9b5f2f1679c4d4d7f4d9f3cd5a71acf840d4d59ce2731b52d82914c200744eb03
|
7
|
+
data.tar.gz: 41f707560dd3ce232f54c80bc83f2210d4667d715c5f25aab812382a54f4115cab03d3e8e23d1c8c8b1e5e572404c91b332b040b741648c2577499779c0bf6a1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 1.9.0 (2023-05-22)
|
2
|
+
|
3
|
+
* Add support for webauthn_autofill feature to the views generator (@janko)
|
4
|
+
|
5
|
+
* Generate view templates for two_factor_base feature only if explicitly specified (@janko)
|
6
|
+
|
7
|
+
* Set `login_param "email"` in generated Rodauth configuration (@janko)
|
8
|
+
|
9
|
+
* Handle Trilogy adapter in generators (@janko)
|
10
|
+
|
11
|
+
* Use `email_subject_prefix` in generated mailer (@janko)
|
12
|
+
|
13
|
+
* Fix typo in `unlock_account` email template (@zavan)
|
14
|
+
|
15
|
+
* Retrieve current account using `account!` in `#rails_account` method (@janko)
|
16
|
+
|
17
|
+
* Drop support for Rails 4.2 (@janko)
|
18
|
+
|
1
19
|
## 1.8.0 (2023-02-25)
|
2
20
|
|
3
21
|
* Add table argument to `rodauth:install` generator (@janko)
|
data/README.md
CHANGED
@@ -31,16 +31,13 @@ There are already several popular authentication solutions for Rails (Devise,
|
|
31
31
|
Sorcery, Clearance, Authlogic), so why would you choose Rodauth? Here are some
|
32
32
|
of the advantages that stand out for me:
|
33
33
|
|
34
|
-
* multifactor authentication ([TOTP][otp], [SMS codes][sms_codes], [recovery codes][recovery_codes], [
|
34
|
+
* multifactor authentication ([TOTP][otp], [SMS codes][sms_codes], [recovery codes][recovery_codes], [passkeys][webauthn])
|
35
35
|
* standardized [JSON API support][json] for every feature (including [JWT][jwt])
|
36
36
|
* enterprise security features ([password complexity][password_complexity], [disallow password reuse][disallow_password_reuse], [password expiration][password_expiration], [session expiration][session_expiration], [single session][single_session], [account expiration][account_expiration])
|
37
|
-
* [email
|
38
|
-
* [audit logging][audit_logging]
|
37
|
+
* passwordless authentication ([email][email_auth], [passkeys][webauthn_login])
|
38
|
+
* [audit logging][audit_logging] for any action
|
39
39
|
* ability to protect password hashes even in case of SQL injection ([more details][password protection])
|
40
|
-
*
|
41
|
-
* uniform configuration DSL (any setting can be static or dynamic)
|
42
|
-
* consistent before/after hooks around everything
|
43
|
-
* dedicated object encapsulating all authentication logic
|
40
|
+
* uniform configuration DSL with before/after hooks around everything
|
44
41
|
|
45
42
|
### Sequel
|
46
43
|
|
@@ -349,7 +346,7 @@ $ rails generate rodauth:views --all
|
|
349
346
|
Use `--name` to generate views for a different Rodauth configuration:
|
350
347
|
|
351
348
|
```sh
|
352
|
-
$ rails generate rodauth:views webauthn --name admin
|
349
|
+
$ rails generate rodauth:views webauthn two_factor_base --name admin
|
353
350
|
```
|
354
351
|
|
355
352
|
#### Page titles
|
@@ -855,32 +852,27 @@ documentation].
|
|
855
852
|
### Defining custom methods
|
856
853
|
|
857
854
|
All Rodauth configuration methods are just syntax sugar for defining instance
|
858
|
-
methods on the auth class. You can also define your own custom methods
|
859
|
-
auth class:
|
855
|
+
methods on the auth class. You can also define your own custom methods:
|
860
856
|
|
861
857
|
```rb
|
862
858
|
class RodauthMain < Rodauth::Rails::Auth
|
863
859
|
configure do
|
864
|
-
# ...
|
865
860
|
password_match? { |password| ldap_valid?(password) }
|
866
|
-
# ...
|
867
861
|
end
|
868
862
|
|
869
|
-
|
870
|
-
|
871
|
-
db[:account_identities].where(account_id: account_id).all
|
863
|
+
def admin?
|
864
|
+
rails_account.admin?
|
872
865
|
end
|
873
866
|
|
874
867
|
private
|
875
868
|
|
876
|
-
# Example LDAP authentication
|
877
869
|
def ldap_valid?(password)
|
878
870
|
SimpleLdapAuthenticator.valid?(account[:email], password)
|
879
871
|
end
|
880
872
|
end
|
881
873
|
```
|
882
874
|
```rb
|
883
|
-
rodauth.
|
875
|
+
rodauth.admin? #=> true
|
884
876
|
```
|
885
877
|
|
886
878
|
### Rails URL helpers
|
@@ -1227,12 +1219,12 @@ conduct](CODE_OF_CONDUCT.md).
|
|
1227
1219
|
[sms_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/sms_codes_rdoc.html
|
1228
1220
|
[recovery_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/recovery_codes_rdoc.html
|
1229
1221
|
[webauthn]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_rdoc.html
|
1222
|
+
[webauthn_login]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_login_rdoc.html
|
1230
1223
|
[json]: http://rodauth.jeremyevans.net/rdoc/files/doc/json_rdoc.html
|
1231
1224
|
[jwt]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
1232
1225
|
[email_auth]: http://rodauth.jeremyevans.net/rdoc/files/doc/email_auth_rdoc.html
|
1233
1226
|
[audit_logging]: http://rodauth.jeremyevans.net/rdoc/files/doc/audit_logging_rdoc.html
|
1234
1227
|
[password protection]: https://github.com/jeremyevans/rodauth#label-Password+Hash+Access+Via+Database+Functions
|
1235
|
-
[bruteforce tokens]: https://github.com/jeremyevans/rodauth#label-Tokens
|
1236
1228
|
[password_complexity]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_complexity_rdoc.html
|
1237
1229
|
[disallow_password_reuse]: http://rodauth.jeremyevans.net/rdoc/files/doc/disallow_password_reuse_rdoc.html
|
1238
1230
|
[password_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_expiration_rdoc.html
|
@@ -2,6 +2,6 @@
|
|
2
2
|
create_table :<%= table_prefix %>_active_session_keys, primary_key: [:<%= table_prefix %>_id, :session_id] do |t|
|
3
3
|
t.references :<%= table_prefix %>, foreign_key: true<%= primary_key_type(:type) %>
|
4
4
|
t.string :session_id
|
5
|
-
t.datetime :created_at, null: false, default: <%= current_timestamp %>
|
6
|
-
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
5
|
+
t.datetime :created_at, null: false, default: -> { "<%= current_timestamp %>" }
|
6
|
+
t.datetime :last_use, null: false, default: -> { "<%= current_timestamp %>" }
|
7
7
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Used by the audit logging feature
|
2
2
|
create_table :<%= table_prefix %>_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
3
|
t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
-
t.datetime :at, null: false, default: <%= current_timestamp %>
|
4
|
+
t.datetime :at, null: false, default: -> { "<%= current_timestamp %>" }
|
5
5
|
t.text :message, null: false
|
6
6
|
<% case activerecord_adapter -%>
|
7
7
|
<% when "postgresql" -%>
|
8
8
|
t.jsonb :metadata
|
9
|
-
<% when "sqlite3", "mysql2" -%>
|
9
|
+
<% when "sqlite3", "mysql2", "trilogy" -%>
|
10
10
|
t.json :metadata
|
11
11
|
<% else -%>
|
12
12
|
t.string :metadata
|
@@ -4,5 +4,5 @@ create_table :<%= table_prefix %>_email_auth_keys, id: false do |t|
|
|
4
4
|
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.datetime :deadline, null: false
|
7
|
-
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
7
|
+
t.datetime :email_last_sent, null: false, default: -> { "<%= current_timestamp %>" }
|
8
8
|
end
|
@@ -4,5 +4,5 @@ create_table :<%= table_prefix %>_otp_keys, id: false do |t|
|
|
4
4
|
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.integer :num_failures, null: false, default: 0
|
7
|
-
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
7
|
+
t.datetime :last_use, null: false, default: -> { "<%= current_timestamp %>" }
|
8
8
|
end
|
@@ -2,5 +2,5 @@
|
|
2
2
|
create_table :<%= table_prefix %>_password_change_times, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
4
|
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
|
-
t.datetime :changed_at, null: false, default: <%= current_timestamp %>
|
5
|
+
t.datetime :changed_at, null: false, default: -> { "<%= current_timestamp %>" }
|
6
6
|
end
|
@@ -4,5 +4,5 @@ create_table :<%= table_prefix %>_password_reset_keys, id: false do |t|
|
|
4
4
|
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.datetime :deadline, null: false
|
7
|
-
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
7
|
+
t.datetime :email_last_sent, null: false, default: -> { "<%= current_timestamp %>" }
|
8
8
|
end
|
@@ -5,5 +5,5 @@ create_table :<%= table_prefix %>_sms_codes, id: false do |t|
|
|
5
5
|
t.string :phone_number, null: false
|
6
6
|
t.integer :num_failures
|
7
7
|
t.string :code
|
8
|
-
t.datetime :code_issued_at, null: false, default: <%= current_timestamp %>
|
8
|
+
t.datetime :code_issued_at, null: false, default: -> { "<%= current_timestamp %>" }
|
9
9
|
end
|
@@ -3,6 +3,6 @@ create_table :<%= table_prefix %>_verification_keys, id: false do |t|
|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
4
|
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
|
-
t.datetime :requested_at, null: false, default: <%= current_timestamp %>
|
7
|
-
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
6
|
+
t.datetime :requested_at, null: false, default: -> { "<%= current_timestamp %>" }
|
7
|
+
t.datetime :email_last_sent, null: false, default: -> { "<%= current_timestamp %>" }
|
8
8
|
end
|
@@ -9,5 +9,5 @@ create_table :<%= table_prefix %>_webauthn_keys, primary_key: [:<%= table_prefix
|
|
9
9
|
t.string :webauthn_id
|
10
10
|
t.string :public_key, null: false
|
11
11
|
t.integer :sign_count, null: false
|
12
|
-
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
12
|
+
t.datetime :last_use, null: false, default: -> { "<%= current_timestamp %>" }
|
13
13
|
end
|
@@ -111,18 +111,6 @@ module Rodauth
|
|
111
111
|
|
112
112
|
MIGRATION_DIR = "#{__dir__}/migration/active_record"
|
113
113
|
|
114
|
-
def db_migrate_path
|
115
|
-
return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
|
116
|
-
|
117
|
-
super
|
118
|
-
end
|
119
|
-
|
120
|
-
def migration_version
|
121
|
-
return unless ActiveRecord.version >= Gem::Version.new("5.0")
|
122
|
-
|
123
|
-
"[#{ActiveRecord::Migration.current_version}]"
|
124
|
-
end
|
125
|
-
|
126
114
|
def activerecord_adapter
|
127
115
|
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
128
116
|
ActiveRecord::Base.connection_db_config.adapter
|
@@ -150,18 +138,10 @@ module Rodauth
|
|
150
138
|
end
|
151
139
|
end
|
152
140
|
|
153
|
-
def current_timestamp
|
154
|
-
if ActiveRecord.version >= Gem::Version.new("5.0")
|
155
|
-
%(-> { "#{current_timestamp_literal}" })
|
156
|
-
else
|
157
|
-
%(OpenStruct.new(quoted_id: "#{current_timestamp_literal}"))
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
141
|
# Active Record 7+ sets default precision to 6 for timestamp columns,
|
162
142
|
# so we need to ensure we match this when setting the default value.
|
163
|
-
def
|
164
|
-
if ActiveRecord.version >= Gem::Version.new("7.0") &&
|
143
|
+
def current_timestamp
|
144
|
+
if ActiveRecord.version >= Gem::Version.new("7.0") && ["mysql2", "trilogy"].include?(activerecord_adapter) && ActiveRecord::Base.connection.supports_datetime_with_precision?
|
165
145
|
"CURRENT_TIMESTAMP(6)"
|
166
146
|
else
|
167
147
|
"CURRENT_TIMESTAMP"
|
@@ -5,14 +5,14 @@ class RodauthMailer < ApplicationMailer
|
|
5
5
|
@rodauth = rodauth(name, account_id) { @verify_account_key_value = key }
|
6
6
|
@account = @rodauth.rails_account
|
7
7
|
|
8
|
-
mail subject: @rodauth.verify_account_email_subject
|
8
|
+
mail subject: @rodauth.email_subject_prefix + @rodauth.verify_account_email_subject
|
9
9
|
end
|
10
10
|
|
11
11
|
def reset_password(name, account_id, key)
|
12
12
|
@rodauth = rodauth(name, account_id) { @reset_password_key_value = key }
|
13
13
|
@account = @rodauth.rails_account
|
14
14
|
|
15
|
-
mail subject: @rodauth.reset_password_email_subject
|
15
|
+
mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_email_subject
|
16
16
|
end
|
17
17
|
|
18
18
|
def verify_login_change(name, account_id, key)
|
@@ -20,35 +20,35 @@ class RodauthMailer < ApplicationMailer
|
|
20
20
|
@account = @rodauth.rails_account
|
21
21
|
@new_email = @account.login_change_key.login
|
22
22
|
|
23
|
-
mail to: @new_email, subject: @rodauth.verify_login_change_email_subject
|
23
|
+
mail to: @new_email, subject: @rodauth.email_subject_prefix + @rodauth.verify_login_change_email_subject
|
24
24
|
end
|
25
25
|
|
26
26
|
def password_changed(name, account_id)
|
27
27
|
@rodauth = rodauth(name, account_id)
|
28
28
|
@account = @rodauth.rails_account
|
29
29
|
|
30
|
-
mail subject: @rodauth.password_changed_email_subject
|
30
|
+
mail subject: @rodauth.email_subject_prefix + @rodauth.password_changed_email_subject
|
31
31
|
end
|
32
32
|
|
33
33
|
# def reset_password_notify(name, account_id)
|
34
34
|
# @rodauth = rodauth(name, account_id)
|
35
35
|
# @account = @rodauth.rails_account
|
36
36
|
|
37
|
-
# mail subject: @rodauth.reset_password_notify_email_subject
|
37
|
+
# mail subject: @rodauth.email_subject_prefix + @rodauth.reset_password_notify_email_subject
|
38
38
|
# end
|
39
39
|
|
40
40
|
# def email_auth(name, account_id, key)
|
41
41
|
# @rodauth = rodauth(name, account_id) { @email_auth_key_value = key }
|
42
42
|
# @account = @rodauth.rails_account
|
43
43
|
|
44
|
-
# mail subject: @rodauth.email_auth_email_subject
|
44
|
+
# mail subject: @rodauth.email_subject_prefix + @rodauth.email_auth_email_subject
|
45
45
|
# end
|
46
46
|
|
47
47
|
# def unlock_account(name, account_id, key)
|
48
48
|
# @rodauth = rodauth(name, account_id) { @unlock_account_key_value = key }
|
49
49
|
# @account = @rodauth.rails_account
|
50
50
|
|
51
|
-
# mail subject: @rodauth.unlock_account_email_subject
|
51
|
+
# mail subject: @rodauth.email_subject_prefix + @rodauth.unlock_account_email_subject
|
52
52
|
# end
|
53
53
|
|
54
54
|
private
|
@@ -85,7 +85,7 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
85
85
|
verify_account_set_password? false
|
86
86
|
|
87
87
|
# Change some default param keys.
|
88
|
-
|
88
|
+
login_param "email"
|
89
89
|
# password_confirm_param "confirm_password"
|
90
90
|
|
91
91
|
# Redirect back to originally requested location after authentication.
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<% else %>
|
8
8
|
<div class="form-group mb-3">
|
9
9
|
<%= form.label "login", rodauth.login_label, class: "form-label" %>
|
10
|
-
<%= form.email_field rodauth.login_param, value: params[rodauth.login_param], id: "login", autocomplete:
|
10
|
+
<%= form.email_field rodauth.login_param, value: params[rodauth.login_param], id: "login", autocomplete: rodauth.login_field_autocomplete_value, required: true, class: "form-control #{"is-invalid" if rodauth.field_error(rodauth.login_param)}", aria: ({ invalid: true, describedby: "login_error_message" } if rodauth.field_error(rodauth.login_param)) %>
|
11
11
|
<%= content_tag(:span, rodauth.field_error(rodauth.login_param), class: "invalid-feedback", id: "login_error_message") if rodauth.field_error(rodauth.login_param) %>
|
12
12
|
</div>
|
13
13
|
<% end %>
|
@@ -1,3 +1,3 @@
|
|
1
|
-
|
1
|
+
<%== rodauth.login_form_header %>
|
2
2
|
<%= render "login_form" %>
|
3
|
-
|
3
|
+
<%== rodauth.login_form_footer %>
|
@@ -1,3 +1,3 @@
|
|
1
|
-
|
1
|
+
<%== rodauth.login_form_header %>
|
2
2
|
<%== rodauth.render_multi_phase_login_forms %>
|
3
|
-
|
3
|
+
<%== rodauth.login_form_footer %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<% else %>
|
8
8
|
<div class="mb-6">
|
9
9
|
<%= form.label "login", rodauth.login_label, class: "block text-sm font-semibold" %>
|
10
|
-
<%= form.email_field rodauth.login_param, value: params[rodauth.login_param], id: "login", autocomplete:
|
10
|
+
<%= form.email_field rodauth.login_param, value: params[rodauth.login_param], id: "login", autocomplete: rodauth.login_field_autocomplete_value, required: true, class: "mt-2 text-sm w-full px-3 py-2 border rounded-md dark:bg-gray-900 dark:text-gray-100 dark:focus:bg-gray-800 #{rodauth.field_error(rodauth.login_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "login_error_message" } if rodauth.field_error(rodauth.login_param)) %>
|
11
11
|
<%= content_tag(:span, rodauth.field_error(rodauth.login_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "login_error_message") if rodauth.field_error(rodauth.login_param) %>
|
12
12
|
</div>
|
13
13
|
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% cred = rodauth.webauthn_credential_options_for_get %>
|
2
|
+
|
3
|
+
<%= form_with url: rodauth.webauthn_login_path, method: :post, id: "webauthn-login-form", data: { credential_options: cred.as_json.to_json, turbo: false } do |form| %>
|
4
|
+
<%= form.hidden_field rodauth.webauthn_auth_challenge_param, value: cred.challenge %>
|
5
|
+
<%= form.hidden_field rodauth.webauthn_auth_challenge_hmac_param, value: rodauth.compute_hmac(cred.challenge) %>
|
6
|
+
<%= form.text_field rodauth.webauthn_auth_param, value: "", id: "webauthn-auth", class: "hidden", aria: { hidden: "true" } %>
|
7
|
+
<%= form.submit rodauth.webauthn_auth_button, class: "hidden" %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= javascript_include_tag rodauth.webauthn_autofill_js_path, extname: false %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% cred = rodauth.webauthn_credential_options_for_get %>
|
2
|
+
|
3
|
+
<%= form_with url: rodauth.webauthn_login_path, method: :post, id: "webauthn-login-form", data: { credential_options: cred.as_json.to_json, turbo: false } do |form| %>
|
4
|
+
<%= form.hidden_field rodauth.webauthn_auth_challenge_param, value: cred.challenge %>
|
5
|
+
<%= form.hidden_field rodauth.webauthn_auth_challenge_hmac_param, value: rodauth.compute_hmac(cred.challenge) %>
|
6
|
+
<%= form.text_field rodauth.webauthn_auth_param, value: "", id: "webauthn-auth", class: "d-none", aria: { hidden: "true" } %>
|
7
|
+
<%= form.submit rodauth.webauthn_auth_button, class: "d-none" %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= javascript_include_tag rodauth.webauthn_autofill_js_path, extname: false %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Someone has requested
|
1
|
+
Someone has requested that the account with this email be unlocked.
|
2
2
|
If you did not request the unlocking of this account, please ignore this
|
3
3
|
message. If you requested the unlocking of this account, please go to
|
4
4
|
<%= @rodauth.unlock_account_email_link %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if defined?(::ActiveRecord::Railtie) -%>
|
2
|
-
class <%= migration_class_name %> < ActiveRecord::Migration<%=
|
2
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
3
3
|
def change
|
4
4
|
<%= migration_content -%>
|
5
5
|
end
|
@@ -23,7 +23,7 @@ module Rodauth
|
|
23
23
|
default: nil
|
24
24
|
|
25
25
|
VIEWS = {
|
26
|
-
login: %w[_login_form _login_form_footer
|
26
|
+
login: %w[_login_form _login_form_footer login multi_phase_login],
|
27
27
|
create_account: %w[create_account],
|
28
28
|
logout: %w[logout],
|
29
29
|
reset_password: %w[reset_password_request reset_password],
|
@@ -40,13 +40,7 @@ module Rodauth
|
|
40
40
|
sms_codes: %w[sms_setup sms_confirm sms_auth sms_request sms_disable],
|
41
41
|
recovery_codes: %w[recovery_codes add_recovery_codes recovery_auth],
|
42
42
|
webauthn: %w[webauthn_setup webauthn_auth webauthn_remove],
|
43
|
-
|
44
|
-
|
45
|
-
DEPENDENCIES = {
|
46
|
-
otp: :two_factor_base,
|
47
|
-
sms_codes: :two_factor_base,
|
48
|
-
recovery_codes: :two_factor_base,
|
49
|
-
webauthn: :two_factor_base,
|
43
|
+
webauthn_autofill: %w[webauthn_autofill],
|
50
44
|
}
|
51
45
|
|
52
46
|
def create_views
|
@@ -65,10 +59,7 @@ module Rodauth
|
|
65
59
|
private
|
66
60
|
|
67
61
|
def views
|
68
|
-
features.
|
69
|
-
list |= VIEWS.fetch(feature)
|
70
|
-
list |= VIEWS[DEPENDENCIES[feature]] || []
|
71
|
-
end
|
62
|
+
features.flat_map { |feature| VIEWS.fetch(feature) }
|
72
63
|
end
|
73
64
|
|
74
65
|
def validate_features
|
data/lib/rodauth/rails/app.rb
CHANGED
@@ -43,7 +43,7 @@ module Rodauth
|
|
43
43
|
|
44
44
|
after do
|
45
45
|
rails_request.commit_flash
|
46
|
-
end
|
46
|
+
end
|
47
47
|
|
48
48
|
def flash
|
49
49
|
rails_request.flash
|
@@ -92,14 +92,12 @@ module Rodauth
|
|
92
92
|
super
|
93
93
|
end
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
super
|
102
|
-
end
|
95
|
+
# When calling a Rodauth method that redirects inside the Rails
|
96
|
+
# router, Roda's after hook that commits the flash would never get
|
97
|
+
# called, so we make sure to commit the flash beforehand.
|
98
|
+
def redirect(*)
|
99
|
+
scope.rails_request.commit_flash
|
100
|
+
super
|
103
101
|
end
|
104
102
|
end
|
105
103
|
end
|
@@ -13,16 +13,7 @@ module Rodauth
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def rails_account
|
16
|
-
|
17
|
-
|
18
|
-
account_from_session unless account
|
19
|
-
|
20
|
-
unless account
|
21
|
-
clear_session
|
22
|
-
return
|
23
|
-
end
|
24
|
-
|
25
|
-
@rails_account ||= instantiate_rails_account
|
16
|
+
@rails_account ||= instantiate_rails_account if account!
|
26
17
|
end
|
27
18
|
|
28
19
|
# Reset Rails session to protect from session fixation attacks.
|
@@ -41,7 +32,7 @@ module Rodauth
|
|
41
32
|
end
|
42
33
|
|
43
34
|
def rails_controller
|
44
|
-
if only_json? &&
|
35
|
+
if only_json? && ::Rails.application.config.api_only
|
45
36
|
ActionController::API
|
46
37
|
else
|
47
38
|
ActionController::Base
|
@@ -70,28 +61,13 @@ module Rodauth
|
|
70
61
|
end
|
71
62
|
end
|
72
63
|
|
73
|
-
#
|
64
|
+
# Instance of the configured controller with current request's env hash.
|
74
65
|
def _rails_controller_instance
|
75
66
|
controller = rails_controller.new
|
76
|
-
|
67
|
+
controller.set_request! rails_request
|
68
|
+
controller.set_response! rails_controller.make_response!(controller.request)
|
77
69
|
controller
|
78
70
|
end
|
79
|
-
|
80
|
-
if ActionPack.version >= Gem::Version.new("5.0")
|
81
|
-
def prepare_rails_controller(controller, rails_request)
|
82
|
-
controller.set_request! rails_request
|
83
|
-
controller.set_response! rails_controller.make_response!(rails_request)
|
84
|
-
end
|
85
|
-
else
|
86
|
-
def prepare_rails_controller(controller, rails_request)
|
87
|
-
controller.send(:set_response!, rails_request)
|
88
|
-
controller.instance_variable_set(:@_request, rails_request)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def rails_api_controller?
|
93
|
-
defined?(ActionController::API) && rails_controller <= ActionController::API
|
94
|
-
end
|
95
71
|
end
|
96
72
|
end
|
97
73
|
end
|
@@ -32,7 +32,7 @@ module Rodauth
|
|
32
32
|
|
33
33
|
# Calls the Rails renderer, returning nil if a template is missing.
|
34
34
|
def rails_render(*args)
|
35
|
-
return if
|
35
|
+
return if rails_controller <= ActionController::API
|
36
36
|
|
37
37
|
rails_controller_instance.render_to_string(*args)
|
38
38
|
rescue ActionView::MissingTemplate
|
@@ -23,12 +23,8 @@ module Rodauth
|
|
23
23
|
# Rodauth uses RACK_ENV to set the default bcrypt hash cost
|
24
24
|
ENV["RACK_ENV"] = "test" if ::Rails.env.test?
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
include Rodauth::Rails::Test::Controller
|
29
|
-
end
|
30
|
-
else
|
31
|
-
ActionController::TestCase.include Rodauth::Rails::Test::Controller
|
26
|
+
ActiveSupport.on_load(:action_controller_test_case) do
|
27
|
+
include Rodauth::Rails::Test::Controller
|
32
28
|
end
|
33
29
|
end
|
34
30
|
|
data/lib/rodauth/rails.rb
CHANGED
data/rodauth-rails.gemspec
CHANGED
@@ -16,8 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = Dir["README.md", "LICENSE.txt", "CHANGELOG.md", "lib/**/*", "*.gemspec"]
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
-
spec.add_dependency "railties", ">=
|
20
|
-
spec.add_dependency "rodauth", "~> 2.
|
19
|
+
spec.add_dependency "railties", ">= 5.0", "< 8"
|
20
|
+
spec.add_dependency "rodauth", "~> 2.30"
|
21
21
|
spec.add_dependency "roda", "~> 3.55"
|
22
22
|
spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
|
23
23
|
spec.add_dependency "rodauth-model", "~> 0.2"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '8'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '5.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '8'
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '2.
|
39
|
+
version: '2.30'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '2.
|
46
|
+
version: '2.30'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: roda
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -227,7 +227,6 @@ files:
|
|
227
227
|
- lib/generators/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb
|
228
228
|
- lib/generators/rodauth/templates/app/views/rodauth/_login_form.html.erb
|
229
229
|
- lib/generators/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb
|
230
|
-
- lib/generators/rodauth/templates/app/views/rodauth/_login_form_header.html.erb
|
231
230
|
- lib/generators/rodauth/templates/app/views/rodauth/add_recovery_codes.html.erb
|
232
231
|
- lib/generators/rodauth/templates/app/views/rodauth/change_login.html.erb
|
233
232
|
- lib/generators/rodauth/templates/app/views/rodauth/change_password.html.erb
|
@@ -254,7 +253,6 @@ files:
|
|
254
253
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/_email_auth_request_form.html.erb
|
255
254
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb
|
256
255
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form_footer.html.erb
|
257
|
-
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form_header.html.erb
|
258
256
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/add_recovery_codes.html.erb
|
259
257
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/change_login.html.erb
|
260
258
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/change_password.html.erb
|
@@ -287,6 +285,7 @@ files:
|
|
287
285
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/verify_account_resend.html.erb
|
288
286
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/verify_login_change.html.erb
|
289
287
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_auth.html.erb
|
288
|
+
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb
|
290
289
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb
|
291
290
|
- lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_setup.html.erb
|
292
291
|
- lib/generators/rodauth/templates/app/views/rodauth/two_factor_auth.html.erb
|
@@ -298,6 +297,7 @@ files:
|
|
298
297
|
- lib/generators/rodauth/templates/app/views/rodauth/verify_account_resend.html.erb
|
299
298
|
- lib/generators/rodauth/templates/app/views/rodauth/verify_login_change.html.erb
|
300
299
|
- lib/generators/rodauth/templates/app/views/rodauth/webauthn_auth.html.erb
|
300
|
+
- lib/generators/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb
|
301
301
|
- lib/generators/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb
|
302
302
|
- lib/generators/rodauth/templates/app/views/rodauth/webauthn_setup.html.erb
|
303
303
|
- lib/generators/rodauth/templates/app/views/rodauth_mailer/email_auth.text.erb
|
@@ -351,7 +351,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
351
351
|
- !ruby/object:Gem::Version
|
352
352
|
version: '0'
|
353
353
|
requirements: []
|
354
|
-
rubygems_version: 3.4.
|
354
|
+
rubygems_version: 3.4.12
|
355
355
|
signing_key:
|
356
356
|
specification_version: 4
|
357
357
|
summary: Provides Rails integration for Rodauth.
|