rodauth-rails 1.10.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adfcbce27e52d0a53b5cd670489635c841dff9e2809c92be059286943894db6c
4
- data.tar.gz: e98584823e926c810bc66366496df5fb3c8eed0f38e291b76b9f132480941a9c
3
+ metadata.gz: 1dac2131f831b908d4bfd7a3367b310bd04b4141202b16f5e98d80e769972e32
4
+ data.tar.gz: 1742fb2bb8fb16c221a4f09d5a5f53bdc898475383f91311100571e4902c8700
5
5
  SHA512:
6
- metadata.gz: 845b037926a9372522da9b3507b5fd2959454bc24198f72a7832d9025ccd27f9bac3790823577e1e68c3a1e1a076472e1629825973c37cc932e2b63299e1408b
7
- data.tar.gz: af417d7bbe9732c677ca15c6796817554fe68d5f8f3db8001b56a736db33382f3efd8f86952509d038f45f449f76d3c9ea61f1a7f5a29c1cef5f45e72cf1c9ce
6
+ metadata.gz: 53dc0c219dc640431b553c8e843cc728ee1aff0c57a759dfebb0254a9e885a193ab1c3dff8d6fba6ba8423abdc49e9d6e38c14125a48a82954c42942b4a16838
7
+ data.tar.gz: 07ea61d890bb27ae8cbaed4c203366ddb07c152b5f76272e2acec9865e1c7ec72472aef8b20e2a112ad831ab3bc69602f443fc80ffcb0f6b1754f1b3d317cff4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## 1.12.0 (2023-10-20)
2
+
3
+ * Allow generating view template for `confirm_password` feature (igor-alexandrov)
4
+
5
+ * Forward all requests unhandled by the Rodauth app to the Rails router (@janko)
6
+
7
+ * Use `Rodauth::Model()` directly for including in generated account model (@janko)
8
+
9
+ * Set `{jwt,argon2}_secret` to `hmac_secret` on `rodauth:install` with `--{jwt,argon2}` (@janko)
10
+
11
+ * Expose `#turbo_stream` method in `Rodauth::Rails::Auth` when using turbo-rails gem (@janko)
12
+
13
+ * Add `#rails_cookies` method for accessing the Action Dispatch cookie jar (@janko)
14
+
15
+ ## 1.11.0 (2023-08-21)
16
+
17
+ * Exclude WebAuthn JS routes in `rodauth:routes`, since those stop being relevant with custom JS (@janko)
18
+
19
+ * Separate HTTP verbs with `|` symbol in `rodauth:routes` for consistency with `rails routes` (@janko)
20
+
21
+ * Include two factor manage & auth JSON POST routes in `rodauth:routes` task (@janko)
22
+
23
+ * Make `rodauth:routes` rake task appear in `rails -T` list (@janko)
24
+
25
+ * Accept plugin options in `Rodauth::Rails.lib` (@janko)
26
+
27
+ * Support skipping loading Roda `render` plugin by passing `render: false` (@janko)
28
+
1
29
  ## 1.10.0 (2023-07-26)
2
30
 
3
31
  * Add `Rodauth::Rails.lib` for easier usage of Rodauth as a library in Rails apps (@janko)
data/README.md CHANGED
@@ -15,6 +15,7 @@ Provides Rails integration for the [Rodauth] authentication framework.
15
15
 
16
16
  * [Rails Authentication with Rodauth](https://www.youtube.com/watch?v=2hDpNikacf0)
17
17
  * [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))
18
+ * [Add Admin Accounts](https://www.youtube.com/watch?v=N6z7AtKSpNI)
18
19
 
19
20
  📚 Articles:
20
21
 
@@ -44,11 +45,7 @@ of the advantages that stand out for me:
44
45
 
45
46
  One common concern for people coming from other Rails authentication frameworks
46
47
  is the fact that Rodauth uses [Sequel] for database interaction instead of
47
- Active Record. Sequel has powerful APIs for building advanced queries,
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
48
+ Active Record. For Rails apps using Active Record, rodauth-rails configures Sequel to [reuse
52
49
  Active Record's database connection][sequel-activerecord_connection]. This
53
50
  makes it run smoothly alongside Active Record, even allowing calling Active
54
51
  Record code from within Rodauth configuration. So, for all intents and
@@ -68,7 +65,28 @@ Next, run the install generator:
68
65
  $ rails generate rodauth:install
69
66
  ```
70
67
 
71
- This will use the `accounts` table. If you want a different table name:
68
+ This generator will create a Rodauth app and configuration with common
69
+ authentication features enabled, a database migration with tables required by
70
+ those features, a mailer with default templates, and a few other files.
71
+
72
+ Feel free to remove any features you don't need, along with their corresponding
73
+ tables. Afterwards, run the migration:
74
+
75
+ ```sh
76
+ $ rails db:migrate
77
+ ```
78
+
79
+ For your mailer to be able to generate email links, you'll need to set up
80
+ default URL options in each environment. Here is a possible configuration for
81
+ `config/environments/development.rb`:
82
+
83
+ ```rb
84
+ config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
85
+ ```
86
+
87
+ ### Install options
88
+
89
+ The install generator will use the `accounts` table by default. You can specify a different table name:
72
90
 
73
91
  ```sh
74
92
  $ rails generate rodauth:install users
@@ -90,25 +108,6 @@ $ rails generate rodauth:install --argon2
90
108
  $ bundle add argon2
91
109
  ```
92
110
 
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
111
  ## Usage
113
112
 
114
113
  The Rodauth app will be called for each request before it reaches the Rails
@@ -134,18 +133,18 @@ $ rails rodauth:routes
134
133
  ```
135
134
  Routes handled by RodauthApp:
136
135
 
137
- GET/POST /login rodauth.login_path
138
- GET/POST /create-account rodauth.create_account_path
139
- GET/POST /verify-account-resend rodauth.verify_account_resend_path
140
- GET/POST /verify-account rodauth.verify_account_path
141
- GET/POST /change-password rodauth.change_password_path
142
- GET/POST /change-login rodauth.change_login_path
143
- GET/POST /logout rodauth.logout_path
144
- GET/POST /remember rodauth.remember_path
145
- GET/POST /reset-password-request rodauth.reset_password_request_path
146
- GET/POST /reset-password rodauth.reset_password_path
147
- GET/POST /verify-login-change rodauth.verify_login_change_path
148
- GET/POST /close-account rodauth.close_account_path
136
+ GET|POST /login rodauth.login_path
137
+ GET|POST /create-account rodauth.create_account_path
138
+ GET|POST /verify-account-resend rodauth.verify_account_resend_path
139
+ GET|POST /verify-account rodauth.verify_account_path
140
+ GET|POST /change-password rodauth.change_password_path
141
+ GET|POST /change-login rodauth.change_login_path
142
+ GET|POST /logout rodauth.logout_path
143
+ GET|POST /remember rodauth.remember_path
144
+ GET|POST /reset-password-request rodauth.reset_password_request_path
145
+ GET|POST /reset-password rodauth.reset_password_path
146
+ GET|POST /verify-login-change rodauth.verify_login_change_path
147
+ GET|POST /close-account rodauth.close_account_path
149
148
  ```
150
149
 
151
150
  Using this information, you can add some basic authentication links to your
@@ -153,7 +152,7 @@ navigation header:
153
152
 
154
153
  ```erb
155
154
  <% if rodauth.logged_in? %>
156
- <%= link_to "Sign out", rodauth.logout_path, method: :post %>
155
+ <%= link_to "Sign out", rodauth.logout_path, data: { turbo_method: :post } %>
157
156
  <% else %>
158
157
  <%= link_to "Sign in", rodauth.login_path %>
159
158
  <%= link_to "Sign up", rodauth.create_account_path %>
@@ -181,28 +180,18 @@ class ApplicationController < ActionController::Base
181
180
  end
182
181
  ```
183
182
 
184
- ```rb
185
- current_account #=> #<Account id=123 email="user@example.com">
186
- current_account.email #=> "user@example.com"
187
- ```
188
-
189
183
  ### Requiring authentication
190
184
 
191
- You'll likely want to require authentication for certain parts of your app,
192
- redirecting the user to the login page if they're not logged in. You can do this
193
- in your Rodauth app's routing block, which helps keep the authentication logic
194
- encapsulated:
185
+ You can require authentication for routes at the middleware level in in your Rodauth
186
+ app's routing block, which helps keep the authentication logic encapsulated:
195
187
 
196
188
  ```rb
197
189
  # app/misc/rodauth_app.rb
198
190
  class RodauthApp < Rodauth::Rails::App
199
- # ...
200
191
  route do |r|
201
- # ...
202
192
  r.rodauth # route rodauth requests
203
193
 
204
- # require authentication for /dashboard/* routes
205
- if r.path.start_with?("/dashboard")
194
+ if r.path.start_with?("/dashboard") # /dashboard/* routes
206
195
  rodauth.require_account # redirect to login page if not authenticated
207
196
  end
208
197
  end
@@ -212,7 +201,6 @@ end
212
201
  You can also require authentication at the controller layer:
213
202
 
214
203
  ```rb
215
- # app/controllers/application_controller.rb
216
204
  class ApplicationController < ActionController::Base
217
205
  private
218
206
 
@@ -222,68 +210,46 @@ class ApplicationController < ActionController::Base
222
210
  end
223
211
  ```
224
212
  ```rb
225
- # app/controllers/dashboard_controller.rb
226
213
  class DashboardController < ApplicationController
227
214
  before_action :authenticate
228
215
  end
229
216
  ```
230
217
 
231
- #### Routing constraints
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:
218
+ Additionally, routes can be authenticated at the Rails router level:
235
219
 
236
220
  ```rb
237
221
  # config/routes.rb
238
222
  Rails.application.routes.draw do
239
- constraints Rodauth::Rails.authenticated do
240
- # ... authenticated routes ...
223
+ constraints Rodauth::Rails.authenticate do
224
+ # ... these routes will require authentication ...
241
225
  end
242
- end
243
- ```
244
226
 
245
- If you want additional conditions, you can pass in a block, which is
246
- called with the Rodauth instance:
247
-
248
- ```rb
249
- # config/routes.rb
250
- Rails.application.routes.draw do
251
- # require multifactor authentication to be setup
252
- constraints Rodauth::Rails.authenticated { |rodauth| rodauth.uses_two_factor_authentication? } do
253
- # ...
227
+ constraints Rodauth::Rails.authenticate { |rodauth| rodauth.uses_two_factor_authentication? } do
228
+ # ... these routes will be available only if 2FA is setup ...
254
229
  end
255
- end
256
- ```
257
-
258
- You can specify a different Rodauth configuration by passing the configuration name:
259
230
 
260
- ```rb
261
- # config/routes.rb
262
- Rails.application.routes.draw do
263
- constraints Rodauth::Rails.authenticated(:admin) do
264
- # ...
231
+ constraints Rodauth::Rails.authenticate(:admin) do
232
+ # ... these routes will be authenticated with secondary "admin" configuration ...
265
233
  end
266
- end
267
- ```
268
-
269
- If you need something more custom, you can always create the routing constraint
270
- manually:
271
234
 
272
- ```rb
273
- # config/routes.rb
274
- Rails.application.routes.draw do
275
235
  constraints -> (r) { !r.env["rodauth"].logged_in? } do # or env["rodauth.admin"]
276
- # routes when the user is not logged in
236
+ # ... these routes will be available only if not authenticated ...
277
237
  end
278
238
  end
279
239
  ```
280
240
 
281
241
  ### Controller
282
242
 
283
- Your Rodauth configuration is connected to a Rails controller (`RodauthController` by default), and
284
- it automatically executes any callbacks and rescue handlers defined on it (or the parent controller)
285
- around Rodauth endpoints.
243
+ 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
244
 
245
+ ```rb
246
+ # app/misc/rodauth_main.rb
247
+ class RodauthMain < Rodauth::Rails::Auth
248
+ configure do
249
+ rails_controller { RodauthController }
250
+ end
251
+ end
252
+ ```
287
253
  ```rb
288
254
  class RodauthController < ApplicationController
289
255
  before_action :set_locale # executes before Rodauth endpoints
@@ -291,45 +257,31 @@ class RodauthController < ApplicationController
291
257
  end
292
258
  ```
293
259
 
294
- #### Calling controller methods
295
-
296
- You can call any controller methods from your Rodauth configuration via `rails_controller_eval`:
260
+ Various methods are available in your Rodauth configuration to bridge the gap with the controller:
297
261
 
298
262
  ```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
- ```rb
308
- # app/misc/rodauth_main.rb
309
263
  class RodauthMain < Rodauth::Rails::Auth
310
264
  configure do
265
+ # calling methods on the controller:
311
266
  after_create_account do
312
- rails_controller_eval { setup_tracking(account_id) }
267
+ rails_controller_eval { some_controller_method(account_id) }
313
268
  end
314
- end
315
- end
316
- ```
317
269
 
318
- ### Rails URL helpers
270
+ # accessing Rails URL helpers:
271
+ login_redirect { rails_routes.dashboard_path }
319
272
 
320
- Inside Rodauth configuration and the `route` block you can access Rails route
321
- helpers through `#rails_routes`:
273
+ # accessing Rails request object:
274
+ after_change_password do
275
+ if rails_request.format.turbo_stream?
276
+ return_response rails_render(turbo_stream: [turbo_stream.replace(...)])
277
+ end
278
+ end
322
279
 
323
- ```rb
324
- # app/misc/rodauth_main.rb
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 }
280
+ # accessing Rails cookies:
281
+ after_login { rails_cookies.permanent[:last_account_id] = account_id }
330
282
  end
331
283
  end
332
- ```
284
+ ```
333
285
 
334
286
  ## Views
335
287
 
@@ -338,97 +290,29 @@ you'll want to start editing the markup. You can run the following command to
338
290
  copy Rodauth templates into your Rails app:
339
291
 
340
292
  ```sh
341
- $ rails generate rodauth:views # bootstrap views
342
- # or
343
- $ rails generate rodauth:views --css=tailwind # tailwind views (requires @tailwindcss/forms plugin)
293
+ $ rails generate rodauth:views
344
294
  ```
345
295
 
346
296
  This will generate views for Rodauth features you have currently enabled into
347
- the `app/views/rodauth` directory, provided that `RodauthController` is set for
348
- the main configuration.
297
+ the `app/views/rodauth` directory (provided that `RodauthController` is set for
298
+ the main configuration).
349
299
 
350
- You can pass a list of Rodauth features to the generator to create views for
351
- these features (this will not remove any existing views):
300
+ The generator accepts various options:
352
301
 
353
302
  ```sh
354
- $ rails generate rodauth:views login create_account lockout otp
355
- ```
303
+ # generate views with Tailwind markup (requires @tailwindcss/forms plugin)
304
+ $ rails generate rodauth:views --css=tailwind
356
305
 
357
- Or you can generate views for all features:
306
+ # specify Rodauth features to generate views for
307
+ $ rails generate rodauth:views login create_account lockout otp
358
308
 
359
- ```sh
309
+ # generate views for all Rodauth features
360
310
  $ rails generate rodauth:views --all
361
- ```
362
-
363
- Use `--name` to generate views for a different Rodauth configuration:
364
311
 
365
- ```sh
312
+ # specify a different Rodauth configuration
366
313
  $ rails generate rodauth:views webauthn two_factor_base --name admin
367
314
  ```
368
315
 
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
316
  ## Mailer
433
317
 
434
318
  The install generator will create `RodauthMailer` with default email templates,
@@ -492,8 +376,6 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
492
376
  end
493
377
  ```
494
378
 
495
- ### Table prefix
496
-
497
379
  If you're storing account records in a table other than `accounts`, you'll want
498
380
  to specify the appropriate table prefix when generating new migrations:
499
381
 
@@ -516,15 +398,13 @@ class CreateRodauthUserBaseActiveSessions < ActiveRecord::Migration
516
398
  end
517
399
  ```
518
400
 
519
- ### Custom migration name
520
-
521
401
  You can change the default migration name:
522
402
 
523
403
  ```sh
524
404
  $ rails generate rodauth:migration email_auth --name create_account_email_auth_keys
525
405
  ```
526
406
  ```rb
527
- # db/migration/*_create_account_email_auth_keys
407
+ # db/migration/*_create_account_email_auth_keys.rb
528
408
  class CreateAccountEmailAuthKeys < ActiveRecord::Migration
529
409
  def change
530
410
  create_table :account_email_auth_keys do |t| ... end
@@ -540,7 +420,7 @@ tables used by enabled authentication features.
540
420
 
541
421
  ```rb
542
422
  class Account < ActiveRecord::Base # Sequel::Model
543
- include Rodauth::Rails.model # or Rodauth::Rails.model(:admin)
423
+ include Rodauth::Model(RodauthMain)
544
424
  end
545
425
  ```
546
426
  ```rb
@@ -573,6 +453,10 @@ class RodauthApp < Rodauth::Rails::App
573
453
  route do |r|
574
454
  r.rodauth # route primary rodauth requests
575
455
  r.rodauth(:admin) # route secondary rodauth requests
456
+
457
+ if request.path.start_with?("/admin")
458
+ rodauth(:admin).require_account
459
+ end
576
460
  end
577
461
  end
578
462
  ```
@@ -599,6 +483,7 @@ end
599
483
  Then in your application you can reference the secondary Rodauth instance:
600
484
 
601
485
  ```rb
486
+ rodauth(:admin).authenticated? # checks "admin_account_id" session value
602
487
  rodauth(:admin).login_path #=> "/admin/login"
603
488
  ```
604
489
 
@@ -608,66 +493,24 @@ that. Note that you can also [share configuration via inheritance][inheritance].
608
493
 
609
494
  ## Outside of a request
610
495
 
611
- ### Calling actions
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.
496
+ The [internal_request] and [path_class_methods] features are supported, with defaults taken from `config.action_mailer.default_url_options`.
616
497
 
617
498
  ```rb
618
- # app/misc/rodauth_main.rb
619
- class RodauthMain < Rodauth::Rails::Auth
620
- configure do
621
- enable :internal_request
622
- end
623
- end
624
- ```
625
- ```rb
626
- # primary configuration
499
+ # internal requests
627
500
  RodauthApp.rodauth.create_account(login: "user@example.com", password: "secret123")
628
- RodauthApp.rodauth.verify_account(account_login: "user@example.com")
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"
501
+ RodauthApp.rodauth(:admin).verify_account(account_login: "admin@example.com")
652
502
 
653
- # secondary configuration
654
- RodauthApp.rodauth(:admin).close_account_path(foo: "bar") #=> "/admin/close-account?foo=bar"
503
+ # path and URL methods
504
+ RodauthApp.rodauth.close_account_path #=> "/close-account"
505
+ RodauthApp.rodauth(:admin).otp_setup_url #=> "http://localhost:3000/admin/otp-setup"
655
506
  ```
656
507
 
657
508
  ### Calling instance methods
658
509
 
659
510
  If you need to access Rodauth methods not exposed as internal requests, you can
660
- use `Rodauth::Rails.rodauth` to retrieve the Rodauth instance used by the
661
- internal_request feature:
511
+ use `Rodauth::Rails.rodauth` to retrieve the Rodauth instance (this requires enabling
512
+ the internal_request feature):
662
513
 
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
514
  ```rb
672
515
  account = Account.find_by!(email: "user@example.com")
673
516
  rodauth = Rodauth::Rails.rodauth(account: account) #=> #<RodauthMain::InternalRequest ...>
@@ -693,8 +536,12 @@ Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
693
536
 
694
537
  ### Using as a library
695
538
 
696
- Rodauth offers a `Rodauth.lib` method for configuring Rodauth so that it can be used as a library, instead of routing requests (see [internal_request] feature). This gem provides a `Rodauth::Rails.lib` counterpart that does the same but with Rails integration:
539
+ Rodauth offers a [`Rodauth.lib`][library] method for when you want to use it as a library (via [internal requests][internal_request]), as opposed to having it route requests. This gem provides a `Rodauth::Rails.lib` counterpart that does the same but with Rails integration:
697
540
 
541
+ ```rb
542
+ # skip require on boot to avoid inserting Rodauth middleware
543
+ gem "rodauth-rails", require: false
544
+ ```
698
545
  ```rb
699
546
  # app/misc/rodauth_main.rb
700
547
  require "rodauth/rails"
@@ -712,13 +559,6 @@ RodauthMain.login(login: "email@example.com", password: "secret123")
712
559
  RodauthMain.close_account(account_login: "email@example.com")
713
560
  ```
714
561
 
715
- Note that you'll want to skip requiring `rodauth-rails` on Rails boot, so that it doesn't insert the middleware automatically, and remove the initializer.
716
-
717
- ```rb
718
- # Gemfile
719
- gem "rodauth-rails", require: false
720
- ```
721
-
722
562
  ## Testing
723
563
 
724
564
  For system and integration tests, which run the whole middleware stack,
@@ -780,10 +620,7 @@ For more examples and information about testing with rodauth, see
780
620
 
781
621
  ## Configuring
782
622
 
783
- ### Configuration methods
784
-
785
- The `rails` feature rodauth-rails loads provides the following configuration
786
- methods:
623
+ The `rails` feature rodauth-rails loads provides the following configuration methods:
787
624
 
788
625
  | Name | Description |
789
626
  | :---- | :---------- |
@@ -796,70 +633,6 @@ methods:
796
633
  | `rails_controller` | Controller class to use for rendering and CSRF protection. |
797
634
  | `rails_account_model` | Model class connected with the accounts table. |
798
635
 
799
- ```rb
800
- class RodauthMain < Rodauth::Rails::Auth
801
- configure do
802
- rails_controller { Authentication::RodauthController }
803
- rails_account_model { Authentication::Account }
804
- end
805
- end
806
- ```
807
-
808
- For the list of configuration methods provided by Rodauth, see the [feature
809
- documentation].
810
-
811
- ### Defining custom methods
812
-
813
- All Rodauth configuration methods are just syntax sugar for defining instance
814
- methods on the auth class. You can also define your own custom methods:
815
-
816
- ```rb
817
- class RodauthMain < Rodauth::Rails::Auth
818
- configure do
819
- password_match? { |password| ldap_valid?(password) }
820
- end
821
-
822
- def admin?
823
- rails_account.admin?
824
- end
825
-
826
- private
827
-
828
- def ldap_valid?(password)
829
- SimpleLdapAuthenticator.valid?(account[:email], password)
830
- end
831
- end
832
- ```
833
- ```rb
834
- rodauth.admin? #=> true
835
- ```
836
-
837
- ### Single-file configuration
838
-
839
- If you would prefer, you can have all your Rodauth logic contained inside the
840
- Rodauth app class:
841
-
842
- ```rb
843
- # app/misc/rodauth_app.rb
844
- class RodauthApp < Rodauth::Rails::App
845
- # primary configuration
846
- configure do
847
- enable :login, :logout, :create_account, :verify_account
848
- # ...
849
- end
850
-
851
- # secondary configuration
852
- configure(:admin) do
853
- enable :email_auth, :single_session
854
- # ...
855
- end
856
-
857
- route do |r|
858
- # ...
859
- end
860
- end
861
- ```
862
-
863
636
  ### Manually inserting middleware
864
637
 
865
638
  You can choose to insert the Rodauth middleware somewhere earlier than
@@ -878,7 +651,7 @@ Rails.application.config.middleware.insert_before AnotherMiddleware, Rodauth::Ra
878
651
  ### Rack middleware
879
652
 
880
653
  The railtie inserts [`Rodauth::Rails::Middleware`](/lib/rodauth/rails/middleware.rb)
881
- at the end of the middleware stack, which calls your Rodauth app around each request.
654
+ at the end of the middleware stack, which is just a wrapper around your Rodauth app.
882
655
 
883
656
  ```sh
884
657
  $ rails middleware
@@ -887,34 +660,15 @@ $ rails middleware
887
660
  # run MyApp::Application.routes
888
661
  ```
889
662
 
890
- The middleware retrieves the Rodauth app via `Rodauth::Rails.app`, which is
891
- specified as a string to keep the class autoloadable and reloadable in
892
- development.
893
-
894
- ```rb
895
- Rodauth::Rails.configure do |config|
896
- config.app = "RodauthApp"
897
- end
898
- ```
899
-
900
- In addition to Zeitwerk compatibility, this extra layer catches Rodauth redirects
901
- that happen on the controller level (e.g. when calling
902
- `rodauth.require_account` in a `before_action` filter).
903
-
904
663
  ### Roda app
905
664
 
906
665
  The [`Rodauth::Rails::App`](/lib/rodauth/rails/app.rb) class is a [Roda]
907
- subclass that provides a convenience layer for Rodauth:
908
-
909
- * uses Action Dispatch flash messages
910
- * provides syntax sugar for loading the rodauth plugin
911
- * saves Rodauth object(s) to Rack env hash
912
- * propagates edited headers to Rails responses
666
+ subclass that provides a convenience layer over Rodauth.
913
667
 
914
668
  #### Configure block
915
669
 
916
- The `configure` call loads the rodauth plugin. By convention, it receives an
917
- auth class and configuration name as positional arguments (forwarded as
670
+ The `configure` call is a wrapper around `plugin :rodauth`. By convention, it receives an
671
+ auth class and configuration name as positional arguments (which get converted into
918
672
  `:auth_class` and `:name` plugin options), a block for anonymous auth classes,
919
673
  and also accepts any additional plugin options.
920
674
 
@@ -929,7 +683,7 @@ class RodauthApp < Rodauth::Rails::App
929
683
  configure(:admin) { ... }
930
684
 
931
685
  # plugin options
932
- configure(RodauthMain, json: :only)
686
+ configure(RodauthMain, json: :only, render: false)
933
687
  end
934
688
  ```
935
689
 
@@ -946,29 +700,21 @@ class RodauthApp < Rodauth::Rails::App
946
700
  end
947
701
  ```
948
702
 
949
- #### Routing prefix
703
+ #### Rack env
950
704
 
951
- If you use a routing prefix, you don't need to add a call to `r.on` like with
952
- vanilla Rodauth, as `r.rodauth` has been modified to automatically route the
953
- prefix.
705
+ The app sets Rodauth objects for each registered configuration in the Rack env,
706
+ so that they're accessible downstream by the Rails router, controllers and views:
954
707
 
955
708
  ```rb
956
- class RodauthApp < Rodauth::Rails::App
957
- configure do
958
- prefix "/user"
959
- end
960
-
961
- route do |r|
962
- r.rodauth # no need to wrap with `r.on("user") { ... }`
963
- end
964
- end
709
+ request.env["rodauth"] #=> #<RodauthMain>
710
+ request.env["rodauth.admin"] #=> #<RodauthAdmin> (if using multiple configurations)
965
711
  ```
966
712
 
967
713
  ### Auth class
968
714
 
969
715
  The [`Rodauth::Rails::Auth`](/lib/rodauth/rails/auth.rb) class is a subclass of
970
716
  `Rodauth::Auth`, which preloads the `rails` rodauth feature, sets [HMAC] secret to
971
- Rails' secret key base, and modifies some [configuration defaults](#rodauth-defaults).
717
+ Rails' secret key base, and modifies some [configuration defaults][restoring defaults].
972
718
 
973
719
  ```rb
974
720
  class RodauthMain < Rodauth::Rails::Auth
@@ -990,128 +736,6 @@ The [`rails`](/lib/rodauth/rails/feature.rb) Rodauth feature loaded by
990
736
  * uses Action Controller instrumentation around Rodauth requests
991
737
  * uses Action Mailer's default URL options when calling Rodauth outside of a request
992
738
 
993
- ### Controller
994
-
995
- The Rodauth app stores the `Rodauth::Rails::Auth` instances in the Rack env
996
- hash, which is then available in your Rails app:
997
-
998
- ```rb
999
- request.env["rodauth"] #=> #<RodauthMain>
1000
- request.env["rodauth.admin"] #=> #<RodauthAdmin> (if using multiple configurations)
1001
- ```
1002
-
1003
- For convenience, this object can be accessed via the `#rodauth` method in views
1004
- and controllers:
1005
-
1006
- ```rb
1007
- class MyController < ApplicationController
1008
- def my_action
1009
- rodauth #=> #<RodauthMain>
1010
- rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations)
1011
- end
1012
- end
1013
- ```
1014
- ```erb
1015
- <% rodauth #=> #<RodauthMain> %>
1016
- <% rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations) %>
1017
- ```
1018
-
1019
- ## Rodauth defaults
1020
-
1021
- rodauth-rails changes some of the default Rodauth settings for easier setup:
1022
-
1023
- ### Database functions
1024
-
1025
- By default, on PostgreSQL, MySQL, and Microsoft SQL Server Rodauth uses
1026
- database functions to access password hashes, with the user running the
1027
- application unable to get direct access to password hashes. This reduces the
1028
- risk of an attacker being able to access password hashes and use them to attack
1029
- other sites.
1030
-
1031
- While this is useful additional security, it is also more complex to set up and
1032
- to reason about, as it requires having two different database users and making
1033
- sure the correct migration is run for the correct user.
1034
-
1035
- To keep with Rails' "convention over configuration" doctrine, rodauth-rails
1036
- disables the use of database functions, though you can always turn it back on.
1037
-
1038
- ```rb
1039
- use_database_authentication_functions? true
1040
- ```
1041
-
1042
- To create the database functions, pass the Sequel database object into the
1043
- Rodauth method for creating database functions:
1044
-
1045
- ```rb
1046
- # db/migrate/*_create_rodauth_database_functions.rb
1047
- require "rodauth/migrations"
1048
-
1049
- class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
1050
- def up
1051
- Rodauth.create_database_authentication_functions(db)
1052
- end
1053
-
1054
- def down
1055
- Rodauth.drop_database_authentication_functions(db)
1056
- end
1057
-
1058
- private
1059
-
1060
- def db
1061
- RodauthMain.allocate.db
1062
- end
1063
- end
1064
- ```
1065
-
1066
- ### Account statuses
1067
-
1068
- The recommended [Rodauth migration] stores possible account status values in a
1069
- separate table, and creates a foreign key on the accounts table, which ensures
1070
- only a valid status value will be persisted. Unfortunately, this doesn't work
1071
- when the database is restored from the schema file, in which case the account
1072
- statuses table will be empty. This happens in tests by default, but it's also
1073
- not unusual to do it in development.
1074
-
1075
- To address this, rodauth-rails uses a `status` column without a separate table.
1076
- If you're worried about invalid status values creeping in, you may use enums
1077
- instead. Alternatively, you can always go back to the setup recommended by
1078
- Rodauth.
1079
-
1080
- ```rb
1081
- # in the migration:
1082
- create_table :account_statuses do |t|
1083
- t.string :name, null: false, unique: true
1084
- end
1085
- execute "INSERT INTO account_statuses (id, name) VALUES (1, 'Unverified'), (2, 'Verified'), (3, 'Closed')"
1086
-
1087
- create_table :accounts do |t|
1088
- # ...
1089
- t.references :status, foreign_key: { to_table: :account_statuses }, null: false, default: 1
1090
- # ...
1091
- end
1092
- ```
1093
- ```diff
1094
- class RodauthMain < Rodauth::Rails::Auth
1095
- configure do
1096
- # ...
1097
- - account_status_column :status
1098
- # ...
1099
- end
1100
- end
1101
- ```
1102
-
1103
- ### Deadline values
1104
-
1105
- To simplify changes to the database schema, rodauth-rails configures Rodauth
1106
- to set deadline values for various features in Ruby, instead of relying on
1107
- the database to set default column values.
1108
-
1109
- You can easily change this back:
1110
-
1111
- ```rb
1112
- set_deadline_values? false
1113
- ```
1114
-
1115
739
  ## License
1116
740
 
1117
741
  The gem is available as open source under the terms of the [MIT
@@ -1125,12 +749,10 @@ conduct](CODE_OF_CONDUCT.md).
1125
749
 
1126
750
  [Rodauth]: https://github.com/jeremyevans/rodauth
1127
751
  [Sequel]: https://github.com/jeremyevans/sequel
1128
- [feature documentation]: http://rodauth.jeremyevans.net/documentation.html
1129
752
  [Bootstrap]: https://getbootstrap.com/
1130
753
  [Roda]: http://roda.jeremyevans.net/
1131
754
  [HMAC]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
1132
755
  [database authentication functions]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Password+Hash+Access+Via+Database+Functions
1133
- [Rodauth migration]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Creating+tables
1134
756
  [sequel-activerecord_connection]: https://github.com/janko/sequel-activerecord_connection
1135
757
  [plugin options]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Plugin+Options
1136
758
  [hmac]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
@@ -1159,3 +781,5 @@ conduct](CODE_OF_CONDUCT.md).
1159
781
  [rodauth-model]: https://github.com/janko/rodauth-model
1160
782
  [JSON API]: https://github.com/janko/rodauth-rails/wiki/JSON-API
1161
783
  [inheritance]: http://rodauth.jeremyevans.net/rdoc/files/doc/guides/share_configuration_rdoc.html
784
+ [library]: https://github.com/jeremyevans/rodauth#label-Using+Rodauth+as+a+Library
785
+ [restoring defaults]: https://github.com/janko/rodauth-rails/wiki/Restoring-Rodauth-Defaults
@@ -46,7 +46,7 @@ class RodauthMain < Rodauth::Rails::Auth
46
46
  <% if argon2? -%>
47
47
 
48
48
  # Use a rotatable password pepper when hashing passwords with Argon2.
49
- # argon2_secret "<SECRET_KEY>"
49
+ # argon2_secret { hmac_secret }
50
50
 
51
51
  # Since we're using argon2, prevent loading the bcrypt gem to save memory.
52
52
  require_bcrypt? false
@@ -54,7 +54,7 @@ class RodauthMain < Rodauth::Rails::Auth
54
54
  <% if jwt? -%>
55
55
 
56
56
  # Set JWT secret, which is used to cryptographically protect the token.
57
- jwt_secret "<%= SecureRandom.hex(64) %>"
57
+ jwt_secret { hmac_secret }
58
58
  <% end -%>
59
59
  <% if json? || jwt? -%>
60
60
 
@@ -72,7 +72,7 @@ class RodauthMain < Rodauth::Rails::Auth
72
72
  # Specify the controller used for view rendering, CSRF, and callbacks.
73
73
  rails_controller { RodauthController }
74
74
 
75
- # Set in Rodauth controller instance with the title of the current page.
75
+ # Make built-in page titles accessible in your views via an instance variable.
76
76
  title_instance_variable :@page_title
77
77
 
78
78
  # Store account status in an integer column without foreign key constraint.
@@ -1,6 +1,6 @@
1
1
  <% if defined?(ActiveRecord::Railtie) -%>
2
2
  class <%= table_prefix.camelize %> < ApplicationRecord
3
- include Rodauth::Rails.model
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::Rails.model
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
@@ -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"
@@ -18,16 +18,17 @@ module Rodauth
18
18
  end
19
19
 
20
20
  plugin :hooks
21
- plugin :render, layout: false
22
21
  plugin :pass
23
22
 
24
23
  def self.configure(*args, **options, &block)
25
24
  auth_class = args.shift if args[0].is_a?(Class)
26
- name = args.shift if args[0].is_a?(Symbol)
25
+ auth_class ||= Class.new(Rodauth::Rails::Auth)
26
+ name = args.shift if args[0].is_a?(Symbol)
27
27
 
28
28
  fail ArgumentError, "need to pass optional Rodauth::Auth subclass and optional configuration name" if args.any?
29
29
 
30
- auth_class ||= Class.new(Rodauth::Rails::Auth)
30
+ # we'll render Rodauth's built-in view templates within Rails layouts
31
+ plugin :render, layout: false unless options[:render] == false
31
32
 
32
33
  plugin :rodauth, auth_class: auth_class, name: name, csrf: false, flash: false, json: true, **options, &block
33
34
 
@@ -53,6 +54,10 @@ module Rodauth
53
54
  ::Rails.application.routes.url_helpers
54
55
  end
55
56
 
57
+ def rails_cookies
58
+ rails_request.cookie_jar
59
+ end
60
+
56
61
  def rails_request
57
62
  ActionDispatch::Request.new(env)
58
63
  end
@@ -76,7 +81,7 @@ module Rodauth
76
81
  if prefix.present? && remaining_path == path_info
77
82
  on prefix[1..-1] do
78
83
  super
79
- pass # forward other {prefix}/* requests downstream
84
+ pass
80
85
  end
81
86
  else
82
87
  super
@@ -47,7 +47,7 @@ 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
51
 
52
52
  private
53
53
 
@@ -28,6 +28,12 @@ module Rodauth
28
28
  super.html_safe
29
29
  end
30
30
 
31
+ if defined?(::Turbo)
32
+ def turbo_stream
33
+ rails_controller_instance.send(:turbo_stream)
34
+ end
35
+ end
36
+
31
37
  private
32
38
 
33
39
  # Calls the Rails renderer, returning nil if a template is missing.
@@ -0,0 +1,70 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Tasks
4
+ class Routes
5
+ IGNORE = [:webauthn_setup_js, :webauthn_auth_js, :webauthn_autofill_js]
6
+ JSON_POST = [:two_factor_manage, :two_factor_auth]
7
+
8
+ attr_reader :auth_class
9
+
10
+ def initialize(auth_class)
11
+ @auth_class = auth_class
12
+ end
13
+
14
+ def call
15
+ routes = auth_class.route_hash.map do |path, handle_method|
16
+ route_name = handle_method.to_s.sub(/\Ahandle_/, "").to_sym
17
+ next if IGNORE.include?(route_name)
18
+ verbs = route_verbs(route_name)
19
+
20
+ [
21
+ verbs.join("|"),
22
+ "#{rodauth.prefix}#{path}",
23
+ "rodauth#{configuration_name && "(:#{configuration_name})"}.#{route_name}_path",
24
+ ]
25
+ end
26
+
27
+ routes.compact!
28
+ padding = routes.transpose.map { |string| string.map(&:length).max }
29
+
30
+ output_lines = routes.map do |columns|
31
+ [columns[0].ljust(padding[0]), columns[1].ljust(padding[1]), columns[2]].join(" ")
32
+ end
33
+
34
+ puts "\n #{output_lines.join("\n ")}"
35
+ end
36
+
37
+ private
38
+
39
+ def route_verbs(route_name)
40
+ file_path, start_line = rodauth.method(:"_handle_#{route_name}").source_location
41
+ lines = File.foreach(file_path).to_a
42
+ indentation = lines[start_line - 1][/^\s+/]
43
+ verbs = []
44
+
45
+ lines[start_line..-1].each do |code|
46
+ verbs << :GET if code.include?("r.get") && !rodauth.only_json?
47
+ verbs << :POST if code.include?("r.post")
48
+ break if code.start_with?("#{indentation}end")
49
+ end
50
+
51
+ verbs << :POST if rodauth.features.include?(:json) && JSON_POST.include?(route_name)
52
+ verbs
53
+ end
54
+
55
+ def rodauth
56
+ auth_class.new(scope)
57
+ end
58
+
59
+ def scope
60
+ auth_class.roda_class.new({})
61
+ end
62
+
63
+ def configuration_name
64
+ auth_class.configuration_name
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
@@ -1,42 +1,12 @@
1
+ require "rodauth/rails/tasks/routes"
2
+
1
3
  namespace :rodauth do
4
+ desc "Lists endpoints that will be routed by your Rodauth app"
2
5
  task routes: :environment do
3
- app = Rodauth::Rails.app
4
-
5
- puts "Routes handled by #{app}:"
6
-
7
- app.opts[:rodauths].each do |configuration_name, auth_class|
8
- rodauth = auth_class.allocate
9
- only_json = rodauth.method(:only_json?).owner != Rodauth::Base && rodauth.only_json?
10
-
11
- routes = auth_class.route_hash.map do |path, handle_method|
12
- file_path, start_line = rodauth.method(:"_#{handle_method}").source_location
13
- lines = File.foreach(file_path).to_a
14
- indentation = lines[start_line - 1][/^\s+/]
15
- verbs = []
16
-
17
- lines[start_line..-1].each do |code|
18
- verbs << :GET if code.include?("r.get") && !only_json
19
- verbs << :POST if code.include?("r.post")
20
- break if code.start_with?("#{indentation}end")
21
- end
22
-
23
- path_method = "#{handle_method.to_s.sub(/\Ahandle_/, "")}_path"
24
-
25
- [
26
- verbs.join("/"),
27
- "#{rodauth.prefix}#{path}",
28
- "rodauth#{configuration_name && "(:#{configuration_name})"}.#{path_method}",
29
- ]
30
- end
31
-
32
- verbs_padding = routes.map { |verbs, _, _| verbs.length }.max
33
- path_padding = routes.map { |_, path, _| path.length }.max
34
-
35
- route_lines = routes.map do |verbs, path, code|
36
- "#{verbs.ljust(verbs_padding)} #{path.ljust(path_padding)} #{code}"
37
- end
6
+ puts "Routes handled by #{Rodauth::Rails.app}:"
38
7
 
39
- puts "\n #{route_lines.join("\n ")}" unless route_lines.empty?
8
+ Rodauth::Rails.app.opts[:rodauths].each_value do |auth_class|
9
+ Rodauth::Rails::Tasks::Routes.new(auth_class).call
40
10
  end
41
11
  end
42
12
  end
@@ -1,5 +1,5 @@
1
1
  module Rodauth
2
2
  module Rails
3
- VERSION = "1.10.0"
3
+ VERSION = "1.12.0"
4
4
  end
5
5
  end
data/lib/rodauth/rails.rb CHANGED
@@ -16,9 +16,9 @@ module Rodauth
16
16
  @middleware = true
17
17
 
18
18
  class << self
19
- def lib(&block)
19
+ def lib(**options, &block)
20
20
  c = Class.new(Rodauth::Rails::App)
21
- c.configure(json: false) do
21
+ c.configure(json: false, **options) do
22
22
  enable :internal_request
23
23
  instance_exec(&block)
24
24
  end
@@ -57,8 +57,17 @@ module Rodauth
57
57
  Rodauth::Model.new(app.rodauth!(name), **options)
58
58
  end
59
59
 
60
- # routing constraint that requires authentication
60
+ # Routing constraint that requires authenticated account.
61
+ def authenticate(name = nil, &condition)
62
+ lambda do |request|
63
+ rodauth = request.env.fetch ["rodauth", *name].join(".")
64
+ rodauth.require_account
65
+ condition.nil? || condition.call(rodauth)
66
+ end
67
+ end
68
+
61
69
  def authenticated(name = nil, &condition)
70
+ warn "Rodauth::Rails.authenticated has been deprecated in favor of Rodauth::Rails.authenticate, which additionally requires existence of the account record."
62
71
  lambda do |request|
63
72
  rodauth = request.env.fetch ["rodauth", *name].join(".")
64
73
  rodauth.require_authentication
@@ -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.55"
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.10.0
4
+ version: 1.12.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-07-26 00:00:00.000000000 Z
11
+ date: 2023-10-20 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.55'
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.55'
60
+ version: '3.73'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: sequel-activerecord_connection
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -328,6 +328,7 @@ files:
328
328
  - lib/rodauth/rails/model.rb
329
329
  - lib/rodauth/rails/railtie.rb
330
330
  - lib/rodauth/rails/tasks.rake
331
+ - lib/rodauth/rails/tasks/routes.rb
331
332
  - lib/rodauth/rails/test.rb
332
333
  - lib/rodauth/rails/test/controller.rb
333
334
  - lib/rodauth/rails/version.rb
@@ -351,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
351
352
  - !ruby/object:Gem::Version
352
353
  version: '0'
353
354
  requirements: []
354
- rubygems_version: 3.4.12
355
+ rubygems_version: 3.4.10
355
356
  signing_key:
356
357
  specification_version: 4
357
358
  summary: Provides Rails integration for Rodauth.