rodauth-rails 1.11.0 → 1.13.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 +24 -0
- data/README.md +103 -488
- data/lib/generators/rodauth/install_generator.rb +7 -3
- data/lib/generators/rodauth/migration_generator.rb +1 -1
- data/lib/generators/rodauth/templates/app/misc/rodauth_main.rb.tt +7 -3
- data/lib/generators/rodauth/templates/app/models/account.rb.tt +2 -2
- data/lib/generators/rodauth/views_generator.rb +2 -1
- data/lib/rodauth/rails/app.rb +6 -2
- data/lib/rodauth/rails/feature/base.rb +8 -2
- data/lib/rodauth/rails/feature/internal_request.rb +1 -1
- data/lib/rodauth/rails/feature/render.rb +6 -0
- data/lib/rodauth/rails/middleware.rb +2 -2
- data/lib/rodauth/rails/test/controller.rb +4 -0
- data/lib/rodauth/rails/version.rb +1 -1
- data/rodauth-rails.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f56967000d0a2cc64e51a707783fc541d4ff37dbb3e68f1fc519ef02a0a83e65
|
4
|
+
data.tar.gz: dfe189f65d18781e42058e133f0e403ed769421fb8682e4a63078b1f7e39cb8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f582926f90ab796d491210e28705585e166047c3b3f093e27ad556fb5271041e5c0a34ce78a42d9ec84c5b074958938527b233b750ec944043611df6f1bf7112
|
7
|
+
data.tar.gz: 04e475c871440131db6c42c1eabcecc95a34e323cfdd2ce045f59b196439d404321ee27e64b857321df642e362168e146b15ed354a3710d3fff5160ad23f18d1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## 1.13.0 (2023-12-25) :christmas_tree:
|
2
|
+
|
3
|
+
* Add `#rodauth` method to controller test helpers (@janko)
|
4
|
+
|
5
|
+
* When session middleware is required by Rodauth but missing, point to Rails docs instead of Roda (@janko)
|
6
|
+
|
7
|
+
* Set `login_confirm_param` to `"email-confirm"` in default configuration for consistency (@janko)
|
8
|
+
|
9
|
+
* Set `convert_token_id_to_integer?` in default configuration to avoid DB queries on boot (@janko)
|
10
|
+
|
11
|
+
## 1.12.0 (2023-10-20)
|
12
|
+
|
13
|
+
* Allow generating view template for `confirm_password` feature (igor-alexandrov)
|
14
|
+
|
15
|
+
* Forward all requests unhandled by the Rodauth app to the Rails router (@janko)
|
16
|
+
|
17
|
+
* Use `Rodauth::Model()` directly for including in generated account model (@janko)
|
18
|
+
|
19
|
+
* Set `{jwt,argon2}_secret` to `hmac_secret` on `rodauth:install` with `--{jwt,argon2}` (@janko)
|
20
|
+
|
21
|
+
* Expose `#turbo_stream` method in `Rodauth::Rails::Auth` when using turbo-rails gem (@janko)
|
22
|
+
|
23
|
+
* Add `#rails_cookies` method for accessing the Action Dispatch cookie jar (@janko)
|
24
|
+
|
1
25
|
## 1.11.0 (2023-08-21)
|
2
26
|
|
3
27
|
* Exclude WebAuthn JS routes in `rodauth:routes`, since those stop being relevant with custom JS (@janko)
|
data/README.md
CHANGED
@@ -10,18 +10,20 @@ Provides Rails integration for the [Rodauth] authentication framework.
|
|
10
10
|
* [Rails demo](https://github.com/janko/rodauth-demo-rails)
|
11
11
|
* [JSON API guide](https://github.com/janko/rodauth-rails/wiki/JSON-API)
|
12
12
|
* [OmniAuth guide](https://github.com/janko/rodauth-rails/wiki/OmniAuth)
|
13
|
+
* [JSON Request Documentation for Rodauth](https://documenter.getpostman.com/view/26686011/2s9YC7SWn9)
|
13
14
|
|
14
15
|
🎥 Screencasts:
|
15
16
|
|
16
17
|
* [Rails Authentication with Rodauth](https://www.youtube.com/watch?v=2hDpNikacf0)
|
17
18
|
* [Multifactor Authentication with Rodauth](https://www.youtube.com/watch?v=9ON-kgXpz2A&list=PLkGQXZLACDTGKsaRWstkHQdm2CUmT3SZ-) ([TOTP](https://youtu.be/9ON-kgXpz2A), [Recovery Codes](https://youtu.be/lkFCcE1Q5-w))
|
19
|
+
* [Add Admin Accounts](https://www.youtube.com/watch?v=N6z7AtKSpNI)
|
18
20
|
|
19
21
|
📚 Articles:
|
20
22
|
|
21
23
|
* [Rodauth: A Refreshing Authentication Solution for Ruby](https://janko.io/rodauth-a-refreshing-authentication-solution-for-ruby/)
|
22
24
|
* [Rails Authentication with Rodauth](https://janko.io/adding-authentication-in-rails-with-rodauth/)
|
23
25
|
* [Multifactor Authentication in Rails with Rodauth](https://janko.io/adding-multifactor-authentication-in-rails-with-rodauth/)
|
24
|
-
* [How to build an OIDC provider using rodauth-oauth on Rails](https://honeyryderchuck.gitlab.io/
|
26
|
+
* [How to build an OIDC provider using rodauth-oauth on Rails](https://honeyryderchuck.gitlab.io/2021/03/15/oidc-provider-on-rails-using-rodauth-oauth.html)
|
25
27
|
* [What It Took to Build a Rails Integration for Rodauth](https://janko.io/what-it-took-to-build-a-rails-integration-for-rodauth/)
|
26
28
|
* [Social Login in Rails with Rodauth](https://janko.io/social-login-in-rails-with-rodauth/)
|
27
29
|
* [Passkey Authentication with Rodauth](https://janko.io/passkey-authentication-with-rodauth/)
|
@@ -44,11 +46,7 @@ of the advantages that stand out for me:
|
|
44
46
|
|
45
47
|
One common concern for people coming from other Rails authentication frameworks
|
46
48
|
is the fact that Rodauth uses [Sequel] for database interaction instead of
|
47
|
-
Active Record.
|
48
|
-
supporting complex SQL expressions, database-agnostic date arithmetic, SQL
|
49
|
-
function calls and more, all without having to drop down to raw SQL.
|
50
|
-
|
51
|
-
For Rails apps using Active Record, rodauth-rails configures Sequel to [reuse
|
49
|
+
Active Record. For Rails apps using Active Record, rodauth-rails configures Sequel to [reuse
|
52
50
|
Active Record's database connection][sequel-activerecord_connection]. This
|
53
51
|
makes it run smoothly alongside Active Record, even allowing calling Active
|
54
52
|
Record code from within Rodauth configuration. So, for all intents and
|
@@ -68,7 +66,28 @@ Next, run the install generator:
|
|
68
66
|
$ rails generate rodauth:install
|
69
67
|
```
|
70
68
|
|
71
|
-
This will
|
69
|
+
This generator will create a Rodauth app and configuration with common
|
70
|
+
authentication features enabled, a database migration with tables required by
|
71
|
+
those features, a mailer with default templates, and a few other files.
|
72
|
+
|
73
|
+
Feel free to remove any features you don't need, along with their corresponding
|
74
|
+
tables. Afterwards, run the migration:
|
75
|
+
|
76
|
+
```sh
|
77
|
+
$ rails db:migrate
|
78
|
+
```
|
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
|
+
### Install options
|
89
|
+
|
90
|
+
The install generator will use the `accounts` table by default. You can specify a different table name:
|
72
91
|
|
73
92
|
```sh
|
74
93
|
$ rails generate rodauth:install users
|
@@ -90,25 +109,6 @@ $ rails generate rodauth:install --argon2
|
|
90
109
|
$ bundle add argon2
|
91
110
|
```
|
92
111
|
|
93
|
-
This generator will create a Rodauth app and configuration with common
|
94
|
-
authentication features enabled, a database migration with tables required by
|
95
|
-
those features, a mailer with default templates, and a few other files.
|
96
|
-
|
97
|
-
Feel free to remove any features you don't need, along with their corresponding
|
98
|
-
tables. Afterwards, run the migration:
|
99
|
-
|
100
|
-
```sh
|
101
|
-
$ rails db:migrate
|
102
|
-
```
|
103
|
-
|
104
|
-
For your mailer to be able to generate email links, you'll need to set up
|
105
|
-
default URL options in each environment. Here is a possible configuration for
|
106
|
-
`config/environments/development.rb`:
|
107
|
-
|
108
|
-
```rb
|
109
|
-
config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
|
110
|
-
```
|
111
|
-
|
112
112
|
## Usage
|
113
113
|
|
114
114
|
The Rodauth app will be called for each request before it reaches the Rails
|
@@ -153,7 +153,7 @@ navigation header:
|
|
153
153
|
|
154
154
|
```erb
|
155
155
|
<% if rodauth.logged_in? %>
|
156
|
-
<%= link_to "Sign out", rodauth.logout_path,
|
156
|
+
<%= link_to "Sign out", rodauth.logout_path, data: { turbo_method: :post } %>
|
157
157
|
<% else %>
|
158
158
|
<%= link_to "Sign in", rodauth.login_path %>
|
159
159
|
<%= link_to "Sign up", rodauth.create_account_path %>
|
@@ -181,28 +181,18 @@ class ApplicationController < ActionController::Base
|
|
181
181
|
end
|
182
182
|
```
|
183
183
|
|
184
|
-
```rb
|
185
|
-
current_account #=> #<Account id=123 email="user@example.com">
|
186
|
-
current_account.email #=> "user@example.com"
|
187
|
-
```
|
188
|
-
|
189
184
|
### Requiring authentication
|
190
185
|
|
191
|
-
You
|
192
|
-
|
193
|
-
in your Rodauth app's routing block, which helps keep the authentication logic
|
194
|
-
encapsulated:
|
186
|
+
You can require authentication for routes at the middleware level in in your Rodauth
|
187
|
+
app's routing block, which helps keep the authentication logic encapsulated:
|
195
188
|
|
196
189
|
```rb
|
197
190
|
# app/misc/rodauth_app.rb
|
198
191
|
class RodauthApp < Rodauth::Rails::App
|
199
|
-
# ...
|
200
192
|
route do |r|
|
201
|
-
# ...
|
202
193
|
r.rodauth # route rodauth requests
|
203
194
|
|
204
|
-
|
205
|
-
if r.path.start_with?("/dashboard")
|
195
|
+
if r.path.start_with?("/dashboard") # /dashboard/* routes
|
206
196
|
rodauth.require_account # redirect to login page if not authenticated
|
207
197
|
end
|
208
198
|
end
|
@@ -212,7 +202,6 @@ end
|
|
212
202
|
You can also require authentication at the controller layer:
|
213
203
|
|
214
204
|
```rb
|
215
|
-
# app/controllers/application_controller.rb
|
216
205
|
class ApplicationController < ActionController::Base
|
217
206
|
private
|
218
207
|
|
@@ -222,68 +211,46 @@ class ApplicationController < ActionController::Base
|
|
222
211
|
end
|
223
212
|
```
|
224
213
|
```rb
|
225
|
-
# app/controllers/dashboard_controller.rb
|
226
214
|
class DashboardController < ApplicationController
|
227
215
|
before_action :authenticate
|
228
216
|
end
|
229
217
|
```
|
230
218
|
|
231
|
-
|
232
|
-
|
233
|
-
In some cases it makes sense to require authentication at the Rails router
|
234
|
-
level. You can do this via the built-in `authenticated` routing constraint:
|
219
|
+
Additionally, routes can be authenticated at the Rails router level:
|
235
220
|
|
236
221
|
```rb
|
237
222
|
# config/routes.rb
|
238
223
|
Rails.application.routes.draw do
|
239
224
|
constraints Rodauth::Rails.authenticate do
|
240
|
-
# ...
|
225
|
+
# ... these routes will require authentication ...
|
241
226
|
end
|
242
|
-
end
|
243
|
-
```
|
244
|
-
|
245
|
-
If you want additional conditions, you can pass in a block, which is
|
246
|
-
called with the Rodauth instance:
|
247
227
|
|
248
|
-
```rb
|
249
|
-
# config/routes.rb
|
250
|
-
Rails.application.routes.draw do
|
251
|
-
# require multifactor authentication to be setup
|
252
228
|
constraints Rodauth::Rails.authenticate { |rodauth| rodauth.uses_two_factor_authentication? } do
|
253
|
-
# ...
|
229
|
+
# ... these routes will be available only if 2FA is setup ...
|
254
230
|
end
|
255
|
-
end
|
256
|
-
```
|
257
231
|
|
258
|
-
You can specify a different Rodauth configuration by passing the configuration name:
|
259
|
-
|
260
|
-
```rb
|
261
|
-
# config/routes.rb
|
262
|
-
Rails.application.routes.draw do
|
263
232
|
constraints Rodauth::Rails.authenticate(:admin) do
|
264
|
-
# ...
|
233
|
+
# ... these routes will be authenticated with secondary "admin" configuration ...
|
265
234
|
end
|
266
|
-
end
|
267
|
-
```
|
268
235
|
|
269
|
-
If you need something more custom, you can always create the routing constraint
|
270
|
-
manually:
|
271
|
-
|
272
|
-
```rb
|
273
|
-
# config/routes.rb
|
274
|
-
Rails.application.routes.draw do
|
275
236
|
constraints -> (r) { !r.env["rodauth"].logged_in? } do # or env["rodauth.admin"]
|
276
|
-
# routes
|
237
|
+
# ... these routes will be available only if not authenticated ...
|
277
238
|
end
|
278
239
|
end
|
279
240
|
```
|
280
241
|
|
281
242
|
### Controller
|
282
243
|
|
283
|
-
Your Rodauth configuration is
|
284
|
-
it automatically executes any callbacks and rescue handlers defined on it (or the parent controller)
|
285
|
-
around Rodauth endpoints.
|
244
|
+
Your Rodauth configuration is linked to a Rails controller, which is primarily used to render views and handle CSRF protection, but will also execute any callbacks and rescue handlers defined on it around Rodauth endpoints.
|
286
245
|
|
246
|
+
```rb
|
247
|
+
# app/misc/rodauth_main.rb
|
248
|
+
class RodauthMain < Rodauth::Rails::Auth
|
249
|
+
configure do
|
250
|
+
rails_controller { RodauthController }
|
251
|
+
end
|
252
|
+
end
|
253
|
+
```
|
287
254
|
```rb
|
288
255
|
class RodauthController < ApplicationController
|
289
256
|
before_action :set_locale # executes before Rodauth endpoints
|
@@ -291,42 +258,28 @@ class RodauthController < ApplicationController
|
|
291
258
|
end
|
292
259
|
```
|
293
260
|
|
294
|
-
|
261
|
+
Various methods are available in your Rodauth configuration to bridge the gap with the controller:
|
295
262
|
|
296
|
-
You can call any controller methods from your Rodauth configuration via `rails_controller_eval`:
|
297
|
-
|
298
|
-
```rb
|
299
|
-
# app/controllers/application_controller.rb
|
300
|
-
class ApplicationController < ActionController::Base
|
301
|
-
private
|
302
|
-
def setup_tracking(account_id)
|
303
|
-
# ... some implementation ...
|
304
|
-
end
|
305
|
-
end
|
306
|
-
```
|
307
263
|
```rb
|
308
|
-
# app/misc/rodauth_main.rb
|
309
264
|
class RodauthMain < Rodauth::Rails::Auth
|
310
265
|
configure do
|
266
|
+
# calling methods on the controller:
|
311
267
|
after_create_account do
|
312
|
-
rails_controller_eval {
|
268
|
+
rails_controller_eval { some_controller_method(account_id) }
|
313
269
|
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
```
|
317
270
|
|
318
|
-
|
271
|
+
# accessing Rails URL helpers:
|
272
|
+
login_redirect { rails_routes.dashboard_path }
|
319
273
|
|
320
|
-
|
321
|
-
|
274
|
+
# accessing Rails request object:
|
275
|
+
after_change_password do
|
276
|
+
if rails_request.format.turbo_stream?
|
277
|
+
return_response rails_render(turbo_stream: [turbo_stream.replace(...)])
|
278
|
+
end
|
279
|
+
end
|
322
280
|
|
323
|
-
|
324
|
-
|
325
|
-
class RodauthMain < Rodauth::Rails::Auth
|
326
|
-
configure do
|
327
|
-
login_redirect { rails_routes.activity_path }
|
328
|
-
change_password_redirect { rails_routes.profile_path }
|
329
|
-
change_login_redirect { rails_routes.profile_path }
|
281
|
+
# accessing Rails cookies:
|
282
|
+
after_login { rails_cookies.permanent[:last_account_id] = account_id }
|
330
283
|
end
|
331
284
|
end
|
332
285
|
```
|
@@ -338,97 +291,29 @@ you'll want to start editing the markup. You can run the following command to
|
|
338
291
|
copy Rodauth templates into your Rails app:
|
339
292
|
|
340
293
|
```sh
|
341
|
-
$ rails generate rodauth:views
|
342
|
-
# or
|
343
|
-
$ rails generate rodauth:views --css=tailwind # tailwind views (requires @tailwindcss/forms plugin)
|
294
|
+
$ rails generate rodauth:views
|
344
295
|
```
|
345
296
|
|
346
297
|
This will generate views for Rodauth features you have currently enabled into
|
347
|
-
the `app/views/rodauth` directory
|
348
|
-
the main configuration.
|
298
|
+
the `app/views/rodauth` directory (provided that `RodauthController` is set for
|
299
|
+
the main configuration).
|
349
300
|
|
350
|
-
|
351
|
-
these features (this will not remove any existing views):
|
301
|
+
The generator accepts various options:
|
352
302
|
|
353
303
|
```sh
|
354
|
-
|
355
|
-
|
304
|
+
# generate views with Tailwind markup (requires @tailwindcss/forms plugin)
|
305
|
+
$ rails generate rodauth:views --css=tailwind
|
356
306
|
|
357
|
-
|
307
|
+
# specify Rodauth features to generate views for
|
308
|
+
$ rails generate rodauth:views login create_account lockout otp
|
358
309
|
|
359
|
-
|
310
|
+
# generate views for all Rodauth features
|
360
311
|
$ rails generate rodauth:views --all
|
361
|
-
```
|
362
312
|
|
363
|
-
|
364
|
-
|
365
|
-
```sh
|
313
|
+
# specify a different Rodauth configuration
|
366
314
|
$ rails generate rodauth:views webauthn two_factor_base --name admin
|
367
315
|
```
|
368
316
|
|
369
|
-
### Page titles
|
370
|
-
|
371
|
-
The generated configuration sets `title_instance_variable` to make page titles
|
372
|
-
available in your views via `@page_title` instance variable, which you can then
|
373
|
-
use in your layout:
|
374
|
-
|
375
|
-
```rb
|
376
|
-
# app/misc/rodauth_main.rb
|
377
|
-
class RodauthMain < Rodauth::Rails::Auth
|
378
|
-
configure do
|
379
|
-
title_instance_variable :@page_title
|
380
|
-
end
|
381
|
-
end
|
382
|
-
```
|
383
|
-
```erb
|
384
|
-
<!-- app/views/layouts/application.html.erb -->
|
385
|
-
<!DOCTYPE html>
|
386
|
-
<html>
|
387
|
-
<head>
|
388
|
-
<title><%= @page_title || "Default title" %></title>
|
389
|
-
<!-- ... -->
|
390
|
-
</head>
|
391
|
-
<!-- ... -->
|
392
|
-
</html>
|
393
|
-
```
|
394
|
-
|
395
|
-
### Layout
|
396
|
-
|
397
|
-
To use different layouts for different Rodauth views, you can compare the
|
398
|
-
request path in the layout method:
|
399
|
-
|
400
|
-
```rb
|
401
|
-
# app/controllers/rodauth_controller.rb
|
402
|
-
class RodauthController < ApplicationController
|
403
|
-
layout :rodauth_layout
|
404
|
-
|
405
|
-
private
|
406
|
-
|
407
|
-
def rodauth_layout
|
408
|
-
case request.path
|
409
|
-
when rodauth.login_path,
|
410
|
-
rodauth.create_account_path,
|
411
|
-
rodauth.verify_account_path,
|
412
|
-
rodauth.verify_account_resend_path,
|
413
|
-
rodauth.reset_password_path,
|
414
|
-
rodauth.reset_password_request_path
|
415
|
-
"authentication"
|
416
|
-
else
|
417
|
-
"dashboard"
|
418
|
-
end
|
419
|
-
end
|
420
|
-
end
|
421
|
-
```
|
422
|
-
|
423
|
-
### Turbo
|
424
|
-
|
425
|
-
[Turbo] has been disabled by default on all built-in and generated view
|
426
|
-
templates, because some Rodauth actions (multi-phase login, adding recovery
|
427
|
-
codes) aren't Turbo-compatible, as they return 200 responses on POST requests.
|
428
|
-
|
429
|
-
That being said, most of Rodauth *is* Turbo-compatible, so feel free to enable
|
430
|
-
Turbo for actions where you want to use it.
|
431
|
-
|
432
317
|
## Mailer
|
433
318
|
|
434
319
|
The install generator will create `RodauthMailer` with default email templates,
|
@@ -492,8 +377,6 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
|
492
377
|
end
|
493
378
|
```
|
494
379
|
|
495
|
-
### Table prefix
|
496
|
-
|
497
380
|
If you're storing account records in a table other than `accounts`, you'll want
|
498
381
|
to specify the appropriate table prefix when generating new migrations:
|
499
382
|
|
@@ -516,15 +399,13 @@ class CreateRodauthUserBaseActiveSessions < ActiveRecord::Migration
|
|
516
399
|
end
|
517
400
|
```
|
518
401
|
|
519
|
-
### Custom migration name
|
520
|
-
|
521
402
|
You can change the default migration name:
|
522
403
|
|
523
404
|
```sh
|
524
405
|
$ rails generate rodauth:migration email_auth --name create_account_email_auth_keys
|
525
406
|
```
|
526
407
|
```rb
|
527
|
-
# db/migration/*_create_account_email_auth_keys
|
408
|
+
# db/migration/*_create_account_email_auth_keys.rb
|
528
409
|
class CreateAccountEmailAuthKeys < ActiveRecord::Migration
|
529
410
|
def change
|
530
411
|
create_table :account_email_auth_keys do |t| ... end
|
@@ -540,7 +421,7 @@ tables used by enabled authentication features.
|
|
540
421
|
|
541
422
|
```rb
|
542
423
|
class Account < ActiveRecord::Base # Sequel::Model
|
543
|
-
include Rodauth::
|
424
|
+
include Rodauth::Model(RodauthMain)
|
544
425
|
end
|
545
426
|
```
|
546
427
|
```rb
|
@@ -573,6 +454,10 @@ class RodauthApp < Rodauth::Rails::App
|
|
573
454
|
route do |r|
|
574
455
|
r.rodauth # route primary rodauth requests
|
575
456
|
r.rodauth(:admin) # route secondary rodauth requests
|
457
|
+
|
458
|
+
if request.path.start_with?("/admin")
|
459
|
+
rodauth(:admin).require_account
|
460
|
+
end
|
576
461
|
end
|
577
462
|
end
|
578
463
|
```
|
@@ -599,6 +484,7 @@ end
|
|
599
484
|
Then in your application you can reference the secondary Rodauth instance:
|
600
485
|
|
601
486
|
```rb
|
487
|
+
rodauth(:admin).authenticated? # checks "admin_account_id" session value
|
602
488
|
rodauth(:admin).login_path #=> "/admin/login"
|
603
489
|
```
|
604
490
|
|
@@ -608,66 +494,24 @@ that. Note that you can also [share configuration via inheritance][inheritance].
|
|
608
494
|
|
609
495
|
## Outside of a request
|
610
496
|
|
611
|
-
|
612
|
-
|
613
|
-
In some cases you might need to use Rodauth more programmatically. If you want
|
614
|
-
to perform authentication operations outside of request context, Rodauth ships
|
615
|
-
with the [internal_request] feature just for that.
|
497
|
+
The [internal_request] and [path_class_methods] features are supported, with defaults taken from `config.action_mailer.default_url_options`.
|
616
498
|
|
617
499
|
```rb
|
618
|
-
#
|
619
|
-
class RodauthMain < Rodauth::Rails::Auth
|
620
|
-
configure do
|
621
|
-
enable :internal_request
|
622
|
-
end
|
623
|
-
end
|
624
|
-
```
|
625
|
-
```rb
|
626
|
-
# primary configuration
|
500
|
+
# internal requests
|
627
501
|
RodauthApp.rodauth.create_account(login: "user@example.com", password: "secret123")
|
628
|
-
RodauthApp.rodauth.verify_account(account_login: "
|
629
|
-
|
630
|
-
# secondary configuration
|
631
|
-
RodauthApp.rodauth(:admin).close_account(account_login: "user@example.com")
|
632
|
-
```
|
633
|
-
|
634
|
-
### Generating URLs
|
635
|
-
|
636
|
-
For generating authentication URLs outside of a request use the
|
637
|
-
[path_class_methods] plugin:
|
638
|
-
|
639
|
-
```rb
|
640
|
-
# app/misc/rodauth_main.rb
|
641
|
-
class RodauthMain < Rodauth::Rails::Auth
|
642
|
-
configure do
|
643
|
-
enable :path_class_methods
|
644
|
-
create_account_route "register"
|
645
|
-
end
|
646
|
-
end
|
647
|
-
```
|
648
|
-
```rb
|
649
|
-
# primary configuration
|
650
|
-
RodauthApp.rodauth.create_account_path # => "/register"
|
651
|
-
RodauthApp.rodauth.verify_account_url(key: "abc123") #=> "https://example.com/verify-account?key=abc123"
|
502
|
+
RodauthApp.rodauth(:admin).verify_account(account_login: "admin@example.com")
|
652
503
|
|
653
|
-
#
|
654
|
-
RodauthApp.rodauth
|
504
|
+
# path and URL methods
|
505
|
+
RodauthApp.rodauth.close_account_path #=> "/close-account"
|
506
|
+
RodauthApp.rodauth(:admin).otp_setup_url #=> "http://localhost:3000/admin/otp-setup"
|
655
507
|
```
|
656
508
|
|
657
509
|
### Calling instance methods
|
658
510
|
|
659
511
|
If you need to access Rodauth methods not exposed as internal requests, you can
|
660
|
-
use `Rodauth::Rails.rodauth` to retrieve the Rodauth instance
|
661
|
-
internal_request feature:
|
512
|
+
use `Rodauth::Rails.rodauth` to retrieve the Rodauth instance (this requires enabling
|
513
|
+
the internal_request feature):
|
662
514
|
|
663
|
-
```rb
|
664
|
-
# app/misc/rodauth_main.rb
|
665
|
-
class RodauthMain < Rodauth::Rails::Auth
|
666
|
-
configure do
|
667
|
-
enable :internal_request # this is required
|
668
|
-
end
|
669
|
-
end
|
670
|
-
```
|
671
515
|
```rb
|
672
516
|
account = Account.find_by!(email: "user@example.com")
|
673
517
|
rodauth = Rodauth::Rails.rodauth(account: account) #=> #<RodauthMain::InternalRequest ...>
|
@@ -693,8 +537,12 @@ Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
|
|
693
537
|
|
694
538
|
### Using as a library
|
695
539
|
|
696
|
-
Rodauth offers a `Rodauth.lib` method for
|
540
|
+
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:
|
697
541
|
|
542
|
+
```rb
|
543
|
+
# skip require on boot to avoid inserting Rodauth middleware
|
544
|
+
gem "rodauth-rails", require: false
|
545
|
+
```
|
698
546
|
```rb
|
699
547
|
# app/misc/rodauth_main.rb
|
700
548
|
require "rodauth/rails"
|
@@ -712,23 +560,6 @@ RodauthMain.login(login: "email@example.com", password: "secret123")
|
|
712
560
|
RodauthMain.close_account(account_login: "email@example.com")
|
713
561
|
```
|
714
562
|
|
715
|
-
Note that you'll want to skip requiring `rodauth-rails` on Rails boot, to avoid it automatically inserting the Rodauth middleware, and remove some unnecessary files generated by the install generator.
|
716
|
-
|
717
|
-
```rb
|
718
|
-
# Gemfile
|
719
|
-
gem "rodauth-rails", require: false
|
720
|
-
```
|
721
|
-
```sh
|
722
|
-
$ rm config/initializers/rodauth.rb app/misc/rodauth_app.rb app/controllers/rodauth_controller.rb
|
723
|
-
```
|
724
|
-
|
725
|
-
The `Rodauth::Rails.lib` call will forward any Rodauth [plugin options] passed to it:
|
726
|
-
|
727
|
-
```rb
|
728
|
-
# skips loading Roda render plugin and Tilt gem (used for rendering built-in templates)
|
729
|
-
Rodauth::Rails.lib(render: false) { ... }
|
730
|
-
```
|
731
|
-
|
732
563
|
## Testing
|
733
564
|
|
734
565
|
For system and integration tests, which run the whole middleware stack,
|
@@ -762,7 +593,7 @@ class ArticlesControllerTest < ActionDispatch::IntegrationTest
|
|
762
593
|
post "/logout"
|
763
594
|
assert_redirected_to "/"
|
764
595
|
end
|
765
|
-
|
596
|
+
|
766
597
|
test "required authentication" do
|
767
598
|
get :index
|
768
599
|
|
@@ -786,14 +617,11 @@ end
|
|
786
617
|
```
|
787
618
|
|
788
619
|
For more examples and information about testing with rodauth, see
|
789
|
-
[this wiki page about testing](https://github.com/janko/rodauth-rails/wiki/Testing).
|
620
|
+
[this wiki page about testing](https://github.com/janko/rodauth-rails/wiki/Testing).
|
790
621
|
|
791
622
|
## Configuring
|
792
623
|
|
793
|
-
|
794
|
-
|
795
|
-
The `rails` feature rodauth-rails loads provides the following configuration
|
796
|
-
methods:
|
624
|
+
The `rails` feature rodauth-rails loads provides the following configuration methods:
|
797
625
|
|
798
626
|
| Name | Description |
|
799
627
|
| :---- | :---------- |
|
@@ -806,70 +634,6 @@ methods:
|
|
806
634
|
| `rails_controller` | Controller class to use for rendering and CSRF protection. |
|
807
635
|
| `rails_account_model` | Model class connected with the accounts table. |
|
808
636
|
|
809
|
-
```rb
|
810
|
-
class RodauthMain < Rodauth::Rails::Auth
|
811
|
-
configure do
|
812
|
-
rails_controller { Authentication::RodauthController }
|
813
|
-
rails_account_model { Authentication::Account }
|
814
|
-
end
|
815
|
-
end
|
816
|
-
```
|
817
|
-
|
818
|
-
For the list of configuration methods provided by Rodauth, see the [feature
|
819
|
-
documentation].
|
820
|
-
|
821
|
-
### Defining custom methods
|
822
|
-
|
823
|
-
All Rodauth configuration methods are just syntax sugar for defining instance
|
824
|
-
methods on the auth class. You can also define your own custom methods:
|
825
|
-
|
826
|
-
```rb
|
827
|
-
class RodauthMain < Rodauth::Rails::Auth
|
828
|
-
configure do
|
829
|
-
password_match? { |password| ldap_valid?(password) }
|
830
|
-
end
|
831
|
-
|
832
|
-
def admin?
|
833
|
-
rails_account.admin?
|
834
|
-
end
|
835
|
-
|
836
|
-
private
|
837
|
-
|
838
|
-
def ldap_valid?(password)
|
839
|
-
SimpleLdapAuthenticator.valid?(account[:email], password)
|
840
|
-
end
|
841
|
-
end
|
842
|
-
```
|
843
|
-
```rb
|
844
|
-
rodauth.admin? #=> true
|
845
|
-
```
|
846
|
-
|
847
|
-
### Single-file configuration
|
848
|
-
|
849
|
-
If you would prefer, you can have all your Rodauth logic contained inside the
|
850
|
-
Rodauth app class:
|
851
|
-
|
852
|
-
```rb
|
853
|
-
# app/misc/rodauth_app.rb
|
854
|
-
class RodauthApp < Rodauth::Rails::App
|
855
|
-
# primary configuration
|
856
|
-
configure do
|
857
|
-
enable :login, :logout, :create_account, :verify_account
|
858
|
-
# ...
|
859
|
-
end
|
860
|
-
|
861
|
-
# secondary configuration
|
862
|
-
configure(:admin) do
|
863
|
-
enable :email_auth, :single_session
|
864
|
-
# ...
|
865
|
-
end
|
866
|
-
|
867
|
-
route do |r|
|
868
|
-
# ...
|
869
|
-
end
|
870
|
-
end
|
871
|
-
```
|
872
|
-
|
873
637
|
### Manually inserting middleware
|
874
638
|
|
875
639
|
You can choose to insert the Rodauth middleware somewhere earlier than
|
@@ -880,7 +644,7 @@ Rodauth::Rails.configure do |config|
|
|
880
644
|
config.middleware = false # disable auto-insertion
|
881
645
|
end
|
882
646
|
|
883
|
-
Rails.
|
647
|
+
Rails.configuration.middleware.insert_before AnotherMiddleware, Rodauth::Rails::Middleware
|
884
648
|
```
|
885
649
|
|
886
650
|
## How it works
|
@@ -888,7 +652,7 @@ Rails.application.config.middleware.insert_before AnotherMiddleware, Rodauth::Ra
|
|
888
652
|
### Rack middleware
|
889
653
|
|
890
654
|
The railtie inserts [`Rodauth::Rails::Middleware`](/lib/rodauth/rails/middleware.rb)
|
891
|
-
at the end of the middleware stack, which
|
655
|
+
at the end of the middleware stack, which is just a wrapper around your Rodauth app.
|
892
656
|
|
893
657
|
```sh
|
894
658
|
$ rails middleware
|
@@ -897,34 +661,15 @@ $ rails middleware
|
|
897
661
|
# run MyApp::Application.routes
|
898
662
|
```
|
899
663
|
|
900
|
-
The middleware retrieves the Rodauth app via `Rodauth::Rails.app`, which is
|
901
|
-
specified as a string to keep the class autoloadable and reloadable in
|
902
|
-
development.
|
903
|
-
|
904
|
-
```rb
|
905
|
-
Rodauth::Rails.configure do |config|
|
906
|
-
config.app = "RodauthApp"
|
907
|
-
end
|
908
|
-
```
|
909
|
-
|
910
|
-
In addition to Zeitwerk compatibility, this extra layer catches Rodauth redirects
|
911
|
-
that happen on the controller level (e.g. when calling
|
912
|
-
`rodauth.require_account` in a `before_action` filter).
|
913
|
-
|
914
664
|
### Roda app
|
915
665
|
|
916
666
|
The [`Rodauth::Rails::App`](/lib/rodauth/rails/app.rb) class is a [Roda]
|
917
|
-
subclass that provides a convenience layer
|
918
|
-
|
919
|
-
* uses Action Dispatch flash messages
|
920
|
-
* provides syntax sugar for loading the rodauth plugin
|
921
|
-
* saves Rodauth object(s) to Rack env hash
|
922
|
-
* propagates edited headers to Rails responses
|
667
|
+
subclass that provides a convenience layer over Rodauth.
|
923
668
|
|
924
669
|
#### Configure block
|
925
670
|
|
926
|
-
The `configure` call
|
927
|
-
auth class and configuration name as positional arguments (
|
671
|
+
The `configure` call is a wrapper around `plugin :rodauth`. By convention, it receives an
|
672
|
+
auth class and configuration name as positional arguments (which get converted into
|
928
673
|
`:auth_class` and `:name` plugin options), a block for anonymous auth classes,
|
929
674
|
and also accepts any additional plugin options.
|
930
675
|
|
@@ -956,29 +701,21 @@ class RodauthApp < Rodauth::Rails::App
|
|
956
701
|
end
|
957
702
|
```
|
958
703
|
|
959
|
-
####
|
704
|
+
#### Rack env
|
960
705
|
|
961
|
-
|
962
|
-
|
963
|
-
prefix.
|
706
|
+
The app sets Rodauth objects for each registered configuration in the Rack env,
|
707
|
+
so that they're accessible downstream by the Rails router, controllers and views:
|
964
708
|
|
965
709
|
```rb
|
966
|
-
|
967
|
-
|
968
|
-
prefix "/user"
|
969
|
-
end
|
970
|
-
|
971
|
-
route do |r|
|
972
|
-
r.rodauth # no need to wrap with `r.on("user") { ... }`
|
973
|
-
end
|
974
|
-
end
|
710
|
+
request.env["rodauth"] #=> #<RodauthMain>
|
711
|
+
request.env["rodauth.admin"] #=> #<RodauthAdmin> (if using multiple configurations)
|
975
712
|
```
|
976
713
|
|
977
714
|
### Auth class
|
978
715
|
|
979
716
|
The [`Rodauth::Rails::Auth`](/lib/rodauth/rails/auth.rb) class is a subclass of
|
980
717
|
`Rodauth::Auth`, which preloads the `rails` rodauth feature, sets [HMAC] secret to
|
981
|
-
Rails' secret key base, and modifies some [configuration defaults]
|
718
|
+
Rails' secret key base, and modifies some [configuration defaults][restoring defaults].
|
982
719
|
|
983
720
|
```rb
|
984
721
|
class RodauthMain < Rodauth::Rails::Auth
|
@@ -1000,128 +737,6 @@ The [`rails`](/lib/rodauth/rails/feature.rb) Rodauth feature loaded by
|
|
1000
737
|
* uses Action Controller instrumentation around Rodauth requests
|
1001
738
|
* uses Action Mailer's default URL options when calling Rodauth outside of a request
|
1002
739
|
|
1003
|
-
### Controller
|
1004
|
-
|
1005
|
-
The Rodauth app stores the `Rodauth::Rails::Auth` instances in the Rack env
|
1006
|
-
hash, which is then available in your Rails app:
|
1007
|
-
|
1008
|
-
```rb
|
1009
|
-
request.env["rodauth"] #=> #<RodauthMain>
|
1010
|
-
request.env["rodauth.admin"] #=> #<RodauthAdmin> (if using multiple configurations)
|
1011
|
-
```
|
1012
|
-
|
1013
|
-
For convenience, this object can be accessed via the `#rodauth` method in views
|
1014
|
-
and controllers:
|
1015
|
-
|
1016
|
-
```rb
|
1017
|
-
class MyController < ApplicationController
|
1018
|
-
def my_action
|
1019
|
-
rodauth #=> #<RodauthMain>
|
1020
|
-
rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations)
|
1021
|
-
end
|
1022
|
-
end
|
1023
|
-
```
|
1024
|
-
```erb
|
1025
|
-
<% rodauth #=> #<RodauthMain> %>
|
1026
|
-
<% rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations) %>
|
1027
|
-
```
|
1028
|
-
|
1029
|
-
## Rodauth defaults
|
1030
|
-
|
1031
|
-
rodauth-rails changes some of the default Rodauth settings for easier setup:
|
1032
|
-
|
1033
|
-
### Database functions
|
1034
|
-
|
1035
|
-
By default, on PostgreSQL, MySQL, and Microsoft SQL Server Rodauth uses
|
1036
|
-
database functions to access password hashes, with the user running the
|
1037
|
-
application unable to get direct access to password hashes. This reduces the
|
1038
|
-
risk of an attacker being able to access password hashes and use them to attack
|
1039
|
-
other sites.
|
1040
|
-
|
1041
|
-
While this is useful additional security, it is also more complex to set up and
|
1042
|
-
to reason about, as it requires having two different database users and making
|
1043
|
-
sure the correct migration is run for the correct user.
|
1044
|
-
|
1045
|
-
To keep with Rails' "convention over configuration" doctrine, rodauth-rails
|
1046
|
-
disables the use of database functions, though you can always turn it back on.
|
1047
|
-
|
1048
|
-
```rb
|
1049
|
-
use_database_authentication_functions? true
|
1050
|
-
```
|
1051
|
-
|
1052
|
-
To create the database functions, pass the Sequel database object into the
|
1053
|
-
Rodauth method for creating database functions:
|
1054
|
-
|
1055
|
-
```rb
|
1056
|
-
# db/migrate/*_create_rodauth_database_functions.rb
|
1057
|
-
require "rodauth/migrations"
|
1058
|
-
|
1059
|
-
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
1060
|
-
def up
|
1061
|
-
Rodauth.create_database_authentication_functions(db)
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
def down
|
1065
|
-
Rodauth.drop_database_authentication_functions(db)
|
1066
|
-
end
|
1067
|
-
|
1068
|
-
private
|
1069
|
-
|
1070
|
-
def db
|
1071
|
-
RodauthMain.allocate.db
|
1072
|
-
end
|
1073
|
-
end
|
1074
|
-
```
|
1075
|
-
|
1076
|
-
### Account statuses
|
1077
|
-
|
1078
|
-
The recommended [Rodauth migration] stores possible account status values in a
|
1079
|
-
separate table, and creates a foreign key on the accounts table, which ensures
|
1080
|
-
only a valid status value will be persisted. Unfortunately, this doesn't work
|
1081
|
-
when the database is restored from the schema file, in which case the account
|
1082
|
-
statuses table will be empty. This happens in tests by default, but it's also
|
1083
|
-
not unusual to do it in development.
|
1084
|
-
|
1085
|
-
To address this, rodauth-rails uses a `status` column without a separate table.
|
1086
|
-
If you're worried about invalid status values creeping in, you may use enums
|
1087
|
-
instead. Alternatively, you can always go back to the setup recommended by
|
1088
|
-
Rodauth.
|
1089
|
-
|
1090
|
-
```rb
|
1091
|
-
# in the migration:
|
1092
|
-
create_table :account_statuses do |t|
|
1093
|
-
t.string :name, null: false, unique: true
|
1094
|
-
end
|
1095
|
-
execute "INSERT INTO account_statuses (id, name) VALUES (1, 'Unverified'), (2, 'Verified'), (3, 'Closed')"
|
1096
|
-
|
1097
|
-
create_table :accounts do |t|
|
1098
|
-
# ...
|
1099
|
-
t.references :status, foreign_key: { to_table: :account_statuses }, null: false, default: 1
|
1100
|
-
# ...
|
1101
|
-
end
|
1102
|
-
```
|
1103
|
-
```diff
|
1104
|
-
class RodauthMain < Rodauth::Rails::Auth
|
1105
|
-
configure do
|
1106
|
-
# ...
|
1107
|
-
- account_status_column :status
|
1108
|
-
# ...
|
1109
|
-
end
|
1110
|
-
end
|
1111
|
-
```
|
1112
|
-
|
1113
|
-
### Deadline values
|
1114
|
-
|
1115
|
-
To simplify changes to the database schema, rodauth-rails configures Rodauth
|
1116
|
-
to set deadline values for various features in Ruby, instead of relying on
|
1117
|
-
the database to set default column values.
|
1118
|
-
|
1119
|
-
You can easily change this back:
|
1120
|
-
|
1121
|
-
```rb
|
1122
|
-
set_deadline_values? false
|
1123
|
-
```
|
1124
|
-
|
1125
740
|
## License
|
1126
741
|
|
1127
742
|
The gem is available as open source under the terms of the [MIT
|
@@ -1135,12 +750,10 @@ conduct](CODE_OF_CONDUCT.md).
|
|
1135
750
|
|
1136
751
|
[Rodauth]: https://github.com/jeremyevans/rodauth
|
1137
752
|
[Sequel]: https://github.com/jeremyevans/sequel
|
1138
|
-
[feature documentation]: http://rodauth.jeremyevans.net/documentation.html
|
1139
753
|
[Bootstrap]: https://getbootstrap.com/
|
1140
754
|
[Roda]: http://roda.jeremyevans.net/
|
1141
755
|
[HMAC]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
|
1142
756
|
[database authentication functions]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Password+Hash+Access+Via+Database+Functions
|
1143
|
-
[Rodauth migration]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Creating+tables
|
1144
757
|
[sequel-activerecord_connection]: https://github.com/janko/sequel-activerecord_connection
|
1145
758
|
[plugin options]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Plugin+Options
|
1146
759
|
[hmac]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
|
@@ -1169,3 +782,5 @@ conduct](CODE_OF_CONDUCT.md).
|
|
1169
782
|
[rodauth-model]: https://github.com/janko/rodauth-model
|
1170
783
|
[JSON API]: https://github.com/janko/rodauth-rails/wiki/JSON-API
|
1171
784
|
[inheritance]: http://rodauth.jeremyevans.net/rdoc/files/doc/guides/share_configuration_rdoc.html
|
785
|
+
[library]: https://github.com/jeremyevans/rodauth#label-Using+Rodauth+as+a+Library
|
786
|
+
[restoring defaults]: https://github.com/janko/rodauth-rails/wiki/Restoring-Rodauth-Defaults
|
@@ -66,7 +66,7 @@ module Rodauth
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def create_fixtures
|
69
|
-
generator_options = ::Rails.
|
69
|
+
generator_options = ::Rails.configuration.generators.options
|
70
70
|
if generator_options[:test_unit][:fixture] && generator_options[:test_unit][:fixture_replacement].nil?
|
71
71
|
test_dir = generator_options[:rails][:test_framework] == :rspec ? "spec" : "test"
|
72
72
|
template "test/fixtures/accounts.yml", "#{test_dir}/fixtures/#{table_prefix.pluralize}.yml"
|
@@ -101,17 +101,21 @@ module Rodauth
|
|
101
101
|
options[:argon2]
|
102
102
|
end
|
103
103
|
|
104
|
+
def primary_key_integer?
|
105
|
+
!::Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
|
106
|
+
end
|
107
|
+
|
104
108
|
def sequel_activerecord_integration?
|
105
109
|
defined?(ActiveRecord::Railtie) &&
|
106
110
|
(!defined?(Sequel) || Sequel::DATABASES.empty?)
|
107
111
|
end
|
108
112
|
|
109
113
|
def session_store?
|
110
|
-
!!::Rails.
|
114
|
+
!!::Rails.configuration.session_store
|
111
115
|
end
|
112
116
|
|
113
117
|
def api_only?
|
114
|
-
::Rails.
|
118
|
+
::Rails.configuration.api_only
|
115
119
|
end
|
116
120
|
|
117
121
|
def sequel_adapter
|
@@ -120,7 +120,7 @@ module Rodauth
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def primary_key_type(key = :id)
|
123
|
-
generators = ::Rails.
|
123
|
+
generators = ::Rails.configuration.generators
|
124
124
|
column_type = generators.options[:active_record][:primary_key_type]
|
125
125
|
|
126
126
|
if key
|
@@ -20,6 +20,9 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
20
20
|
db Sequel.<%= sequel_adapter %>(extensions: :activerecord_connection, keep_reference: false)
|
21
21
|
<% end -%>
|
22
22
|
|
23
|
+
# Avoid DB query that checks accounts table schema at boot time.
|
24
|
+
convert_token_id_to_integer? <%= primary_key_integer? %>
|
25
|
+
|
23
26
|
<% end -%>
|
24
27
|
# Change prefix of table and foreign key column names from default "account"
|
25
28
|
<% if table -%>
|
@@ -46,7 +49,7 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
46
49
|
<% if argon2? -%>
|
47
50
|
|
48
51
|
# Use a rotatable password pepper when hashing passwords with Argon2.
|
49
|
-
# argon2_secret
|
52
|
+
# argon2_secret { hmac_secret }
|
50
53
|
|
51
54
|
# Since we're using argon2, prevent loading the bcrypt gem to save memory.
|
52
55
|
require_bcrypt? false
|
@@ -54,7 +57,7 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
54
57
|
<% if jwt? -%>
|
55
58
|
|
56
59
|
# Set JWT secret, which is used to cryptographically protect the token.
|
57
|
-
jwt_secret
|
60
|
+
jwt_secret { hmac_secret }
|
58
61
|
<% end -%>
|
59
62
|
<% if json? || jwt? -%>
|
60
63
|
|
@@ -72,7 +75,7 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
72
75
|
# Specify the controller used for view rendering, CSRF, and callbacks.
|
73
76
|
rails_controller { RodauthController }
|
74
77
|
|
75
|
-
#
|
78
|
+
# Make built-in page titles accessible in your views via an instance variable.
|
76
79
|
title_instance_variable :@page_title
|
77
80
|
|
78
81
|
# Store account status in an integer column without foreign key constraint.
|
@@ -86,6 +89,7 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
86
89
|
|
87
90
|
# Change some default param keys.
|
88
91
|
login_param "email"
|
92
|
+
login_confirm_param "email-confirm"
|
89
93
|
# password_confirm_param "confirm_password"
|
90
94
|
|
91
95
|
# Redirect back to originally requested location after authentication.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% if defined?(ActiveRecord::Railtie) -%>
|
2
2
|
class <%= table_prefix.camelize %> < ApplicationRecord
|
3
|
-
include Rodauth::
|
3
|
+
include Rodauth::Model(RodauthMain)
|
4
4
|
<% if ActiveRecord.version >= Gem::Version.new("7.0") -%>
|
5
5
|
enum :status, unverified: 1, verified: 2, closed: 3
|
6
6
|
<% else -%>
|
@@ -9,7 +9,7 @@ class <%= table_prefix.camelize %> < ApplicationRecord
|
|
9
9
|
end
|
10
10
|
<% else -%>
|
11
11
|
class <%= table_prefix.camelize %> < Sequel::Model
|
12
|
-
include Rodauth::
|
12
|
+
include Rodauth::Model(RodauthMain)
|
13
13
|
plugin :enum
|
14
14
|
enum :status, unverified: 1, verified: 2, closed: 3
|
15
15
|
end
|
@@ -41,6 +41,7 @@ module Rodauth
|
|
41
41
|
recovery_codes: %w[recovery_codes add_recovery_codes recovery_auth],
|
42
42
|
webauthn: %w[webauthn_setup webauthn_auth webauthn_remove],
|
43
43
|
webauthn_autofill: %w[webauthn_autofill],
|
44
|
+
confirm_password: %w[confirm_password],
|
44
45
|
}
|
45
46
|
|
46
47
|
def create_views
|
@@ -120,7 +121,7 @@ module Rodauth
|
|
120
121
|
end
|
121
122
|
|
122
123
|
def tailwind?
|
123
|
-
::Rails.
|
124
|
+
::Rails.configuration.generators.options[:rails][:template_engine] == :tailwindcss ||
|
124
125
|
options[:css]&.downcase&.start_with?("tailwind")
|
125
126
|
end
|
126
127
|
end
|
data/lib/rodauth/rails/app.rb
CHANGED
@@ -5,7 +5,7 @@ module Rodauth
|
|
5
5
|
module Rails
|
6
6
|
# The superclass for creating a Rodauth middleware.
|
7
7
|
class App < Roda
|
8
|
-
plugin :middleware, forward_response_headers: true do |middleware|
|
8
|
+
plugin :middleware, forward_response_headers: true, next_if_not_found: true do |middleware|
|
9
9
|
middleware.class_eval do
|
10
10
|
def self.inspect
|
11
11
|
"#{superclass}::Middleware"
|
@@ -54,6 +54,10 @@ module Rodauth
|
|
54
54
|
::Rails.application.routes.url_helpers
|
55
55
|
end
|
56
56
|
|
57
|
+
def rails_cookies
|
58
|
+
rails_request.cookie_jar
|
59
|
+
end
|
60
|
+
|
57
61
|
def rails_request
|
58
62
|
ActionDispatch::Request.new(env)
|
59
63
|
end
|
@@ -77,7 +81,7 @@ module Rodauth
|
|
77
81
|
if prefix.present? && remaining_path == path_info
|
78
82
|
on prefix[1..-1] do
|
79
83
|
super
|
80
|
-
pass
|
84
|
+
pass
|
81
85
|
end
|
82
86
|
else
|
83
87
|
super
|
@@ -32,7 +32,7 @@ module Rodauth
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def rails_controller
|
35
|
-
if only_json? && ::Rails.
|
35
|
+
if only_json? && ::Rails.configuration.api_only
|
36
36
|
ActionController::API
|
37
37
|
else
|
38
38
|
ActionController::Base
|
@@ -47,7 +47,13 @@ module Rodauth
|
|
47
47
|
raise Error, "cannot infer account model, please set `rails_account_model` in your rodauth configuration"
|
48
48
|
end
|
49
49
|
|
50
|
-
delegate :rails_routes, :rails_request, to: :scope
|
50
|
+
delegate :rails_routes, :rails_cookies, :rails_request, to: :scope
|
51
|
+
|
52
|
+
def session
|
53
|
+
super
|
54
|
+
rescue Roda::RodaError
|
55
|
+
fail Rodauth::Rails::Error, "There is no session middleware configured, see instructions on how to add it: https://guides.rubyonrails.org/api_app.html#using-session-middlewares"
|
56
|
+
end
|
51
57
|
|
52
58
|
private
|
53
59
|
|
@@ -47,7 +47,7 @@ module Rodauth
|
|
47
47
|
def rails_url_options
|
48
48
|
return nil unless defined?(ActionMailer)
|
49
49
|
|
50
|
-
::Rails.
|
50
|
+
::Rails.configuration.action_mailer.default_url_options or
|
51
51
|
fail Error, "There is no information to set the URL host from. Please set config.action_mailer.default_url_options in your Rails application, or configure #domain and #base_url in your Rodauth configuration."
|
52
52
|
end
|
53
53
|
end
|
@@ -21,9 +21,9 @@ module Rodauth
|
|
21
21
|
|
22
22
|
# Check whether it's a request to an asset managed by Sprockets or Propshaft.
|
23
23
|
def asset_request?(env)
|
24
|
-
return false unless ::Rails.
|
24
|
+
return false unless ::Rails.configuration.respond_to?(:assets)
|
25
25
|
|
26
|
-
env["PATH_INFO"] =~ %r(\A/{0,2}#{::Rails.
|
26
|
+
env["PATH_INFO"] =~ %r(\A/{0,2}#{::Rails.configuration.assets.prefix})
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/rodauth-rails.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.add_dependency "railties", ">= 5.0", "< 8"
|
20
20
|
spec.add_dependency "rodauth", "~> 2.30"
|
21
|
-
spec.add_dependency "roda", "~> 3.
|
21
|
+
spec.add_dependency "roda", "~> 3.73"
|
22
22
|
spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
|
23
23
|
spec.add_dependency "rodauth-model", "~> 0.2"
|
24
24
|
spec.add_dependency "tilt"
|
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.13.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-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '3.
|
53
|
+
version: '3.73'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '3.
|
60
|
+
version: '3.73'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: sequel-activerecord_connection
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|