rodauth-rails 1.7.1 → 1.8.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 +18 -0
- data/README.md +50 -10
- data/lib/generators/rodauth/install_generator.rb +35 -34
- data/lib/generators/rodauth/migration/active_record/account_expiration.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/active_sessions.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/audit_logging.erb +3 -3
- data/lib/generators/rodauth/migration/active_record/base.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/disallow_password_reuse.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/email_auth.erb +2 -1
- data/lib/generators/rodauth/migration/active_record/jwt_refresh.erb +3 -3
- data/lib/generators/rodauth/migration/active_record/lockout.erb +4 -4
- data/lib/generators/rodauth/migration/active_record/otp.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/password_expiration.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/recovery_codes.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/remember.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/reset_password.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/single_session.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/sms_codes.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/verify_account.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/verify_login_change.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/webauthn.erb +4 -4
- data/lib/generators/rodauth/migration/sequel/account_expiration.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/active_sessions.erb +3 -3
- data/lib/generators/rodauth/migration/sequel/audit_logging.erb +3 -3
- data/lib/generators/rodauth/migration/sequel/base.erb +1 -1
- data/lib/generators/rodauth/migration/sequel/disallow_password_reuse.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/email_auth.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/jwt_refresh.erb +3 -3
- data/lib/generators/rodauth/migration/sequel/lockout.erb +4 -4
- data/lib/generators/rodauth/migration/sequel/otp.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/password_expiration.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/recovery_codes.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/remember.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/reset_password.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/single_session.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/sms_codes.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/verify_account.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/verify_login_change.erb +2 -2
- data/lib/generators/rodauth/migration/sequel/webauthn.erb +5 -5
- data/lib/generators/rodauth/migration_generator.rb +43 -1
- data/lib/generators/rodauth/templates/app/mailers/{rodauth_mailer.rb → rodauth_mailer.rb.tt} +8 -6
- data/lib/generators/rodauth/templates/app/misc/{rodauth_main.rb → rodauth_main.rb.tt} +69 -10
- data/lib/generators/rodauth/templates/app/models/{account.rb → account.rb.tt} +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +2 -2
- data/lib/generators/rodauth/templates/test/fixtures/{accounts.yml → accounts.yml.tt} +2 -2
- data/lib/rodauth/rails/app.rb +19 -0
- data/lib/rodauth/rails/feature/base.rb +0 -10
- data/lib/rodauth/rails/version.rb +1 -1
- data/rodauth-rails.gemspec +1 -1
- metadata +13 -14
- data/lib/generators/rodauth/templates/config/initializers/sequel.rb +0 -4
- /data/lib/generators/rodauth/templates/app/controllers/{rodauth_controller.rb → rodauth_controller.rb.tt} +0 -0
- /data/lib/generators/rodauth/templates/app/misc/{rodauth_app.rb → rodauth_app.rb.tt} +0 -0
- /data/lib/generators/rodauth/templates/config/initializers/{rodauth.rb → rodauth.rb.tt} +0 -0
- /data/lib/generators/rodauth/templates/db/migrate/{create_rodauth.rb → create_rodauth.rb.tt} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df597e01d85bea28254330ac00e288d569fe709744e11ade3ada370784034b6a
|
4
|
+
data.tar.gz: 2934d9ea6177fa55e383cfbcbfdca6b4b27a36a1afdb7c9971e918fbca76e604
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf30eabb2fb372e96caf39ceb0e01696dcc45003db00703fd4eaa127bba8378a0e76c4194b0f2161851df82a066f0147ed72cedea25429657a287734f76d4e49
|
7
|
+
data.tar.gz: 40f773856e54971d573995e7f6c11b9a67c42c881ce95e458739fc5a12151a954233b3e80339beff622b82e79bc5485fc6497f7dd90c09cfd42ed2ca1abe3912
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 1.8.0 (2023-02-25)
|
2
|
+
|
3
|
+
* Add table argument to `rodauth:install` generator (@janko)
|
4
|
+
|
5
|
+
* Add `--prefix` option to `rodauth:migration` generator for choosing table prefix (@janko)
|
6
|
+
|
7
|
+
* Add `--argon2` option to `rodauth:install` generator for configuring password hashing using Argon2 (@janko)
|
8
|
+
|
9
|
+
* Move generated Sequel setup from initializer into the Rodauth configuration for faster boot time (@janko)
|
10
|
+
|
11
|
+
* Use `email_to` and `email_from` Rodauth methods in generated mailer (@janko)
|
12
|
+
|
13
|
+
* Add missing foreign key constraint in `email_auth` Active Record migration (@janko)
|
14
|
+
|
15
|
+
* Correctly retrieve JSON request body when using Falcon (@janko)
|
16
|
+
|
17
|
+
* Render validation error correctly in generated `webauthn_remove` Tailwind template (@janko)
|
18
|
+
|
1
19
|
## 1.7.1 (2023-01-25)
|
2
20
|
|
3
21
|
* Make internal_request integration work on Rack 3.x (@janko)
|
data/README.md
CHANGED
@@ -70,7 +70,13 @@ Next, run the install generator:
|
|
70
70
|
$ rails generate rodauth:install
|
71
71
|
```
|
72
72
|
|
73
|
-
|
73
|
+
This will use the `accounts` table. If you want a different table name:
|
74
|
+
|
75
|
+
```sh
|
76
|
+
$ rails generate rodauth:install users
|
77
|
+
```
|
78
|
+
|
79
|
+
If you want Rodauth endpoints to be exposed via [JSON API]:
|
74
80
|
|
75
81
|
```sh
|
76
82
|
$ rails generate rodauth:install --json # regular authentication using the Rails session
|
@@ -79,6 +85,13 @@ $ rails generate rodauth:install --jwt # token authentication via the "Authoriza
|
|
79
85
|
$ bundle add jwt
|
80
86
|
```
|
81
87
|
|
88
|
+
To use Argon2 instead of bcrypt for password hashing:
|
89
|
+
|
90
|
+
```sh
|
91
|
+
$ rails generate rodauth:install --argon2
|
92
|
+
$ bundle add argon2
|
93
|
+
```
|
94
|
+
|
82
95
|
This generator will create a Rodauth app and configuration with common
|
83
96
|
authentication features enabled, a database migration with tables required by
|
84
97
|
those features, a mailer with default templates, and a few other files.
|
@@ -180,12 +193,9 @@ session will be reset.
|
|
180
193
|
|
181
194
|
#### Custom account model
|
182
195
|
|
183
|
-
The `#rails_account` method will try to infer the account model class from
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
However, if the model class cannot be inferred from the table name, you can
|
188
|
-
configure it manually:
|
196
|
+
The `#rails_account` method will try to infer the account model class from the
|
197
|
+
configured accounts table name. However, if the model class cannot be inferred
|
198
|
+
from the table name, you can configure it manually:
|
189
199
|
|
190
200
|
```rb
|
191
201
|
# app/misc/rodauth_main.rb
|
@@ -499,7 +509,7 @@ page][custom mailer worker] on how to set it up.
|
|
499
509
|
|
500
510
|
The install generator will create a migration for tables used by the Rodauth
|
501
511
|
features enabled by default. For any additional features, you can use the
|
502
|
-
migration generator
|
512
|
+
migration generator for creating the required tables:
|
503
513
|
|
504
514
|
```sh
|
505
515
|
$ rails generate rodauth:migration otp sms_codes recovery_codes
|
@@ -515,6 +525,30 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
|
515
525
|
end
|
516
526
|
```
|
517
527
|
|
528
|
+
#### Table prefix
|
529
|
+
|
530
|
+
If you're storing account records in a table other than `accounts`, you'll want
|
531
|
+
to specify the correct table prefix when generating new migrations:
|
532
|
+
|
533
|
+
```sh
|
534
|
+
$ rails generate rodauth:migration base active_sessions --prefix user
|
535
|
+
|
536
|
+
# Add the following to your Rodauth configuration:
|
537
|
+
#
|
538
|
+
# accounts_table :users
|
539
|
+
# active_sessions_table :user_active_session_keys
|
540
|
+
# active_sessions_account_id_column :user_id
|
541
|
+
```
|
542
|
+
```rb
|
543
|
+
# db/migration/*_create_rodauth_user_base_active_sessions.rb
|
544
|
+
class CreateRodauthUserBaseActiveSessions < ActiveRecord::Migration
|
545
|
+
def change
|
546
|
+
create_table :users do |t| ... end
|
547
|
+
create_table :user_active_session_keys do |t| ... end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
```
|
551
|
+
|
518
552
|
#### Custom migration name
|
519
553
|
|
520
554
|
You can change the default migration name:
|
@@ -1103,11 +1137,17 @@ require "rodauth/migrations"
|
|
1103
1137
|
|
1104
1138
|
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
1105
1139
|
def up
|
1106
|
-
Rodauth.create_database_authentication_functions(
|
1140
|
+
Rodauth.create_database_authentication_functions(db)
|
1107
1141
|
end
|
1108
1142
|
|
1109
1143
|
def down
|
1110
|
-
Rodauth.drop_database_authentication_functions(
|
1144
|
+
Rodauth.drop_database_authentication_functions(db)
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
private
|
1148
|
+
|
1149
|
+
def db
|
1150
|
+
RodauthMain.allocate.db
|
1111
1151
|
end
|
1112
1152
|
end
|
1113
1153
|
```
|
@@ -5,19 +5,13 @@ module Rodauth
|
|
5
5
|
module Rails
|
6
6
|
module Generators
|
7
7
|
class InstallGenerator < ::Rails::Generators::Base
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
SEQUEL_ADAPTERS = {
|
16
|
-
"sqlite3" => "sqlite",
|
17
|
-
"oracle_enhanced" => "oracle", # https://github.com/rsim/oracle-enhanced
|
18
|
-
"sqlserver" => "tinytds", # https://github.com/rails-sqlserver/activerecord-sqlserver-adapter
|
19
|
-
}
|
20
|
-
end
|
8
|
+
SEQUEL_ADAPTERS = {
|
9
|
+
"postgresql" => RUBY_ENGINE == "jruby" ? "postgresql" : "postgres",
|
10
|
+
"mysql2" => RUBY_ENGINE == "jruby" ? "mysql" : "mysql2",
|
11
|
+
"sqlite3" => "sqlite",
|
12
|
+
"oracle_enhanced" => "oracle",
|
13
|
+
"sqlserver" => RUBY_ENGINE == "jruby" ? "mssql" : "tinytds",
|
14
|
+
}
|
21
15
|
|
22
16
|
MAILER_VIEWS = %w[
|
23
17
|
email_auth
|
@@ -31,24 +25,23 @@ module Rodauth
|
|
31
25
|
source_root "#{__dir__}/templates"
|
32
26
|
namespace "rodauth:install"
|
33
27
|
|
28
|
+
argument :table, optional: true, type: :string, desc: "Name of the accounts table"
|
29
|
+
|
30
|
+
class_option :prefix, type: :string, desc: "Change name for account tables"
|
31
|
+
class_option :argon2, type: :boolean, desc: "Use Argon2 for password hashing"
|
34
32
|
class_option :json, type: :boolean, desc: "Configure JSON support"
|
35
33
|
class_option :jwt, type: :boolean, desc: "Configure JWT support"
|
36
34
|
|
37
|
-
def
|
38
|
-
invoke "rodauth:migration", migration_features,
|
35
|
+
def generate_rodauth_migration
|
36
|
+
invoke "rodauth:migration", migration_features,
|
37
|
+
name: "create_rodauth",
|
38
|
+
prefix: table_prefix
|
39
39
|
end
|
40
40
|
|
41
41
|
def create_rodauth_initializer
|
42
42
|
template "config/initializers/rodauth.rb"
|
43
43
|
end
|
44
44
|
|
45
|
-
def create_sequel_initializer
|
46
|
-
return unless defined?(ActiveRecord::Railtie)
|
47
|
-
return if defined?(Sequel) && !Sequel::DATABASES.empty?
|
48
|
-
|
49
|
-
template "config/initializers/sequel.rb"
|
50
|
-
end
|
51
|
-
|
52
45
|
def create_rodauth_app
|
53
46
|
template "app/misc/rodauth_app.rb"
|
54
47
|
template "app/misc/rodauth_main.rb"
|
@@ -59,7 +52,7 @@ module Rodauth
|
|
59
52
|
end
|
60
53
|
|
61
54
|
def create_account_model
|
62
|
-
template "app/models/account.rb"
|
55
|
+
template "app/models/account.rb", "app/models/#{table_prefix}.rb"
|
63
56
|
end
|
64
57
|
|
65
58
|
def create_mailer
|
@@ -73,13 +66,10 @@ module Rodauth
|
|
73
66
|
end
|
74
67
|
|
75
68
|
def create_fixtures
|
76
|
-
|
77
|
-
if
|
78
|
-
|
79
|
-
|
80
|
-
else
|
81
|
-
template "test/fixtures/accounts.yml", "test/fixtures/accounts.yml"
|
82
|
-
end
|
69
|
+
generator_options = ::Rails.application.config.generators.options
|
70
|
+
if generator_options[:test_unit][:fixture] && generator_options[:test_unit][:fixture_replacement].nil?
|
71
|
+
test_dir = generator_options[:rails][:test_framework] == :rspec ? "spec" : "test"
|
72
|
+
template "test/fixtures/accounts.yml", "#{test_dir}/fixtures/#{table_prefix.pluralize}.yml"
|
83
73
|
end
|
84
74
|
end
|
85
75
|
|
@@ -95,6 +85,10 @@ module Rodauth
|
|
95
85
|
features
|
96
86
|
end
|
97
87
|
|
88
|
+
def table_prefix
|
89
|
+
table&.underscore&.singularize || "account"
|
90
|
+
end
|
91
|
+
|
98
92
|
def json?
|
99
93
|
options[:json] || api_only? && session_store? && !options[:jwt]
|
100
94
|
end
|
@@ -103,6 +97,15 @@ module Rodauth
|
|
103
97
|
options[:jwt] || api_only? && !session_store? && !options[:json]
|
104
98
|
end
|
105
99
|
|
100
|
+
def argon2?
|
101
|
+
options[:argon2]
|
102
|
+
end
|
103
|
+
|
104
|
+
def sequel_activerecord_integration?
|
105
|
+
defined?(ActiveRecord::Railtie) &&
|
106
|
+
(!defined?(Sequel) || Sequel::DATABASES.empty?)
|
107
|
+
end
|
108
|
+
|
106
109
|
def session_store?
|
107
110
|
!!::Rails.application.config.session_store
|
108
111
|
end
|
@@ -111,10 +114,8 @@ module Rodauth
|
|
111
114
|
Rodauth::Rails.api_only?
|
112
115
|
end
|
113
116
|
|
114
|
-
def
|
115
|
-
|
116
|
-
scheme = "jdbc:#{scheme}" if RUBY_ENGINE == "jruby"
|
117
|
-
scheme
|
117
|
+
def sequel_adapter
|
118
|
+
SEQUEL_ADAPTERS[activerecord_adapter] || activerecord_adapter
|
118
119
|
end
|
119
120
|
|
120
121
|
def activerecord_adapter
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the account expiration feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_activity_times, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.datetime :last_activity_at, null: false
|
6
6
|
t.datetime :last_login_at, null: false
|
7
7
|
t.datetime :expired_at
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the active sessions feature
|
2
|
-
create_table
|
3
|
-
t.references
|
2
|
+
create_table :<%= table_prefix %>_active_session_keys, primary_key: [:<%= table_prefix %>_id, :session_id] do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true<%= primary_key_type(:type) %>
|
4
4
|
t.string :session_id
|
5
5
|
t.datetime :created_at, null: false, default: <%= current_timestamp %>
|
6
6
|
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the audit logging feature
|
2
|
-
create_table
|
3
|
-
t.references
|
2
|
+
create_table :<%= table_prefix %>_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
4
|
t.datetime :at, null: false, default: <%= current_timestamp %>
|
5
5
|
t.text :message, null: false
|
6
6
|
<% case activerecord_adapter -%>
|
@@ -11,6 +11,6 @@ create_table :account_authentication_audit_logs<%= primary_key_type %> do |t|
|
|
11
11
|
<% else -%>
|
12
12
|
t.string :metadata
|
13
13
|
<% end -%>
|
14
|
-
t.index [
|
14
|
+
t.index [:<%= table_prefix %>_id, :at], name: "audit_<%= table_prefix %>_at_idx"
|
15
15
|
t.index :at, name: "audit_at_idx"
|
16
16
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
enable_extension "citext"
|
3
3
|
|
4
4
|
<% end -%>
|
5
|
-
create_table
|
5
|
+
create_table :<%= table_prefix.pluralize %><%= primary_key_type %> do |t|
|
6
6
|
t.integer :status, null: false, default: 1
|
7
7
|
<% case activerecord_adapter -%>
|
8
8
|
<% when "postgresql" -%>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Used by the disallow password reuse feature
|
2
|
-
create_table
|
3
|
-
t.references
|
2
|
+
create_table :<%= table_prefix %>_previous_password_hashes do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true<%= primary_key_type(:type) %>
|
4
4
|
t.string :password_hash, null: false
|
5
5
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# Used by the email auth feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_email_auth_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
4
5
|
t.string :key, null: false
|
5
6
|
t.datetime :deadline, null: false
|
6
7
|
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the jwt refresh feature
|
2
|
-
create_table
|
3
|
-
t.references
|
2
|
+
create_table :<%= table_prefix %>_jwt_refresh_keys<%= primary_key_type %> do |t|
|
3
|
+
t.references :<%= table_prefix %>, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
4
|
t.string :key, null: false
|
5
5
|
t.datetime :deadline, null: false
|
6
|
-
t.index
|
6
|
+
t.index :<%= table_prefix %>_id, name: "<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx"
|
7
7
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Used by the lockout feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_login_failures, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.integer :number, null: false, default: 1
|
6
6
|
end
|
7
|
-
create_table
|
7
|
+
create_table :<%= table_prefix %>_lockouts, id: false do |t|
|
8
8
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
9
|
-
t.foreign_key
|
9
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
10
10
|
t.string :key, null: false
|
11
11
|
t.datetime :deadline, null: false
|
12
12
|
t.datetime :email_last_sent
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the otp feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_otp_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.integer :num_failures, null: false, default: 0
|
7
7
|
t.datetime :last_use, null: false, default: <%= current_timestamp %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the password expiration feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_password_change_times, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.datetime :changed_at, null: false, default: <%= current_timestamp %>
|
6
6
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the recovery codes feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_recovery_codes, primary_key: [:id, :code] do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :code
|
6
6
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the remember me feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_remember_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.datetime :deadline, null: false
|
7
7
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the password reset feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_password_reset_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.datetime :deadline, null: false
|
7
7
|
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the single session feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_session_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the sms codes feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_sms_codes, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :phone_number, null: false
|
6
6
|
t.integer :num_failures
|
7
7
|
t.string :code
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the account verification feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_verification_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.datetime :requested_at, null: false, default: <%= current_timestamp %>
|
7
7
|
t.datetime :email_last_sent, null: false, default: <%= current_timestamp %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the verify login change feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_login_change_keys, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :key, null: false
|
6
6
|
t.string :login, null: false
|
7
7
|
t.datetime :deadline, null: false
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# Used by the webauthn feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_webauthn_user_ids, id: false do |t|
|
3
3
|
t.<%= primary_key_type(nil) %> :id, primary_key: true
|
4
|
-
t.foreign_key
|
4
|
+
t.foreign_key :<%= table_prefix.pluralize %>, column: :id
|
5
5
|
t.string :webauthn_id, null: false
|
6
6
|
end
|
7
|
-
create_table
|
8
|
-
t.references
|
7
|
+
create_table :<%= table_prefix %>_webauthn_keys, primary_key: [:<%= table_prefix %>_id, :webauthn_id] do |t|
|
8
|
+
t.references :<%= table_prefix %>, foreign_key: true<%= primary_key_type(:type) %>
|
9
9
|
t.string :webauthn_id
|
10
10
|
t.string :public_key, null: false
|
11
11
|
t.integer :sign_count, null: false
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the account expiration feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_activity_times do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
DateTime :last_activity_at, null: false
|
5
5
|
DateTime :last_login_at, null: false
|
6
6
|
DateTime :expired_at
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# Used by the active sessions feature
|
2
|
-
create_table
|
3
|
-
foreign_key
|
2
|
+
create_table :<%= table_prefix %>_active_session_keys do
|
3
|
+
foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, type: :Bignum
|
4
4
|
String :session_id
|
5
5
|
Time :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
6
|
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
-
primary_key [
|
7
|
+
primary_key [:<%= table_prefix %>_id, :session_id]
|
8
8
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Used by the audit logging feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_authentication_audit_logs do
|
3
3
|
primary_key :id, type: :Bignum
|
4
|
-
foreign_key
|
4
|
+
foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, null: false, type: :Bignum
|
5
5
|
DateTime :at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
6
|
String :message, null: false
|
7
7
|
<% case db.database_type -%>
|
@@ -12,6 +12,6 @@ create_table :account_authentication_audit_logs do
|
|
12
12
|
<% else -%>
|
13
13
|
String :metadata
|
14
14
|
<% end -%>
|
15
|
-
index [
|
15
|
+
index [:<%= table_prefix %>_id, :at], name: :audit_<%= table_prefix %>_at_idx
|
16
16
|
index :at, name: :audit_at_idx
|
17
17
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the disallow password reuse feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_previous_password_hashes do
|
3
3
|
primary_key :id, type: :Bignum
|
4
|
-
foreign_key
|
4
|
+
foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, type: :Bignum
|
5
5
|
String :password_hash, null: false
|
6
6
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the email auth feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_email_auth_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
DateTime :deadline, null: false
|
6
6
|
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# Used by the jwt refresh feature
|
2
|
-
create_table
|
2
|
+
create_table :<%= table_prefix %>_jwt_refresh_keys do
|
3
3
|
primary_key :id, type: :Bignum
|
4
|
-
foreign_key
|
4
|
+
foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, null: false, type: :Bignum
|
5
5
|
String :key, null: false
|
6
6
|
DateTime :deadline, null: false
|
7
|
-
index
|
7
|
+
index :<%= table_prefix %>_id, name: :<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx
|
8
8
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# Used by the lockout feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_login_failures do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
Integer :number, null: false, default: 1
|
5
5
|
end
|
6
|
-
create_table
|
7
|
-
foreign_key :id,
|
6
|
+
create_table :<%= table_prefix %>_lockouts do
|
7
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
8
8
|
String :key, null: false
|
9
9
|
DateTime :deadline, null: false
|
10
10
|
DateTime :email_last_sent
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the otp feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_otp_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
Integer :num_failures, null: false, default: 0
|
6
6
|
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Used by the password expiration feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_password_change_times do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
DateTime :changed_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
5
5
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the recovery codes feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_recovery_codes do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, type: :Bignum
|
4
4
|
String :code
|
5
5
|
primary_key [:id, :code]
|
6
6
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the remember me feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_remember_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
DateTime :deadline, null: false
|
6
6
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the password reset feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_password_reset_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
DateTime :deadline, null: false
|
6
6
|
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Used by the single session feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_session_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the sms codes feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_sms_codes do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :phone_number, null: false
|
5
5
|
Integer :num_failures
|
6
6
|
String :code
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the account verification feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_verification_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
DateTime :requested_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
6
|
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Used by the verify login change feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_login_change_keys do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :key, null: false
|
5
5
|
String :login, null: false
|
6
6
|
DateTime :deadline, null: false
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# Used by the webauthn feature
|
2
|
-
create_table
|
3
|
-
foreign_key :id,
|
2
|
+
create_table :<%= table_prefix %>_webauthn_user_ids do
|
3
|
+
foreign_key :id, :<%= table_prefix.pluralize %>, primary_key: true, type: :Bignum
|
4
4
|
String :webauthn_id, null: false
|
5
5
|
end
|
6
|
-
create_table
|
7
|
-
foreign_key
|
6
|
+
create_table :<%= table_prefix %>_webauthn_keys do
|
7
|
+
foreign_key :<%= table_prefix %>_id, :<%= table_prefix.pluralize %>, type: :Bignum
|
8
8
|
String :webauthn_id
|
9
9
|
String :public_key, null: false
|
10
10
|
Integer :sign_count, null: false
|
11
11
|
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
12
|
-
primary_key [
|
12
|
+
primary_key [:<%= table_prefix %>_id, :webauthn_id]
|
13
13
|
end
|
@@ -13,6 +13,9 @@ module Rodauth
|
|
13
13
|
desc: "Rodauth features to create tables for (otp, sms_codes, single_session, account_expiration etc.)",
|
14
14
|
default: %w[]
|
15
15
|
|
16
|
+
class_option :prefix, optional: true, type: :string,
|
17
|
+
desc: "Change prefix for generated tables (default: account)"
|
18
|
+
|
16
19
|
class_option :name, optional: true, type: :string,
|
17
20
|
desc: "Name of the generated migration file"
|
18
21
|
|
@@ -22,10 +25,24 @@ module Rodauth
|
|
22
25
|
migration_template "db/migrate/create_rodauth.rb", File.join(db_migrate_path, "#{migration_name}.rb")
|
23
26
|
end
|
24
27
|
|
28
|
+
def show_instructions
|
29
|
+
# skip if called from install generator, it already adds configuration
|
30
|
+
return if current_command_chain.include?(:generate_rodauth_migration)
|
31
|
+
return unless options[:prefix] && behavior == :invoke
|
32
|
+
|
33
|
+
configuration = CONFIGURATION.values_at(*features.map(&:to_sym))
|
34
|
+
.flat_map(&:to_a)
|
35
|
+
.map { |config, format| "#{config} :#{format % { plural: table_prefix.pluralize, singular: table_prefix }}" }
|
36
|
+
.join("\n")
|
37
|
+
.indent(2)
|
38
|
+
|
39
|
+
say "\nAdd the following to your Rodauth configuration:\n\n#{configuration}"
|
40
|
+
end
|
41
|
+
|
25
42
|
private
|
26
43
|
|
27
44
|
def migration_name
|
28
|
-
options[:name] || "
|
45
|
+
options[:name] || ["create_rodauth", *options[:prefix], *features].join("_")
|
29
46
|
end
|
30
47
|
|
31
48
|
def migration_content
|
@@ -64,6 +81,31 @@ module Rodauth
|
|
64
81
|
Dir["#{MIGRATION_DIR}/*.erb"].map { |filename| File.basename(filename, ".erb") }
|
65
82
|
end
|
66
83
|
|
84
|
+
def table_prefix
|
85
|
+
options[:prefix]&.singularize || "account"
|
86
|
+
end
|
87
|
+
|
88
|
+
CONFIGURATION = {
|
89
|
+
base: { accounts_table: "%{plural}" },
|
90
|
+
remember: { remember_table: "%{singular}_remember_keys" },
|
91
|
+
verify_account: { verify_account_table: "%{singular}_verification_keys" },
|
92
|
+
verify_login_change: { verify_login_change_table: "%{singular}_login_change_keys" },
|
93
|
+
reset_password: { reset_password_table: "%{singular}_password_reset_keys" },
|
94
|
+
email_auth: { email_auth_table: "%{singular}_email_auth_keys" },
|
95
|
+
otp: { otp_keys_table: "%{singular}_otp_keys" },
|
96
|
+
sms_codes: { sms_codes_table: "%{singular}_sms_codes" },
|
97
|
+
recovery_codes: { recovery_codes_table: "%{singular}_recovery_codes" },
|
98
|
+
webauthn: { webauthn_keys_table: "%{singular}_webauthn_keys", webauthn_user_ids_table: "%{singular}_webauthn_user_ids", webauthn_keys_account_id_column: "%{singular}_id" },
|
99
|
+
lockout: { account_login_failures_table: "%{singular}_login_failures", account_lockouts_table: "%{singular}_lockouts" },
|
100
|
+
active_sessions: { active_sessions_table: "%{singular}_active_session_keys", active_sessions_account_id_column: "%{singular}_id" },
|
101
|
+
account_expiration: { account_activity_table: "%{singular}_activity_times" },
|
102
|
+
password_expiration: { password_expiration_table: "%{singular}_password_change_times" },
|
103
|
+
single_session: { single_session_table: "%{singular}_session_keys" },
|
104
|
+
audit_logging: { audit_logging_table: "%{singular}_authentication_audit_logs", audit_logging_account_id_column: "%{singular}_id" },
|
105
|
+
disallow_password_reuse: { previous_password_hash_table: "%{singular}_previous_password_hashes", previous_password_account_id_column: "%{singular}_id" },
|
106
|
+
jwt_refresh: { jwt_refresh_token_table: "%{singular}_jwt_refresh_keys", jwt_refresh_token_account_id_column: "%{singular}_id" },
|
107
|
+
}
|
108
|
+
|
67
109
|
if defined?(::ActiveRecord::Railtie) # Active Record
|
68
110
|
include ::ActiveRecord::Generators::Migration
|
69
111
|
|
data/lib/generators/rodauth/templates/app/mailers/{rodauth_mailer.rb → rodauth_mailer.rb.tt}
RENAMED
@@ -1,16 +1,18 @@
|
|
1
1
|
class RodauthMailer < ApplicationMailer
|
2
|
+
default to: -> { @rodauth.email_to }, from: -> { @rodauth.email_from }
|
3
|
+
|
2
4
|
def verify_account(name, account_id, key)
|
3
5
|
@rodauth = rodauth(name, account_id) { @verify_account_key_value = key }
|
4
6
|
@account = @rodauth.rails_account
|
5
7
|
|
6
|
-
mail
|
8
|
+
mail subject: @rodauth.verify_account_email_subject
|
7
9
|
end
|
8
10
|
|
9
11
|
def reset_password(name, account_id, key)
|
10
12
|
@rodauth = rodauth(name, account_id) { @reset_password_key_value = key }
|
11
13
|
@account = @rodauth.rails_account
|
12
14
|
|
13
|
-
mail
|
15
|
+
mail subject: @rodauth.reset_password_email_subject
|
14
16
|
end
|
15
17
|
|
16
18
|
def verify_login_change(name, account_id, key)
|
@@ -25,28 +27,28 @@ class RodauthMailer < ApplicationMailer
|
|
25
27
|
@rodauth = rodauth(name, account_id)
|
26
28
|
@account = @rodauth.rails_account
|
27
29
|
|
28
|
-
mail
|
30
|
+
mail subject: @rodauth.password_changed_email_subject
|
29
31
|
end
|
30
32
|
|
31
33
|
# def reset_password_notify(name, account_id)
|
32
34
|
# @rodauth = rodauth(name, account_id)
|
33
35
|
# @account = @rodauth.rails_account
|
34
36
|
|
35
|
-
# mail
|
37
|
+
# mail subject: @rodauth.reset_password_notify_email_subject
|
36
38
|
# end
|
37
39
|
|
38
40
|
# def email_auth(name, account_id, key)
|
39
41
|
# @rodauth = rodauth(name, account_id) { @email_auth_key_value = key }
|
40
42
|
# @account = @rodauth.rails_account
|
41
43
|
|
42
|
-
# mail
|
44
|
+
# mail subject: @rodauth.email_auth_email_subject
|
43
45
|
# end
|
44
46
|
|
45
47
|
# def unlock_account(name, account_id, key)
|
46
48
|
# @rodauth = rodauth(name, account_id) { @unlock_account_key_value = key }
|
47
49
|
# @account = @rodauth.rails_account
|
48
50
|
|
49
|
-
# mail
|
51
|
+
# mail subject: @rodauth.unlock_account_email_subject
|
50
52
|
# end
|
51
53
|
|
52
54
|
private
|
@@ -1,18 +1,56 @@
|
|
1
|
+
require "sequel/core"
|
2
|
+
|
1
3
|
class RodauthMain < Rodauth::Rails::Auth
|
2
4
|
configure do
|
3
5
|
# List of authentication features that are loaded.
|
4
6
|
enable :create_account, :verify_account, :verify_account_grace_period,
|
5
7
|
:login, :logout<%= ", :remember" unless jwt? %><%= ", :json" if json? %><%= ", :jwt" if jwt? %>,
|
6
8
|
:reset_password, :change_password, :change_password_notify,
|
7
|
-
:change_login, :verify_login_change, :close_account
|
9
|
+
:change_login, :verify_login_change, :close_account<%= ", :argon2" if argon2? %>
|
8
10
|
|
9
11
|
# See the Rodauth documentation for the list of available config options:
|
10
12
|
# http://rodauth.jeremyevans.net/documentation.html
|
11
13
|
|
12
14
|
# ==> General
|
15
|
+
<% if sequel_activerecord_integration? -%>
|
16
|
+
# Initialize Sequel and have it reuse Active Record's database connection.
|
17
|
+
<% if RUBY_ENGINE == "jruby" -%>
|
18
|
+
db Sequel.connect("jdbc:<%= sequel_adapter %>://", extensions: :activerecord_connection, keep_reference: false)
|
19
|
+
<% else -%>
|
20
|
+
db Sequel.<%= sequel_adapter %>(extensions: :activerecord_connection, keep_reference: false)
|
21
|
+
<% end -%>
|
22
|
+
|
23
|
+
<% end -%>
|
24
|
+
# Change prefix of table and foreign key column names from default "account"
|
25
|
+
<% if table -%>
|
26
|
+
accounts_table :<%= table_prefix.pluralize %>
|
27
|
+
verify_account_table :<%= table_prefix %>_verification_keys
|
28
|
+
verify_login_change_table :<%= table_prefix %>_login_change_keys
|
29
|
+
reset_password_table :<%= table_prefix %>_password_reset_keys
|
30
|
+
<% unless jwt? -%>
|
31
|
+
remember_table :<%= table_prefix %>_remember_keys
|
32
|
+
<% end -%>
|
33
|
+
<% else -%>
|
34
|
+
# accounts_table :users
|
35
|
+
# verify_account_table :user_verification_keys
|
36
|
+
# verify_login_change_table :user_login_change_keys
|
37
|
+
# reset_password_table :user_password_reset_keys
|
38
|
+
<% unless jwt? -%>
|
39
|
+
# remember_table :user_remember_keys
|
40
|
+
<% end -%>
|
41
|
+
<% end -%>
|
42
|
+
|
13
43
|
# The secret key used for hashing public-facing tokens for various features.
|
14
44
|
# Defaults to Rails `secret_key_base`, but you can use your own secret key.
|
15
45
|
# hmac_secret "<%= SecureRandom.hex(64) %>"
|
46
|
+
<% if argon2? -%>
|
47
|
+
|
48
|
+
# Use a rotatable password pepper when hashing passwords with Argon2.
|
49
|
+
# argon2_secret "<SECRET_KEY>"
|
50
|
+
|
51
|
+
# Since we're using argon2, prevent loading the bcrypt gem to save memory.
|
52
|
+
require_bcrypt? false
|
53
|
+
<% end -%>
|
16
54
|
<% if jwt? -%>
|
17
55
|
|
18
56
|
# Set JWT secret, which is used to cryptographically protect the token.
|
@@ -28,10 +66,13 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
28
66
|
# require_login_confirmation? false
|
29
67
|
<% end -%>
|
30
68
|
|
31
|
-
#
|
69
|
+
# Use path prefix for all routes.
|
70
|
+
# prefix "/auth"
|
71
|
+
|
72
|
+
# Specify the controller used for view rendering, CSRF, and callbacks.
|
32
73
|
rails_controller { RodauthController }
|
33
74
|
|
34
|
-
# Set
|
75
|
+
# Set in Rodauth controller instance with the title of the current page.
|
35
76
|
title_instance_variable :@page_title
|
36
77
|
|
37
78
|
# Store account status in an integer column without foreign key constraint.
|
@@ -40,14 +81,13 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
40
81
|
# Store password hash in a column instead of a separate table.
|
41
82
|
account_password_hash_column :password_hash
|
42
83
|
|
43
|
-
# Passwords shorter than 8 characters are considered weak according to OWASP.
|
44
|
-
password_minimum_length 8
|
45
|
-
# bcrypt has a maximum input length of 72 bytes, truncating any extra bytes.
|
46
|
-
password_maximum_bytes 72
|
47
|
-
|
48
84
|
# Set password when creating account instead of when verifying.
|
49
85
|
verify_account_set_password? false
|
50
86
|
|
87
|
+
# Change some default param keys.
|
88
|
+
# login_param "email"
|
89
|
+
# password_confirm_param "confirm_password"
|
90
|
+
|
51
91
|
# Redirect back to originally requested location after authentication.
|
52
92
|
# login_return_to_requested_location? true
|
53
93
|
# two_factor_auth_return_to_requested_location? true # if using MFA
|
@@ -110,8 +150,27 @@ class RodauthMain < Rodauth::Rails::Auth
|
|
110
150
|
# password_too_short_message { "needs to have at least #{password_minimum_length} characters" }
|
111
151
|
# login_does_not_meet_requirements_message { "invalid email#{", #{login_requirement_message}" if login_requirement_message}" }
|
112
152
|
|
113
|
-
#
|
114
|
-
|
153
|
+
# Passwords shorter than 8 characters are considered weak according to OWASP.
|
154
|
+
password_minimum_length 8
|
155
|
+
<% if argon2? -%>
|
156
|
+
# Having a maximum password length set prevents long password DoS attacks.
|
157
|
+
password_maximum_length 64
|
158
|
+
<% else -%>
|
159
|
+
# bcrypt has a maximum input length of 72 bytes, truncating any extra bytes.
|
160
|
+
password_maximum_bytes 72
|
161
|
+
<% end -%>
|
162
|
+
|
163
|
+
# Custom password complexity requirements (alternative to password_complexity feature).
|
164
|
+
# password_meets_requirements? do |password|
|
165
|
+
# super(password) && password_complex_enough?(password)
|
166
|
+
# end
|
167
|
+
# auth_class_eval do
|
168
|
+
# def password_complex_enough?(password)
|
169
|
+
# return true if password.match?(/\d/) && password.match?(/[^a-zA-Z\d]/)
|
170
|
+
# set_password_requirement_error_message(:password_simple, "requires one number and one special character")
|
171
|
+
# false
|
172
|
+
# end
|
173
|
+
# end
|
115
174
|
<% unless jwt? -%>
|
116
175
|
|
117
176
|
# ==> Remember Feature
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if defined?(ActiveRecord::Railtie) -%>
|
2
|
-
class
|
2
|
+
class <%= table_prefix.camelize %> < ApplicationRecord
|
3
3
|
include Rodauth::Rails.model
|
4
4
|
<% if ActiveRecord.version >= Gem::Version.new("7.0") -%>
|
5
5
|
enum :status, unverified: 1, verified: 2, closed: 3
|
@@ -8,7 +8,7 @@ class Account < ApplicationRecord
|
|
8
8
|
<% end -%>
|
9
9
|
end
|
10
10
|
<% else -%>
|
11
|
-
class
|
11
|
+
class <%= table_prefix.camelize %> < Sequel::Model
|
12
12
|
include Rodauth::Rails.model
|
13
13
|
plugin :enum
|
14
14
|
enum :status, unverified: 1, verified: 2, closed: 3
|
@@ -8,13 +8,13 @@
|
|
8
8
|
<% end %>
|
9
9
|
|
10
10
|
<fieldset class="mb-6">
|
11
|
-
<%
|
11
|
+
<% rodauth.account_webauthn_usage.each do |id, last_use| %>
|
12
12
|
<div class="flex items-center space-x-2">
|
13
13
|
<%= form.radio_button rodauth.webauthn_remove_param, id, id: "webauthn-remove-#{id}", class: "dark:bg-gray-900 dark:border-gray-600 dark:checked:bg-current dark:checked:border-current dark:checked:text-emerald-400 dark:focus:ring-emerald-400 dark:focus:ring-offset-gray-900" %>
|
14
14
|
<%= form.label "webauthn-remove-#{id}", "Last use: #{last_use}", class: "text-sm" %>
|
15
|
-
<%= content_tag(:span, rodauth.field_error(rodauth.webauthn_remove_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "webauthn_remove_error_message") if rodauth.field_error(rodauth.webauthn_remove_param) && id == usage.keys.last %>
|
16
15
|
</div>
|
17
16
|
<% end %>
|
17
|
+
<%= content_tag(:span, rodauth.field_error(rodauth.webauthn_remove_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "webauthn_remove_error_message") if rodauth.field_error(rodauth.webauthn_remove_param) %>
|
18
18
|
</fieldset>
|
19
19
|
|
20
20
|
<%= form.submit rodauth.webauthn_remove_button, class: "w-full px-8 py-3 cursor-pointer font-semibold text-sm rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-600 dark:bg-emerald-400 dark:hover:bg-emerald-500 dark:text-gray-900 dark:focus:ring-emerald-400 dark:focus:ring-offset-current" %>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
2
2
|
one:
|
3
3
|
email: freddie@queen.com
|
4
|
-
password_hash: <%%=
|
4
|
+
password_hash: <%%= RodauthMain.allocate.password_hash("password") %>
|
5
5
|
status: verified
|
6
6
|
|
7
7
|
two:
|
8
8
|
email: brian@queen.com
|
9
|
-
password_hash: <%%=
|
9
|
+
password_hash: <%%= RodauthMain.allocate.password_hash("password") %>
|
10
10
|
status: verified
|
data/lib/rodauth/rails/app.rb
CHANGED
@@ -82,6 +82,25 @@ module Rodauth
|
|
82
82
|
super
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
# The Rack input might not be rewindable, so ensure we parse the JSON
|
87
|
+
# request body in Rails, and avoid parsing it again in Roda.
|
88
|
+
def POST
|
89
|
+
if content_type =~ /json/
|
90
|
+
env["roda.json_params"] = scope.rails_request.POST.to_hash
|
91
|
+
end
|
92
|
+
super
|
93
|
+
end
|
94
|
+
|
95
|
+
unless ActionPack.version < Gem::Version.new("5.0")
|
96
|
+
# When calling a Rodauth method that redirects inside the Rails
|
97
|
+
# router, Roda's after hook that commits the flash would never get
|
98
|
+
# called, so we make sure to commit the flash beforehand.
|
99
|
+
def redirect(*)
|
100
|
+
scope.rails_request.commit_flash
|
101
|
+
super
|
102
|
+
end
|
103
|
+
end
|
85
104
|
end
|
86
105
|
end
|
87
106
|
end
|
@@ -60,16 +60,6 @@ module Rodauth
|
|
60
60
|
|
61
61
|
private
|
62
62
|
|
63
|
-
unless ActionPack.version < Gem::Version.new("5.0")
|
64
|
-
# When calling a Rodauth method that redirects inside the Rails
|
65
|
-
# router, Roda's after hook that commits the flash would never get
|
66
|
-
# called, so we make sure to commit the flash beforehand.
|
67
|
-
def redirect(*)
|
68
|
-
rails_request.commit_flash
|
69
|
-
super
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
63
|
def instantiate_rails_account
|
74
64
|
if defined?(ActiveRecord::Base) && rails_account_model < ActiveRecord::Base
|
75
65
|
rails_account_model.instantiate(account.stringify_keys)
|
data/rodauth-rails.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
19
|
spec.add_dependency "railties", ">= 4.2", "< 8"
|
20
|
-
spec.add_dependency "rodauth", "~> 2.
|
20
|
+
spec.add_dependency "rodauth", "~> 2.28"
|
21
21
|
spec.add_dependency "roda", "~> 3.55"
|
22
22
|
spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
|
23
23
|
spec.add_dependency "rodauth-model", "~> 0.2"
|
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: 1.
|
4
|
+
version: 1.8.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: 2023-
|
11
|
+
date: 2023-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '2.
|
39
|
+
version: '2.28'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '2.
|
46
|
+
version: '2.28'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: roda
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -219,11 +219,11 @@ files:
|
|
219
219
|
- lib/generators/rodauth/migration/sequel/webauthn.erb
|
220
220
|
- lib/generators/rodauth/migration_generator.rb
|
221
221
|
- lib/generators/rodauth/templates/INSTRUCTIONS
|
222
|
-
- lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb
|
223
|
-
- lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb
|
224
|
-
- lib/generators/rodauth/templates/app/misc/rodauth_app.rb
|
225
|
-
- lib/generators/rodauth/templates/app/misc/rodauth_main.rb
|
226
|
-
- lib/generators/rodauth/templates/app/models/account.rb
|
222
|
+
- lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb.tt
|
223
|
+
- lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb.tt
|
224
|
+
- lib/generators/rodauth/templates/app/misc/rodauth_app.rb.tt
|
225
|
+
- lib/generators/rodauth/templates/app/misc/rodauth_main.rb.tt
|
226
|
+
- lib/generators/rodauth/templates/app/models/account.rb.tt
|
227
227
|
- lib/generators/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb
|
228
228
|
- lib/generators/rodauth/templates/app/views/rodauth/_login_form.html.erb
|
229
229
|
- lib/generators/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb
|
@@ -307,10 +307,9 @@ files:
|
|
307
307
|
- lib/generators/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb
|
308
308
|
- lib/generators/rodauth/templates/app/views/rodauth_mailer/verify_account.text.erb
|
309
309
|
- lib/generators/rodauth/templates/app/views/rodauth_mailer/verify_login_change.text.erb
|
310
|
-
- lib/generators/rodauth/templates/config/initializers/rodauth.rb
|
311
|
-
- lib/generators/rodauth/templates/
|
312
|
-
- lib/generators/rodauth/templates/
|
313
|
-
- lib/generators/rodauth/templates/test/fixtures/accounts.yml
|
310
|
+
- lib/generators/rodauth/templates/config/initializers/rodauth.rb.tt
|
311
|
+
- lib/generators/rodauth/templates/db/migrate/create_rodauth.rb.tt
|
312
|
+
- lib/generators/rodauth/templates/test/fixtures/accounts.yml.tt
|
314
313
|
- lib/generators/rodauth/views_generator.rb
|
315
314
|
- lib/rodauth-rails.rb
|
316
315
|
- lib/rodauth/rails.rb
|
@@ -352,7 +351,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
352
351
|
- !ruby/object:Gem::Version
|
353
352
|
version: '0'
|
354
353
|
requirements: []
|
355
|
-
rubygems_version: 3.4.
|
354
|
+
rubygems_version: 3.4.6
|
356
355
|
signing_key:
|
357
356
|
specification_version: 4
|
358
357
|
summary: Provides Rails integration for Rodauth.
|
File without changes
|
File without changes
|
File without changes
|
/data/lib/generators/rodauth/templates/db/migrate/{create_rodauth.rb → create_rodauth.rb.tt}
RENAMED
File without changes
|