rodauth-rails 0.4.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +177 -77
  4. data/lib/generators/rodauth/install_generator.rb +28 -18
  5. data/lib/generators/rodauth/migration/account_expiration.erb +7 -0
  6. data/lib/generators/rodauth/migration/active_sessions.erb +7 -0
  7. data/lib/generators/rodauth/migration/audit_logging.erb +16 -0
  8. data/lib/generators/rodauth/migration/base.erb +19 -0
  9. data/lib/generators/rodauth/migration/disallow_password_reuse.erb +5 -0
  10. data/lib/generators/rodauth/migration/email_auth.erb +7 -0
  11. data/lib/generators/rodauth/migration/jwt_refresh.erb +7 -0
  12. data/lib/generators/rodauth/migration/lockout.erb +11 -0
  13. data/lib/generators/rodauth/migration/otp.erb +7 -0
  14. data/lib/generators/rodauth/migration/password_expiration.erb +5 -0
  15. data/lib/generators/rodauth/migration/recovery_codes.erb +6 -0
  16. data/lib/generators/rodauth/migration/remember.erb +6 -0
  17. data/lib/generators/rodauth/migration/reset_password.erb +7 -0
  18. data/lib/generators/rodauth/migration/single_session.erb +5 -0
  19. data/lib/generators/rodauth/migration/sms_codes.erb +8 -0
  20. data/lib/generators/rodauth/migration/verify_account.erb +7 -0
  21. data/lib/generators/rodauth/migration/verify_login_change.erb +7 -0
  22. data/lib/generators/rodauth/migration/webauthn.erb +12 -0
  23. data/lib/generators/rodauth/migration_generator.rb +32 -0
  24. data/lib/generators/rodauth/migration_helpers.rb +69 -0
  25. data/lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb +2 -1
  26. data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +18 -18
  27. data/lib/generators/rodauth/templates/config/initializers/sequel.rb +1 -5
  28. data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +2 -176
  29. data/lib/rodauth/rails.rb +23 -4
  30. data/lib/rodauth/rails/app.rb +3 -1
  31. data/lib/rodauth/rails/app/flash.rb +1 -1
  32. data/lib/rodauth/rails/app/middleware.rb +26 -0
  33. data/lib/rodauth/rails/feature.rb +92 -25
  34. data/lib/rodauth/rails/railtie.rb +11 -0
  35. data/lib/rodauth/rails/tasks.rake +28 -0
  36. data/lib/rodauth/rails/version.rb +1 -1
  37. data/rodauth-rails.gemspec +3 -3
  38. metadata +29 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd5d6b153ae21b024570d612aff57a2c0d6f090f2215723b25bbc362ee743c9b
4
- data.tar.gz: e6aac1fe20d00bd4c94559c74dbc56bd971da4404d086ec3193db8e06fe2a3bd
3
+ metadata.gz: 9805b35cefee7e30cc6f7190e2ace9e7ea75c20f40651eb364edafea2f2382f7
4
+ data.tar.gz: 503b821866aaf2b6aa108265ed8015869a8c8a6a73e910aa3c38b35c5a542ac1
5
5
  SHA512:
6
- metadata.gz: 83a5c386eaf39c7aa9b0536e9aed25e8a61bc069e2388bee556b28e9ee00941528fd5431199711d77a28212d281376258ecf0b914d6aa928954d8d99543b827b
7
- data.tar.gz: 815d7fee34954d2f512e4532d02bb9d183ad9bde92fc622d522c517cd9db575c8fef98c857dce81c8329cd1798481b8e2f4609390b2472d83825d393886a3576
6
+ metadata.gz: 5a3e69b6d62f20ee5bc5a13c89acd2974401830a4f0f8917cc7716c9a5ccaad021a20c0f3269a211336b648bd8eb65ae60094c90a039fa1d3968eaf322ec2e47
7
+ data.tar.gz: 567cf154e656f7062029e207d92149fa8cf2c87404d1ba72fef6327cb31f928d0bcf453a4a0d55f71740251cb74f8b6829b8c775373daec4fe638690cd702104
@@ -1,3 +1,45 @@
1
+ ## 0.6.1 (2020-11-25)
2
+
3
+ * Generate the Rodauth controller for API-only Rails apps as well (@janko)
4
+
5
+ * Fix remember cookie deadline not extending in remember feature (@janko)
6
+
7
+ ## 0.6.0 (2020-11-22)
8
+
9
+ * Add `Rodauth::Rails.rodauth` method for retrieving Rodauth instance outside of request context (@janko)
10
+
11
+ * Add default Action Dispatch response headers in Rodauth responses (@janko)
12
+
13
+ * Run controller rescue handlers around Rodauth actions (@janko)
14
+
15
+ * Run controller action callbacks around Rodauth actions (@janko)
16
+
17
+ ## 0.5.0 (2020-11-16)
18
+
19
+ * Support more Active Record adapters in `rodauth:install` generator (@janko)
20
+
21
+ * Add `rodauth:migration` generator for creating tables of specified features (@janko)
22
+
23
+ * Use UUIDs for primary keys if so configured in Rails generators (@janko)
24
+
25
+ * Add `rodauth:routes` rake task for printing routes handled by Rodauth middleware (@janko)
26
+
27
+ ## 0.4.2 (2020-11-08)
28
+
29
+ * Drop support for Ruby 2.2 (@janko)
30
+
31
+ * Bump `sequel-activerecord_connection` dependency to 1.1+ (@janko)
32
+
33
+ * Set default bcrypt hash cost to `1` in tests (@janko)
34
+
35
+ * Call `AR::Base.connection_db_config` on Rails 6.1+ in `rodauth:install` generator (@janko)
36
+
37
+ ## 0.4.1 (2020-11-02)
38
+
39
+ * Don't generate `RodauthController` in API-only mode (@janko)
40
+
41
+ * Pass `test: false` to Sequel in the `sequel.rb` initializer (@janko)
42
+
1
43
  ## 0.4.0 (2020-11-02)
2
44
 
3
45
  * Support Rails API-only mode (@janko)
data/README.md CHANGED
@@ -4,16 +4,22 @@ Provides Rails integration for the [Rodauth] authentication framework.
4
4
 
5
5
  ## Resources
6
6
 
7
+ Useful links:
8
+
7
9
  * [Rodauth documentation](http://rodauth.jeremyevans.net/documentation.html)
8
- * [rodauth-rails wiki](https://github.com/janko/rodauth-rails/wiki)
9
10
  * [Rails demo](https://github.com/janko/rodauth-demo-rails)
10
11
 
12
+ Articles:
13
+
14
+ * [Rodauth: A Refreshing Authentication Solution for Ruby](https://janko.io/rodauth-a-refreshing-authentication-solution-for-ruby/)
15
+ * [Adding Authentication in Rails 6 with Rodauth](https://janko.io/adding-authentication-in-rails-with-rodauth/)
16
+
11
17
  ## Installation
12
18
 
13
19
  Add the gem to your Gemfile:
14
20
 
15
21
  ```rb
16
- gem "rodauth-rails", "~> 0.3"
22
+ gem "rodauth-rails", "~> 0.6"
17
23
 
18
24
  # gem "jwt", require: false # for JWT feature
19
25
  # gem "rotp", require: false # for OTP feature
@@ -54,7 +60,6 @@ class CreateRodauth < ActiveRecord::Migration
54
60
  create_table :account_verification_keys do |t| ... end
55
61
  create_table :account_login_change_keys do |t| ... end
56
62
  create_table :account_remember_keys do |t| ... end
57
- # ...
58
63
  end
59
64
  end
60
65
  ```
@@ -88,7 +93,7 @@ ActiveRecord connection.
88
93
  require "sequel/core"
89
94
 
90
95
  # initialize Sequel and have it reuse Active Record's database connection
91
- DB = Sequel.postgres(extensions: :activerecord_connection)
96
+ DB = Sequel.connect("postgresql://", extensions: :activerecord_connection)
92
97
  ```
93
98
 
94
99
  ### Rodauth app
@@ -112,8 +117,9 @@ end
112
117
 
113
118
  ### Controller
114
119
 
115
- Your Rodauth app will by default use `RodauthController` for view rendering
116
- and CSRF protection.
120
+ Your Rodauth app will by default use `RodauthController` for view rendering,
121
+ CSRF protection, and running controller callbacks and rescue handlers around
122
+ Rodauth actions.
117
123
 
118
124
  ```rb
119
125
  # app/controllers/rodauth_controller.rb
@@ -121,7 +127,7 @@ class RodauthController < ApplicationController
121
127
  end
122
128
  ```
123
129
 
124
- ### Account Model
130
+ ### Account model
125
131
 
126
132
  Rodauth stores user accounts in the `accounts` table, so the generator will
127
133
  also create an `Account` model for custom use.
@@ -132,10 +138,34 @@ class Account < ApplicationRecord
132
138
  end
133
139
  ```
134
140
 
135
- ## Getting started
141
+ ## Usage
142
+
143
+ ### Routes
144
+
145
+ We can see the list of routes our Rodauth middleware handles:
136
146
 
137
- Let's start by adding some basic authentication navigation links to our home
138
- page:
147
+ ```sh
148
+ $ rails rodauth:routes
149
+ ```
150
+ ```
151
+ Routes handled by RodauthApp:
152
+
153
+ /login rodauth.login_path
154
+ /create-account rodauth.create_account_path
155
+ /verify-account-resend rodauth.verify_account_resend_path
156
+ /verify-account rodauth.verify_account_path
157
+ /change-password rodauth.change_password_path
158
+ /change-login rodauth.change_login_path
159
+ /logout rodauth.logout_path
160
+ /remember rodauth.remember_path
161
+ /reset-password-request rodauth.reset_password_request_path
162
+ /reset-password rodauth.reset_password_path
163
+ /verify-login-change rodauth.verify_login_change_path
164
+ /close-account rodauth.close_account_path
165
+ ```
166
+
167
+ Using this information, we could add some basic authentication links to our
168
+ navigation header:
139
169
 
140
170
  ```erb
141
171
  <ul>
@@ -148,43 +178,48 @@ page:
148
178
  </ul>
149
179
  ```
150
180
 
151
- These links are fully functional, feel free to visit them and interact with the
181
+ These routes are fully functional, feel free to visit them and interact with the
152
182
  pages. The templates that ship with Rodauth aim to provide a complete
153
183
  authentication experience, and the forms use [Bootstrap] markup.
154
184
 
155
- Let's also load the account record for authenticated requests and expose it via
156
- `#current_account`:
185
+ ### Current account
186
+
187
+ To be able to fetch currently authenticated account, let's define a
188
+ `#current_account` method that fetches the account id from session and
189
+ retrieves the corresponding account record:
157
190
 
158
191
  ```rb
159
192
  # app/controllers/application_controller.rb
160
193
  class ApplicationController < ActionController::Base
161
- before_action :load_account, if: -> { rodauth.authenticated? }
194
+ before_action :current_account, if: -> { rodauth.authenticated? }
162
195
 
163
196
  private
164
197
 
165
- def load_account
166
- @current_account = Account.find(rodauth.session_value)
198
+ def current_account
199
+ @current_account ||= Account.find(rodauth.session_value)
167
200
  rescue ActiveRecord::RecordNotFound
168
201
  rodauth.logout
169
202
  rodauth.login_required
170
203
  end
171
-
172
- attr_reader :current_account
173
204
  helper_method :current_account
174
205
  end
175
206
  ```
207
+
208
+ This allows us to access the current account in controllers and views:
209
+
176
210
  ```erb
177
211
  <p>Authenticated as: <%= current_account.email %></p>
178
212
  ```
179
213
 
180
214
  ### Requiring authentication
181
215
 
182
- Next, we'll likely want to require authentication for certain sections/pages of
183
- our app. We can do this in our Rodauth app's routing block, which helps keep
184
- the authentication logic encapsulated:
216
+ We'll likely want to require authentication for certain parts of our app,
217
+ redirecting the user to the login page if they're not logged in. We can do this
218
+ in our Rodauth app's routing block, which helps keep the authentication logic
219
+ encapsulated:
185
220
 
186
221
  ```rb
187
- # lib/rodauth_app.rb
222
+ # app/lib/rodauth_app.rb
188
223
  class RodauthApp < Rodauth::Rails::App
189
224
  # ...
190
225
  route do |r|
@@ -239,9 +274,9 @@ end
239
274
 
240
275
  ### Views
241
276
 
242
- The templates built into Rodauth are useful when getting started, but at some
243
- point we'll probably want more control over the markup. For that we can run the
244
- following command:
277
+ The templates built into Rodauth are useful when getting started, but soon
278
+ you'll want to start editing the markup. You can run the following command to
279
+ copy Rodauth templates into your Rails app:
245
280
 
246
281
  ```sh
247
282
  $ rails generate rodauth:views
@@ -265,7 +300,7 @@ $ rails generate rodauth:views --all
265
300
  ```
266
301
 
267
302
  You can also tell the generator to create views into another directory (in this
268
- case don't forget to rename the Rodauth controller accordingly).
303
+ case make sure to rename the Rodauth controller accordingly):
269
304
 
270
305
  ```sh
271
306
  # generates views into app/views/authentication
@@ -300,11 +335,11 @@ end
300
335
 
301
336
  ### Mailer
302
337
 
303
- Rodauth may send emails as part of the authentication flow. Most email settings
304
- can be customized:
338
+ Depending on the features you've enabled, Rodauth may send emails as part of
339
+ the authentication flow. Most email settings can be customized:
305
340
 
306
341
  ```rb
307
- # lib/rodauth_app.rb
342
+ # app/lib/rodauth_app.rb
308
343
  class RodauthApp < Rodauth::Rails::App
309
344
  # ...
310
345
  configure do
@@ -345,46 +380,117 @@ end
345
380
  ```
346
381
 
347
382
  You can then uncomment the lines in your Rodauth configuration to have it call
348
- your mailer. If you've enabled additional authentication features, make sure to
349
- override their `send_*_email` methods as well.
383
+ your mailer. If you've enabled additional authentication features that send
384
+ emails, make sure to override their `create_*_email` methods as well.
350
385
 
351
386
  ```rb
352
- # lib/rodauth_app.rb
387
+ # app/lib/rodauth_app.rb
353
388
  class RodauthApp < Rodauth::Rails::App
354
389
  # ...
355
390
  configure do
356
391
  # ...
357
- send_reset_password_email do
358
- mailer_send(:reset_password, email_to, reset_password_email_link)
392
+ create_reset_password_email do
393
+ RodauthMailer.reset_password(email_to, reset_password_email_link)
359
394
  end
360
- send_verify_account_email do
361
- mailer_send(:verify_account, email_to, verify_account_email_link)
395
+ create_verify_account_email do
396
+ RodauthMailer.verify_account(email_to, verify_account_email_link)
362
397
  end
363
- send_verify_login_change_email do |login|
364
- mailer_send(:verify_login_change, login, verify_login_change_old_login, verify_login_change_new_login, verify_login_change_email_link)
398
+ create_verify_login_change_email do |login|
399
+ RodauthMailer.verify_login_change(login, verify_login_change_old_login, verify_login_change_new_login, verify_login_change_email_link)
365
400
  end
366
- send_password_changed_email do
367
- mailer_send(:password_changed, email_to)
401
+ create_password_changed_email do
402
+ RodauthMailer.password_changed(email_to)
368
403
  end
369
- # send_email_auth_email do
370
- # mailer_send(:email_auth, email_to, email_auth_email_link)
404
+ # create_email_auth_email do
405
+ # RodauthMailer.email_auth(email_to, email_auth_email_link)
371
406
  # end
372
- # send_unlock_account_email do
373
- # mailer_send(:unlock_account, email_to, unlock_account_email_link)
407
+ # create_unlock_account_email do
408
+ # RodauthMailer.unlock_account(email_to, unlock_account_email_link)
374
409
  # end
375
- auth_class_eval do
410
+ send_email do |email|
376
411
  # queue email delivery on the mailer after the transaction commits
377
- def mailer_send(type, *args)
378
- db.after_commit do
379
- RodauthMailer.public_send(type, *args).deliver_later
380
- end
381
- end
412
+ db.after_commit { email.deliver_later }
382
413
  end
383
414
  # ...
384
415
  end
385
416
  end
386
417
  ```
387
418
 
419
+ This approach can be used even if you're using a 3rd-party service for
420
+ transactional emails, where emails are sent via API requests instead of
421
+ SMTP. Whatever the `create_*_email` block returns will be passed to
422
+ `send_email`, so you can be creative.
423
+
424
+ ### Migrations
425
+
426
+ The install generator will create a migration for tables used by the Rodauth
427
+ features enabled by default. For any additional features, you can use the
428
+ migration generator to create the corresponding tables:
429
+
430
+ ```sh
431
+ $ rails generate rodauth:migration otp sms_codes recovery_codes
432
+ ```
433
+ ```rb
434
+ # db/migration/*_create_rodauth_otp_sms_codes_recovery_codes.rb
435
+ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
436
+ def change
437
+ create_table :account_otp_keys do |t| ... end
438
+ create_table :account_sms_codes do |t| ... end
439
+ create_table :account_recovery_codes do |t| ... end
440
+ end
441
+ end
442
+ ```
443
+
444
+ ### JSON API
445
+
446
+ JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
447
+ to add the [JWT gem] to your Gemfile:
448
+
449
+ ```rb
450
+ gem "jwt"
451
+ ```
452
+
453
+ The following configuration will enable the Rodauth endpoints to be accessed
454
+ via JSON requests (in addition to HTML requests):
455
+
456
+ ```rb
457
+ # app/lib/rodauth_app.rb
458
+ class RodauthApp < Rodauth::Rails::App
459
+ configure(json: true) do
460
+ # ...
461
+ enable :jwt
462
+ jwt_secret "...your secret key..."
463
+ # ...
464
+ end
465
+ end
466
+ ```
467
+
468
+ If you want the endpoints to be only accessible via JSON requests, or if your
469
+ Rails app is in API-only mode, instead of `json: true` pass `json: :only` to
470
+ the configure method.
471
+
472
+ Make sure to store the `jwt_secret` in a secure place, such as Rails
473
+ credentials or environment variables.
474
+
475
+ ### Rodauth instance
476
+
477
+ In some cases you might need to use Rodauth more programmatically, and perform
478
+ Rodauth operations outside of the request context. rodauth-rails gives you the
479
+ ability to retrieve the Rodauth instance:
480
+
481
+ ```rb
482
+ rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:secondary)
483
+
484
+ rodauth.login_url #=> "https://example.com/login"
485
+ rodauth.account_from_login("user@example.com") # loads user by email
486
+ rodauth.password_match?("secret") #=> true
487
+ rodauth.setup_account_verification
488
+ rodauth.close_account
489
+ ```
490
+
491
+ This Rodauth instance will be initialized with basic Rack env that allows is it
492
+ to generate URLs, using `config.action_mailer.default_url_options` options.
493
+
388
494
  ## How it works
389
495
 
390
496
  ### Middleware
@@ -429,11 +535,12 @@ end
429
535
  The `Rodauth::Rails::App` class is a [Roda] subclass that provides Rails
430
536
  integration for Rodauth:
431
537
 
432
- * uses Rails' flash instead of Roda's
433
- * uses Rails' CSRF protection instead of Roda's
538
+ * uses Action Dispatch flash instead of Roda's
539
+ * uses Action Dispatch CSRF protection instead of Roda's
434
540
  * sets [HMAC] secret to Rails' secret key base
435
- * uses ActionController for rendering templates
436
- * uses ActionMailer for sending emails
541
+ * uses Action Controller for rendering templates
542
+ * runs Action Controller callbacks & rescue handlers around Rodauth actions
543
+ * uses Action Mailer for sending emails
437
544
 
438
545
  The `configure { ... }` method wraps configuring the Rodauth plugin, forwarding
439
546
  any additional [plugin options].
@@ -490,28 +597,6 @@ Rodauth::Rails.configure do |config|
490
597
  end
491
598
  ```
492
599
 
493
- ## Working with JWT
494
-
495
- To use Rodauth's [JWT feature], you'll need to load Roda's JSON support in
496
- `configure`:
497
-
498
- ```rb
499
- # lib/rodauth_app.rb
500
- class RodauthApp < Rodauth::Rails::App
501
- configure(json: true) do
502
- enable :jwt
503
- jwt_secret "...your secret key..."
504
- # your configuration
505
- end
506
- end
507
- ```
508
-
509
- Make sure to store the `jwt_secret` in a secure place, such as Rails
510
- credentials or environment variables.
511
-
512
- Rodauth's JWT feature depends on the [JWT gem], so make sure to add it to your
513
- Gemfile.
514
-
515
600
  ## Testing
516
601
 
517
602
  If you're writing system tests, it's generally better to go through the actual
@@ -579,6 +664,22 @@ disables the use of database functions, though you can always turn it back on.
579
664
  use_database_authentication_functions? true
580
665
  ```
581
666
 
667
+ To create the database functions, pass the Sequel database object into the
668
+ Rodauth method for creating database functions:
669
+
670
+ ```rb
671
+ # db/migrate/*_create_rodauth_database_functions.rb
672
+ class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
673
+ def up
674
+ Rodauth.create_database_authentication_functions(DB)
675
+ end
676
+
677
+ def down
678
+ Rodauth.drop_database_authentication_functions(DB)
679
+ end
680
+ end
681
+ ```
682
+
582
683
  ### Account statuses
583
684
 
584
685
  The recommended [Rodauth migration] stores possible account status values in a
@@ -631,7 +732,6 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
631
732
 
632
733
  [Rodauth]: https://github.com/jeremyevans/rodauth
633
734
  [Sequel]: https://github.com/jeremyevans/sequel
634
- [rendering views outside of controllers]: https://blog.bigbinary.com/2016/01/08/rendering-views-outside-of-controllers-in-rails-5.html
635
735
  [feature documentation]: http://rodauth.jeremyevans.net/documentation.html
636
736
  [JWT feature]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
637
737
  [JWT gem]: https://github.com/jwt/ruby-jwt