rodauth-rails 1.1.0 โ 1.2.2
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 +39 -25
- data/lib/generators/rodauth/migration/active_sessions.erb +2 -2
- data/lib/generators/rodauth/migration/audit_logging.erb +1 -1
- data/lib/generators/rodauth/migration/base.erb +2 -2
- data/lib/generators/rodauth/migration/email_auth.erb +1 -1
- data/lib/generators/rodauth/migration/otp.erb +1 -1
- data/lib/generators/rodauth/migration/password_expiration.erb +1 -1
- data/lib/generators/rodauth/migration/reset_password.erb +1 -1
- data/lib/generators/rodauth/migration/sms_codes.erb +1 -1
- data/lib/generators/rodauth/migration/verify_account.erb +2 -2
- data/lib/generators/rodauth/migration/webauthn.erb +1 -1
- data/lib/generators/rodauth/migration_helpers.rb +8 -0
- data/lib/generators/rodauth/templates/app/misc/rodauth_main.rb +1 -4
- data/lib/generators/rodauth/templates/app/models/account.rb +1 -0
- data/lib/rodauth/rails/app/flash.rb +1 -2
- data/lib/rodauth/rails/controller_methods.rb +4 -29
- data/lib/rodauth/rails/feature/base.rb +21 -0
- data/lib/rodauth/rails/feature/instrumentation.rb +1 -1
- data/lib/rodauth/rails/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 402cbf2f62d93eae97353a3aed436ce742b41421e880176649a7271c5516b39c
|
4
|
+
data.tar.gz: ca035e7a60c54b4e1b6f2a42ea6405f43811146141c30c5a6d14fd7c0600669e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 888fd37f380d6f4896b544374c6681445dbb0e90d692dd7c0239aa043c9d6c0cb2aaafa9b47f271cd6cc70ad3a6c88693c988901aed1e5bc0f77ed5c92cb4ab1
|
7
|
+
data.tar.gz: 48fe23bfbd3d78c3378ab47ecf92ffd7f87fe768f996764a71b8534a2cab8731ebc080998b03ea9a78f1fecd949548782ca8e38dc17c56fa2606ea11f7a7fbe9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 1.2.2 (2022-02-22)
|
2
|
+
|
3
|
+
* Fix flash messages not being preserved through consecutive redirects (@janko)
|
4
|
+
|
5
|
+
## 1.2.1 (2022-02-19)
|
6
|
+
|
7
|
+
* Change `accounts.status` column type from string to integer (@zhongsheng)
|
8
|
+
|
9
|
+
## 1.2.0 (2022-02-11)
|
10
|
+
|
11
|
+
* Work around Active Record 4.2 not supporting procs for literal SQL column default (@janko)
|
12
|
+
|
13
|
+
* Avoid re-fetching the account in `#current_account` when it has already been fetched by Rodauth (@janko)
|
14
|
+
|
15
|
+
* Extract `#current_account` helper functionality into `#rails_account` Rodauth method (@janko)
|
16
|
+
|
17
|
+
* Use default account status values in generated configuration, with enum on `Account` model (@janko)
|
18
|
+
|
1
19
|
## 1.1.0 (2022-01-16)
|
2
20
|
|
3
21
|
* Automatically route the path prefix in `r.rodauth` if one has been set (@janko)
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Provides Rails integration for the [Rodauth] authentication framework.
|
|
4
4
|
|
5
5
|
## Resources
|
6
6
|
|
7
|
-
Useful links:
|
7
|
+
๐ Useful links:
|
8
8
|
|
9
9
|
* [Rodauth documentation](http://rodauth.jeremyevans.net/documentation.html)
|
10
10
|
* [Rails demo](https://github.com/janko/rodauth-demo-rails)
|
@@ -12,11 +12,15 @@ Useful links:
|
|
12
12
|
* [OmniAuth guide](https://github.com/janko/rodauth-rails/wiki/OmniAuth)
|
13
13
|
* [Testing guide](https://github.com/janko/rodauth-rails/wiki/Testing)
|
14
14
|
|
15
|
-
|
15
|
+
๐ฅ Screencasts:
|
16
|
+
|
17
|
+
* [Rails Authentication with Rodauth](https://www.youtube.com/watch?v=2hDpNikacf0)
|
18
|
+
|
19
|
+
๐ Articles:
|
16
20
|
|
17
21
|
* [Rodauth: A Refreshing Authentication Solution for Ruby](https://janko.io/rodauth-a-refreshing-authentication-solution-for-ruby/)
|
18
|
-
* [
|
19
|
-
* [
|
22
|
+
* [Rails Authentication with Rodauth](https://janko.io/adding-authentication-in-rails-with-rodauth/)
|
23
|
+
* [Multifactor Authentication in Rails with Rodauth](https://janko.io/adding-multifactor-authentication-in-rails-with-rodauth/)
|
20
24
|
* [How to build an OIDC provider using rodauth-oauth on Rails](https://honeyryderchuck.gitlab.io/httpx/2021/03/15/oidc-provider-on-rails-using-rodauth-oauth.html)
|
21
25
|
|
22
26
|
## Why Rodauth?
|
@@ -140,16 +144,14 @@ authentication experience, and the forms use [Bootstrap] markup.
|
|
140
144
|
### Current account
|
141
145
|
|
142
146
|
The `#current_account` method is defined in controllers and views, which
|
143
|
-
returns the model instance of the currently logged in account.
|
147
|
+
returns the model instance of the currently logged in account. If the account
|
148
|
+
doesn't exist in the database, the session will be cleared.
|
144
149
|
|
145
150
|
```rb
|
146
151
|
current_account #=> #<Account id=123 email="user@example.com">
|
147
152
|
current_account.email #=> "user@example.com"
|
148
153
|
```
|
149
154
|
|
150
|
-
If the account doesn't exist in the database, the session will be cleared and
|
151
|
-
login required.
|
152
|
-
|
153
155
|
Pass the configuration name to retrieve accounts belonging to other Rodauth
|
154
156
|
configurations:
|
155
157
|
|
@@ -157,6 +159,8 @@ configurations:
|
|
157
159
|
current_account(:admin)
|
158
160
|
```
|
159
161
|
|
162
|
+
This just delegates to the `#rails_account` method on the Rodauth object.
|
163
|
+
|
160
164
|
#### Custom account model
|
161
165
|
|
162
166
|
The `#current_account` method will try to infer the account model class from
|
@@ -248,6 +252,18 @@ Rails.application.routes.draw do
|
|
248
252
|
end
|
249
253
|
```
|
250
254
|
|
255
|
+
The current account can be retrieved via the `#rails_account` method:
|
256
|
+
|
257
|
+
```rb
|
258
|
+
# config/routes.rb
|
259
|
+
Rails.application.routes.draw do
|
260
|
+
# require user to be admin
|
261
|
+
constraints Rodauth::Rails.authenticated { |rodauth| rodauth.rails_account.admin? } do
|
262
|
+
# ...
|
263
|
+
end
|
264
|
+
end
|
265
|
+
```
|
266
|
+
|
251
267
|
You can specify the Rodauth configuration by passing the configuration name:
|
252
268
|
|
253
269
|
```rb
|
@@ -1097,16 +1113,15 @@ end
|
|
1097
1113
|
|
1098
1114
|
The recommended [Rodauth migration] stores possible account status values in a
|
1099
1115
|
separate table, and creates a foreign key on the accounts table, which ensures
|
1100
|
-
only a valid status value will be persisted.
|
1116
|
+
only a valid status value will be persisted. Unfortunately, this doesn't work
|
1117
|
+
when the database is restored from the schema file, in which case the account
|
1118
|
+
statuses table will be empty. This happens in tests by default, but it's also
|
1119
|
+
not unusual to do it in development.
|
1101
1120
|
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
To address this, rodauth-rails modifies the setup to store account status text
|
1107
|
-
directly in the accounts table. If you're worried about invalid status values
|
1108
|
-
creeping in, you may use enums instead. Alternatively, you can always go back
|
1109
|
-
to the setup recommended by Rodauth.
|
1121
|
+
To address this, rodauth-rails uses a `status` column without a separate table.
|
1122
|
+
If you're worried about invalid status values creeping in, you may use enums
|
1123
|
+
instead. Alternatively, you can always go back to the setup recommended by
|
1124
|
+
Rodauth.
|
1110
1125
|
|
1111
1126
|
```rb
|
1112
1127
|
# in the migration:
|
@@ -1122,14 +1137,13 @@ create_table :accounts do |t|
|
|
1122
1137
|
end
|
1123
1138
|
```
|
1124
1139
|
```diff
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
end
|
1140
|
+
class RodauthMain < Rodauth::Rails::Auth
|
1141
|
+
configure do
|
1142
|
+
# ...
|
1143
|
+
- account_status_column :status
|
1144
|
+
# ...
|
1145
|
+
end
|
1146
|
+
end
|
1133
1147
|
```
|
1134
1148
|
|
1135
1149
|
### Deadline values
|
@@ -2,6 +2,6 @@
|
|
2
2
|
create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
|
3
3
|
t.references :account, foreign_key: true<%= primary_key_type(:type) %>
|
4
4
|
t.string :session_id
|
5
|
-
t.datetime :created_at, null: false, default:
|
6
|
-
t.datetime :last_use, null: false, default:
|
5
|
+
t.datetime :created_at, null: false, default: <%= current_timestamp %>
|
6
|
+
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
7
7
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the audit logging feature
|
2
2
|
create_table :account_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
3
|
t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
-
t.datetime :at, null: false, default:
|
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" -%>
|
@@ -9,10 +9,10 @@ create_table :accounts<%= primary_key_type %> do |t|
|
|
9
9
|
<% else -%>
|
10
10
|
t.string :email, null: false
|
11
11
|
<% end -%>
|
12
|
-
t.
|
12
|
+
t.integer :status, null: false, default: 1
|
13
13
|
<% case activerecord_adapter -%>
|
14
14
|
<% when "postgresql", "sqlite3" -%>
|
15
|
-
t.index :email, unique: true, where: "status IN (
|
15
|
+
t.index :email, unique: true, where: "status IN (1, 2)"
|
16
16
|
<% else -%>
|
17
17
|
t.index :email, unique: true
|
18
18
|
<% end -%>
|
@@ -3,5 +3,5 @@ create_table :account_email_auth_keys<%= primary_key_type %> do |t|
|
|
3
3
|
t.foreign_key :accounts, column: :id
|
4
4
|
t.string :key, null: false
|
5
5
|
t.datetime :deadline, null: false
|
6
|
-
t.datetime :email_last_sent, null: false, default:
|
6
|
+
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
7
7
|
end
|
@@ -3,5 +3,5 @@ create_table :account_otp_keys<%= primary_key_type %> do |t|
|
|
3
3
|
t.foreign_key :accounts, column: :id
|
4
4
|
t.string :key, null: false
|
5
5
|
t.integer :num_failures, null: false, default: 0
|
6
|
-
t.datetime :last_use, null: false, default:
|
6
|
+
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
7
7
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Used by the password expiration feature
|
2
2
|
create_table :account_password_change_times<%= primary_key_type %> do |t|
|
3
3
|
t.foreign_key :accounts, column: :id
|
4
|
-
t.datetime :changed_at, null: false, default:
|
4
|
+
t.datetime :changed_at, null: false, default: <%= current_timestamp %>
|
5
5
|
end
|
@@ -3,5 +3,5 @@ create_table :account_password_reset_keys<%= primary_key_type %> do |t|
|
|
3
3
|
t.foreign_key :accounts, column: :id
|
4
4
|
t.string :key, null: false
|
5
5
|
t.datetime :deadline, null: false
|
6
|
-
t.datetime :email_last_sent, null: false, default:
|
6
|
+
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
7
7
|
end
|
@@ -4,5 +4,5 @@ create_table :account_sms_codes<%= primary_key_type %> do |t|
|
|
4
4
|
t.string :phone_number, null: false
|
5
5
|
t.integer :num_failures
|
6
6
|
t.string :code
|
7
|
-
t.datetime :code_issued_at, null: false, default:
|
7
|
+
t.datetime :code_issued_at, null: false, default: <%= current_timestamp %>
|
8
8
|
end
|
@@ -2,6 +2,6 @@
|
|
2
2
|
create_table :account_verification_keys<%= primary_key_type %> do |t|
|
3
3
|
t.foreign_key :accounts, column: :id
|
4
4
|
t.string :key, null: false
|
5
|
-
t.datetime :requested_at, null: false, default:
|
6
|
-
t.datetime :email_last_sent, null: false, default:
|
5
|
+
t.datetime :requested_at, null: false, default: <%= current_timestamp %>
|
6
|
+
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
7
7
|
end
|
@@ -8,5 +8,5 @@ create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do
|
|
8
8
|
t.string :webauthn_id
|
9
9
|
t.string :public_key, null: false
|
10
10
|
t.integer :sign_count, null: false
|
11
|
-
t.datetime :last_use, null: false, default:
|
11
|
+
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
12
12
|
end
|
@@ -63,6 +63,14 @@ module Rodauth
|
|
63
63
|
ERB.new(content, 0, "-").result(binding)
|
64
64
|
end
|
65
65
|
end
|
66
|
+
|
67
|
+
def current_timestamp
|
68
|
+
if ActiveRecord.version >= Gem::Version.new("5.0")
|
69
|
+
%(-> { "CURRENT_TIMESTAMP" })
|
70
|
+
else
|
71
|
+
%(OpenStruct.new(quoted_id: "CURRENT_TIMESTAMP"))
|
72
|
+
end
|
73
|
+
end
|
66
74
|
end
|
67
75
|
end
|
68
76
|
end
|
@@ -31,11 +31,8 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
31
31
|
# Specify the controller used for view rendering and CSRF verification.
|
32
32
|
rails_controller { RodauthController }
|
33
33
|
|
34
|
-
# Store account status in
|
34
|
+
# Store account status in an integer column without foreign key constraint.
|
35
35
|
account_status_column :status
|
36
|
-
account_unverified_status_value "unverified"
|
37
|
-
account_open_status_value "verified"
|
38
|
-
account_closed_status_value "closed"
|
39
36
|
|
40
37
|
# Store password hash in a column instead of a separate table.
|
41
38
|
# account_password_hash_column :password_digest
|
@@ -8,41 +8,16 @@ module Rodauth
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def rodauth(name = nil)
|
12
|
-
request.env.fetch ["rodauth", *name].join(".")
|
13
|
-
end
|
14
|
-
|
15
11
|
def current_account(name = nil)
|
16
|
-
|
17
|
-
|
12
|
+
rodauth(name).rails_account || rodauth(name).login_required
|
13
|
+
end
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
rodauth(name).clear_session
|
22
|
-
rodauth(name).login_required
|
23
|
-
end
|
15
|
+
def rodauth(name = nil)
|
16
|
+
request.env.fetch ["rodauth", *name].join(".")
|
24
17
|
end
|
25
18
|
|
26
19
|
private
|
27
20
|
|
28
|
-
def fetch_account(model, id, ¬_found)
|
29
|
-
if defined?(ActiveRecord::Base) && model < ActiveRecord::Base
|
30
|
-
begin
|
31
|
-
model.find(id)
|
32
|
-
rescue ActiveRecord::RecordNotFound
|
33
|
-
not_found.call
|
34
|
-
end
|
35
|
-
elsif defined?(Sequel::Model) && model < Sequel::Model
|
36
|
-
begin
|
37
|
-
model.with_pk!(id)
|
38
|
-
rescue Sequel::NoMatchingRow
|
39
|
-
not_found.call
|
40
|
-
end
|
41
|
-
else
|
42
|
-
fail Error, "unsupported model type: #{model}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
21
|
def rodauth_response
|
47
22
|
res = catch(:halt) { return yield }
|
48
23
|
|
@@ -8,6 +8,17 @@ module Rodauth
|
|
8
8
|
feature.auth_cached_method :rails_controller_instance
|
9
9
|
end
|
10
10
|
|
11
|
+
def rails_account
|
12
|
+
account_from_session unless account
|
13
|
+
|
14
|
+
unless account
|
15
|
+
clear_session if logged_in?
|
16
|
+
return
|
17
|
+
end
|
18
|
+
|
19
|
+
@rails_account ||= instantiate_rails_account
|
20
|
+
end
|
21
|
+
|
11
22
|
# Reset Rails session to protect from session fixation attacks.
|
12
23
|
def clear_session
|
13
24
|
rails_controller_instance.reset_session
|
@@ -43,6 +54,16 @@ module Rodauth
|
|
43
54
|
|
44
55
|
private
|
45
56
|
|
57
|
+
def instantiate_rails_account
|
58
|
+
if defined?(ActiveRecord::Base) && rails_account_model < ActiveRecord::Base
|
59
|
+
rails_account_model.instantiate(account.stringify_keys)
|
60
|
+
elsif defined?(Sequel::Model) && rails_account_model < Sequel::Model
|
61
|
+
rails_account_model.load(account)
|
62
|
+
else
|
63
|
+
fail Error, "unsupported model type: #{rails_account_model}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
46
67
|
# Instances of the configured controller with current request's env hash.
|
47
68
|
def _rails_controller_instance
|
48
69
|
controller = rails_controller.new
|
@@ -40,7 +40,7 @@ module Rodauth
|
|
40
40
|
begin
|
41
41
|
result = catch(:halt) { yield }
|
42
42
|
|
43
|
-
response = ActionDispatch::Response.new
|
43
|
+
response = ActionDispatch::Response.new(*(result || [404, {}, []]))
|
44
44
|
payload[:response] = response
|
45
45
|
payload[:status] = response.status
|
46
46
|
|
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.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohniฤ
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -268,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
268
|
- !ruby/object:Gem::Version
|
269
269
|
version: '0'
|
270
270
|
requirements: []
|
271
|
-
rubygems_version: 3.
|
271
|
+
rubygems_version: 3.3.3
|
272
272
|
signing_key:
|
273
273
|
specification_version: 4
|
274
274
|
summary: Provides Rails integration for Rodauth.
|