rodauth-rails 0.3.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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