rodauth-tools 0.3.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 +7 -0
- data/.gitignore +93 -0
- data/.gitlint +9 -0
- data/.markdownlint-cli2.jsonc +26 -0
- data/.pre-commit-config.yaml +46 -0
- data/.rubocop.yml +18 -0
- data/.rubocop_todo.yml +243 -0
- data/CHANGELOG.md +81 -0
- data/CLAUDE.md +262 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +111 -0
- data/Gemfile +35 -0
- data/Gemfile.lock +356 -0
- data/LICENSE.txt +21 -0
- data/README.md +339 -0
- data/Rakefile +8 -0
- data/lib/rodauth/features/external_identity.rb +946 -0
- data/lib/rodauth/features/hmac_secret_guard.rb +119 -0
- data/lib/rodauth/features/jwt_secret_guard.rb +120 -0
- data/lib/rodauth/features/table_guard.rb +937 -0
- data/lib/rodauth/sequel_generator.rb +531 -0
- data/lib/rodauth/table_inspector.rb +124 -0
- data/lib/rodauth/template_inspector.rb +134 -0
- data/lib/rodauth/tools/console_helpers.rb +158 -0
- data/lib/rodauth/tools/migration/sequel/account_expiration.erb +9 -0
- data/lib/rodauth/tools/migration/sequel/active_sessions.erb +10 -0
- data/lib/rodauth/tools/migration/sequel/audit_logging.erb +12 -0
- data/lib/rodauth/tools/migration/sequel/base.erb +41 -0
- data/lib/rodauth/tools/migration/sequel/disallow_password_reuse.erb +8 -0
- data/lib/rodauth/tools/migration/sequel/email_auth.erb +17 -0
- data/lib/rodauth/tools/migration/sequel/jwt_refresh.erb +18 -0
- data/lib/rodauth/tools/migration/sequel/lockout.erb +21 -0
- data/lib/rodauth/tools/migration/sequel/otp.erb +9 -0
- data/lib/rodauth/tools/migration/sequel/otp_unlock.erb +8 -0
- data/lib/rodauth/tools/migration/sequel/password_expiration.erb +7 -0
- data/lib/rodauth/tools/migration/sequel/recovery_codes.erb +8 -0
- data/lib/rodauth/tools/migration/sequel/remember.erb +16 -0
- data/lib/rodauth/tools/migration/sequel/reset_password.erb +17 -0
- data/lib/rodauth/tools/migration/sequel/single_session.erb +7 -0
- data/lib/rodauth/tools/migration/sequel/sms_codes.erb +10 -0
- data/lib/rodauth/tools/migration/sequel/verify_account.erb +9 -0
- data/lib/rodauth/tools/migration/sequel/verify_login_change.erb +17 -0
- data/lib/rodauth/tools/migration/sequel/webauthn.erb +15 -0
- data/lib/rodauth/tools/migration.rb +188 -0
- data/lib/rodauth/tools/version.rb +9 -0
- data/lib/rodauth/tools.rb +29 -0
- data/package-lock.json +500 -0
- data/package.json +11 -0
- data/rodauth-tools.gemspec +40 -0
- metadata +136 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# lib/rodauth/template_inspector.rb
|
|
2
|
+
#
|
|
3
|
+
# frozen_string_literal: true
|
|
4
|
+
|
|
5
|
+
require 'erb'
|
|
6
|
+
require 'dry/inflector'
|
|
7
|
+
|
|
8
|
+
module Rodauth
|
|
9
|
+
# Inspects ERB templates to extract table information
|
|
10
|
+
#
|
|
11
|
+
# This module solves the "hidden tables" problem where ERB templates create
|
|
12
|
+
# tables that don't have corresponding *_table methods in Rodauth features.
|
|
13
|
+
# For example, base.erb creates account_statuses and account_password_hashes
|
|
14
|
+
# tables, but only accounts_table method exists.
|
|
15
|
+
#
|
|
16
|
+
# By evaluating ERB templates, we can discover ALL tables that will be created,
|
|
17
|
+
# which is essential for generating complete DROP statements.
|
|
18
|
+
module TemplateInspector
|
|
19
|
+
# Extract table names from a single ERB template
|
|
20
|
+
#
|
|
21
|
+
# @param feature [Symbol] Feature name (e.g., :base, :verify_account)
|
|
22
|
+
# @param table_prefix [String] Table prefix to use (default: 'account')
|
|
23
|
+
# @param db_type [Symbol] Database type for conditional logic (default: :postgres)
|
|
24
|
+
# @return [Array<Symbol>] Array of table names that will be created
|
|
25
|
+
def self.extract_tables_from_template(feature, table_prefix: 'account', db_type: :postgres)
|
|
26
|
+
template_path = template_path_for_feature(feature)
|
|
27
|
+
return [] unless File.exist?(template_path)
|
|
28
|
+
|
|
29
|
+
template_content = File.read(template_path)
|
|
30
|
+
|
|
31
|
+
# Create binding context with necessary methods
|
|
32
|
+
context = BindingContext.new(table_prefix, db_type)
|
|
33
|
+
|
|
34
|
+
# Evaluate ERB template
|
|
35
|
+
begin
|
|
36
|
+
rendered = ERB.new(template_content, trim_mode: '-').result(context.get_binding)
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
warn "Failed to evaluate template for #{feature}: #{e.message}"
|
|
39
|
+
return []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Extract table names from create_table calls
|
|
43
|
+
# Matches: create_table(:table_name) or create_table?(:table_name)
|
|
44
|
+
tables = rendered.scan(/create_table\??[:(\s]+:?(\w+)/).flatten
|
|
45
|
+
|
|
46
|
+
tables.map(&:to_sym).uniq
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get all tables for a set of features
|
|
50
|
+
#
|
|
51
|
+
# @param features [Array<Symbol>] Feature names
|
|
52
|
+
# @param table_prefix [String] Table prefix to use
|
|
53
|
+
# @param db_type [Symbol] Database type
|
|
54
|
+
# @return [Array<Symbol>] Array of all table names across features
|
|
55
|
+
def self.all_tables_for_features(features, table_prefix: 'account', db_type: :postgres)
|
|
56
|
+
tables = []
|
|
57
|
+
|
|
58
|
+
features.each do |feature|
|
|
59
|
+
feature_tables = extract_tables_from_template(
|
|
60
|
+
feature,
|
|
61
|
+
table_prefix: table_prefix,
|
|
62
|
+
db_type: db_type
|
|
63
|
+
)
|
|
64
|
+
tables.concat(feature_tables)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
tables.uniq
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Get template path for a feature
|
|
71
|
+
#
|
|
72
|
+
# @param feature [Symbol] Feature name
|
|
73
|
+
# @return [String] Absolute path to ERB template
|
|
74
|
+
def self.template_path_for_feature(feature)
|
|
75
|
+
File.join(__dir__, 'tools', 'migration', 'sequel', "#{feature}.erb")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Binding context for ERB evaluation
|
|
79
|
+
#
|
|
80
|
+
# Provides minimal methods needed for ERB template evaluation without
|
|
81
|
+
# requiring a full database connection or Rodauth instance.
|
|
82
|
+
class BindingContext
|
|
83
|
+
attr_reader :table_prefix
|
|
84
|
+
|
|
85
|
+
def initialize(table_prefix, db_type)
|
|
86
|
+
@table_prefix = table_prefix
|
|
87
|
+
@db_type = db_type
|
|
88
|
+
@inflector = Dry::Inflector.new
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Pluralize a word using dry-inflector
|
|
92
|
+
def pluralize(word)
|
|
93
|
+
@inflector.pluralize(word.to_s)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Mock database object for template evaluation
|
|
97
|
+
#
|
|
98
|
+
# Templates check db.database_type and db.supports_partial_indexes?
|
|
99
|
+
# to generate database-specific code.
|
|
100
|
+
def db
|
|
101
|
+
@db ||= MockDatabase.new(@db_type)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Get binding for ERB evaluation
|
|
105
|
+
def get_binding
|
|
106
|
+
binding
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Mock Sequel database for ERB templates
|
|
110
|
+
class MockDatabase
|
|
111
|
+
attr_reader :database_type
|
|
112
|
+
|
|
113
|
+
def initialize(db_type)
|
|
114
|
+
@database_type = db_type
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def supports_partial_indexes?
|
|
118
|
+
# PostgreSQL and SQLite support partial indexes
|
|
119
|
+
%i[postgres sqlite].include?(@database_type)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Stub other methods that might be called in templates
|
|
123
|
+
def method_missing(_method, *_args)
|
|
124
|
+
# Return a safe default for unknown methods
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def respond_to_missing?(_method, _include_private = false)
|
|
129
|
+
true
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# lib/rodauth/tools/console_helpers.rb
|
|
2
|
+
#
|
|
3
|
+
# frozen_string_literal: true
|
|
4
|
+
|
|
5
|
+
module Rodauth
|
|
6
|
+
module Tools
|
|
7
|
+
# Console helper methods for inspecting Rodauth table configuration
|
|
8
|
+
#
|
|
9
|
+
# Usage in console:
|
|
10
|
+
# require 'rodauth/tools/console_helpers'
|
|
11
|
+
# include Rodauth::Tools::ConsoleHelpers
|
|
12
|
+
# rodauth.table_configuration
|
|
13
|
+
#
|
|
14
|
+
# Or use the convenience loader:
|
|
15
|
+
# Rodauth::Tools::ConsoleHelpers.load!(rodauth_instance)
|
|
16
|
+
module ConsoleHelpers
|
|
17
|
+
# Get or create a Rodauth instance
|
|
18
|
+
#
|
|
19
|
+
# Override this method in your console script to provide the actual instance
|
|
20
|
+
def rodauth
|
|
21
|
+
@rodauth ||= raise NotImplementedError, 'You must define a `rodauth` method that returns a Rodauth instance'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Get discovered table configuration
|
|
25
|
+
def config
|
|
26
|
+
rodauth.table_configuration
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Get missing tables
|
|
30
|
+
def missing
|
|
31
|
+
rodauth.missing_tables
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# List all required table names
|
|
35
|
+
def tables
|
|
36
|
+
rodauth.list_all_required_tables
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get detailed status for each table
|
|
40
|
+
def status
|
|
41
|
+
rodauth.table_status
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Access database connection
|
|
45
|
+
def db
|
|
46
|
+
rodauth.db if rodauth.respond_to?(:db)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Pretty-print table configuration
|
|
50
|
+
def show_config
|
|
51
|
+
puts "\n=== Table Configuration ==="
|
|
52
|
+
config.each do |method, info|
|
|
53
|
+
puts "\n#{method}:"
|
|
54
|
+
puts " Table: #{info[:name]}"
|
|
55
|
+
puts " Feature: #{info[:feature]}"
|
|
56
|
+
puts " Type: #{info[:structure][:type]}"
|
|
57
|
+
puts " Exists: #{rodauth.table_exists?(info[:name])}"
|
|
58
|
+
end
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Pretty-print missing tables
|
|
63
|
+
def show_missing
|
|
64
|
+
puts "\n=== Missing Tables ==="
|
|
65
|
+
if missing.empty?
|
|
66
|
+
puts '✓ All tables exist!'
|
|
67
|
+
else
|
|
68
|
+
missing.each do |info|
|
|
69
|
+
puts "✗ #{info[:table]} (feature: #{info[:feature]})"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Pretty-print table status
|
|
76
|
+
def show_status
|
|
77
|
+
puts "\n=== Table Status ==="
|
|
78
|
+
status.each do |info|
|
|
79
|
+
marker = info[:exists] ? '✓' : '✗'
|
|
80
|
+
puts "#{marker} #{info[:table].to_s.ljust(30)} (#{info[:feature]})"
|
|
81
|
+
end
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Create missing tables immediately
|
|
86
|
+
def create_tables!
|
|
87
|
+
puts "\n=== Creating Missing Tables ==="
|
|
88
|
+
missing_list = missing
|
|
89
|
+
if missing_list.empty?
|
|
90
|
+
puts '✓ All tables already exist!'
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
generator = Rodauth::SequelGenerator.new(missing_list, rodauth)
|
|
95
|
+
generator.execute_creates(db)
|
|
96
|
+
puts "✓ Created #{missing_list.size} table(s)"
|
|
97
|
+
show_status
|
|
98
|
+
nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Display generated migration code
|
|
102
|
+
def show_migration
|
|
103
|
+
puts "\n=== Generated Migration ==="
|
|
104
|
+
missing_list = missing
|
|
105
|
+
if missing_list.empty?
|
|
106
|
+
puts '✓ All tables exist - no migration needed'
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
generator = Rodauth::SequelGenerator.new(missing_list, rodauth)
|
|
111
|
+
puts generator.generate_migration
|
|
112
|
+
nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Show help message
|
|
116
|
+
def help
|
|
117
|
+
puts <<~HELP
|
|
118
|
+
|
|
119
|
+
🔍 Rodauth Console Helpers
|
|
120
|
+
============================
|
|
121
|
+
|
|
122
|
+
rodauth # Get Rodauth instance
|
|
123
|
+
config # Get discovered table configuration
|
|
124
|
+
missing # Get missing tables
|
|
125
|
+
tables # List all required table names
|
|
126
|
+
status # Get detailed status for each table
|
|
127
|
+
db # Access Sequel database connection
|
|
128
|
+
|
|
129
|
+
show_config # Pretty-print table configuration
|
|
130
|
+
show_missing # Pretty-print missing tables
|
|
131
|
+
show_status # Pretty-print table status
|
|
132
|
+
create_tables! # Create all missing tables
|
|
133
|
+
show_migration # Display generated migration code
|
|
134
|
+
|
|
135
|
+
help # Show this help
|
|
136
|
+
|
|
137
|
+
Examples:
|
|
138
|
+
---------
|
|
139
|
+
config.keys # See all table methods
|
|
140
|
+
missing.size # How many tables are missing?
|
|
141
|
+
rodauth.table_exists?(:accounts) # Check specific table
|
|
142
|
+
db.tables # See what's in the database
|
|
143
|
+
|
|
144
|
+
HELP
|
|
145
|
+
nil
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Class method to extend a context with helpers and set up rodauth method
|
|
149
|
+
#
|
|
150
|
+
# @param rodauth_instance [Rodauth::Auth] Rodauth instance
|
|
151
|
+
# @return [Module] Extended module
|
|
152
|
+
def self.extended(base)
|
|
153
|
+
puts "\n✓ Rodauth console helpers loaded!"
|
|
154
|
+
base.help if base.respond_to?(:help)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the account expiration feature
|
|
4
|
+
create_table(:<%= table_prefix %>_activity_times) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
DateTime :last_activity_at, null: false
|
|
7
|
+
DateTime :last_login_at, null: false
|
|
8
|
+
DateTime :expired_at
|
|
9
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the active sessions feature
|
|
4
|
+
create_table(:<%= table_prefix %>_active_session_keys) do
|
|
5
|
+
foreign_key :<%= table_prefix %>_id, :<%= pluralize(table_prefix) %>, type: :Bignum
|
|
6
|
+
String :session_id
|
|
7
|
+
Time :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
8
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
9
|
+
primary_key [:<%= table_prefix %>_id, :session_id]
|
|
10
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the audit logging feature
|
|
4
|
+
create_table(:<%= table_prefix %>_authentication_audit_logs) do
|
|
5
|
+
primary_key :id, type: :Bignum
|
|
6
|
+
foreign_key :<%= table_prefix %>_id, :<%= pluralize(table_prefix) %>, null: false, type: :Bignum
|
|
7
|
+
DateTime :at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
8
|
+
String :message, null: false
|
|
9
|
+
column :metadata, <%= json_type %>
|
|
10
|
+
index [:<%= table_prefix %>_id, :at], name: :audit_<%= table_prefix %>_at_idx
|
|
11
|
+
index :at, name: :audit_at_idx
|
|
12
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/base.erb %>
|
|
2
|
+
|
|
3
|
+
db = self
|
|
4
|
+
<% if db.database_type == :postgres -%>
|
|
5
|
+
begin
|
|
6
|
+
run "CREATE EXTENSION IF NOT EXISTS citext"
|
|
7
|
+
rescue NoMethodError # migration is being reverted
|
|
8
|
+
end
|
|
9
|
+
<% end -%>
|
|
10
|
+
|
|
11
|
+
# Sequel extension
|
|
12
|
+
extension :date_arithmetic
|
|
13
|
+
|
|
14
|
+
# Used by the account verification and close account features
|
|
15
|
+
create_table(:<%= table_prefix %>_statuses) do
|
|
16
|
+
Integer :id, primary_key: true
|
|
17
|
+
String :name, null: false, unique: true
|
|
18
|
+
end
|
|
19
|
+
from(:<%= table_prefix %>_statuses).import([:id, :name], [[1, 'Unverified'], [2, 'Verified'], [3, 'Closed']])
|
|
20
|
+
|
|
21
|
+
create_table(:<%= table_prefix %>_password_hashes) do
|
|
22
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
23
|
+
String :password_hash, null: false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
create_table(:<%= pluralize(table_prefix) %>) do
|
|
27
|
+
primary_key :id, type: :Bignum
|
|
28
|
+
foreign_key :status_id, :<%= table_prefix %>_statuses, null: false, default: 1
|
|
29
|
+
<% if db.database_type == :postgres -%>
|
|
30
|
+
citext :email, null: false
|
|
31
|
+
constraint :valid_email, email: /^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
|
|
32
|
+
<% else -%>
|
|
33
|
+
String :email, null: false
|
|
34
|
+
<% end -%>
|
|
35
|
+
<% if db.supports_partial_indexes? -%>
|
|
36
|
+
index :email, unique: true, where: {status_id: [1, 2]}
|
|
37
|
+
<% else -%>
|
|
38
|
+
index :email, unique: true
|
|
39
|
+
<% end -%>
|
|
40
|
+
String :password_hash, null: true
|
|
41
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the disallow password reuse feature
|
|
4
|
+
create_table(:<%= table_prefix %>_previous_password_hashes) do
|
|
5
|
+
primary_key :id, type: :Bignum
|
|
6
|
+
foreign_key :<%= table_prefix %>_id, :<%= pluralize(table_prefix) %>, type: :Bignum
|
|
7
|
+
String :password_hash, null: false
|
|
8
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the email auth feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_email_auth_keys) do
|
|
13
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
14
|
+
String :key, null: false
|
|
15
|
+
DateTime :deadline, deadline_opts[1]
|
|
16
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
17
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the jwt refresh feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_jwt_refresh_keys) do
|
|
13
|
+
primary_key :id, type: :Bignum
|
|
14
|
+
foreign_key :<%= table_prefix %>_id, :<%= pluralize(table_prefix) %>, null: false, type: :Bignum
|
|
15
|
+
String :key, null: false
|
|
16
|
+
DateTime :deadline, deadline_opts[1]
|
|
17
|
+
index :<%= table_prefix %>_id, name: :<%= table_prefix %>_jwt_rk_<%= table_prefix %>_id_idx
|
|
18
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the lockout feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_login_failures) do
|
|
13
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
14
|
+
Integer :number, null: false, default: 1
|
|
15
|
+
end
|
|
16
|
+
create_table(:<%= table_prefix %>_lockouts) do
|
|
17
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
18
|
+
String :key, null: false
|
|
19
|
+
DateTime :deadline, deadline_opts[1]
|
|
20
|
+
DateTime :email_last_sent
|
|
21
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the otp feature
|
|
4
|
+
create_table(:<%= table_prefix %>_otp_keys) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
String :key, null: false
|
|
7
|
+
Integer :num_failures, null: false, default: 0
|
|
8
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
9
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the otp_unlock feature
|
|
4
|
+
create_table(:<%= table_prefix %>_otp_unlocks) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
Integer :num_successes, null: false, default: 1
|
|
7
|
+
Time :next_auth_attempt_after, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
8
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the password expiration feature
|
|
4
|
+
create_table(:<%= table_prefix %>_password_change_times) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
DateTime :changed_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
7
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the recovery codes feature
|
|
4
|
+
create_table(:<%= table_prefix %>_recovery_codes) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, type: :Bignum
|
|
6
|
+
String :code
|
|
7
|
+
primary_key [:id, :code]
|
|
8
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the remember me feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_remember_keys) do
|
|
13
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
14
|
+
String :key, null: false
|
|
15
|
+
DateTime :deadline, deadline_opts[14]
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the password reset feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_password_reset_keys) do
|
|
13
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
14
|
+
String :key, null: false
|
|
15
|
+
DateTime :deadline, deadline_opts[1]
|
|
16
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
17
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the single session feature
|
|
4
|
+
create_table(:<%= table_prefix %>_session_keys) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
String :key, null: false
|
|
7
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the sms codes feature
|
|
4
|
+
create_table(:<%= table_prefix %>_sms_codes) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
String :phone_number, null: false
|
|
7
|
+
Integer :num_failures
|
|
8
|
+
String :code
|
|
9
|
+
DateTime :code_issued_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
10
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the account verification feature
|
|
4
|
+
create_table(:<%= table_prefix %>_verification_keys) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
String :key, null: false
|
|
7
|
+
DateTime :requested_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
8
|
+
DateTime :email_last_sent, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
9
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the verify login change feature
|
|
4
|
+
deadline_opts = proc do |days|
|
|
5
|
+
if db.database_type == :mysql
|
|
6
|
+
{null: false}
|
|
7
|
+
else
|
|
8
|
+
{null: false, default: Sequel.date_add(Sequel::CURRENT_TIMESTAMP, days: days)}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table(:<%= table_prefix %>_login_change_keys) do
|
|
13
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
14
|
+
String :key, null: false
|
|
15
|
+
String :login, null: false
|
|
16
|
+
DateTime :deadline, deadline_opts[1]
|
|
17
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<%# lib/rodauth/tools/migration/sequel/audit_logging.erb %>
|
|
2
|
+
|
|
3
|
+
# Used by the webauthn feature
|
|
4
|
+
create_table(:<%= table_prefix %>_webauthn_user_ids) do
|
|
5
|
+
foreign_key :id, :<%= pluralize(table_prefix) %>, primary_key: true, type: :Bignum
|
|
6
|
+
String :webauthn_id, null: false
|
|
7
|
+
end
|
|
8
|
+
create_table(:<%= table_prefix %>_webauthn_keys) do
|
|
9
|
+
foreign_key :<%= table_prefix %>_id, :<%= pluralize(table_prefix) %>, type: :Bignum
|
|
10
|
+
String :webauthn_id
|
|
11
|
+
String :public_key, null: false
|
|
12
|
+
Integer :sign_count, null: false
|
|
13
|
+
Time :last_use, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
14
|
+
primary_key [:<%= table_prefix %>_id, :webauthn_id]
|
|
15
|
+
end
|