rodauth-rails 0.4.2 → 0.5.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 +11 -1
- data/README.md +68 -8
- data/lib/generators/rodauth/install_generator.rb +26 -20
- data/lib/generators/rodauth/migration/account_expiration.erb +7 -0
- data/lib/generators/rodauth/migration/active_sessions.erb +7 -0
- data/lib/generators/rodauth/migration/audit_logging.erb +16 -0
- data/lib/generators/rodauth/migration/base.erb +19 -0
- data/lib/generators/rodauth/migration/disallow_password_reuse.erb +5 -0
- data/lib/generators/rodauth/migration/email_auth.erb +7 -0
- data/lib/generators/rodauth/migration/jwt_refresh.erb +7 -0
- data/lib/generators/rodauth/migration/lockout.erb +11 -0
- data/lib/generators/rodauth/migration/otp.erb +7 -0
- data/lib/generators/rodauth/migration/password_expiration.erb +5 -0
- data/lib/generators/rodauth/migration/recovery_codes.erb +6 -0
- data/lib/generators/rodauth/migration/remember.erb +6 -0
- data/lib/generators/rodauth/migration/reset_password.erb +7 -0
- data/lib/generators/rodauth/migration/single_session.erb +5 -0
- data/lib/generators/rodauth/migration/sms_codes.erb +8 -0
- data/lib/generators/rodauth/migration/verify_account.erb +7 -0
- data/lib/generators/rodauth/migration/verify_login_change.erb +7 -0
- data/lib/generators/rodauth/migration/webauthn.erb +12 -0
- data/lib/generators/rodauth/migration_generator.rb +32 -0
- data/lib/generators/rodauth/migration_helpers.rb +69 -0
- data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +4 -0
- data/lib/generators/rodauth/templates/config/initializers/sequel.rb +1 -5
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb +2 -176
- data/lib/rodauth/rails/railtie.rb +6 -0
- data/lib/rodauth/rails/tasks.rake +32 -0
- data/lib/rodauth/rails/version.rb +1 -1
- metadata +23 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0d00b7ad2f6198fff3a5cc3c720c6f30d9296898e3fd764ddf7408e36232a6d
|
4
|
+
data.tar.gz: 9ba008116fc5521c98ed62dda5b1f6b2eccd733d06ccb0a2c5b9b4db8df94539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 848873e599cfb8dc8a5d274ac5fec5987cf4c895c77757a4b21529ddcd9a635ba8086c037f55c55ef097ae926549234e5abebb97a5300f0ead6118927d737d91
|
7
|
+
data.tar.gz: aa75fb48217e79c40000cf1f226f36a65fdffdcb764233572ae45341b7ab9dd2f1d8f8470e593d8260495962b1b5c352e62d0d5e71fed0cb96891da93a0f344c
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
|
1
|
+
## 0.5.0 (2020-11-16)
|
2
|
+
|
3
|
+
* Support more Active Record adapters in `rodauth:install` generator (@janko)
|
4
|
+
|
5
|
+
* Add `rodauth:migration` generator for creating tables of specified features (@janko)
|
6
|
+
|
7
|
+
* Use UUIDs for primary keys if so configured in Rails generators (@janko)
|
8
|
+
|
9
|
+
* Add `rodauth:routes` rake task for printing routes handled by Rodauth middleware (@janko)
|
10
|
+
|
11
|
+
## 0.4.2 (2020-11-08)
|
2
12
|
|
3
13
|
* Drop support for Ruby 2.2 (@janko)
|
4
14
|
|
data/README.md
CHANGED
@@ -54,7 +54,6 @@ class CreateRodauth < ActiveRecord::Migration
|
|
54
54
|
create_table :account_verification_keys do |t| ... end
|
55
55
|
create_table :account_login_change_keys do |t| ... end
|
56
56
|
create_table :account_remember_keys do |t| ... end
|
57
|
-
# ...
|
58
57
|
end
|
59
58
|
end
|
60
59
|
```
|
@@ -88,7 +87,7 @@ ActiveRecord connection.
|
|
88
87
|
require "sequel/core"
|
89
88
|
|
90
89
|
# initialize Sequel and have it reuse Active Record's database connection
|
91
|
-
DB = Sequel.
|
90
|
+
DB = Sequel.connect("postgresql://", extensions: :activerecord_connection)
|
92
91
|
```
|
93
92
|
|
94
93
|
### Rodauth app
|
@@ -121,7 +120,7 @@ class RodauthController < ApplicationController
|
|
121
120
|
end
|
122
121
|
```
|
123
122
|
|
124
|
-
### Account
|
123
|
+
### Account model
|
125
124
|
|
126
125
|
Rodauth stores user accounts in the `accounts` table, so the generator will
|
127
126
|
also create an `Account` model for custom use.
|
@@ -134,8 +133,30 @@ end
|
|
134
133
|
|
135
134
|
## Getting started
|
136
135
|
|
137
|
-
|
138
|
-
|
136
|
+
First, let's see what routes our Rodauth middleware will handle:
|
137
|
+
|
138
|
+
```sh
|
139
|
+
$ rails rodauth:routes
|
140
|
+
```
|
141
|
+
```
|
142
|
+
Routes handled by RodauthApp:
|
143
|
+
|
144
|
+
/login rodauth.login_path
|
145
|
+
/create-account rodauth.create_account_path
|
146
|
+
/verify-account-resend rodauth.verify_account_resend_path
|
147
|
+
/verify-account rodauth.verify_account_path
|
148
|
+
/change-password rodauth.change_password_path
|
149
|
+
/change-login rodauth.change_login_path
|
150
|
+
/logout rodauth.logout_path
|
151
|
+
/remember rodauth.remember_path
|
152
|
+
/reset-password-request rodauth.reset_password_request_path
|
153
|
+
/reset-password rodauth.reset_password_path
|
154
|
+
/verify-login-change rodauth.verify_login_change_path
|
155
|
+
/close-account rodauth.close_account_path
|
156
|
+
```
|
157
|
+
|
158
|
+
We can use this information to add some basic authentication navigation links
|
159
|
+
to our home page:
|
139
160
|
|
140
161
|
```erb
|
141
162
|
<ul>
|
@@ -265,7 +286,7 @@ $ rails generate rodauth:views --all
|
|
265
286
|
```
|
266
287
|
|
267
288
|
You can also tell the generator to create views into another directory (in this
|
268
|
-
case
|
289
|
+
case make sure to rename the Rodauth controller accordingly).
|
269
290
|
|
270
291
|
```sh
|
271
292
|
# generates views into app/views/authentication
|
@@ -300,8 +321,8 @@ end
|
|
300
321
|
|
301
322
|
### Mailer
|
302
323
|
|
303
|
-
Rodauth may send emails as part of
|
304
|
-
can be customized:
|
324
|
+
Depending on the features you've enabled, Rodauth may send emails as part of
|
325
|
+
the authentication flow. Most email settings can be customized:
|
305
326
|
|
306
327
|
```rb
|
307
328
|
# app/lib/rodauth_app.rb
|
@@ -385,6 +406,25 @@ class RodauthApp < Rodauth::Rails::App
|
|
385
406
|
end
|
386
407
|
```
|
387
408
|
|
409
|
+
### Migrations
|
410
|
+
|
411
|
+
The install generator will have created some default tables, but you can use
|
412
|
+
the migration generator to create tables for any additional Rodauth features:
|
413
|
+
|
414
|
+
```
|
415
|
+
$ rails generate rodauth:migration otp sms_codes recovery_codes
|
416
|
+
```
|
417
|
+
```rb
|
418
|
+
# db/migration/*_create_rodauth_otp_sms_codes_recovery_codes.rb
|
419
|
+
class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
420
|
+
def change
|
421
|
+
create_table :account_otp_keys do |t| ... end
|
422
|
+
create_table :account_sms_codes do |t| ... end
|
423
|
+
create_table :account_recovery_codes do |t| ... end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
```
|
427
|
+
|
388
428
|
### JSON API
|
389
429
|
|
390
430
|
JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
|
@@ -588,6 +628,26 @@ disables the use of database functions, though you can always turn it back on.
|
|
588
628
|
use_database_authentication_functions? true
|
589
629
|
```
|
590
630
|
|
631
|
+
To create the database functions, pass the Sequel database object into the
|
632
|
+
Rodauth method for creating database functions:
|
633
|
+
|
634
|
+
```rb
|
635
|
+
# db/migrate/*_create_rodauth_database_functions.rb
|
636
|
+
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
637
|
+
def up
|
638
|
+
# ...
|
639
|
+
Rodauth.create_database_authentication_functions(DB)
|
640
|
+
# ...
|
641
|
+
end
|
642
|
+
|
643
|
+
def down
|
644
|
+
# ...
|
645
|
+
Rodauth.drop_database_authentication_functions(DB)
|
646
|
+
# ...
|
647
|
+
end
|
648
|
+
end
|
649
|
+
```
|
650
|
+
|
591
651
|
### Account statuses
|
592
652
|
|
593
653
|
The recommended [Rodauth migration] stores possible account status values in a
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "rails/generators/base"
|
2
2
|
require "rails/generators/active_record/migration"
|
3
|
-
|
3
|
+
require "generators/rodauth/migration_helpers"
|
4
4
|
require "securerandom"
|
5
5
|
|
6
6
|
module Rodauth
|
@@ -8,6 +8,7 @@ module Rodauth
|
|
8
8
|
module Generators
|
9
9
|
class InstallGenerator < ::Rails::Generators::Base
|
10
10
|
include ::ActiveRecord::Generators::Migration
|
11
|
+
include MigrationHelpers
|
11
12
|
|
12
13
|
source_root "#{__dir__}/templates"
|
13
14
|
namespace "rodauth:install"
|
@@ -15,7 +16,7 @@ module Rodauth
|
|
15
16
|
def create_rodauth_migration
|
16
17
|
return unless defined?(ActiveRecord::Base)
|
17
18
|
|
18
|
-
migration_template "db/migrate/create_rodauth.rb"
|
19
|
+
migration_template "db/migrate/create_rodauth.rb"
|
19
20
|
end
|
20
21
|
|
21
22
|
def create_rodauth_initializer
|
@@ -24,7 +25,6 @@ module Rodauth
|
|
24
25
|
|
25
26
|
def create_sequel_initializer
|
26
27
|
return unless defined?(ActiveRecord::Base)
|
27
|
-
return unless %w[postgresql mysql2 sqlite3].include?(activerecord_adapter)
|
28
28
|
return if defined?(Sequel) && !Sequel::DATABASES.empty?
|
29
29
|
|
30
30
|
template "config/initializers/sequel.rb"
|
@@ -48,39 +48,45 @@ module Rodauth
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
def migration_version
|
58
|
-
if ActiveRecord.version >= Gem::Version.new("5.0")
|
59
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
51
|
+
def sequel_uri_scheme
|
52
|
+
if RUBY_ENGINE == "jruby"
|
53
|
+
"jdbc:#{sequel_jdbc_subadapter}"
|
54
|
+
else
|
55
|
+
sequel_adapter
|
60
56
|
end
|
61
57
|
end
|
62
58
|
|
63
59
|
def sequel_adapter
|
64
60
|
case activerecord_adapter
|
65
|
-
when "
|
66
|
-
when "
|
67
|
-
when "
|
61
|
+
when "sqlite3" then "sqlite"
|
62
|
+
when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
|
63
|
+
when "sqlserver" then "tinytds" # https://github.com/rails-sqlserver/activerecord-sqlserver-adapter
|
64
|
+
else
|
65
|
+
activerecord_adapter
|
68
66
|
end
|
69
67
|
end
|
70
68
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
69
|
+
def sequel_jdbc_subadapter
|
70
|
+
case activerecord_adapter
|
71
|
+
when "sqlite3" then "sqlite"
|
72
|
+
when "oracle_enhanced" then "oracle" # https://github.com/rsim/oracle-enhanced
|
73
|
+
when "sqlserver" then "mssql"
|
74
74
|
else
|
75
|
-
|
75
|
+
activerecord_adapter
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
79
|
def api_only?
|
80
|
-
return
|
80
|
+
return unless ::Rails.gem_version >= Gem::Version.new("5.0")
|
81
81
|
|
82
82
|
::Rails.application.config.api_only
|
83
83
|
end
|
84
|
+
|
85
|
+
def migration_features
|
86
|
+
features = [:base, :reset_password, :verify_account, :verify_login_change]
|
87
|
+
features << :remember unless api_only?
|
88
|
+
features
|
89
|
+
end
|
84
90
|
end
|
85
91
|
end
|
86
92
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the active sessions feature
|
2
|
+
create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
|
3
|
+
t.references :account, foreign_key: true<%= primary_key_type(:type) %>
|
4
|
+
t.string :session_id
|
5
|
+
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
6
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Used by the audit logging feature
|
2
|
+
create_table :account_authentication_audit_logs<%= primary_key_type %> do |t|
|
3
|
+
t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
5
|
+
t.text :message, null: false
|
6
|
+
<% case activerecord_adapter -%>
|
7
|
+
<% when "postgresql" -%>
|
8
|
+
t.jsonb :metadata
|
9
|
+
<% when "sqlite3", "mysql2" -%>
|
10
|
+
t.json :metadata
|
11
|
+
<% else -%>
|
12
|
+
t.string :metadata
|
13
|
+
<% end -%>
|
14
|
+
t.index [:account_id, :at], name: "audit_account_at_idx"
|
15
|
+
t.index :at, name: "audit_at_idx"
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% if activerecord_adapter == "postgresql" -%>
|
2
|
+
enable_extension "citext"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
create_table :accounts<%= primary_key_type %> do |t|
|
6
|
+
<% case activerecord_adapter -%>
|
7
|
+
<% when "postgresql" -%>
|
8
|
+
t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
|
9
|
+
<% else -%>
|
10
|
+
t.string :email, null: false, index: { unique: true }
|
11
|
+
<% end -%>
|
12
|
+
t.string :status, null: false, default: "verified"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Used if storing password hashes in a separate table (default)
|
16
|
+
create_table :account_password_hashes<%= primary_key_type %> do |t|
|
17
|
+
t.foreign_key :accounts, column: :id
|
18
|
+
t.string :password_hash, null: false
|
19
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the email auth feature
|
2
|
+
create_table :account_email_auth_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the jwt refresh feature
|
2
|
+
create_table :account_jwt_refresh_keys<%= primary_key_type %> do |t|
|
3
|
+
t.references :account, foreign_key: true, null: false<%= primary_key_type(:type) %>
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.index :account_id, name: "account_jwt_rk_account_id_idx"
|
7
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Used by the lockout feature
|
2
|
+
create_table :account_login_failures<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.integer :number, null: false, default: 1
|
5
|
+
end
|
6
|
+
create_table :account_lockouts<%= primary_key_type %> do |t|
|
7
|
+
t.foreign_key :accounts, column: :id
|
8
|
+
t.string :key, null: false
|
9
|
+
t.datetime :deadline, null: false
|
10
|
+
t.datetime :email_last_sent
|
11
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the otp feature
|
2
|
+
create_table :account_otp_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.integer :num_failures, null: false, default: 0
|
6
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the password reset feature
|
2
|
+
create_table :account_password_reset_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :deadline, null: false
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Used by the sms codes feature
|
2
|
+
create_table :account_sms_codes<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :phone_number, null: false
|
5
|
+
t.integer :num_failures
|
6
|
+
t.string :code
|
7
|
+
t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
8
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Used by the account verification feature
|
2
|
+
create_table :account_verification_keys<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :key, null: false
|
5
|
+
t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
6
|
+
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
7
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Used by the webauthn feature
|
2
|
+
create_table :account_webauthn_user_ids<%= primary_key_type %> do |t|
|
3
|
+
t.foreign_key :accounts, column: :id
|
4
|
+
t.string :webauthn_id, null: false
|
5
|
+
end
|
6
|
+
create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
|
7
|
+
t.references :account, foreign_key: true<%= primary_key_type(:type) %>
|
8
|
+
t.string :webauthn_id
|
9
|
+
t.string :public_key, null: false
|
10
|
+
t.integer :sign_count, null: false
|
11
|
+
t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
12
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
require "rails/generators/active_record/migration"
|
3
|
+
require "generators/rodauth/migration_helpers"
|
4
|
+
|
5
|
+
module Rodauth
|
6
|
+
module Rails
|
7
|
+
module Generators
|
8
|
+
class MigrationGenerator < ::Rails::Generators::Base
|
9
|
+
include ::ActiveRecord::Generators::Migration
|
10
|
+
include MigrationHelpers
|
11
|
+
|
12
|
+
source_root "#{__dir__}/templates"
|
13
|
+
namespace "rodauth:migration"
|
14
|
+
|
15
|
+
argument :features, optional: true, type: :array,
|
16
|
+
desc: "Rodauth features to create tables for (otp, sms_codes, single_session, account_expiration etc.)",
|
17
|
+
default: %w[]
|
18
|
+
|
19
|
+
def create_rodauth_migration
|
20
|
+
return unless defined?(ActiveRecord::Base)
|
21
|
+
return if features.empty?
|
22
|
+
|
23
|
+
migration_template "db/migrate/create_rodauth.rb", "create_rodauth_#{features.join("_")}.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
def migration_features
|
27
|
+
features
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
module Rails
|
5
|
+
module Generators
|
6
|
+
module MigrationHelpers
|
7
|
+
attr_reader :migration_class_name
|
8
|
+
|
9
|
+
def migration_template(source, destination = File.basename(source))
|
10
|
+
@migration_class_name = destination.chomp(".rb").camelize
|
11
|
+
|
12
|
+
super source, File.join(db_migrate_path, destination)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def migration_content
|
18
|
+
migration_features
|
19
|
+
.select { |feature| File.exist?("#{__dir__}/migration/#{feature}.erb") }
|
20
|
+
.map { |feature| File.read("#{__dir__}/migration/#{feature}.erb") }
|
21
|
+
.map { |content| erb_eval(content) }
|
22
|
+
.join("\n")
|
23
|
+
.indent(4)
|
24
|
+
end
|
25
|
+
|
26
|
+
def activerecord_adapter
|
27
|
+
if ActiveRecord::Base.respond_to?(:connection_db_config)
|
28
|
+
ActiveRecord::Base.connection_db_config.adapter
|
29
|
+
else
|
30
|
+
ActiveRecord::Base.connection_config.fetch(:adapter)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def migration_version
|
35
|
+
return unless ActiveRecord.version >= Gem::Version.new("5.0")
|
36
|
+
|
37
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
38
|
+
end
|
39
|
+
|
40
|
+
def db_migrate_path
|
41
|
+
return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
|
42
|
+
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def primary_key_type(key = :id)
|
47
|
+
generators = ::Rails.application.config.generators
|
48
|
+
column_type = generators.options[:active_record][:primary_key_type]
|
49
|
+
|
50
|
+
return unless column_type
|
51
|
+
|
52
|
+
if key
|
53
|
+
", #{key}: :#{column_type}"
|
54
|
+
else
|
55
|
+
column_type
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def erb_eval(content)
|
60
|
+
if ERB.version[/\d+\.\d+\.\d+/].to_s >= "2.2.0"
|
61
|
+
ERB.new(content, trim_mode: "-").result(binding)
|
62
|
+
else
|
63
|
+
ERB.new(content, 0, "-").result(binding)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -11,6 +11,10 @@ class RodauthApp < Rodauth::Rails::App
|
|
11
11
|
# http://rodauth.jeremyevans.net/documentation.html
|
12
12
|
|
13
13
|
# ==> General
|
14
|
+
# The secret key used for hashing public-facing tokens for various features.
|
15
|
+
# Defaults to Rails `secret_key_base`, but you can use your own secret key.
|
16
|
+
# hmac_secret "<%= SecureRandom.hex(64) %>"
|
17
|
+
|
14
18
|
<% unless api_only? -%>
|
15
19
|
# Specify the controller used for view rendering and CSRF verification.
|
16
20
|
rails_controller { RodauthController }
|
@@ -1,8 +1,4 @@
|
|
1
1
|
require "sequel/core"
|
2
2
|
|
3
3
|
# initialize Sequel and have it reuse Active Record's database connection
|
4
|
-
|
5
|
-
DB = Sequel.connect("jdbc:<%= sequel_adapter %>://", extensions: :activerecord_connection)
|
6
|
-
<% else -%>
|
7
|
-
DB = Sequel.<%= sequel_adapter %>(extensions: :activerecord_connection)
|
8
|
-
<% end -%>
|
4
|
+
DB = Sequel.connect("<%= sequel_uri_scheme %>://", extensions: :activerecord_connection)
|
@@ -1,179 +1,5 @@
|
|
1
|
-
class
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
|
4
|
-
enable_extension "citext"
|
5
|
-
|
6
|
-
<% end -%>
|
7
|
-
create_table :accounts do |t|
|
8
|
-
<% case activerecord_adapter -%>
|
9
|
-
<% when "postgresql" -%>
|
10
|
-
t.citext :email, null: false, index: { unique: true, where: "status IN ('verified', 'unverified')" }
|
11
|
-
<% else -%>
|
12
|
-
t.string :email, null: false, index: { unique: true }
|
13
|
-
<% end -%>
|
14
|
-
t.string :status, null: false, default: "verified"
|
15
|
-
end
|
16
|
-
|
17
|
-
# Used if storing password hashes in a separate table (default)
|
18
|
-
create_table :account_password_hashes do |t|
|
19
|
-
t.foreign_key :accounts, column: :id
|
20
|
-
t.string :password_hash, null: false
|
21
|
-
end
|
22
|
-
|
23
|
-
# Used by the password reset feature
|
24
|
-
create_table :account_password_reset_keys do |t|
|
25
|
-
t.foreign_key :accounts, column: :id
|
26
|
-
t.string :key, null: false
|
27
|
-
t.datetime :deadline, null: false
|
28
|
-
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
29
|
-
end
|
30
|
-
|
31
|
-
# Used by the account verification feature
|
32
|
-
create_table :account_verification_keys do |t|
|
33
|
-
t.foreign_key :accounts, column: :id
|
34
|
-
t.string :key, null: false
|
35
|
-
t.datetime :requested_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
36
|
-
t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Used by the verify login change feature
|
40
|
-
create_table :account_login_change_keys do |t|
|
41
|
-
t.foreign_key :accounts, column: :id
|
42
|
-
t.string :key, null: false
|
43
|
-
t.string :login, null: false
|
44
|
-
t.datetime :deadline, null: false
|
45
|
-
end
|
46
|
-
|
47
|
-
<% unless api_only? -%>
|
48
|
-
# Used by the remember me feature
|
49
|
-
create_table :account_remember_keys do |t|
|
50
|
-
t.foreign_key :accounts, column: :id
|
51
|
-
t.string :key, null: false
|
52
|
-
t.datetime :deadline, null: false
|
53
|
-
end
|
54
|
-
<% else -%>
|
55
|
-
# # Used by the remember me feature
|
56
|
-
# create_table :account_remember_keys do |t|
|
57
|
-
# t.foreign_key :accounts, column: :id
|
58
|
-
# t.string :key, null: false
|
59
|
-
# t.datetime :deadline, null: false
|
60
|
-
# end
|
61
|
-
<% end -%>
|
62
|
-
|
63
|
-
# # Used by the audit logging feature
|
64
|
-
# create_table :account_authentication_audit_logs do |t|
|
65
|
-
# t.references :account, foreign_key: true, null: false
|
66
|
-
# t.datetime :at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
67
|
-
# t.text :message, null: false
|
68
|
-
<% case activerecord_adapter -%>
|
69
|
-
<% when "postgresql" -%>
|
70
|
-
# t.jsonb :metadata
|
71
|
-
<% when "sqlite3", "mysql2" -%>
|
72
|
-
# t.json :metadata
|
73
|
-
<% else -%>
|
74
|
-
# t.string :metadata
|
75
|
-
<% end -%>
|
76
|
-
# t.index [:account_id, :at], name: "audit_account_at_idx"
|
77
|
-
# t.index :at, name: "audit_at_idx"
|
78
|
-
# end
|
79
|
-
|
80
|
-
# # Used by the jwt refresh feature
|
81
|
-
# create_table :account_jwt_refresh_keys do |t|
|
82
|
-
# t.references :account, foreign_key: true, null: false
|
83
|
-
# t.string :key, null: false
|
84
|
-
# t.datetime :deadline, null: false
|
85
|
-
# t.index :account_id, name: "account_jwt_rk_account_id_idx"
|
86
|
-
# end
|
87
|
-
|
88
|
-
# # Used by the disallow_password_reuse feature
|
89
|
-
# create_table :account_previous_password_hashes do |t|
|
90
|
-
# t.references :account, foreign_key: true
|
91
|
-
# t.string :password_hash, null: false
|
92
|
-
# end
|
93
|
-
|
94
|
-
# # Used by the lockout feature
|
95
|
-
# create_table :account_login_failures do |t|
|
96
|
-
# t.foreign_key :accounts, column: :id
|
97
|
-
# t.integer :number, null: false, default: 1
|
98
|
-
# end
|
99
|
-
# create_table :account_lockouts do |t|
|
100
|
-
# t.foreign_key :accounts, column: :id
|
101
|
-
# t.string :key, null: false
|
102
|
-
# t.datetime :deadline, null: false
|
103
|
-
# t.datetime :email_last_sent
|
104
|
-
# end
|
105
|
-
|
106
|
-
# # Used by the email auth feature
|
107
|
-
# create_table :account_email_auth_keys do |t|
|
108
|
-
# t.foreign_key :accounts, column: :id
|
109
|
-
# t.string :key, null: false
|
110
|
-
# t.datetime :deadline, null: false
|
111
|
-
# t.datetime :email_last_sent, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
112
|
-
# end
|
113
|
-
|
114
|
-
# # Used by the password expiration feature
|
115
|
-
# create_table :account_password_change_times do |t|
|
116
|
-
# t.foreign_key :accounts, column: :id
|
117
|
-
# t.datetime :changed_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
118
|
-
# end
|
119
|
-
|
120
|
-
# # Used by the account expiration feature
|
121
|
-
# create_table :account_activity_times do |t|
|
122
|
-
# t.foreign_key :accounts, column: :id
|
123
|
-
# t.datetime :last_activity_at, null: false
|
124
|
-
# t.datetime :last_login_at, null: false
|
125
|
-
# t.datetime :expired_at
|
126
|
-
# end
|
127
|
-
|
128
|
-
# # Used by the single session feature
|
129
|
-
# create_table :account_session_keys do |t|
|
130
|
-
# t.foreign_key :accounts, column: :id
|
131
|
-
# t.string :key, null: false
|
132
|
-
# end
|
133
|
-
|
134
|
-
# # Used by the active sessions feature
|
135
|
-
# create_table :account_active_session_keys, primary_key: [:account_id, :session_id] do |t|
|
136
|
-
# t.references :account, foreign_key: true
|
137
|
-
# t.string :session_id
|
138
|
-
# t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
139
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
140
|
-
# end
|
141
|
-
|
142
|
-
# # Used by the webauthn feature
|
143
|
-
# create_table :account_webauthn_user_ids do |t|
|
144
|
-
# t.foreign_key :accounts, column: :id
|
145
|
-
# t.string :webauthn_id, null: false
|
146
|
-
# end
|
147
|
-
# create_table :account_webauthn_keys, primary_key: [:account_id, :webauthn_id] do |t|
|
148
|
-
# t.references :account, foreign_key: true
|
149
|
-
# t.string :webauthn_id
|
150
|
-
# t.string :public_key, null: false
|
151
|
-
# t.integer :sign_count, null: false
|
152
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
153
|
-
# end
|
154
|
-
|
155
|
-
# # Used by the otp feature
|
156
|
-
# create_table :account_otp_keys do |t|
|
157
|
-
# t.foreign_key :accounts, column: :id
|
158
|
-
# t.string :key, null: false
|
159
|
-
# t.integer :num_failures, null: false, default: 0
|
160
|
-
# t.datetime :last_use, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
161
|
-
# end
|
162
|
-
|
163
|
-
# # Used by the recovery codes feature
|
164
|
-
# create_table :account_recovery_codes, primary_key: [:id, :code] do |t|
|
165
|
-
# t.integer :id
|
166
|
-
# t.foreign_key :accounts, column: :id
|
167
|
-
# t.string :code
|
168
|
-
# end
|
169
|
-
|
170
|
-
# # Used by the sms codes feature
|
171
|
-
# create_table :account_sms_codes do |t|
|
172
|
-
# t.foreign_key :accounts, column: :id
|
173
|
-
# t.string :phone_number, null: false
|
174
|
-
# t.integer :num_failures
|
175
|
-
# t.string :code
|
176
|
-
# t.datetime :code_issued_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
177
|
-
# end
|
3
|
+
<%= migration_content -%>
|
178
4
|
end
|
179
5
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "rodauth/rails/middleware"
|
2
2
|
require "rodauth/rails/controller_methods"
|
3
3
|
|
4
|
+
require "rails"
|
5
|
+
|
4
6
|
module Rodauth
|
5
7
|
module Rails
|
6
8
|
class Railtie < ::Rails::Railtie
|
@@ -18,6 +20,10 @@ module Rodauth
|
|
18
20
|
# Rodauth uses RACK_ENV to set the default bcrypt hash cost
|
19
21
|
ENV["RACK_ENV"] = "test" if ::Rails.env.test?
|
20
22
|
end
|
23
|
+
|
24
|
+
rake_tasks do
|
25
|
+
load "rodauth/rails/tasks.rake"
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
namespace :rodauth do
|
2
|
+
task routes: :environment do
|
3
|
+
app = Rodauth::Rails.app
|
4
|
+
|
5
|
+
puts "Routes handled by #{app}:"
|
6
|
+
puts
|
7
|
+
|
8
|
+
app.opts[:rodauths].each do |rodauth_name, rodauth_class|
|
9
|
+
route_names = rodauth_class.routes
|
10
|
+
.map { |handle_method| handle_method.to_s.sub(/\Ahandle_/, "") }
|
11
|
+
.uniq
|
12
|
+
|
13
|
+
rodauth = rodauth_class.allocate
|
14
|
+
|
15
|
+
routes = route_names.map do |name|
|
16
|
+
[
|
17
|
+
rodauth.public_send(:"#{name}_path"),
|
18
|
+
"rodauth#{rodauth_name && "(:#{rodauth_name})"}.#{name}_path",
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
padding = routes.map { |path, _| path.length }.max
|
23
|
+
|
24
|
+
route_lines = routes.map do |path, code|
|
25
|
+
"#{path.ljust(padding)} #{code}"
|
26
|
+
end
|
27
|
+
|
28
|
+
puts " #{route_lines.join("\n ")}"
|
29
|
+
puts
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -98,6 +98,26 @@ files:
|
|
98
98
|
- README.md
|
99
99
|
- lib/generators/rodauth/install_generator.rb
|
100
100
|
- lib/generators/rodauth/mailer_generator.rb
|
101
|
+
- lib/generators/rodauth/migration/account_expiration.erb
|
102
|
+
- lib/generators/rodauth/migration/active_sessions.erb
|
103
|
+
- lib/generators/rodauth/migration/audit_logging.erb
|
104
|
+
- lib/generators/rodauth/migration/base.erb
|
105
|
+
- lib/generators/rodauth/migration/disallow_password_reuse.erb
|
106
|
+
- lib/generators/rodauth/migration/email_auth.erb
|
107
|
+
- lib/generators/rodauth/migration/jwt_refresh.erb
|
108
|
+
- lib/generators/rodauth/migration/lockout.erb
|
109
|
+
- lib/generators/rodauth/migration/otp.erb
|
110
|
+
- lib/generators/rodauth/migration/password_expiration.erb
|
111
|
+
- lib/generators/rodauth/migration/recovery_codes.erb
|
112
|
+
- lib/generators/rodauth/migration/remember.erb
|
113
|
+
- lib/generators/rodauth/migration/reset_password.erb
|
114
|
+
- lib/generators/rodauth/migration/single_session.erb
|
115
|
+
- lib/generators/rodauth/migration/sms_codes.erb
|
116
|
+
- lib/generators/rodauth/migration/verify_account.erb
|
117
|
+
- lib/generators/rodauth/migration/verify_login_change.erb
|
118
|
+
- lib/generators/rodauth/migration/webauthn.erb
|
119
|
+
- lib/generators/rodauth/migration_generator.rb
|
120
|
+
- lib/generators/rodauth/migration_helpers.rb
|
101
121
|
- lib/generators/rodauth/templates/app/controllers/rodauth_controller.rb
|
102
122
|
- lib/generators/rodauth/templates/app/lib/rodauth_app.rb
|
103
123
|
- lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb
|
@@ -175,6 +195,7 @@ files:
|
|
175
195
|
- lib/rodauth/rails/feature.rb
|
176
196
|
- lib/rodauth/rails/middleware.rb
|
177
197
|
- lib/rodauth/rails/railtie.rb
|
198
|
+
- lib/rodauth/rails/tasks.rake
|
178
199
|
- lib/rodauth/rails/version.rb
|
179
200
|
- rodauth-rails.gemspec
|
180
201
|
homepage: https://github.com/janko/rodauth-rails
|