rodauth-rails 1.7.1 → 1.8.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 +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
|