rodauth-rails 1.3.1 → 1.4.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 +8 -0
- data/README.md +27 -0
- data/lib/generators/rodauth/install_generator.rb +9 -10
- data/lib/generators/rodauth/migration/{account_expiration.erb → active_record/account_expiration.erb} +0 -0
- data/lib/generators/rodauth/migration/{active_sessions.erb → active_record/active_sessions.erb} +0 -0
- data/lib/generators/rodauth/migration/{audit_logging.erb → active_record/audit_logging.erb} +0 -0
- data/lib/generators/rodauth/migration/{base.erb → active_record/base.erb} +0 -0
- data/lib/generators/rodauth/migration/{disallow_password_reuse.erb → active_record/disallow_password_reuse.erb} +1 -1
- data/lib/generators/rodauth/migration/{email_auth.erb → active_record/email_auth.erb} +0 -0
- data/lib/generators/rodauth/migration/{jwt_refresh.erb → active_record/jwt_refresh.erb} +0 -0
- data/lib/generators/rodauth/migration/{lockout.erb → active_record/lockout.erb} +0 -0
- data/lib/generators/rodauth/migration/{otp.erb → active_record/otp.erb} +0 -0
- data/lib/generators/rodauth/migration/{password_expiration.erb → active_record/password_expiration.erb} +0 -0
- data/lib/generators/rodauth/migration/{recovery_codes.erb → active_record/recovery_codes.erb} +0 -0
- data/lib/generators/rodauth/migration/{remember.erb → active_record/remember.erb} +0 -0
- data/lib/generators/rodauth/migration/{reset_password.erb → active_record/reset_password.erb} +0 -0
- data/lib/generators/rodauth/migration/{single_session.erb → active_record/single_session.erb} +0 -0
- data/lib/generators/rodauth/migration/{sms_codes.erb → active_record/sms_codes.erb} +0 -0
- data/lib/generators/rodauth/migration/{verify_account.erb → active_record/verify_account.erb} +0 -0
- data/lib/generators/rodauth/migration/{verify_login_change.erb → active_record/verify_login_change.erb} +0 -0
- data/lib/generators/rodauth/migration/{webauthn.erb → active_record/webauthn.erb} +0 -0
- data/lib/generators/rodauth/migration/sequel/account_expiration.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/active_sessions.erb +8 -0
- data/lib/generators/rodauth/migration/sequel/audit_logging.erb +17 -0
- data/lib/generators/rodauth/migration/sequel/base.erb +25 -0
- data/lib/generators/rodauth/migration/sequel/disallow_password_reuse.erb +6 -0
- data/lib/generators/rodauth/migration/sequel/email_auth.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/jwt_refresh.erb +8 -0
- data/lib/generators/rodauth/migration/sequel/lockout.erb +11 -0
- data/lib/generators/rodauth/migration/sequel/otp.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/password_expiration.erb +5 -0
- data/lib/generators/rodauth/migration/sequel/recovery_codes.erb +6 -0
- data/lib/generators/rodauth/migration/sequel/remember.erb +6 -0
- data/lib/generators/rodauth/migration/sequel/reset_password.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/single_session.erb +5 -0
- data/lib/generators/rodauth/migration/sequel/sms_codes.erb +8 -0
- data/lib/generators/rodauth/migration/sequel/verify_account.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/verify_login_change.erb +7 -0
- data/lib/generators/rodauth/migration/sequel/webauthn.erb +13 -0
- data/lib/generators/rodauth/migration_generator.rb +89 -9
- data/lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb +24 -0
- data/lib/generators/rodauth/templates/app/models/account.rb +7 -0
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +8 -0
- data/lib/rodauth/rails/feature/associations.rb +54 -0
- data/lib/rodauth/rails/feature.rb +2 -0
- data/lib/rodauth/rails/middleware.rb +9 -0
- data/lib/rodauth/rails/model.rb +8 -8
- data/lib/rodauth/rails/version.rb +1 -1
- metadata +39 -22
- data/lib/generators/rodauth/migration_helpers.rb +0 -77
- data/lib/rodauth/rails/model/associations.rb +0 -195
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b5fb22e3d8c84eafedffa3463b4e0ecdf481189b8b48adc2d31005f86251d87
|
4
|
+
data.tar.gz: 142e229b7c9a9b078f773f99885117268e759df2eb49e5252ce21754dcf61763
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c30c5b1714a80466ad3775720be50d2f02b8d06d016638e6d1ebfb7515cd6060463b975f9810977fe74eb7330ce12b9c6ff81839e41b2e4044615c606ca7bb
|
7
|
+
data.tar.gz: 4a532058b27cfc07d2ed234457b880a609c7b35186db976a547be2e83d1c18df7ac72402a9d52155819f2d97edb63b0e7742e908b6cb3ed1b40c2deae18e7e2e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 1.4.0 (2022-05-04)
|
2
|
+
|
3
|
+
* Move association definitions to `#associations` Rodauth method, allowing external features to extend them (@janko)
|
4
|
+
|
5
|
+
* Add Sequel support for generating database migrations, model, and mailer (@janko)
|
6
|
+
|
7
|
+
* Skip calling Rodauth app on asset requests when using Sprockets or Propshaft (@janko)
|
8
|
+
|
1
9
|
## 1.3.1 (2022-04-22)
|
2
10
|
|
3
11
|
* Ensure response status is logged when calling a halting rodauth method inside a controller (@janko)
|
data/README.md
CHANGED
@@ -614,6 +614,33 @@ Rodauth::Rails.model(association_options: -> (name) {
|
|
614
614
|
})
|
615
615
|
```
|
616
616
|
|
617
|
+
#### Extending Associations
|
618
|
+
|
619
|
+
External features can extend the list of associations with their own
|
620
|
+
definitions, which the model mixin will pick up and declare the new associations
|
621
|
+
on the model.
|
622
|
+
|
623
|
+
```rb
|
624
|
+
# lib/rodauth/features/foo.rb
|
625
|
+
module Rodauth
|
626
|
+
Feature.define(:foo, :Foo) do
|
627
|
+
auth_value_method :foo_table, :account_foos
|
628
|
+
auth_value_method :foo_id_column, :id
|
629
|
+
|
630
|
+
def associations
|
631
|
+
list = super
|
632
|
+
list << {
|
633
|
+
name: :foo, # will define `Account::Foo` model
|
634
|
+
type: :one, # or :many
|
635
|
+
table: foo_table,
|
636
|
+
foreign_key: foo_id_column
|
637
|
+
}
|
638
|
+
list
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
```
|
643
|
+
|
617
644
|
## Multiple configurations
|
618
645
|
|
619
646
|
If you need to handle multiple types of accounts that require different
|
@@ -1,15 +1,10 @@
|
|
1
1
|
require "rails/generators/base"
|
2
|
-
require "rails/generators/active_record/migration"
|
3
|
-
require "generators/rodauth/migration_helpers"
|
4
2
|
require "securerandom"
|
5
3
|
|
6
4
|
module Rodauth
|
7
5
|
module Rails
|
8
6
|
module Generators
|
9
7
|
class InstallGenerator < ::Rails::Generators::Base
|
10
|
-
include ::ActiveRecord::Generators::Migration
|
11
|
-
include MigrationHelpers
|
12
|
-
|
13
8
|
if RUBY_ENGINE == "jruby"
|
14
9
|
SEQUEL_ADAPTERS = {
|
15
10
|
"sqlite3" => "sqlite",
|
@@ -40,9 +35,7 @@ module Rodauth
|
|
40
35
|
class_option :jwt, type: :boolean, desc: "Configure JWT support"
|
41
36
|
|
42
37
|
def create_rodauth_migration
|
43
|
-
|
44
|
-
|
45
|
-
migration_template "db/migrate/create_rodauth.rb"
|
38
|
+
invoke "rodauth:migration", migration_features, name: "create_rodauth"
|
46
39
|
end
|
47
40
|
|
48
41
|
def create_rodauth_initializer
|
@@ -66,8 +59,6 @@ module Rodauth
|
|
66
59
|
end
|
67
60
|
|
68
61
|
def create_account_model
|
69
|
-
return unless defined?(ActiveRecord::Railtie)
|
70
|
-
|
71
62
|
template "app/models/account.rb"
|
72
63
|
end
|
73
64
|
|
@@ -112,6 +103,14 @@ module Rodauth
|
|
112
103
|
scheme = "jdbc:#{scheme}" if RUBY_ENGINE == "jruby"
|
113
104
|
scheme
|
114
105
|
end
|
106
|
+
|
107
|
+
def activerecord_adapter
|
108
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
109
|
+
ActiveRecord::Base.connection_db_config.adapter
|
110
|
+
else
|
111
|
+
ActiveRecord::Base.connection_config.fetch(:adapter)
|
112
|
+
end
|
113
|
+
end
|
115
114
|
end
|
116
115
|
end
|
117
116
|
end
|
File without changes
|
data/lib/generators/rodauth/migration/{active_sessions.erb → active_record/active_sessions.erb}
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/generators/rodauth/migration/{recovery_codes.erb → active_record/recovery_codes.erb}
RENAMED
File without changes
|
File without changes
|
data/lib/generators/rodauth/migration/{reset_password.erb → active_record/reset_password.erb}
RENAMED
File without changes
|
data/lib/generators/rodauth/migration/{single_session.erb → active_record/single_session.erb}
RENAMED
File without changes
|
File without changes
|
data/lib/generators/rodauth/migration/{verify_account.erb → active_record/verify_account.erb}
RENAMED
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the active sessions feature
|
2
|
+
create_table :account_active_session_keys do
|
3
|
+
foreign_key :account_id, :accounts, type: :Bignum
|
4
|
+
String :session_id
|
5
|
+
Time :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
+
primary_key [:account_id, :session_id]
|
8
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Used by the audit logging feature
|
2
|
+
create_table :account_authentication_audit_logs do
|
3
|
+
primary_key :id, type: :Bignum
|
4
|
+
foreign_key :account_id, :accounts, null: false, type: :Bignum
|
5
|
+
DateTime :at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
|
+
String :message, null: false
|
7
|
+
<% case db.database_type -%>
|
8
|
+
<% when :postgres -%>
|
9
|
+
jsonb :metadata
|
10
|
+
<% when :sqlite, :mysql -%>
|
11
|
+
json :metadata
|
12
|
+
<% else -%>
|
13
|
+
String :metadata
|
14
|
+
<% end -%>
|
15
|
+
index [:account_id, :at], name: :audit_account_at_idx
|
16
|
+
index :at, name: :audit_at_idx
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<% if db.database_type == :postgres -%>
|
2
|
+
enable_extension "citext"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
create_table :accounts do
|
6
|
+
primary_key :id, type: :Bignum
|
7
|
+
<% if db.database_type == :postgres -%>
|
8
|
+
citext :email, null: false
|
9
|
+
constraint :valid_email, email: /^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
|
10
|
+
<% else -%>
|
11
|
+
String :email, null: false
|
12
|
+
<% end -%>
|
13
|
+
String :status, null: false, default: "unverified"
|
14
|
+
<% if db.supports_partial_indexes? -%>
|
15
|
+
index :email, unique: true, where: { status: ["unverified", "verified"] }
|
16
|
+
<% else -%>
|
17
|
+
index :email, unique: true
|
18
|
+
<% end -%>
|
19
|
+
end
|
20
|
+
|
21
|
+
# Used if storing password hashes in a separate table (default)
|
22
|
+
create_table :account_password_hashes do
|
23
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
24
|
+
String :password_hash, null: false
|
25
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the email auth feature
|
2
|
+
create_table :account_email_auth_keys do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :key, null: false
|
5
|
+
DateTime :deadline, null: false
|
6
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the jwt refresh feature
|
2
|
+
create_table :account_jwt_refresh_keys do
|
3
|
+
primary_key :id, type: :Bignum
|
4
|
+
foreign_key :account_id, :accounts, null: false, type: :Bignum
|
5
|
+
String :key, null: false
|
6
|
+
DateTime :deadline, null: false
|
7
|
+
index :account_id, name: :account_jwt_rk_account_id_idx
|
8
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Used by the lockout feature
|
2
|
+
create_table :account_login_failures do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
Integer :number, null: false, default: 1
|
5
|
+
end
|
6
|
+
create_table :account_lockouts do
|
7
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
8
|
+
String :key, null: false
|
9
|
+
DateTime :deadline, null: false
|
10
|
+
DateTime :email_last_sent
|
11
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the otp feature
|
2
|
+
create_table :account_otp_keys do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :key, null: false
|
5
|
+
Integer :num_failures, null: false, default: 0
|
6
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the password reset feature
|
2
|
+
create_table :account_password_reset_keys do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :key, null: false
|
5
|
+
DateTime :deadline, null: false
|
6
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the sms codes feature
|
2
|
+
create_table :account_sms_codes do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :phone_number, null: false
|
5
|
+
Integer :num_failures
|
6
|
+
String :code
|
7
|
+
DateTime :code_issued_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the account verification feature
|
2
|
+
create_table :account_verification_keys do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :key, null: false
|
5
|
+
DateTime :requested_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
6
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
7
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Used by the webauthn feature
|
2
|
+
create_table :account_webauthn_user_ids do
|
3
|
+
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
4
|
+
String :webauthn_id, null: false
|
5
|
+
end
|
6
|
+
create_table :account_webauthn_keys do
|
7
|
+
foreign_key :account_id, :accounts, type: :Bignum
|
8
|
+
String :webauthn_id
|
9
|
+
String :public_key, null: false
|
10
|
+
Integer :sign_count, null: false
|
11
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
12
|
+
primary_key [:account_id, :webauthn_id]
|
13
|
+
end
|
@@ -1,14 +1,11 @@
|
|
1
1
|
require "rails/generators/base"
|
2
2
|
require "rails/generators/active_record/migration"
|
3
|
-
require "
|
3
|
+
require "erb"
|
4
4
|
|
5
5
|
module Rodauth
|
6
6
|
module Rails
|
7
7
|
module Generators
|
8
8
|
class MigrationGenerator < ::Rails::Generators::Base
|
9
|
-
include ::ActiveRecord::Generators::Migration
|
10
|
-
include MigrationHelpers
|
11
|
-
|
12
9
|
source_root "#{__dir__}/templates"
|
13
10
|
namespace "rodauth:migration"
|
14
11
|
|
@@ -20,19 +17,102 @@ module Rodauth
|
|
20
17
|
desc: "Name of the generated migration file"
|
21
18
|
|
22
19
|
def create_rodauth_migration
|
23
|
-
return unless defined?(ActiveRecord::Railtie)
|
24
20
|
return if features.empty?
|
25
21
|
|
26
|
-
migration_template "db/migrate/create_rodauth.rb", "#{migration_name}.rb"
|
22
|
+
migration_template "db/migrate/create_rodauth.rb", File.join(db_migrate_path, "#{migration_name}.rb")
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
features
|
31
|
-
end
|
25
|
+
private
|
32
26
|
|
33
27
|
def migration_name
|
34
28
|
options[:name] || "create_rodauth_#{features.join("_")}"
|
35
29
|
end
|
30
|
+
|
31
|
+
def migration_content
|
32
|
+
features
|
33
|
+
.select { |feature| File.exist?(migration_chunk(feature)) }
|
34
|
+
.map { |feature| File.read(migration_chunk(feature)) }
|
35
|
+
.map { |content| erb_eval(content) }
|
36
|
+
.join("\n")
|
37
|
+
.indent(4)
|
38
|
+
end
|
39
|
+
|
40
|
+
def erb_eval(content)
|
41
|
+
if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
|
42
|
+
ERB.new(content, trim_mode: "-").result(binding)
|
43
|
+
else
|
44
|
+
ERB.new(content, 0, "-").result(binding)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if defined?(::ActiveRecord::Railtie) # Active Record
|
49
|
+
include ::ActiveRecord::Generators::Migration
|
50
|
+
|
51
|
+
def db_migrate_path
|
52
|
+
return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
|
53
|
+
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def migration_chunk(feature)
|
58
|
+
"#{__dir__}/migration/active_record/#{feature}.erb"
|
59
|
+
end
|
60
|
+
|
61
|
+
def migration_version
|
62
|
+
return unless ActiveRecord.version >= Gem::Version.new("5.0")
|
63
|
+
|
64
|
+
"[#{ActiveRecord::Migration.current_version}]"
|
65
|
+
end
|
66
|
+
|
67
|
+
def activerecord_adapter
|
68
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
69
|
+
ActiveRecord::Base.connection_db_config.adapter
|
70
|
+
else
|
71
|
+
ActiveRecord::Base.connection_config.fetch(:adapter)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def primary_key_type(key = :id)
|
76
|
+
generators = ::Rails.application.config.generators
|
77
|
+
column_type = generators.options[:active_record][:primary_key_type]
|
78
|
+
|
79
|
+
return unless column_type
|
80
|
+
|
81
|
+
if key
|
82
|
+
", #{key}: :#{column_type}"
|
83
|
+
else
|
84
|
+
column_type
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def current_timestamp
|
89
|
+
if ActiveRecord.version >= Gem::Version.new("5.0")
|
90
|
+
%(-> { "CURRENT_TIMESTAMP" })
|
91
|
+
else
|
92
|
+
%(OpenStruct.new(quoted_id: "CURRENT_TIMESTAMP"))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
else # Sequel
|
96
|
+
include ::Rails::Generators::Migration
|
97
|
+
|
98
|
+
def self.next_migration_number(dirname)
|
99
|
+
next_migration_number = current_migration_number(dirname) + 1
|
100
|
+
[Time.now.utc.strftime('%Y%m%d%H%M%S'), format('%.14d', next_migration_number)].max
|
101
|
+
end
|
102
|
+
|
103
|
+
def db_migrate_path
|
104
|
+
"db/migrate"
|
105
|
+
end
|
106
|
+
|
107
|
+
def migration_chunk(feature)
|
108
|
+
"#{__dir__}/migration/sequel/#{feature}.erb"
|
109
|
+
end
|
110
|
+
|
111
|
+
def db
|
112
|
+
db = ::Sequel::DATABASES.first if defined?(::Sequel)
|
113
|
+
db or fail Rodauth::Rails::Error, "missing Sequel database connection"
|
114
|
+
end
|
115
|
+
end
|
36
116
|
end
|
37
117
|
end
|
38
118
|
end
|
@@ -1,14 +1,22 @@
|
|
1
1
|
class RodauthMailer < ApplicationMailer
|
2
2
|
def verify_account(account_id, key)
|
3
3
|
@email_link = rodauth.verify_account_url(key: email_token(account_id, key))
|
4
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
4
5
|
@account = Account.find(account_id)
|
6
|
+
<% else -%>
|
7
|
+
@account = Account.with_pk!(account_id)
|
8
|
+
<% end -%>
|
5
9
|
|
6
10
|
mail to: @account.email, subject: rodauth.verify_account_email_subject
|
7
11
|
end
|
8
12
|
|
9
13
|
def reset_password(account_id, key)
|
10
14
|
@email_link = rodauth.reset_password_url(key: email_token(account_id, key))
|
15
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
11
16
|
@account = Account.find(account_id)
|
17
|
+
<% else -%>
|
18
|
+
@account = Account.with_pk!(account_id)
|
19
|
+
<% end -%>
|
12
20
|
|
13
21
|
mail to: @account.email, subject: rodauth.reset_password_email_subject
|
14
22
|
end
|
@@ -17,27 +25,43 @@ class RodauthMailer < ApplicationMailer
|
|
17
25
|
@old_login = old_login
|
18
26
|
@new_login = new_login
|
19
27
|
@email_link = rodauth.verify_login_change_url(key: email_token(account_id, key))
|
28
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
20
29
|
@account = Account.find(account_id)
|
30
|
+
<% else -%>
|
31
|
+
@account = Account.with_pk!(account_id)
|
32
|
+
<% end -%>
|
21
33
|
|
22
34
|
mail to: new_login, subject: rodauth.verify_login_change_email_subject
|
23
35
|
end
|
24
36
|
|
25
37
|
def password_changed(account_id)
|
38
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
26
39
|
@account = Account.find(account_id)
|
40
|
+
<% else -%>
|
41
|
+
@account = Account.with_pk!(account_id)
|
42
|
+
<% end -%>
|
27
43
|
|
28
44
|
mail to: @account.email, subject: rodauth.password_changed_email_subject
|
29
45
|
end
|
30
46
|
|
31
47
|
# def email_auth(account_id, key)
|
32
48
|
# @email_link = rodauth.email_auth_url(key: email_token(account_id, key))
|
49
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
33
50
|
# @account = Account.find(account_id)
|
51
|
+
<% else -%>
|
52
|
+
# @account = Account.with_pk!(account_id)
|
53
|
+
<% end -%>
|
34
54
|
|
35
55
|
# mail to: @account.email, subject: rodauth.email_auth_email_subject
|
36
56
|
# end
|
37
57
|
|
38
58
|
# def unlock_account(account_id, key)
|
39
59
|
# @email_link = rodauth.unlock_account_url(key: email_token(account_id, key))
|
60
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
40
61
|
# @account = Account.find(account_id)
|
62
|
+
<% else -%>
|
63
|
+
# @account = Account.with_pk!(account_id)
|
64
|
+
<% end -%>
|
41
65
|
|
42
66
|
# mail to: @account.email, subject: rodauth.unlock_account_email_subject
|
43
67
|
# end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<% if defined?(ActiveRecord::Railtie) -%>
|
1
2
|
class Account < ApplicationRecord
|
2
3
|
include Rodauth::Rails.model
|
3
4
|
<% if ActiveRecord.version >= Gem::Version.new("7.0") -%>
|
@@ -6,3 +7,9 @@ class Account < ApplicationRecord
|
|
6
7
|
enum status: { unverified: 1, verified: 2, closed: 3 }
|
7
8
|
<% end -%>
|
8
9
|
end
|
10
|
+
<% else -%>
|
11
|
+
class Account < Sequel::Model
|
12
|
+
plugin :enum
|
13
|
+
enum :status, unverified: 1, verified: 2, closed: 3
|
14
|
+
end
|
15
|
+
<% end -%>
|
@@ -1,5 +1,13 @@
|
|
1
|
+
<% if defined?(::ActiveRecord::Railtie) -%>
|
1
2
|
class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
2
3
|
def change
|
3
4
|
<%= migration_content -%>
|
4
5
|
end
|
5
6
|
end
|
7
|
+
<% else -%>
|
8
|
+
Sequel.migration do
|
9
|
+
change do
|
10
|
+
<%= migration_content -%>
|
11
|
+
end
|
12
|
+
end
|
13
|
+
<% end -%>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Rodauth
|
2
|
+
module Rails
|
3
|
+
module Feature
|
4
|
+
module Associations
|
5
|
+
def associations
|
6
|
+
list = []
|
7
|
+
|
8
|
+
features.each do |feature|
|
9
|
+
case feature
|
10
|
+
when :remember
|
11
|
+
list << { name: :remember_key, type: :one, table: remember_table, foreign_key: remember_id_column }
|
12
|
+
when :verify_account
|
13
|
+
list << { name: :verification_key, type: :one, table: verify_account_table, foreign_key: verify_account_id_column }
|
14
|
+
when :reset_password
|
15
|
+
list << { name: :password_reset_key, type: :one, table: reset_password_table, foreign_key: reset_password_id_column }
|
16
|
+
when :verify_login_change
|
17
|
+
list << { name: :login_change_key, type: :one, table: verify_login_change_table, foreign_key: verify_login_change_id_column }
|
18
|
+
when :lockout
|
19
|
+
list << { name: :lockout, type: :one, table: account_lockouts_table, foreign_key: account_lockouts_id_column }
|
20
|
+
list << { name: :login_failure, type: :one, table: account_login_failures_table, foreign_key: account_login_failures_id_column }
|
21
|
+
when :email_auth
|
22
|
+
list << { name: :email_auth_key, type: :one, table: email_auth_table, foreign_key: email_auth_id_column }
|
23
|
+
when :account_expiration
|
24
|
+
list << { name: :activity_time, type: :one, table: account_activity_table, foreign_key: account_activity_id_column }
|
25
|
+
when :active_sessions
|
26
|
+
list << { name: :active_session_keys, type: :many, table: active_sessions_table, foreign_key: active_sessions_account_id_column }
|
27
|
+
when :audit_logging
|
28
|
+
list << { name: :authentication_audit_logs, type: :many, table: audit_logging_table, foreign_key: audit_logging_account_id_column }
|
29
|
+
when :disallow_password_reuse
|
30
|
+
list << { name: :previous_password_hashes, type: :many, table: previous_password_hash_table, foreign_key: previous_password_account_id_column }
|
31
|
+
when :jwt_refresh
|
32
|
+
list << { name: :jwt_refresh_keys, type: :many, table: jwt_refresh_token_table, foreign_key: jwt_refresh_token_account_id_column }
|
33
|
+
when :password_expiration
|
34
|
+
list << { name: :password_change_time, type: :one, table: password_expiration_table, foreign_key: password_expiration_id_column }
|
35
|
+
when :single_session
|
36
|
+
list << { name: :session_key, type: :one, table: single_session_table, foreign_key: single_session_id_column }
|
37
|
+
when :otp
|
38
|
+
list << { name: :otp_key, type: :one, table: otp_keys_table, foreign_key: otp_keys_id_column }
|
39
|
+
when :sms_codes
|
40
|
+
list << { name: :sms_code, type: :one, table: sms_codes_table, foreign_key: sms_id_column }
|
41
|
+
when :recovery_codes
|
42
|
+
list << { name: :recovery_codes, type: :many, table: recovery_codes_table, foreign_key: recovery_codes_id_column }
|
43
|
+
when :webauthn
|
44
|
+
list << { name: :webauthn_user_id, type: :one, table: webauthn_user_ids_table, foreign_key: webauthn_user_ids_account_id_column }
|
45
|
+
list << { name: :webauthn_keys, type: :many, table: webauthn_keys_table, foreign_key: webauthn_keys_account_id_column }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
list
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -11,6 +11,7 @@ module Rodauth
|
|
11
11
|
require "rodauth/rails/feature/email"
|
12
12
|
require "rodauth/rails/feature/instrumentation"
|
13
13
|
require "rodauth/rails/feature/internal_request"
|
14
|
+
require "rodauth/rails/feature/associations"
|
14
15
|
|
15
16
|
include Rodauth::Rails::Feature::Base
|
16
17
|
include Rodauth::Rails::Feature::Callbacks
|
@@ -19,5 +20,6 @@ module Rodauth
|
|
19
20
|
include Rodauth::Rails::Feature::Email
|
20
21
|
include Rodauth::Rails::Feature::Instrumentation
|
21
22
|
include Rodauth::Rails::Feature::InternalRequest
|
23
|
+
include Rodauth::Rails::Feature::Associations
|
22
24
|
end
|
23
25
|
end
|
@@ -9,6 +9,8 @@ module Rodauth
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(env)
|
12
|
+
return @app.call(env) if asset_request?(env)
|
13
|
+
|
12
14
|
app = Rodauth::Rails.app.new(@app)
|
13
15
|
|
14
16
|
# allow the Rails app to call Rodauth methods that throw :halt
|
@@ -16,6 +18,13 @@ module Rodauth
|
|
16
18
|
app.call(env)
|
17
19
|
end
|
18
20
|
end
|
21
|
+
|
22
|
+
# Check whether it's a request to an asset managed by Sprockets or Propshaft.
|
23
|
+
def asset_request?(env)
|
24
|
+
return false unless ::Rails.application.config.respond_to?(:assets)
|
25
|
+
|
26
|
+
env["PATH_INFO"] =~ %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
|
27
|
+
end
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
data/lib/rodauth/rails/model.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Rodauth
|
2
2
|
module Rails
|
3
3
|
class Model < Module
|
4
|
-
|
4
|
+
ASSOCIATION_TYPES = { one: :has_one, many: :has_many }
|
5
5
|
|
6
6
|
def initialize(auth_class, association_options: {})
|
7
7
|
@auth_class = auth_class
|
@@ -46,8 +46,8 @@ module Rodauth
|
|
46
46
|
def define_associations(model)
|
47
47
|
define_password_hash_association(model) unless rodauth.account_password_hash_column
|
48
48
|
|
49
|
-
|
50
|
-
define_association(model, **association)
|
49
|
+
rodauth.associations.each do |association|
|
50
|
+
define_association(model, **association, type: ASSOCIATION_TYPES.fetch(association[:type]))
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -74,19 +74,19 @@ module Rodauth
|
|
74
74
|
|
75
75
|
model.const_set(name.to_s.singularize.camelize, associated_model)
|
76
76
|
|
77
|
+
unless name == :authentication_audit_logs
|
78
|
+
dependent = type == :has_many ? :delete_all : :delete
|
79
|
+
end
|
80
|
+
|
77
81
|
model.public_send type, name, scope,
|
78
82
|
class_name: associated_model.name,
|
79
83
|
foreign_key: foreign_key,
|
80
|
-
dependent:
|
84
|
+
dependent: dependent,
|
81
85
|
inverse_of: :account,
|
82
86
|
**options,
|
83
87
|
**association_options(name)
|
84
88
|
end
|
85
89
|
|
86
|
-
def feature_associations
|
87
|
-
Rodauth::Rails::Model::Associations.call(rodauth)
|
88
|
-
end
|
89
|
-
|
90
90
|
def association_options(name)
|
91
91
|
options = @association_options
|
92
92
|
options = options.call(name) if options.respond_to?(:call)
|
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.4.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: 2022-04
|
11
|
+
date: 2022-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -167,26 +167,43 @@ files:
|
|
167
167
|
- LICENSE.txt
|
168
168
|
- README.md
|
169
169
|
- lib/generators/rodauth/install_generator.rb
|
170
|
-
- lib/generators/rodauth/migration/account_expiration.erb
|
171
|
-
- lib/generators/rodauth/migration/active_sessions.erb
|
172
|
-
- lib/generators/rodauth/migration/audit_logging.erb
|
173
|
-
- lib/generators/rodauth/migration/base.erb
|
174
|
-
- lib/generators/rodauth/migration/disallow_password_reuse.erb
|
175
|
-
- lib/generators/rodauth/migration/email_auth.erb
|
176
|
-
- lib/generators/rodauth/migration/jwt_refresh.erb
|
177
|
-
- lib/generators/rodauth/migration/lockout.erb
|
178
|
-
- lib/generators/rodauth/migration/otp.erb
|
179
|
-
- lib/generators/rodauth/migration/password_expiration.erb
|
180
|
-
- lib/generators/rodauth/migration/recovery_codes.erb
|
181
|
-
- lib/generators/rodauth/migration/remember.erb
|
182
|
-
- lib/generators/rodauth/migration/reset_password.erb
|
183
|
-
- lib/generators/rodauth/migration/single_session.erb
|
184
|
-
- lib/generators/rodauth/migration/sms_codes.erb
|
185
|
-
- lib/generators/rodauth/migration/verify_account.erb
|
186
|
-
- lib/generators/rodauth/migration/verify_login_change.erb
|
187
|
-
- lib/generators/rodauth/migration/webauthn.erb
|
170
|
+
- lib/generators/rodauth/migration/active_record/account_expiration.erb
|
171
|
+
- lib/generators/rodauth/migration/active_record/active_sessions.erb
|
172
|
+
- lib/generators/rodauth/migration/active_record/audit_logging.erb
|
173
|
+
- lib/generators/rodauth/migration/active_record/base.erb
|
174
|
+
- lib/generators/rodauth/migration/active_record/disallow_password_reuse.erb
|
175
|
+
- lib/generators/rodauth/migration/active_record/email_auth.erb
|
176
|
+
- lib/generators/rodauth/migration/active_record/jwt_refresh.erb
|
177
|
+
- lib/generators/rodauth/migration/active_record/lockout.erb
|
178
|
+
- lib/generators/rodauth/migration/active_record/otp.erb
|
179
|
+
- lib/generators/rodauth/migration/active_record/password_expiration.erb
|
180
|
+
- lib/generators/rodauth/migration/active_record/recovery_codes.erb
|
181
|
+
- lib/generators/rodauth/migration/active_record/remember.erb
|
182
|
+
- lib/generators/rodauth/migration/active_record/reset_password.erb
|
183
|
+
- lib/generators/rodauth/migration/active_record/single_session.erb
|
184
|
+
- lib/generators/rodauth/migration/active_record/sms_codes.erb
|
185
|
+
- lib/generators/rodauth/migration/active_record/verify_account.erb
|
186
|
+
- lib/generators/rodauth/migration/active_record/verify_login_change.erb
|
187
|
+
- lib/generators/rodauth/migration/active_record/webauthn.erb
|
188
|
+
- lib/generators/rodauth/migration/sequel/account_expiration.erb
|
189
|
+
- lib/generators/rodauth/migration/sequel/active_sessions.erb
|
190
|
+
- lib/generators/rodauth/migration/sequel/audit_logging.erb
|
191
|
+
- lib/generators/rodauth/migration/sequel/base.erb
|
192
|
+
- lib/generators/rodauth/migration/sequel/disallow_password_reuse.erb
|
193
|
+
- lib/generators/rodauth/migration/sequel/email_auth.erb
|
194
|
+
- lib/generators/rodauth/migration/sequel/jwt_refresh.erb
|
195
|
+
- lib/generators/rodauth/migration/sequel/lockout.erb
|
196
|
+
- lib/generators/rodauth/migration/sequel/otp.erb
|
197
|
+
- lib/generators/rodauth/migration/sequel/password_expiration.erb
|
198
|
+
- lib/generators/rodauth/migration/sequel/recovery_codes.erb
|
199
|
+
- lib/generators/rodauth/migration/sequel/remember.erb
|
200
|
+
- lib/generators/rodauth/migration/sequel/reset_password.erb
|
201
|
+
- lib/generators/rodauth/migration/sequel/single_session.erb
|
202
|
+
- lib/generators/rodauth/migration/sequel/sms_codes.erb
|
203
|
+
- lib/generators/rodauth/migration/sequel/verify_account.erb
|
204
|
+
- lib/generators/rodauth/migration/sequel/verify_login_change.erb
|
205
|
+
- lib/generators/rodauth/migration/sequel/webauthn.erb
|
188
206
|
- lib/generators/rodauth/migration_generator.rb
|
189
|
-
- lib/generators/rodauth/migration_helpers.rb
|
190
207
|
- lib/generators/rodauth/templates/INSTRUCTIONS
|
191
208
|
- lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb
|
192
209
|
- lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb
|
@@ -247,6 +264,7 @@ files:
|
|
247
264
|
- lib/rodauth/rails/auth.rb
|
248
265
|
- lib/rodauth/rails/controller_methods.rb
|
249
266
|
- lib/rodauth/rails/feature.rb
|
267
|
+
- lib/rodauth/rails/feature/associations.rb
|
250
268
|
- lib/rodauth/rails/feature/base.rb
|
251
269
|
- lib/rodauth/rails/feature/callbacks.rb
|
252
270
|
- lib/rodauth/rails/feature/csrf.rb
|
@@ -256,7 +274,6 @@ files:
|
|
256
274
|
- lib/rodauth/rails/feature/render.rb
|
257
275
|
- lib/rodauth/rails/middleware.rb
|
258
276
|
- lib/rodauth/rails/model.rb
|
259
|
-
- lib/rodauth/rails/model/associations.rb
|
260
277
|
- lib/rodauth/rails/railtie.rb
|
261
278
|
- lib/rodauth/rails/tasks.rake
|
262
279
|
- lib/rodauth/rails/test.rb
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require "erb"
|
2
|
-
|
3
|
-
module Rodauth
|
4
|
-
module Rails
|
5
|
-
module Generators
|
6
|
-
module MigrationHelpers
|
7
|
-
attr_reader :migration_class_name
|
8
|
-
|
9
|
-
def migration_template(source, destination = File.basename(source))
|
10
|
-
@migration_class_name = destination.chomp(".rb").camelize
|
11
|
-
|
12
|
-
super source, File.join(db_migrate_path, destination)
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def migration_content
|
18
|
-
migration_features
|
19
|
-
.select { |feature| File.exist?("#{__dir__}/migration/#{feature}.erb") }
|
20
|
-
.map { |feature| File.read("#{__dir__}/migration/#{feature}.erb") }
|
21
|
-
.map { |content| erb_eval(content) }
|
22
|
-
.join("\n")
|
23
|
-
.indent(4)
|
24
|
-
end
|
25
|
-
|
26
|
-
def activerecord_adapter
|
27
|
-
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
28
|
-
ActiveRecord::Base.connection_db_config.adapter
|
29
|
-
else
|
30
|
-
ActiveRecord::Base.connection_config.fetch(:adapter)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def migration_version
|
35
|
-
return unless ActiveRecord.version >= Gem::Version.new("5.0")
|
36
|
-
|
37
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
38
|
-
end
|
39
|
-
|
40
|
-
def db_migrate_path
|
41
|
-
return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
|
42
|
-
|
43
|
-
super
|
44
|
-
end
|
45
|
-
|
46
|
-
def primary_key_type(key = :id)
|
47
|
-
generators = ::Rails.application.config.generators
|
48
|
-
column_type = generators.options[:active_record][:primary_key_type]
|
49
|
-
|
50
|
-
return unless column_type
|
51
|
-
|
52
|
-
if key
|
53
|
-
", #{key}: :#{column_type}"
|
54
|
-
else
|
55
|
-
column_type
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def erb_eval(content)
|
60
|
-
if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
|
61
|
-
ERB.new(content, trim_mode: "-").result(binding)
|
62
|
-
else
|
63
|
-
ERB.new(content, 0, "-").result(binding)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def current_timestamp
|
68
|
-
if ActiveRecord.version >= Gem::Version.new("5.0")
|
69
|
-
%(-> { "CURRENT_TIMESTAMP" })
|
70
|
-
else
|
71
|
-
%(OpenStruct.new(quoted_id: "CURRENT_TIMESTAMP"))
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,195 +0,0 @@
|
|
1
|
-
module Rodauth
|
2
|
-
module Rails
|
3
|
-
class Model
|
4
|
-
class Associations
|
5
|
-
attr_reader :rodauth
|
6
|
-
|
7
|
-
def self.call(rodauth)
|
8
|
-
new(rodauth).call
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(rodauth)
|
12
|
-
@rodauth = rodauth
|
13
|
-
end
|
14
|
-
|
15
|
-
def call
|
16
|
-
rodauth.features
|
17
|
-
.select { |feature| respond_to?(feature, true) }
|
18
|
-
.flat_map { |feature| send(feature) }
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def remember
|
24
|
-
{
|
25
|
-
name: :remember_key,
|
26
|
-
type: :has_one,
|
27
|
-
table: rodauth.remember_table,
|
28
|
-
foreign_key: rodauth.remember_id_column,
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def verify_account
|
33
|
-
{
|
34
|
-
name: :verification_key,
|
35
|
-
type: :has_one,
|
36
|
-
table: rodauth.verify_account_table,
|
37
|
-
foreign_key: rodauth.verify_account_id_column,
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
def reset_password
|
42
|
-
{
|
43
|
-
name: :password_reset_key,
|
44
|
-
type: :has_one,
|
45
|
-
table: rodauth.reset_password_table,
|
46
|
-
foreign_key: rodauth.reset_password_id_column,
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
def verify_login_change
|
51
|
-
{
|
52
|
-
name: :login_change_key,
|
53
|
-
type: :has_one,
|
54
|
-
table: rodauth.verify_login_change_table,
|
55
|
-
foreign_key: rodauth.verify_login_change_id_column,
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def lockout
|
60
|
-
[
|
61
|
-
{
|
62
|
-
name: :lockout,
|
63
|
-
type: :has_one,
|
64
|
-
table: rodauth.account_lockouts_table,
|
65
|
-
foreign_key: rodauth.account_lockouts_id_column,
|
66
|
-
},
|
67
|
-
{
|
68
|
-
name: :login_failure,
|
69
|
-
type: :has_one,
|
70
|
-
table: rodauth.account_login_failures_table,
|
71
|
-
foreign_key: rodauth.account_login_failures_id_column,
|
72
|
-
}
|
73
|
-
]
|
74
|
-
end
|
75
|
-
|
76
|
-
def email_auth
|
77
|
-
{
|
78
|
-
name: :email_auth_key,
|
79
|
-
type: :has_one,
|
80
|
-
table: rodauth.email_auth_table,
|
81
|
-
foreign_key: rodauth.email_auth_id_column,
|
82
|
-
}
|
83
|
-
end
|
84
|
-
|
85
|
-
def account_expiration
|
86
|
-
{
|
87
|
-
name: :activity_time,
|
88
|
-
type: :has_one,
|
89
|
-
table: rodauth.account_activity_table,
|
90
|
-
foreign_key: rodauth.account_activity_id_column,
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def active_sessions
|
95
|
-
{
|
96
|
-
name: :active_session_keys,
|
97
|
-
type: :has_many,
|
98
|
-
table: rodauth.active_sessions_table,
|
99
|
-
foreign_key: rodauth.active_sessions_account_id_column,
|
100
|
-
}
|
101
|
-
end
|
102
|
-
|
103
|
-
def audit_logging
|
104
|
-
{
|
105
|
-
name: :authentication_audit_logs,
|
106
|
-
type: :has_many,
|
107
|
-
table: rodauth.audit_logging_table,
|
108
|
-
foreign_key: rodauth.audit_logging_account_id_column,
|
109
|
-
dependent: nil,
|
110
|
-
}
|
111
|
-
end
|
112
|
-
|
113
|
-
def disallow_password_reuse
|
114
|
-
{
|
115
|
-
name: :previous_password_hashes,
|
116
|
-
type: :has_many,
|
117
|
-
table: rodauth.previous_password_hash_table,
|
118
|
-
foreign_key: rodauth.previous_password_account_id_column,
|
119
|
-
}
|
120
|
-
end
|
121
|
-
|
122
|
-
def jwt_refresh
|
123
|
-
{
|
124
|
-
name: :jwt_refresh_keys,
|
125
|
-
type: :has_many,
|
126
|
-
table: rodauth.jwt_refresh_token_table,
|
127
|
-
foreign_key: rodauth.jwt_refresh_token_account_id_column,
|
128
|
-
}
|
129
|
-
end
|
130
|
-
|
131
|
-
def password_expiration
|
132
|
-
{
|
133
|
-
name: :password_change_time,
|
134
|
-
type: :has_one,
|
135
|
-
table: rodauth.password_expiration_table,
|
136
|
-
foreign_key: rodauth.password_expiration_id_column,
|
137
|
-
}
|
138
|
-
end
|
139
|
-
|
140
|
-
def single_session
|
141
|
-
{
|
142
|
-
name: :session_key,
|
143
|
-
type: :has_one,
|
144
|
-
table: rodauth.single_session_table,
|
145
|
-
foreign_key: rodauth.single_session_id_column,
|
146
|
-
}
|
147
|
-
end
|
148
|
-
|
149
|
-
def otp
|
150
|
-
{
|
151
|
-
name: :otp_key,
|
152
|
-
type: :has_one,
|
153
|
-
table: rodauth.otp_keys_table,
|
154
|
-
foreign_key: rodauth.otp_keys_id_column,
|
155
|
-
}
|
156
|
-
end
|
157
|
-
|
158
|
-
def sms_codes
|
159
|
-
{
|
160
|
-
name: :sms_code,
|
161
|
-
type: :has_one,
|
162
|
-
table: rodauth.sms_codes_table,
|
163
|
-
foreign_key: rodauth.sms_id_column,
|
164
|
-
}
|
165
|
-
end
|
166
|
-
|
167
|
-
def recovery_codes
|
168
|
-
{
|
169
|
-
name: :recovery_codes,
|
170
|
-
type: :has_many,
|
171
|
-
table: rodauth.recovery_codes_table,
|
172
|
-
foreign_key: rodauth.recovery_codes_id_column,
|
173
|
-
}
|
174
|
-
end
|
175
|
-
|
176
|
-
def webauthn
|
177
|
-
[
|
178
|
-
{
|
179
|
-
name: :webauthn_user_id,
|
180
|
-
type: :has_one,
|
181
|
-
table: rodauth.webauthn_user_ids_table,
|
182
|
-
foreign_key: rodauth.webauthn_user_ids_account_id_column,
|
183
|
-
},
|
184
|
-
{
|
185
|
-
name: :webauthn_keys,
|
186
|
-
type: :has_many,
|
187
|
-
table: rodauth.webauthn_keys_table,
|
188
|
-
foreign_key: rodauth.webauthn_keys_account_id_column,
|
189
|
-
}
|
190
|
-
]
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|