rodauth-rails 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.md +114 -44
- data/lib/generators/rodauth/install_generator.rb +34 -17
- data/lib/generators/rodauth/migration/account_expiration.erb +7 -0
- data/lib/generators/rodauth/migration/active_sessions.erb +7 -0
- data/lib/generators/rodauth/migration/audit_logging.erb +16 -0
- data/lib/generators/rodauth/migration/base.erb +19 -0
- data/lib/generators/rodauth/migration/disallow_password_reuse.erb +5 -0
- data/lib/generators/rodauth/migration/email_auth.erb +7 -0
- data/lib/generators/rodauth/migration/jwt_refresh.erb +7 -0
- data/lib/generators/rodauth/migration/lockout.erb +11 -0
- data/lib/generators/rodauth/migration/otp.erb +7 -0
- data/lib/generators/rodauth/migration/password_expiration.erb +5 -0
- data/lib/generators/rodauth/migration/recovery_codes.erb +6 -0
- data/lib/generators/rodauth/migration/remember.erb +6 -0
- data/lib/generators/rodauth/migration/reset_password.erb +7 -0
- data/lib/generators/rodauth/migration/single_session.erb +5 -0
- data/lib/generators/rodauth/migration/sms_codes.erb +8 -0
- data/lib/generators/rodauth/migration/verify_account.erb +7 -0
- data/lib/generators/rodauth/migration/verify_login_change.erb +7 -0
- data/lib/generators/rodauth/migration/webauthn.erb +12 -0
- data/lib/generators/rodauth/migration_generator.rb +32 -0
- data/lib/generators/rodauth/migration_helpers.rb +69 -0
- data/lib/generators/rodauth/templates/{lib → app/lib}/rodauth_app.rb +26 -2
- data/lib/generators/rodauth/templates/config/initializers/sequel.rb +1 -5
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +2 -167
- data/lib/rodauth/rails.rb +1 -1
- data/lib/rodauth/rails/app.rb +5 -4
- data/lib/rodauth/rails/app/flash.rb +1 -1
- data/lib/rodauth/rails/feature.rb +8 -4
- data/lib/rodauth/rails/railtie.rb +11 -0
- data/lib/rodauth/rails/tasks.rake +32 -0
- data/lib/rodauth/rails/version.rb +5 -0
- data/rodauth-rails.gemspec +5 -3
- metadata +29 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0d00b7ad2f6198fff3a5cc3c720c6f30d9296898e3fd764ddf7408e36232a6d
|
4
|
+
data.tar.gz: 9ba008116fc5521c98ed62dda5b1f6b2eccd733d06ccb0a2c5b9b4db8df94539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 848873e599cfb8dc8a5d274ac5fec5987cf4c895c77757a4b21529ddcd9a635ba8086c037f55c55ef097ae926549234e5abebb97a5300f0ead6118927d737d91
|
7
|
+
data.tar.gz: aa75fb48217e79c40000cf1f226f36a65fdffdcb764233572ae45341b7ab9dd2f1d8f8470e593d8260495962b1b5c352e62d0d5e71fed0cb96891da93a0f344c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,39 @@
|
|
1
|
+
## 0.5.0 (2020-11-16)
|
2
|
+
|
3
|
+
* Support more Active Record adapters in `rodauth:install` generator (@janko)
|
4
|
+
|
5
|
+
* Add `rodauth:migration` generator for creating tables of specified features (@janko)
|
6
|
+
|
7
|
+
* Use UUIDs for primary keys if so configured in Rails generators (@janko)
|
8
|
+
|
9
|
+
* Add `rodauth:routes` rake task for printing routes handled by Rodauth middleware (@janko)
|
10
|
+
|
11
|
+
## 0.4.2 (2020-11-08)
|
12
|
+
|
13
|
+
* Drop support for Ruby 2.2 (@janko)
|
14
|
+
|
15
|
+
* Bump `sequel-activerecord_connection` dependency to 1.1+ (@janko)
|
16
|
+
|
17
|
+
* Set default bcrypt hash cost to `1` in tests (@janko)
|
18
|
+
|
19
|
+
* Call `AR::Base.connection_db_config` on Rails 6.1+ in `rodauth:install` generator (@janko)
|
20
|
+
|
21
|
+
## 0.4.1 (2020-11-02)
|
22
|
+
|
23
|
+
* Don't generate `RodauthController` in API-only mode (@janko)
|
24
|
+
|
25
|
+
* Pass `test: false` to Sequel in the `sequel.rb` initializer (@janko)
|
26
|
+
|
27
|
+
## 0.4.0 (2020-11-02)
|
28
|
+
|
29
|
+
* Support Rails API-only mode (@janko)
|
30
|
+
|
31
|
+
* Make `rodauth:install` create `rodauth_app.rb` in `app/lib/` directory (@janko)
|
32
|
+
|
33
|
+
## 0.3.1 (2020-10-25)
|
34
|
+
|
35
|
+
* Depend on sequel-activerecord_connection 1.0+ (@janko)
|
36
|
+
|
1
37
|
## 0.3.0 (2020-09-18)
|
2
38
|
|
3
39
|
* Handle custom configured database migration paths in install generator (@janko)
|
data/README.md
CHANGED
@@ -13,7 +13,12 @@ Provides Rails integration for the [Rodauth] authentication framework.
|
|
13
13
|
Add the gem to your Gemfile:
|
14
14
|
|
15
15
|
```rb
|
16
|
-
gem "rodauth-rails", "~> 0.
|
16
|
+
gem "rodauth-rails", "~> 0.4"
|
17
|
+
|
18
|
+
# gem "jwt", require: false # for JWT feature
|
19
|
+
# gem "rotp", require: false # for OTP feature
|
20
|
+
# gem "rqrcode", require: false # for OTP feature
|
21
|
+
# gem "webauthn", require: false # for WebAuthn feature
|
17
22
|
```
|
18
23
|
|
19
24
|
Then run `bundle install`.
|
@@ -29,7 +34,7 @@ The generator will create the following files:
|
|
29
34
|
* Rodauth migration at `db/migrate/*_create_rodauth.rb`
|
30
35
|
* Rodauth initializer at `config/initializers/rodauth.rb`
|
31
36
|
* Sequel initializer at `config/initializers/sequel.rb` for ActiveRecord integration
|
32
|
-
* Rodauth app at `lib/rodauth_app.rb`
|
37
|
+
* Rodauth app at `app/lib/rodauth_app.rb`
|
33
38
|
* Rodauth controller at `app/controllers/rodauth_controller.rb`
|
34
39
|
* Account model at `app/models/account.rb`
|
35
40
|
|
@@ -49,7 +54,6 @@ class CreateRodauth < ActiveRecord::Migration
|
|
49
54
|
create_table :account_verification_keys do |t| ... end
|
50
55
|
create_table :account_login_change_keys do |t| ... end
|
51
56
|
create_table :account_remember_keys do |t| ... end
|
52
|
-
# ...
|
53
57
|
end
|
54
58
|
end
|
55
59
|
```
|
@@ -83,17 +87,17 @@ ActiveRecord connection.
|
|
83
87
|
require "sequel/core"
|
84
88
|
|
85
89
|
# initialize Sequel and have it reuse Active Record's database connection
|
86
|
-
DB = Sequel.
|
90
|
+
DB = Sequel.connect("postgresql://", extensions: :activerecord_connection)
|
87
91
|
```
|
88
92
|
|
89
93
|
### Rodauth app
|
90
94
|
|
91
|
-
Your Rodauth app is created in the `lib/` directory,
|
92
|
-
set of authentication features enabled, as well as extensive examples
|
93
|
-
you can configure authentication behaviour.
|
95
|
+
Your Rodauth app is created in the `app/lib/` directory, and comes with a
|
96
|
+
default set of authentication features enabled, as well as extensive examples
|
97
|
+
on ways you can configure authentication behaviour.
|
94
98
|
|
95
99
|
```rb
|
96
|
-
# lib/rodauth_app.rb
|
100
|
+
# app/lib/rodauth_app.rb
|
97
101
|
class RodauthApp < Rodauth::Rails::App
|
98
102
|
configure do
|
99
103
|
# authentication configuration
|
@@ -105,19 +109,6 @@ class RodauthApp < Rodauth::Rails::App
|
|
105
109
|
end
|
106
110
|
```
|
107
111
|
|
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
112
|
### Controller
|
122
113
|
|
123
114
|
Your Rodauth app will by default use `RodauthController` for view rendering
|
@@ -129,7 +120,7 @@ class RodauthController < ApplicationController
|
|
129
120
|
end
|
130
121
|
```
|
131
122
|
|
132
|
-
### Account
|
123
|
+
### Account model
|
133
124
|
|
134
125
|
Rodauth stores user accounts in the `accounts` table, so the generator will
|
135
126
|
also create an `Account` model for custom use.
|
@@ -142,8 +133,30 @@ end
|
|
142
133
|
|
143
134
|
## Getting started
|
144
135
|
|
145
|
-
|
146
|
-
|
136
|
+
First, let's see what routes our Rodauth middleware will handle:
|
137
|
+
|
138
|
+
```sh
|
139
|
+
$ rails rodauth:routes
|
140
|
+
```
|
141
|
+
```
|
142
|
+
Routes handled by RodauthApp:
|
143
|
+
|
144
|
+
/login rodauth.login_path
|
145
|
+
/create-account rodauth.create_account_path
|
146
|
+
/verify-account-resend rodauth.verify_account_resend_path
|
147
|
+
/verify-account rodauth.verify_account_path
|
148
|
+
/change-password rodauth.change_password_path
|
149
|
+
/change-login rodauth.change_login_path
|
150
|
+
/logout rodauth.logout_path
|
151
|
+
/remember rodauth.remember_path
|
152
|
+
/reset-password-request rodauth.reset_password_request_path
|
153
|
+
/reset-password rodauth.reset_password_path
|
154
|
+
/verify-login-change rodauth.verify_login_change_path
|
155
|
+
/close-account rodauth.close_account_path
|
156
|
+
```
|
157
|
+
|
158
|
+
We can use this information to add some basic authentication navigation links
|
159
|
+
to our home page:
|
147
160
|
|
148
161
|
```erb
|
149
162
|
<ul>
|
@@ -192,7 +205,7 @@ our app. We can do this in our Rodauth app's routing block, which helps keep
|
|
192
205
|
the authentication logic encapsulated:
|
193
206
|
|
194
207
|
```rb
|
195
|
-
# lib/rodauth_app.rb
|
208
|
+
# app/lib/rodauth_app.rb
|
196
209
|
class RodauthApp < Rodauth::Rails::App
|
197
210
|
# ...
|
198
211
|
route do |r|
|
@@ -273,7 +286,7 @@ $ rails generate rodauth:views --all
|
|
273
286
|
```
|
274
287
|
|
275
288
|
You can also tell the generator to create views into another directory (in this
|
276
|
-
case
|
289
|
+
case make sure to rename the Rodauth controller accordingly).
|
277
290
|
|
278
291
|
```sh
|
279
292
|
# generates views into app/views/authentication
|
@@ -308,11 +321,11 @@ end
|
|
308
321
|
|
309
322
|
### Mailer
|
310
323
|
|
311
|
-
Rodauth may send emails as part of
|
312
|
-
can be customized:
|
324
|
+
Depending on the features you've enabled, Rodauth may send emails as part of
|
325
|
+
the authentication flow. Most email settings can be customized:
|
313
326
|
|
314
327
|
```rb
|
315
|
-
# lib/rodauth_app.rb
|
328
|
+
# app/lib/rodauth_app.rb
|
316
329
|
class RodauthApp < Rodauth::Rails::App
|
317
330
|
# ...
|
318
331
|
configure do
|
@@ -357,7 +370,7 @@ your mailer. If you've enabled additional authentication features, make sure to
|
|
357
370
|
override their `send_*_email` methods as well.
|
358
371
|
|
359
372
|
```rb
|
360
|
-
# lib/rodauth_app.rb
|
373
|
+
# app/lib/rodauth_app.rb
|
361
374
|
class RodauthApp < Rodauth::Rails::App
|
362
375
|
# ...
|
363
376
|
configure do
|
@@ -393,6 +406,56 @@ class RodauthApp < Rodauth::Rails::App
|
|
393
406
|
end
|
394
407
|
```
|
395
408
|
|
409
|
+
### Migrations
|
410
|
+
|
411
|
+
The install generator will have created some default tables, but you can use
|
412
|
+
the migration generator to create tables for any additional Rodauth features:
|
413
|
+
|
414
|
+
```
|
415
|
+
$ rails generate rodauth:migration otp sms_codes recovery_codes
|
416
|
+
```
|
417
|
+
```rb
|
418
|
+
# db/migration/*_create_rodauth_otp_sms_codes_recovery_codes.rb
|
419
|
+
class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
420
|
+
def change
|
421
|
+
create_table :account_otp_keys do |t| ... end
|
422
|
+
create_table :account_sms_codes do |t| ... end
|
423
|
+
create_table :account_recovery_codes do |t| ... end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
```
|
427
|
+
|
428
|
+
### JSON API
|
429
|
+
|
430
|
+
JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
|
431
|
+
to add the [JWT gem] to your Gemfile:
|
432
|
+
|
433
|
+
```rb
|
434
|
+
gem "jwt"
|
435
|
+
```
|
436
|
+
|
437
|
+
The following configuration will enable the Rodauth endpoints to be accessed
|
438
|
+
via JSON requests (in addition to HTML requests):
|
439
|
+
|
440
|
+
```rb
|
441
|
+
# app/lib/rodauth_app.rb
|
442
|
+
class RodauthApp < Rodauth::Rails::App
|
443
|
+
configure(json: true) do
|
444
|
+
# ...
|
445
|
+
enable :jwt
|
446
|
+
jwt_secret "...your secret key..."
|
447
|
+
# ...
|
448
|
+
end
|
449
|
+
end
|
450
|
+
```
|
451
|
+
|
452
|
+
If you want the endpoints to be only accessible via JSON requests, or if your
|
453
|
+
Rails app is in API-only mode, instead of `json: true` pass `json: :only` to
|
454
|
+
the configure method.
|
455
|
+
|
456
|
+
Make sure to store the `jwt_secret` in a secure place, such as Rails
|
457
|
+
credentials or environment variables.
|
458
|
+
|
396
459
|
## How it works
|
397
460
|
|
398
461
|
### Middleware
|
@@ -498,20 +561,6 @@ Rodauth::Rails.configure do |config|
|
|
498
561
|
end
|
499
562
|
```
|
500
563
|
|
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
564
|
## Testing
|
516
565
|
|
517
566
|
If you're writing system tests, it's generally better to go through the actual
|
@@ -579,6 +628,26 @@ disables the use of database functions, though you can always turn it back on.
|
|
579
628
|
use_database_authentication_functions? true
|
580
629
|
```
|
581
630
|
|
631
|
+
To create the database functions, pass the Sequel database object into the
|
632
|
+
Rodauth method for creating database functions:
|
633
|
+
|
634
|
+
```rb
|
635
|
+
# db/migrate/*_create_rodauth_database_functions.rb
|
636
|
+
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
637
|
+
def up
|
638
|
+
# ...
|
639
|
+
Rodauth.create_database_authentication_functions(DB)
|
640
|
+
# ...
|
641
|
+
end
|
642
|
+
|
643
|
+
def down
|
644
|
+
# ...
|
645
|
+
Rodauth.drop_database_authentication_functions(DB)
|
646
|
+
# ...
|
647
|
+
end
|
648
|
+
end
|
649
|
+
```
|
650
|
+
|
582
651
|
### Account statuses
|
583
652
|
|
584
653
|
The recommended [Rodauth migration] stores possible account status values in a
|
@@ -634,6 +703,7 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
|
|
634
703
|
[rendering views outside of controllers]: https://blog.bigbinary.com/2016/01/08/rendering-views-outside-of-controllers-in-rails-5.html
|
635
704
|
[feature documentation]: http://rodauth.jeremyevans.net/documentation.html
|
636
705
|
[JWT feature]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
706
|
+
[JWT gem]: https://github.com/jwt/ruby-jwt
|
637
707
|
[Bootstrap]: https://getbootstrap.com/
|
638
708
|
[Roda]: http://roda.jeremyevans.net/
|
639
709
|
[HMAC]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require "rails/generators/base"
|
2
2
|
require "rails/generators/active_record/migration"
|
3
|
+
require "generators/rodauth/migration_helpers"
|
4
|
+
require "securerandom"
|
3
5
|
|
4
6
|
module Rodauth
|
5
7
|
module Rails
|
6
8
|
module Generators
|
7
9
|
class InstallGenerator < ::Rails::Generators::Base
|
8
10
|
include ::ActiveRecord::Generators::Migration
|
11
|
+
include MigrationHelpers
|
9
12
|
|
10
13
|
source_root "#{__dir__}/templates"
|
11
14
|
namespace "rodauth:install"
|
@@ -13,7 +16,7 @@ module Rodauth
|
|
13
16
|
def create_rodauth_migration
|
14
17
|
return unless defined?(ActiveRecord::Base)
|
15
18
|
|
16
|
-
migration_template "db/migrate/create_rodauth.rb"
|
19
|
+
migration_template "db/migrate/create_rodauth.rb"
|
17
20
|
end
|
18
21
|
|
19
22
|
def create_rodauth_initializer
|
@@ -22,17 +25,18 @@ module Rodauth
|
|
22
25
|
|
23
26
|
def create_sequel_initializer
|
24
27
|
return unless defined?(ActiveRecord::Base)
|
25
|
-
return unless %w[postgresql mysql2 sqlite3].include?(activerecord_adapter)
|
26
28
|
return if defined?(Sequel) && !Sequel::DATABASES.empty?
|
27
29
|
|
28
30
|
template "config/initializers/sequel.rb"
|
29
31
|
end
|
30
32
|
|
31
33
|
def create_rodauth_app
|
32
|
-
template "lib/rodauth_app.rb"
|
34
|
+
template "app/lib/rodauth_app.rb"
|
33
35
|
end
|
34
36
|
|
35
37
|
def create_rodauth_controller
|
38
|
+
return if api_only?
|
39
|
+
|
36
40
|
template "app/controllers/rodauth_controller.rb"
|
37
41
|
end
|
38
42
|
|
@@ -44,31 +48,44 @@ module Rodauth
|
|
44
48
|
|
45
49
|
private
|
46
50
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
51
|
+
def sequel_uri_scheme
|
52
|
+
if RUBY_ENGINE == "jruby"
|
53
|
+
"jdbc:#{sequel_jdbc_subadapter}"
|
54
|
+
else
|
55
|
+
sequel_adapter
|
56
|
+
end
|
50
57
|
end
|
51
58
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
59
|
+
def sequel_adapter
|
60
|
+
case activerecord_adapter
|
61
|
+
when "sqlite3" then "sqlite"
|
62
|
+
when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
|
63
|
+
when "sqlserver" then "tinytds" # https://github.com/rails-sqlserver/activerecord-sqlserver-adapter
|
64
|
+
else
|
65
|
+
activerecord_adapter
|
55
66
|
end
|
56
67
|
end
|
57
68
|
|
58
|
-
def
|
69
|
+
def sequel_jdbc_subadapter
|
59
70
|
case activerecord_adapter
|
60
|
-
when "
|
61
|
-
when "
|
62
|
-
when "
|
71
|
+
when "sqlite3" then "sqlite"
|
72
|
+
when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
|
73
|
+
when "sqlserver" then "mssql"
|
74
|
+
else
|
75
|
+
activerecord_adapter
|
63
76
|
end
|
64
77
|
end
|
65
78
|
|
66
|
-
def
|
67
|
-
|
79
|
+
def api_only?
|
80
|
+
return unless ::Rails.gem_version >= Gem::Version.new("5.0")
|
81
|
+
|
82
|
+
::Rails.application.config.api_only
|
68
83
|
end
|
69
84
|
|
70
|
-
def
|
71
|
-
|
85
|
+
def migration_features
|
86
|
+
features = [:base, :reset_password, :verify_account, :verify_login_change]
|
87
|
+
features << :remember unless api_only?
|
88
|
+
features
|
72
89
|
end
|
73
90
|
end
|
74
91
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the active sessions feature
|
2
|
+
create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
|
3
|
+
t.references :account, foreign_key: true<%= primary_key_type(:type) %>
|
4
|
+
t.string :session_id
|
5
|
+
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
6
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Used by the audit logging feature
|
2
|
+
create_table :account_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
|
+
t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
5
|
+
t.text :message, null: false
|
6
|
+
<% case activerecord_adapter -%>
|
7
|
+
<% when "postgresql" -%>
|
8
|
+
t.jsonb :metadata
|
9
|
+
<% when "sqlite3", "mysql2" -%>
|
10
|
+
t.json :metadata
|
11
|
+
<% else -%>
|
12
|
+
t.string :metadata
|
13
|
+
<% end -%>
|
14
|
+
t.index [:account_id, :at], name: "audit_account_at_idx"
|
15
|
+
t.index :at, name: "audit_at_idx"
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% if activerecord_adapter == "postgresql" -%>
|
2
|
+
enable_extension "citext"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
create_table :accounts<%= primary_key_type %> do |t|
|
6
|
+
<% case activerecord_adapter -%>
|
7
|
+
<% when "postgresql" -%>
|
8
|
+
t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
|
9
|
+
<% else -%>
|
10
|
+
t.string :email, null: false, index: { unique: true }
|
11
|
+
<% end -%>
|
12
|
+
t.string :status, null: false, default: "verified"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Used if storing password hashes in a separate table (default)
|
16
|
+
create_table :account_password_hashes<%= primary_key_type %> do |t|
|
17
|
+
t.foreign_key :accounts, column: :id
|
18
|
+
t.string :password_hash, null: false
|
19
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the email auth feature
|
2
|
+
create_table :account_email_auth_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the jwt refresh feature
|
2
|
+
create_table :account_jwt_refresh_keys<%= primary_key_type %> do |t|
|
3
|
+
t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.index :account_id, name: "account_jwt_rk_account_id_idx"
|
7
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Used by the lockout feature
|
2
|
+
create_table :account_login_failures<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.integer :number, null: false, default: 1
|
5
|
+
end
|
6
|
+
create_table :account_lockouts<%= primary_key_type %> do |t|
|
7
|
+
t.foreign_key :accounts, column: :id
|
8
|
+
t.string :key, null: false
|
9
|
+
t.datetime :deadline, null: false
|
10
|
+
t.datetime :email_last_sent
|
11
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the otp feature
|
2
|
+
create_table :account_otp_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.integer :num_failures, null: false, default: 0
|
6
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the password reset feature
|
2
|
+
create_table :account_password_reset_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the sms codes feature
|
2
|
+
create_table :account_sms_codes<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :phone_number, null: false
|
5
|
+
t.integer :num_failures
|
6
|
+
t.string :code
|
7
|
+
t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the account verification feature
|
2
|
+
create_table :account_verification_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Used by the webauthn feature
|
2
|
+
create_table :account_webauthn_user_ids<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :webauthn_id, null: false
|
5
|
+
end
|
6
|
+
create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
|
7
|
+
t.references :account, foreign_key: true<%= primary_key_type(:type) %>
|
8
|
+
t.string :webauthn_id
|
9
|
+
t.string :public_key, null: false
|
10
|
+
t.integer :sign_count, null: false
|
11
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
12
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
require "rails/generators/active_record/migration"
|
3
|
+
require "generators/rodauth/migration_helpers"
|
4
|
+
|
5
|
+
module Rodauth
|
6
|
+
module Rails
|
7
|
+
module Generators
|
8
|
+
class MigrationGenerator < ::Rails::Generators::Base
|
9
|
+
include ::ActiveRecord::Generators::Migration
|
10
|
+
include MigrationHelpers
|
11
|
+
|
12
|
+
source_root "#{__dir__}/templates"
|
13
|
+
namespace "rodauth:migration"
|
14
|
+
|
15
|
+
argument :features, optional: true, type: :array,
|
16
|
+
desc: "Rodauth features to create tables for (otp, sms_codes, single_session, account_expiration etc.)",
|
17
|
+
default: %w[]
|
18
|
+
|
19
|
+
def create_rodauth_migration
|
20
|
+
return unless defined?(ActiveRecord::Base)
|
21
|
+
return if features.empty?
|
22
|
+
|
23
|
+
migration_template "db/migrate/create_rodauth.rb", "create_rodauth_#{features.join("_")}.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
def migration_features
|
27
|
+
features
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
module Rails
|
5
|
+
module Generators
|
6
|
+
module MigrationHelpers
|
7
|
+
attr_reader :migration_class_name
|
8
|
+
|
9
|
+
def migration_template(source, destination = File.basename(source))
|
10
|
+
@migration_class_name = destination.chomp(".rb").camelize
|
11
|
+
|
12
|
+
super source, File.join(db_migrate_path, destination)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def migration_content
|
18
|
+
migration_features
|
19
|
+
.select { |feature| File.exist?("#{__dir__}/migration/#{feature}.erb") }
|
20
|
+
.map { |feature| File.read("#{__dir__}/migration/#{feature}.erb") }
|
21
|
+
.map { |content| erb_eval(content) }
|
22
|
+
.join("\n")
|
23
|
+
.indent(4)
|
24
|
+
end
|
25
|
+
|
26
|
+
def activerecord_adapter
|
27
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
28
|
+
ActiveRecord::Base.connection_db_config.adapter
|
29
|
+
else
|
30
|
+
ActiveRecord::Base.connection_config.fetch(:adapter)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def migration_version
|
35
|
+
return unless ActiveRecord.version >= Gem::Version.new("5.0")
|
36
|
+
|
37
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
38
|
+
end
|
39
|
+
|
40
|
+
def db_migrate_path
|
41
|
+
return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
|
42
|
+
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def primary_key_type(key = :id)
|
47
|
+
generators = ::Rails.application.config.generators
|
48
|
+
column_type = generators.options[:active_record][:primary_key_type]
|
49
|
+
|
50
|
+
return unless column_type
|
51
|
+
|
52
|
+
if key
|
53
|
+
", #{key}: :#{column_type}"
|
54
|
+
else
|
55
|
+
column_type
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def erb_eval(content)
|
60
|
+
if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
|
61
|
+
ERB.new(content, trim_mode: "-").result(binding)
|
62
|
+
else
|
63
|
+
ERB.new(content, 0, "-").result(binding)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class RodauthApp < Rodauth::Rails::App
|
2
|
-
configure do
|
2
|
+
configure<%= " json: :only" if api_only? %> do
|
3
3
|
# List of authentication features that are loaded.
|
4
4
|
enable :create_account, :verify_account, :verify_account_grace_period,
|
5
|
-
:login, :
|
5
|
+
:login, :logout, <%= api_only? ? ":jwt" : ":remember" %>,
|
6
6
|
:reset_password, :change_password, :change_password_notify,
|
7
7
|
:change_login, :verify_login_change,
|
8
8
|
:close_account
|
@@ -11,9 +11,15 @@ class RodauthApp < Rodauth::Rails::App
|
|
11
11
|
# http://rodauth.jeremyevans.net/documentation.html
|
12
12
|
|
13
13
|
# ==> General
|
14
|
+
# The secret key used for hashing public-facing tokens for various features.
|
15
|
+
# Defaults to Rails `secret_key_base`, but you can use your own secret key.
|
16
|
+
# hmac_secret "<%= SecureRandom.hex(64) %>"
|
17
|
+
|
18
|
+
<% unless api_only? -%>
|
14
19
|
# Specify the controller used for view rendering and CSRF verification.
|
15
20
|
rails_controller { RodauthController }
|
16
21
|
|
22
|
+
<% end -%>
|
17
23
|
# Store account status in a text column.
|
18
24
|
account_status_column :status
|
19
25
|
account_unverified_status_value "unverified"
|
@@ -38,6 +44,18 @@ class RodauthApp < Rodauth::Rails::App
|
|
38
44
|
|
39
45
|
# Redirect to the app from login and registration pages if already logged in.
|
40
46
|
# already_logged_in { redirect login_redirect }
|
47
|
+
<% if api_only? -%>
|
48
|
+
|
49
|
+
# ==> JWT
|
50
|
+
# Set JWT secret, which is used to cryptographically protect the token.
|
51
|
+
jwt_secret "<%= SecureRandom.hex(64) %>"
|
52
|
+
|
53
|
+
# Don't require login confirmation param.
|
54
|
+
require_login_confirmation? false
|
55
|
+
|
56
|
+
# Don't require password confirmation param.
|
57
|
+
require_password_confirmation? false
|
58
|
+
<% end -%>
|
41
59
|
|
42
60
|
# ==> Emails
|
43
61
|
# Uncomment the lines below once you've imported mailer views.
|
@@ -75,10 +93,12 @@ class RodauthApp < Rodauth::Rails::App
|
|
75
93
|
# reset_password_email_body { "Click here to reset your password: #{reset_password_email_link}" }
|
76
94
|
|
77
95
|
# ==> Flash
|
96
|
+
<% unless api_only? -%>
|
78
97
|
# Match flash keys with ones already used in the Rails app.
|
79
98
|
# flash_notice_key :success # default is :notice
|
80
99
|
# flash_error_key :error # default is :alert
|
81
100
|
|
101
|
+
<% end -%>
|
82
102
|
# Override default flash messages.
|
83
103
|
# create_account_notice_flash "Your account has been created. Please verify your account by visiting the confirmation link sent to your email address."
|
84
104
|
# require_login_error_flash "Login is required for accessing this page"
|
@@ -93,6 +113,7 @@ class RodauthApp < Rodauth::Rails::App
|
|
93
113
|
|
94
114
|
# Change minimum number of password characters required when creating an account.
|
95
115
|
# password_minimum_length 8
|
116
|
+
<% unless api_only? -%>
|
96
117
|
|
97
118
|
# ==> Remember Feature
|
98
119
|
# Remember all logged in users.
|
@@ -103,6 +124,7 @@ class RodauthApp < Rodauth::Rails::App
|
|
103
124
|
|
104
125
|
# Extend user's remember period when remembered via a cookie
|
105
126
|
extend_remember_deadline? true
|
127
|
+
<% end -%>
|
106
128
|
|
107
129
|
# ==> Hooks
|
108
130
|
# Validate custom fields in the create account form.
|
@@ -147,8 +169,10 @@ class RodauthApp < Rodauth::Rails::App
|
|
147
169
|
# end
|
148
170
|
|
149
171
|
route do |r|
|
172
|
+
<% unless api_only? -%>
|
150
173
|
rodauth.load_memory # autologin remembered users
|
151
174
|
|
175
|
+
<% end -%>
|
152
176
|
r.rodauth # route rodauth requests
|
153
177
|
|
154
178
|
# ==> Authenticating Requests
|
@@ -1,8 +1,4 @@
|
|
1
1
|
require "sequel/core"
|
2
2
|
|
3
3
|
# initialize Sequel and have it reuse Active Record's database connection
|
4
|
-
|
5
|
-
DB = Sequel.connect("jdbc:<%= sequel_adapter %>://", extensions: :activerecord_connection)
|
6
|
-
<% else -%>
|
7
|
-
DB = Sequel.<%= sequel_adapter %>(extensions: :activerecord_connection)
|
8
|
-
<% end -%>
|
4
|
+
DB = Sequel.connect("<%= sequel_uri_scheme %>://", extensions: :activerecord_connection)
|
@@ -1,170 +1,5 @@
|
|
1
|
-
class
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
|
4
|
-
enable_extension "citext"
|
5
|
-
|
6
|
-
<% end -%>
|
7
|
-
create_table :accounts do |t|
|
8
|
-
<% case activerecord_adapter -%>
|
9
|
-
<% when "postgresql" -%>
|
10
|
-
t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
|
11
|
-
<% else -%>
|
12
|
-
t.string :email, null: false, index: { unique: true }
|
13
|
-
<% end -%>
|
14
|
-
t.string :status, null: false, default: "verified"
|
15
|
-
end
|
16
|
-
|
17
|
-
# Used if storing password hashes in a separate table (default)
|
18
|
-
create_table :account_password_hashes do |t|
|
19
|
-
t.foreign_key :accounts, column: :id
|
20
|
-
t.string :password_hash, null: false
|
21
|
-
end
|
22
|
-
|
23
|
-
# Used by the password reset feature
|
24
|
-
create_table :account_password_reset_keys do |t|
|
25
|
-
t.foreign_key :accounts, column: :id
|
26
|
-
t.string :key, null: false
|
27
|
-
t.datetime :deadline, null: false
|
28
|
-
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
29
|
-
end
|
30
|
-
|
31
|
-
# Used by the account verification feature
|
32
|
-
create_table :account_verification_keys do |t|
|
33
|
-
t.foreign_key :accounts, column: :id
|
34
|
-
t.string :key, null: false
|
35
|
-
t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
36
|
-
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Used by the verify login change feature
|
40
|
-
create_table :account_login_change_keys do |t|
|
41
|
-
t.foreign_key :accounts, column: :id
|
42
|
-
t.string :key, null: false
|
43
|
-
t.string :login, null: false
|
44
|
-
t.datetime :deadline, null: false
|
45
|
-
end
|
46
|
-
|
47
|
-
# Used by the remember me feature
|
48
|
-
create_table :account_remember_keys do |t|
|
49
|
-
t.foreign_key :accounts, column: :id
|
50
|
-
t.string :key, null: false
|
51
|
-
t.datetime :deadline, null: false
|
52
|
-
end
|
53
|
-
|
54
|
-
# # Used by the audit logging feature
|
55
|
-
# create_table :account_authentication_audit_logs do |t|
|
56
|
-
# t.references :account, foreign_key: true, null: false
|
57
|
-
# t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
58
|
-
# t.text :message, null: false
|
59
|
-
<% case activerecord_adapter -%>
|
60
|
-
<% when "postgresql" -%>
|
61
|
-
# t.jsonb :metadata
|
62
|
-
<% when "sqlite3", "mysql2" -%>
|
63
|
-
# t.json :metadata
|
64
|
-
<% else -%>
|
65
|
-
# t.string :metadata
|
66
|
-
<% end -%>
|
67
|
-
# t.index [:account_id, :at], name: "audit_account_at_idx"
|
68
|
-
# t.index :at, name: "audit_at_idx"
|
69
|
-
# end
|
70
|
-
|
71
|
-
# # Used by the jwt refresh feature
|
72
|
-
# create_table :account_jwt_refresh_keys do |t|
|
73
|
-
# t.references :account, foreign_key: true, null: false
|
74
|
-
# t.string :key, null: false
|
75
|
-
# t.datetime :deadline, null: false
|
76
|
-
# t.index :account_id, name: "account_jwt_rk_account_id_idx"
|
77
|
-
# end
|
78
|
-
|
79
|
-
# # Used by the disallow_password_reuse feature
|
80
|
-
# create_table :account_previous_password_hashes do |t|
|
81
|
-
# t.references :account, foreign_key: true
|
82
|
-
# t.string :password_hash, null: false
|
83
|
-
# end
|
84
|
-
|
85
|
-
# # Used by the lockout feature
|
86
|
-
# create_table :account_login_failures do |t|
|
87
|
-
# t.foreign_key :accounts, column: :id
|
88
|
-
# t.integer :number, null: false, default: 1
|
89
|
-
# end
|
90
|
-
# create_table :account_lockouts do |t|
|
91
|
-
# t.foreign_key :accounts, column: :id
|
92
|
-
# t.string :key, null: false
|
93
|
-
# t.datetime :deadline, null: false
|
94
|
-
# t.datetime :email_last_sent
|
95
|
-
# end
|
96
|
-
|
97
|
-
# # Used by the email auth feature
|
98
|
-
# create_table :account_email_auth_keys do |t|
|
99
|
-
# t.foreign_key :accounts, column: :id
|
100
|
-
# t.string :key, null: false
|
101
|
-
# t.datetime :deadline, null: false
|
102
|
-
# t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
103
|
-
# end
|
104
|
-
|
105
|
-
# # Used by the password expiration feature
|
106
|
-
# create_table :account_password_change_times do |t|
|
107
|
-
# t.foreign_key :accounts, column: :id
|
108
|
-
# t.datetime :changed_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
109
|
-
# end
|
110
|
-
|
111
|
-
# # Used by the account expiration feature
|
112
|
-
# create_table :account_activity_times do |t|
|
113
|
-
# t.foreign_key :accounts, column: :id
|
114
|
-
# t.datetime :last_activity_at, null: false
|
115
|
-
# t.datetime :last_login_at, null: false
|
116
|
-
# t.datetime :expired_at
|
117
|
-
# end
|
118
|
-
|
119
|
-
# # Used by the single session feature
|
120
|
-
# create_table :account_session_keys do |t|
|
121
|
-
# t.foreign_key :accounts, column: :id
|
122
|
-
# t.string :key, null: false
|
123
|
-
# end
|
124
|
-
|
125
|
-
# # Used by the active sessions feature
|
126
|
-
# create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
|
127
|
-
# t.references :account, foreign_key: true
|
128
|
-
# t.string :session_id
|
129
|
-
# t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
130
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
131
|
-
# end
|
132
|
-
|
133
|
-
# # Used by the webauthn feature
|
134
|
-
# create_table :account_webauthn_user_ids do |t|
|
135
|
-
# t.foreign_key :accounts, column: :id
|
136
|
-
# t.string :webauthn_id, null: false
|
137
|
-
# end
|
138
|
-
# create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
|
139
|
-
# t.references :account, foreign_key: true
|
140
|
-
# t.string :webauthn_id
|
141
|
-
# t.string :public_key, null: false
|
142
|
-
# t.integer :sign_count, null: false
|
143
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
144
|
-
# end
|
145
|
-
|
146
|
-
# # Used by the otp feature
|
147
|
-
# create_table :account_otp_keys do |t|
|
148
|
-
# t.foreign_key :accounts, column: :id
|
149
|
-
# t.string :key, null: false
|
150
|
-
# t.integer :num_failures, null: false, default: 0
|
151
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
152
|
-
# end
|
153
|
-
|
154
|
-
# # Used by the recovery codes feature
|
155
|
-
# create_table :account_recovery_codes, primary_key: [:id, :code] do |t|
|
156
|
-
# t.integer :id
|
157
|
-
# t.foreign_key :accounts, column: :id
|
158
|
-
# t.string :code
|
159
|
-
# end
|
160
|
-
|
161
|
-
# # Used by the sms codes feature
|
162
|
-
# create_table :account_sms_codes do |t|
|
163
|
-
# t.foreign_key :accounts, column: :id
|
164
|
-
# t.string :phone_number, null: false
|
165
|
-
# t.integer :num_failures
|
166
|
-
# t.string :code
|
167
|
-
# t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
168
|
-
# end
|
3
|
+
<%= migration_content -%>
|
169
4
|
end
|
170
5
|
end
|
data/lib/rodauth/rails.rb
CHANGED
data/lib/rodauth/rails/app.rb
CHANGED
@@ -4,15 +4,16 @@ module Rodauth
|
|
4
4
|
module Rails
|
5
5
|
# The superclass for creating a Rodauth middleware.
|
6
6
|
class App < Roda
|
7
|
-
require "rodauth/rails/app/flash"
|
8
|
-
|
9
7
|
plugin :middleware
|
10
8
|
plugin :hooks
|
11
9
|
plugin :render, layout: false
|
12
10
|
|
13
|
-
plugin Flash
|
14
|
-
|
15
11
|
def self.configure(name = nil, **options, &block)
|
12
|
+
unless options[:json] == :only
|
13
|
+
require "rodauth/rails/app/flash"
|
14
|
+
plugin Flash
|
15
|
+
end
|
16
|
+
|
16
17
|
plugin :rodauth, name: name, csrf: false, flash: false, **options do
|
17
18
|
# load the Rails integration
|
18
19
|
enable :rails
|
@@ -62,9 +62,13 @@ module Rodauth
|
|
62
62
|
|
63
63
|
# Calls the Rails renderer, returning nil if a template is missing.
|
64
64
|
def rails_render(*args)
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
return if only_json?
|
66
|
+
|
67
|
+
begin
|
68
|
+
rails_controller_instance.render_to_string(*args)
|
69
|
+
rescue ActionView::MissingTemplate
|
70
|
+
nil
|
71
|
+
end
|
68
72
|
end
|
69
73
|
|
70
74
|
# Hidden tag with Rails CSRF token inserted into Rodauth templates.
|
@@ -92,7 +96,7 @@ module Rodauth
|
|
92
96
|
request = ActionDispatch::Request.new(scope.env)
|
93
97
|
instance = rails_controller.new
|
94
98
|
|
95
|
-
if ActionPack.version >= Gem::Version.new("5.0
|
99
|
+
if ActionPack.version >= Gem::Version.new("5.0")
|
96
100
|
instance.set_request! request
|
97
101
|
instance.set_response! rails_controller.make_response!(request)
|
98
102
|
else
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "rodauth/rails/middleware"
|
2
2
|
require "rodauth/rails/controller_methods"
|
3
3
|
|
4
|
+
require "rails"
|
5
|
+
|
4
6
|
module Rodauth
|
5
7
|
module Rails
|
6
8
|
class Railtie < ::Rails::Railtie
|
@@ -13,6 +15,15 @@ module Rodauth
|
|
13
15
|
include Rodauth::Rails::ControllerMethods
|
14
16
|
end
|
15
17
|
end
|
18
|
+
|
19
|
+
initializer "rodauth.test" do
|
20
|
+
# Rodauth uses RACK_ENV to set the default bcrypt hash cost
|
21
|
+
ENV["RACK_ENV"] = "test" if ::Rails.env.test?
|
22
|
+
end
|
23
|
+
|
24
|
+
rake_tasks do
|
25
|
+
load "rodauth/rails/tasks.rake"
|
26
|
+
end
|
16
27
|
end
|
17
28
|
end
|
18
29
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
namespace :rodauth do
|
2
|
+
task routes: :environment do
|
3
|
+
app = Rodauth::Rails.app
|
4
|
+
|
5
|
+
puts "Routes handled by #{app}:"
|
6
|
+
puts
|
7
|
+
|
8
|
+
app.opts[:rodauths].each do |rodauth_name, rodauth_class|
|
9
|
+
route_names = rodauth_class.routes
|
10
|
+
.map { |handle_method| handle_method.to_s.sub(/\Ahandle_/, "") }
|
11
|
+
.uniq
|
12
|
+
|
13
|
+
rodauth = rodauth_class.allocate
|
14
|
+
|
15
|
+
routes = route_names.map do |name|
|
16
|
+
[
|
17
|
+
rodauth.public_send(:"#{name}_path"),
|
18
|
+
"rodauth#{rodauth_name && "(:#{rodauth_name})"}.#{name}_path",
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
padding = routes.map { |path, _| path.length }.max
|
23
|
+
|
24
|
+
route_lines = routes.map do |path, code|
|
25
|
+
"#{path.ljust(padding)} #{code}"
|
26
|
+
end
|
27
|
+
|
28
|
+
puts " #{route_lines.join("\n ")}"
|
29
|
+
puts
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/rodauth-rails.gemspec
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require_relative "lib/rodauth/rails/version"
|
2
|
+
|
1
3
|
Gem::Specification.new do |spec|
|
2
4
|
spec.name = "rodauth-rails"
|
3
|
-
spec.version =
|
5
|
+
spec.version = Rodauth::Rails::VERSION
|
4
6
|
spec.authors = ["Janko Marohnić"]
|
5
7
|
spec.email = ["janko.marohnic@gmail.com"]
|
6
8
|
|
@@ -9,14 +11,14 @@ Gem::Specification.new do |spec|
|
|
9
11
|
spec.homepage = "https://github.com/janko/rodauth-rails"
|
10
12
|
spec.license = "MIT"
|
11
13
|
|
12
|
-
spec.required_ruby_version = ">= 2.
|
14
|
+
spec.required_ruby_version = ">= 2.3"
|
13
15
|
|
14
16
|
spec.files = Dir["README.md", "LICENSE.txt", "CHANGELOG.md", "lib/**/*", "*.gemspec"]
|
15
17
|
spec.require_paths = ["lib"]
|
16
18
|
|
17
19
|
spec.add_dependency "railties", ">= 4.2", "< 7"
|
18
20
|
spec.add_dependency "rodauth", "~> 2.1"
|
19
|
-
spec.add_dependency "sequel-activerecord_connection", "~>
|
21
|
+
spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
|
20
22
|
spec.add_dependency "tilt"
|
21
23
|
spec.add_dependency "bcrypt"
|
22
24
|
end
|
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: 0.
|
4
|
+
version: 0.5.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: 2020-
|
11
|
+
date: 2020-11-16 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: '
|
53
|
+
version: '1.1'
|
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: '
|
60
|
+
version: '1.1'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: tilt
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,28 @@ files:
|
|
98
98
|
- README.md
|
99
99
|
- lib/generators/rodauth/install_generator.rb
|
100
100
|
- lib/generators/rodauth/mailer_generator.rb
|
101
|
+
- lib/generators/rodauth/migration/account_expiration.erb
|
102
|
+
- lib/generators/rodauth/migration/active_sessions.erb
|
103
|
+
- lib/generators/rodauth/migration/audit_logging.erb
|
104
|
+
- lib/generators/rodauth/migration/base.erb
|
105
|
+
- lib/generators/rodauth/migration/disallow_password_reuse.erb
|
106
|
+
- lib/generators/rodauth/migration/email_auth.erb
|
107
|
+
- lib/generators/rodauth/migration/jwt_refresh.erb
|
108
|
+
- lib/generators/rodauth/migration/lockout.erb
|
109
|
+
- lib/generators/rodauth/migration/otp.erb
|
110
|
+
- lib/generators/rodauth/migration/password_expiration.erb
|
111
|
+
- lib/generators/rodauth/migration/recovery_codes.erb
|
112
|
+
- lib/generators/rodauth/migration/remember.erb
|
113
|
+
- lib/generators/rodauth/migration/reset_password.erb
|
114
|
+
- lib/generators/rodauth/migration/single_session.erb
|
115
|
+
- lib/generators/rodauth/migration/sms_codes.erb
|
116
|
+
- lib/generators/rodauth/migration/verify_account.erb
|
117
|
+
- lib/generators/rodauth/migration/verify_login_change.erb
|
118
|
+
- lib/generators/rodauth/migration/webauthn.erb
|
119
|
+
- lib/generators/rodauth/migration_generator.rb
|
120
|
+
- lib/generators/rodauth/migration_helpers.rb
|
101
121
|
- lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb
|
122
|
+
- lib/generators/rodauth/templates/app/lib/rodauth_app.rb
|
102
123
|
- lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb
|
103
124
|
- lib/generators/rodauth/templates/app/models/account.rb
|
104
125
|
- lib/generators/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb
|
@@ -164,7 +185,6 @@ files:
|
|
164
185
|
- lib/generators/rodauth/templates/config/initializers/rodauth.rb
|
165
186
|
- lib/generators/rodauth/templates/config/initializers/sequel.rb
|
166
187
|
- lib/generators/rodauth/templates/db/migrate/create_rodauth.rb
|
167
|
-
- lib/generators/rodauth/templates/lib/rodauth_app.rb
|
168
188
|
- lib/generators/rodauth/views_generator.rb
|
169
189
|
- lib/rodauth-rails.rb
|
170
190
|
- lib/rodauth/features/rails.rb
|
@@ -175,6 +195,8 @@ files:
|
|
175
195
|
- lib/rodauth/rails/feature.rb
|
176
196
|
- lib/rodauth/rails/middleware.rb
|
177
197
|
- lib/rodauth/rails/railtie.rb
|
198
|
+
- lib/rodauth/rails/tasks.rake
|
199
|
+
- lib/rodauth/rails/version.rb
|
178
200
|
- rodauth-rails.gemspec
|
179
201
|
homepage: https://github.com/janko/rodauth-rails
|
180
202
|
licenses:
|
@@ -188,14 +210,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
210
|
requirements:
|
189
211
|
- - ">="
|
190
212
|
- !ruby/object:Gem::Version
|
191
|
-
version: 2.
|
213
|
+
version: '2.3'
|
192
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
215
|
requirements:
|
194
216
|
- - ">="
|
195
217
|
- !ruby/object:Gem::Version
|
196
218
|
version: '0'
|
197
219
|
requirements: []
|
198
|
-
rubygems_version: 3.1.
|
220
|
+
rubygems_version: 3.1.4
|
199
221
|
signing_key:
|
200
222
|
specification_version: 4
|
201
223
|
summary: Provides Rails integration for Rodauth.
|