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