rodauth-rails 0.3.1 → 0.6.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +169 -69
  4. data/lib/generators/rodauth/install_generator.rb +34 -17
  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/{lib → app/lib}/rodauth_app.rb +26 -2
  26. data/lib/generators/rodauth/templates/config/initializers/sequel.rb +1 -5
  27. data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +2 -167
  28. data/lib/rodauth/rails.rb +24 -5
  29. data/lib/rodauth/rails/app.rb +5 -4
  30. data/lib/rodauth/rails/feature.rb +69 -13
  31. data/lib/rodauth/rails/flash.rb +48 -0
  32. data/lib/rodauth/rails/railtie.rb +11 -0
  33. data/lib/rodauth/rails/tasks.rake +28 -0
  34. data/lib/rodauth/rails/version.rb +5 -0
  35. data/rodauth-rails.gemspec +6 -4
  36. metadata +31 -9
  37. data/lib/rodauth/rails/app/flash.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b60f1b274889c1809196e62e8f3ba3516bf631593e6263162b3f4af11521d3a3
4
- data.tar.gz: e55af46d9f5886dfc70d1f3112597bf508ba9536e8d0fc9cec141f33d045c94b
3
+ metadata.gz: 00d7ab9dd749cbae17cddc2788005d8570d8d46f89f427ad624c7e61fe177665
4
+ data.tar.gz: d62aed32823b0be9c74d7281de80650b8faf600c01db22ad941a35f30bfeb002
5
5
  SHA512:
6
- metadata.gz: 26c72c879909f9497a9d05802776ef8aa42d73dd8a4ba72695ea88289aebf29b2224bbf9011ab7929b394e708c25379410cb9d62f4d54c9c300002e3405cdc5a
7
- data.tar.gz: 8370be5f4885300ded77d1e0bfea95ab99c0b0889fe464fbea062da7d71dd1a66deb4777a08dc235f841eb241170b1a08eb9badce756325e2291b5e87883068a
6
+ metadata.gz: 7ab0afe5e95fab1af706b64ef5c494252fac49481d49dad1c2ef3510c17ca96050c58bf0832a36af761673137f2fd63d7d49a692656bcf06748840de96f60875
7
+ data.tar.gz: 729bf3b5887647c23f4b11d821d3829c4b4d290c546d2f19ba6b393dd47bf0b357d128577e877ac3e0a4352972b79325d4217d62935d4a683e78ff8e910d13a2
@@ -1,3 +1,45 @@
1
+ ## 0.6.0 (2020-11-22)
2
+
3
+ * Add `Rodauth::Rails.rodauth` method for retrieving Rodauth instance outside of request context (@janko)
4
+
5
+ * Add default Action Dispatch response headers in Rodauth responses (@janko)
6
+
7
+ * Run controller rescue handlers around Rodauth actions (@janko)
8
+
9
+ * Run controller action callbacks around Rodauth actions (@janko)
10
+
11
+ ## 0.5.0 (2020-11-16)
12
+
13
+ * Support more Active Record adapters in `rodauth:install` generator (@janko)
14
+
15
+ * Add `rodauth:migration` generator for creating tables of specified features (@janko)
16
+
17
+ * Use UUIDs for primary keys if so configured in Rails generators (@janko)
18
+
19
+ * Add `rodauth:routes` rake task for printing routes handled by Rodauth middleware (@janko)
20
+
21
+ ## 0.4.2 (2020-11-08)
22
+
23
+ * Drop support for Ruby 2.2 (@janko)
24
+
25
+ * Bump `sequel-activerecord_connection` dependency to 1.1+ (@janko)
26
+
27
+ * Set default bcrypt hash cost to `1` in tests (@janko)
28
+
29
+ * Call `AR::Base.connection_db_config` on Rails 6.1+ in `rodauth:install` generator (@janko)
30
+
31
+ ## 0.4.1 (2020-11-02)
32
+
33
+ * Don't generate `RodauthController` in API-only mode (@janko)
34
+
35
+ * Pass `test: false` to Sequel in the `sequel.rb` initializer (@janko)
36
+
37
+ ## 0.4.0 (2020-11-02)
38
+
39
+ * Support Rails API-only mode (@janko)
40
+
41
+ * Make `rodauth:install` create `rodauth_app.rb` in `app/lib/` directory (@janko)
42
+
1
43
  ## 0.3.1 (2020-10-25)
2
44
 
3
45
  * Depend on sequel-activerecord_connection 1.0+ (@janko)
data/README.md CHANGED
@@ -4,16 +4,27 @@ 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"
23
+
24
+ # gem "jwt", require: false # for JWT feature
25
+ # gem "rotp", require: false # for OTP feature
26
+ # gem "rqrcode", require: false # for OTP feature
27
+ # gem "webauthn", require: false # for WebAuthn feature
17
28
  ```
18
29
 
19
30
  Then run `bundle install`.
@@ -29,7 +40,7 @@ The generator will create the following files:
29
40
  * Rodauth migration at `db/migrate/*_create_rodauth.rb`
30
41
  * Rodauth initializer at `config/initializers/rodauth.rb`
31
42
  * Sequel initializer at `config/initializers/sequel.rb` for ActiveRecord integration
32
- * Rodauth app at `lib/rodauth_app.rb`
43
+ * Rodauth app at `app/lib/rodauth_app.rb`
33
44
  * Rodauth controller at `app/controllers/rodauth_controller.rb`
34
45
  * Account model at `app/models/account.rb`
35
46
 
@@ -49,7 +60,6 @@ class CreateRodauth < ActiveRecord::Migration
49
60
  create_table :account_verification_keys do |t| ... end
50
61
  create_table :account_login_change_keys do |t| ... end
51
62
  create_table :account_remember_keys do |t| ... end
52
- # ...
53
63
  end
54
64
  end
55
65
  ```
@@ -83,17 +93,17 @@ ActiveRecord connection.
83
93
  require "sequel/core"
84
94
 
85
95
  # initialize Sequel and have it reuse Active Record's database connection
86
- DB = Sequel.postgres(extensions: :activerecord_connection)
96
+ DB = Sequel.connect("postgresql://", extensions: :activerecord_connection)
87
97
  ```
88
98
 
89
99
  ### Rodauth app
90
100
 
91
- Your Rodauth app is created in the `lib/` directory, which comes with a default
92
- set of authentication features enabled, as well as extensive examples on ways
93
- you can configure authentication behaviour.
101
+ Your Rodauth app is created in the `app/lib/` directory, and comes with a
102
+ default set of authentication features enabled, as well as extensive examples
103
+ on ways you can configure authentication behaviour.
94
104
 
95
105
  ```rb
96
- # lib/rodauth_app.rb
106
+ # app/lib/rodauth_app.rb
97
107
  class RodauthApp < Rodauth::Rails::App
98
108
  configure do
99
109
  # authentication configuration
@@ -105,23 +115,11 @@ class RodauthApp < Rodauth::Rails::App
105
115
  end
106
116
  ```
107
117
 
108
- Note that Rails doesn't autoload files in the `lib/` directory by default, so
109
- make sure to add `lib/` to your `config.autoload_paths`:
110
-
111
- ```rb
112
- # config/application.rb
113
- module YourApp
114
- class Application < Rails::Application
115
- # ...
116
- config.autoload_paths += %W[#{config.root}/lib]
117
- end
118
- end
119
- ```
120
-
121
118
  ### Controller
122
119
 
123
- Your Rodauth app will by default use `RodauthController` for view rendering
124
- 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.
125
123
 
126
124
  ```rb
127
125
  # app/controllers/rodauth_controller.rb
@@ -129,7 +127,7 @@ class RodauthController < ApplicationController
129
127
  end
130
128
  ```
131
129
 
132
- ### Account Model
130
+ ### Account model
133
131
 
134
132
  Rodauth stores user accounts in the `accounts` table, so the generator will
135
133
  also create an `Account` model for custom use.
@@ -140,10 +138,34 @@ class Account < ApplicationRecord
140
138
  end
141
139
  ```
142
140
 
143
- ## Getting started
141
+ ## Usage
142
+
143
+ ### Routes
144
+
145
+ We can see the list of routes our Rodauth middleware handles:
146
+
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
+ ```
144
166
 
145
- Let's start by adding some basic authentication navigation links to our home
146
- page:
167
+ Using this information, we could add some basic authentication links to our
168
+ navigation header:
147
169
 
148
170
  ```erb
149
171
  <ul>
@@ -156,43 +178,48 @@ page:
156
178
  </ul>
157
179
  ```
158
180
 
159
- 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
160
182
  pages. The templates that ship with Rodauth aim to provide a complete
161
183
  authentication experience, and the forms use [Bootstrap] markup.
162
184
 
163
- Let's also load the account record for authenticated requests and expose it via
164
- `#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:
165
190
 
166
191
  ```rb
167
192
  # app/controllers/application_controller.rb
168
193
  class ApplicationController < ActionController::Base
169
- before_action :load_account, if: -> { rodauth.authenticated? }
194
+ before_action :current_account, if: -> { rodauth.authenticated? }
170
195
 
171
196
  private
172
197
 
173
- def load_account
174
- @current_account = Account.find(rodauth.session_value)
198
+ def current_account
199
+ @current_account ||= Account.find(rodauth.session_value)
175
200
  rescue ActiveRecord::RecordNotFound
176
201
  rodauth.logout
177
202
  rodauth.login_required
178
203
  end
179
-
180
- attr_reader :current_account
181
204
  helper_method :current_account
182
205
  end
183
206
  ```
207
+
208
+ This allows us to access the current account in controllers and views:
209
+
184
210
  ```erb
185
211
  <p>Authenticated as: <%= current_account.email %></p>
186
212
  ```
187
213
 
188
214
  ### Requiring authentication
189
215
 
190
- Next, we'll likely want to require authentication for certain sections/pages of
191
- our app. We can do this in our Rodauth app's routing block, which helps keep
192
- 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:
193
220
 
194
221
  ```rb
195
- # lib/rodauth_app.rb
222
+ # app/lib/rodauth_app.rb
196
223
  class RodauthApp < Rodauth::Rails::App
197
224
  # ...
198
225
  route do |r|
@@ -247,9 +274,9 @@ end
247
274
 
248
275
  ### Views
249
276
 
250
- The templates built into Rodauth are useful when getting started, but at some
251
- point we'll probably want more control over the markup. For that we can run the
252
- 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:
253
280
 
254
281
  ```sh
255
282
  $ rails generate rodauth:views
@@ -273,7 +300,7 @@ $ rails generate rodauth:views --all
273
300
  ```
274
301
 
275
302
  You can also tell the generator to create views into another directory (in this
276
- case don't forget to rename the Rodauth controller accordingly).
303
+ case make sure to rename the Rodauth controller accordingly):
277
304
 
278
305
  ```sh
279
306
  # generates views into app/views/authentication
@@ -308,11 +335,11 @@ end
308
335
 
309
336
  ### Mailer
310
337
 
311
- Rodauth may send emails as part of the authentication flow. Most email settings
312
- 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:
313
340
 
314
341
  ```rb
315
- # lib/rodauth_app.rb
342
+ # app/lib/rodauth_app.rb
316
343
  class RodauthApp < Rodauth::Rails::App
317
344
  # ...
318
345
  configure do
@@ -353,11 +380,11 @@ end
353
380
  ```
354
381
 
355
382
  You can then uncomment the lines in your Rodauth configuration to have it call
356
- your mailer. If you've enabled additional authentication features, make sure to
357
- 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 `send_*_email` methods as well.
358
385
 
359
386
  ```rb
360
- # lib/rodauth_app.rb
387
+ # app/lib/rodauth_app.rb
361
388
  class RodauthApp < Rodauth::Rails::App
362
389
  # ...
363
390
  configure do
@@ -393,6 +420,76 @@ class RodauthApp < Rodauth::Rails::App
393
420
  end
394
421
  ```
395
422
 
423
+ ### Migrations
424
+
425
+ The install generator will create a migration for tables used by the Rodauth
426
+ features enabled by default. For any additional features, you can use the
427
+ migration generator to create the corresponding tables:
428
+
429
+ ```sh
430
+ $ rails generate rodauth:migration otp sms_codes recovery_codes
431
+ ```
432
+ ```rb
433
+ # db/migration/*_create_rodauth_otp_sms_codes_recovery_codes.rb
434
+ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
435
+ def change
436
+ create_table :account_otp_keys do |t| ... end
437
+ create_table :account_sms_codes do |t| ... end
438
+ create_table :account_recovery_codes do |t| ... end
439
+ end
440
+ end
441
+ ```
442
+
443
+ ### JSON API
444
+
445
+ JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
446
+ to add the [JWT gem] to your Gemfile:
447
+
448
+ ```rb
449
+ gem "jwt"
450
+ ```
451
+
452
+ The following configuration will enable the Rodauth endpoints to be accessed
453
+ via JSON requests (in addition to HTML requests):
454
+
455
+ ```rb
456
+ # app/lib/rodauth_app.rb
457
+ class RodauthApp < Rodauth::Rails::App
458
+ configure(json: true) do
459
+ # ...
460
+ enable :jwt
461
+ jwt_secret "...your secret key..."
462
+ # ...
463
+ end
464
+ end
465
+ ```
466
+
467
+ If you want the endpoints to be only accessible via JSON requests, or if your
468
+ Rails app is in API-only mode, instead of `json: true` pass `json: :only` to
469
+ the configure method.
470
+
471
+ Make sure to store the `jwt_secret` in a secure place, such as Rails
472
+ credentials or environment variables.
473
+
474
+ ### Rodauth instance
475
+
476
+ In some cases you might need to use Rodauth more programmatically, and perform
477
+ Rodauth operations outside of the request context. rodauth-rails gives you the
478
+ ability to retrieve the Rodauth instance:
479
+
480
+ ```rb
481
+ rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:secondary)
482
+
483
+ rodauth.login_url #=> "https://example.com/login"
484
+ rodauth.account_from_login("user@example.com") # loads user by email
485
+ rodauth.password_match?("secret") #=> true
486
+ rodauth.setup_account_verification
487
+ rodauth.close_account
488
+ ```
489
+
490
+ This Rodauth instance will be initialized with basic Rack env that allows is it
491
+ to generate URLs, using `config.action_mailer.default_url_options` options.
492
+
396
493
  ## How it works
397
494
 
398
495
  ### Middleware
@@ -437,11 +534,12 @@ end
437
534
  The `Rodauth::Rails::App` class is a [Roda] subclass that provides Rails
438
535
  integration for Rodauth:
439
536
 
440
- * uses Rails' flash instead of Roda's
441
- * uses Rails' CSRF protection instead of Roda's
537
+ * uses Action Dispatch flash instead of Roda's
538
+ * uses Action Dispatch CSRF protection instead of Roda's
442
539
  * sets [HMAC] secret to Rails' secret key base
443
- * uses ActionController for rendering templates
444
- * uses ActionMailer for sending emails
540
+ * uses Action Controller for rendering templates
541
+ * runs Action Controller callbacks & rescue handlers around Rodauth actions
542
+ * uses Action Mailer for sending emails
445
543
 
446
544
  The `configure { ... }` method wraps configuring the Rodauth plugin, forwarding
447
545
  any additional [plugin options].
@@ -498,20 +596,6 @@ Rodauth::Rails.configure do |config|
498
596
  end
499
597
  ```
500
598
 
501
- ## Working with JWT
502
-
503
- To use Rodauth's [JWT feature], you'll need to load Roda's JSON support:
504
-
505
- ```rb
506
- # lib/rodauth_app.rb
507
- class RodauthApp < Rodauth::Rails::App
508
- configure(json: true) do
509
- enable :jwt
510
- # your configuration
511
- end
512
- end
513
- ```
514
-
515
599
  ## Testing
516
600
 
517
601
  If you're writing system tests, it's generally better to go through the actual
@@ -579,6 +663,22 @@ disables the use of database functions, though you can always turn it back on.
579
663
  use_database_authentication_functions? true
580
664
  ```
581
665
 
666
+ To create the database functions, pass the Sequel database object into the
667
+ Rodauth method for creating database functions:
668
+
669
+ ```rb
670
+ # db/migrate/*_create_rodauth_database_functions.rb
671
+ class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
672
+ def up
673
+ Rodauth.create_database_authentication_functions(DB)
674
+ end
675
+
676
+ def down
677
+ Rodauth.drop_database_authentication_functions(DB)
678
+ end
679
+ end
680
+ ```
681
+
582
682
  ### Account statuses
583
683
 
584
684
  The recommended [Rodauth migration] stores possible account status values in a
@@ -631,9 +731,9 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
631
731
 
632
732
  [Rodauth]: https://github.com/jeremyevans/rodauth
633
733
  [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
734
  [feature documentation]: http://rodauth.jeremyevans.net/documentation.html
636
735
  [JWT feature]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
736
+ [JWT gem]: https://github.com/jwt/ruby-jwt
637
737
  [Bootstrap]: https://getbootstrap.com/
638
738
  [Roda]: http://roda.jeremyevans.net/
639
739
  [HMAC]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC