quo_vadis 2.0.0 → 2.0.1
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/.gitignore +1 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +0 -3
- data/README.md +4 -5
- data/lib/quo_vadis/version.rb +1 -1
- data/quo_vadis.gemspec +5 -3
- data/test/dummy/README.markdown +1 -0
- data/test/dummy/Rakefile +3 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/articles_controller.rb +17 -0
- data/test/dummy/app/controllers/sign_ups_controller.rb +42 -0
- data/test/dummy/app/controllers/users_controller.rb +25 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/article.rb +3 -0
- data/test/dummy/app/models/person.rb +6 -0
- data/test/dummy/app/models/user.rb +6 -0
- data/test/dummy/app/views/articles/also_secret.html.erb +1 -0
- data/test/dummy/app/views/articles/index.html.erb +1 -0
- data/test/dummy/app/views/articles/secret.html.erb +1 -0
- data/test/dummy/app/views/articles/very_secret.html.erb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +46 -0
- data/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb +10 -0
- data/test/dummy/app/views/quo_vadis/confirmations/index.html.erb +5 -0
- data/test/dummy/app/views/quo_vadis/confirmations/new.html.erb +16 -0
- data/test/dummy/app/views/quo_vadis/logs/index.html.erb +28 -0
- data/test/dummy/app/views/quo_vadis/mailer/account_confirmation.text.erb +4 -0
- data/test/dummy/app/views/quo_vadis/mailer/email_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/reset_password.text.erb +4 -0
- data/test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb +6 -0
- data/test/dummy/app/views/quo_vadis/mailer/totp_setup_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb +25 -0
- data/test/dummy/app/views/quo_vadis/password_resets/index.html.erb +5 -0
- data/test/dummy/app/views/quo_vadis/password_resets/new.html.erb +12 -0
- data/test/dummy/app/views/quo_vadis/passwords/edit.html.erb +30 -0
- data/test/dummy/app/views/quo_vadis/recovery_codes/challenge.html.erb +11 -0
- data/test/dummy/app/views/quo_vadis/recovery_codes/index.html.erb +25 -0
- data/test/dummy/app/views/quo_vadis/sessions/index.html.erb +26 -0
- data/test/dummy/app/views/quo_vadis/sessions/new.html.erb +24 -0
- data/test/dummy/app/views/quo_vadis/totps/challenge.html.erb +11 -0
- data/test/dummy/app/views/quo_vadis/totps/new.html.erb +17 -0
- data/test/dummy/app/views/quo_vadis/twofas/show.html.erb +20 -0
- data/test/dummy/app/views/sign_ups/new.html.erb +37 -0
- data/test/dummy/app/views/sign_ups/show.html.erb +5 -0
- data/test/dummy/app/views/users/new.html.erb +37 -0
- data/test/dummy/config.ru +7 -0
- data/test/dummy/config/application.rb +30 -0
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/database.yml +10 -0
- data/test/dummy/config/environment.rb +4 -0
- data/test/dummy/config/initializers/quo_vadis.rb +7 -0
- data/test/dummy/config/routes.rb +13 -0
- data/test/dummy/db/migrate/202102121932_create_users.rb +10 -0
- data/test/dummy/db/migrate/202102121935_create_people.rb +10 -0
- data/test/dummy/db/schema.rb +92 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/quo_vadis/mailer/account_confirmation.text +4 -0
- data/test/fixtures/quo_vadis/mailer/email_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/identifier_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/password_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/password_reset_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/recovery_codes_generation_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/reset_password.text +4 -0
- data/test/fixtures/quo_vadis/mailer/totp_reuse_notification.text +6 -0
- data/test/fixtures/quo_vadis/mailer/totp_setup_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/twofa_deactivated_notification.text +8 -0
- data/test/integration/account_confirmation_test.rb +112 -0
- data/test/integration/controller_test.rb +280 -0
- data/test/integration/logging_test.rb +235 -0
- data/test/integration/password_change_test.rb +93 -0
- data/test/integration/password_login_test.rb +125 -0
- data/test/integration/password_reset_test.rb +136 -0
- data/test/integration/recovery_codes_test.rb +48 -0
- data/test/integration/sessions_test.rb +86 -0
- data/test/integration/sign_up_test.rb +35 -0
- data/test/integration/totps_test.rb +96 -0
- data/test/integration/twofa_test.rb +82 -0
- data/test/mailers/mailer_test.rb +200 -0
- data/test/models/account_test.rb +34 -0
- data/test/models/crypt_test.rb +22 -0
- data/test/models/log_test.rb +16 -0
- data/test/models/mask_ip_test.rb +27 -0
- data/test/models/model_test.rb +66 -0
- data/test/models/password_test.rb +163 -0
- data/test/models/recovery_code_test.rb +54 -0
- data/test/models/session_test.rb +67 -0
- data/test/models/token_test.rb +70 -0
- data/test/models/totp_test.rb +68 -0
- data/test/quo_vadis_test.rb +43 -0
- data/test/test_helper.rb +58 -0
- metadata +119 -4
- data/Gemfile.lock +0 -178
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<h1>Reset password</h1>
|
|
2
|
+
|
|
3
|
+
<% if @password.errors.any? %>
|
|
4
|
+
<ul>
|
|
5
|
+
<% @password.errors.full_messages.each do |msg| %>
|
|
6
|
+
<li><%= msg %></li>
|
|
7
|
+
<% end %>
|
|
8
|
+
</ul>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<%= form_with url: password_reset_path(params[:token]), method: :put do |f| %>
|
|
12
|
+
<p>
|
|
13
|
+
<%= f.label :password %>
|
|
14
|
+
<%= f.password_field :password, autocomplete: 'new-password' %>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p>
|
|
18
|
+
<%= f.label :password_confirmation %>
|
|
19
|
+
<%= f.password_field :password_confirmation, autocomplete: 'new-password' %>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p>
|
|
23
|
+
<%= f.submit %>
|
|
24
|
+
</p>
|
|
25
|
+
<% end %>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<h1>Change password</h1>
|
|
2
|
+
|
|
3
|
+
<% if @password.errors.any? %>
|
|
4
|
+
<ul>
|
|
5
|
+
<% @password.errors.full_messages.each do |msg| %>
|
|
6
|
+
<li><%= msg %></li>
|
|
7
|
+
<% end %>
|
|
8
|
+
</ul>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<%= form_with url: password_path, method: :put do |f| %>
|
|
12
|
+
<p>
|
|
13
|
+
<%= f.label :password %>
|
|
14
|
+
<%= f.password_field :password, autocomplete: 'current-password' %>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p>
|
|
18
|
+
<%= f.label :new_password %>
|
|
19
|
+
<%= f.password_field :new_password, autocomplete: 'new-password' %>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p>
|
|
23
|
+
<%= f.label :new_password_confirmation %>
|
|
24
|
+
<%= f.password_field :new_password_confirmation, autocomplete: 'new-password' %>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<p>
|
|
28
|
+
<%= f.submit %>
|
|
29
|
+
</p>
|
|
30
|
+
<% end %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<h1>2FA: Recovery code</h1>
|
|
2
|
+
|
|
3
|
+
<p>Enter one of your recovery codes:</p>
|
|
4
|
+
|
|
5
|
+
<%= form_with url: authenticate_recovery_codes_path, method: :post do |f| %>
|
|
6
|
+
<%= f.text_field :code, inputmode: 'decimal', autofocus: true, maxlength: '11' %>
|
|
7
|
+
|
|
8
|
+
<%= f.submit 'Verify' %>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<p><%= link_to 'Never mind, I want to use my TOTP verification code!', quo_vadis.challenge_totps_path %></p>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<h1>2FA: Recovery codes</h1>
|
|
2
|
+
|
|
3
|
+
<p>If you lose your authenticator app, you can use recovery codes instead while you set up a new authenticator app.</p>
|
|
4
|
+
|
|
5
|
+
<p>Each code can only be used once.</p>
|
|
6
|
+
|
|
7
|
+
<% if @codes.present? %>
|
|
8
|
+
|
|
9
|
+
<p>This is the only time these codes can be shown to you! We recommend you print them out and store them somewhere safely – but not next to your 2FA details in your authenticator app.</p>
|
|
10
|
+
|
|
11
|
+
<ul>
|
|
12
|
+
<% @codes.each do |code| %>
|
|
13
|
+
<li><tt><%= code %></tt></li>
|
|
14
|
+
<% end %>
|
|
15
|
+
</ul>
|
|
16
|
+
|
|
17
|
+
<% else %>
|
|
18
|
+
|
|
19
|
+
<p>You have <%= pluralize @recovery_code_count, 'recovery code' %> left.</p>
|
|
20
|
+
|
|
21
|
+
<% end %>
|
|
22
|
+
|
|
23
|
+
<p>You can generate a fresh set of recovery codes whenever you like.</p>
|
|
24
|
+
|
|
25
|
+
<p><%= button_to 'Generate a fresh set of recovery codes', generate_recovery_codes_path %></p>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<h1>Sessions</h1>
|
|
2
|
+
|
|
3
|
+
<table>
|
|
4
|
+
<thead>
|
|
5
|
+
<tr>
|
|
6
|
+
<th>IP</th>
|
|
7
|
+
<th>User agent</th>
|
|
8
|
+
<th></th>
|
|
9
|
+
</tr>
|
|
10
|
+
</thead>
|
|
11
|
+
<tbody>
|
|
12
|
+
<% @qv_sessions.each do |sess| %>
|
|
13
|
+
<tr>
|
|
14
|
+
<td><%= sess.ip %></td>
|
|
15
|
+
<td><%= sess.user_agent %></td>
|
|
16
|
+
<td>
|
|
17
|
+
<% if sess.id == @qv_session.id %>
|
|
18
|
+
This session
|
|
19
|
+
<% else %>
|
|
20
|
+
<%= button_to 'Log out', quo_vadis.session_path(sess), method: :delete %>
|
|
21
|
+
<% end %>
|
|
22
|
+
</td>
|
|
23
|
+
</tr>
|
|
24
|
+
<% end %>
|
|
25
|
+
</tbody>
|
|
26
|
+
</table>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<h1>Login</h1>
|
|
2
|
+
|
|
3
|
+
<%= form_with url: login_path, method: :post do |f| %>
|
|
4
|
+
<p>
|
|
5
|
+
<%= f.label :email %>
|
|
6
|
+
<%= f.text_field :email, inputmode: 'email', autocomplete: 'email' %>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<%= f.label :password %>
|
|
11
|
+
<%= f.password_field :password, autocomplete: 'current-password' %>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p>
|
|
15
|
+
<%= f.label :remember %>
|
|
16
|
+
<%= f.check_box :remember %>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p>
|
|
20
|
+
<%= f.submit %>
|
|
21
|
+
</p>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
24
|
+
<%= link_to 'I forgot my password', new_password_reset_path %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<h1>2FA</h1>
|
|
2
|
+
|
|
3
|
+
<p>Enter the 6 digit code generated by your authenticator:</p>
|
|
4
|
+
|
|
5
|
+
<%= form_with url: authenticate_totps_path, method: :post do |f| %>
|
|
6
|
+
<%= f.text_field :totp, inputmode: 'decimal', autocomplete: 'one-time-code', autofocus: true, maxlength: '6' %>
|
|
7
|
+
|
|
8
|
+
<%= f.submit 'Verify' %>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<p><%= link_to 'I want to use a recovery code instead.', quo_vadis.challenge_recovery_codes_path %></p>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<h1>2FA: TOTP setup</h1>
|
|
2
|
+
|
|
3
|
+
<p>1. With your authenticator app, either scan this QR code or enter the text: <pre><%= @totp.key %></pre></p>
|
|
4
|
+
|
|
5
|
+
<%== @totp.qr_code.as_svg module_size: 5 %>
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
<p>2. Enter the 6 digit code generated by your authenticator, to check it worked:</p>
|
|
9
|
+
|
|
10
|
+
<%= form_with model: @totp do |f| %>
|
|
11
|
+
<%= f.hidden_field :key %>
|
|
12
|
+
<%= f.hidden_field :hmac_key %>
|
|
13
|
+
|
|
14
|
+
<%= f.text_field :otp, inputmode: 'decimal', autocomplete: 'one-time-code', autofocus: true, maxlength: '6' %>
|
|
15
|
+
|
|
16
|
+
<%= f.submit 'Confirm' %>
|
|
17
|
+
<% end %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<h1>2FA</h1>
|
|
2
|
+
|
|
3
|
+
<% if authenticated_model.qv_account.has_two_factors? %>
|
|
4
|
+
|
|
5
|
+
<p>You have set up 2FA.</p>
|
|
6
|
+
<p><%= button_to 'Deactivate your 2FA credentials', twofa_path, method: :delete %></p>
|
|
7
|
+
|
|
8
|
+
<% else %>
|
|
9
|
+
|
|
10
|
+
<p>You do not have 2FA set up.</p>
|
|
11
|
+
<% if QuoVadis.two_factor_authentication_mandatory %>
|
|
12
|
+
<p>Please <%= link_to 'set it up', new_totp_path %> now.</p>
|
|
13
|
+
<% else %>
|
|
14
|
+
<p>You can <%= link_to 'set it up', new_totp_path %> if you like.</p>
|
|
15
|
+
<% end %>
|
|
16
|
+
|
|
17
|
+
<% end %>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
<p> You have <%= link_to pluralize(@recovery_codes_count, 'recovery code'), recovery_codes_path %> left.</p>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<h1>New sign up (with confirmation)</h1>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<% if @user.errors.any? %>
|
|
5
|
+
<ul>
|
|
6
|
+
<% @user.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<%= form_with model: @user, url: sign_ups_path do |f| %>
|
|
14
|
+
<p>
|
|
15
|
+
<%= f.label :name %>
|
|
16
|
+
<%= f.text_field :name %>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p>
|
|
20
|
+
<%= f.label :email %>
|
|
21
|
+
<%= f.text_field :email %>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p>
|
|
25
|
+
<%= f.label :password %>
|
|
26
|
+
<%= f.password_field :password %>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p>
|
|
30
|
+
<%= f.label :password_confirmation %>
|
|
31
|
+
<%= f.password_field :password_confirmation %>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<p>
|
|
35
|
+
<%= f.submit %>
|
|
36
|
+
</p>
|
|
37
|
+
<% end %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<h1>New user (without confirmation)</h1>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
<% if @user.errors.any? %>
|
|
5
|
+
<ul>
|
|
6
|
+
<% @user.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<%= form_with model: @user do |f| %>
|
|
14
|
+
<p>
|
|
15
|
+
<%= f.label :name %>
|
|
16
|
+
<%= f.text_field :name %>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p>
|
|
20
|
+
<%= f.label :email %>
|
|
21
|
+
<%= f.text_field :email %>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p>
|
|
25
|
+
<%= f.label :password %>
|
|
26
|
+
<%= f.password_field :password %>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p>
|
|
30
|
+
<%= f.label :password_confirmation %>
|
|
31
|
+
<%= f.password_field :password_confirmation %>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<p>
|
|
35
|
+
<%= f.submit %>
|
|
36
|
+
</p>
|
|
37
|
+
<% end %>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require_relative 'boot'
|
|
2
|
+
|
|
3
|
+
# copied from https://github.com/janko/rodauth-rails/blob/master/test/rails_app/config/application.rb
|
|
4
|
+
|
|
5
|
+
# require "rails/all"
|
|
6
|
+
require "active_model/railtie"
|
|
7
|
+
require "active_record/railtie"
|
|
8
|
+
# require "action_controller/railtie"
|
|
9
|
+
# require "action_view/railtie"
|
|
10
|
+
require "action_mailer/railtie"
|
|
11
|
+
require "rails/test_unit/railtie"
|
|
12
|
+
|
|
13
|
+
Bundler.require(*Rails.groups)
|
|
14
|
+
|
|
15
|
+
require 'quo_vadis'
|
|
16
|
+
|
|
17
|
+
module Dummy
|
|
18
|
+
class Application < Rails::Application
|
|
19
|
+
config.load_defaults Rails::VERSION::STRING.to_f
|
|
20
|
+
|
|
21
|
+
# config.logger = Logger.new nil
|
|
22
|
+
config.eager_load = true
|
|
23
|
+
config.action_dispatch.show_exceptions = false
|
|
24
|
+
config.action_controller.allow_forgery_protection = false
|
|
25
|
+
|
|
26
|
+
config.action_mailer.delivery_method = :test
|
|
27
|
+
config.action_mailer.default_url_options = { host: 'example.com' }
|
|
28
|
+
config.action_mailer.delivery_job = 'ActionMailer::MailDeliveryJob'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Rails.application.routes.draw do
|
|
2
|
+
resources :users
|
|
3
|
+
resources :sign_ups
|
|
4
|
+
resources :articles do
|
|
5
|
+
collection do
|
|
6
|
+
get 'secret'
|
|
7
|
+
get 'also_secret'
|
|
8
|
+
get 'very_secret'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
get '/articles/secret', as: 'after_login'
|
|
12
|
+
root 'articles#index'
|
|
13
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
4
|
+
#
|
|
5
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
|
6
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
9
|
+
# migrations use external dependencies or application code.
|
|
10
|
+
#
|
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
12
|
+
|
|
13
|
+
ActiveRecord::Schema.define(version: 202102150904) do
|
|
14
|
+
|
|
15
|
+
create_table "people", force: :cascade do |t|
|
|
16
|
+
t.string "username", null: false
|
|
17
|
+
t.string "email", null: false
|
|
18
|
+
t.datetime "created_at", precision: 6, null: false
|
|
19
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
create_table "qv_accounts", force: :cascade do |t|
|
|
23
|
+
t.string "model_type", null: false
|
|
24
|
+
t.bigint "model_id", null: false
|
|
25
|
+
t.string "identifier", null: false
|
|
26
|
+
t.datetime "confirmed_at"
|
|
27
|
+
t.datetime "created_at", precision: 6, null: false
|
|
28
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
29
|
+
t.index ["identifier"], name: "index_qv_accounts_on_identifier", unique: true
|
|
30
|
+
t.index ["model_type", "model_id"], name: "index_qv_accounts_on_model_type_and_model_id", unique: true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
create_table "qv_logs", force: :cascade do |t|
|
|
34
|
+
t.bigint "account_id"
|
|
35
|
+
t.string "action", null: false
|
|
36
|
+
t.string "ip", null: false
|
|
37
|
+
t.json "metadata", default: {}, null: false
|
|
38
|
+
t.datetime "created_at", precision: 6, null: false
|
|
39
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
40
|
+
t.index ["account_id"], name: "index_qv_logs_on_account_id"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
create_table "qv_passwords", force: :cascade do |t|
|
|
44
|
+
t.bigint "account_id", null: false
|
|
45
|
+
t.string "password_digest", null: false
|
|
46
|
+
t.datetime "created_at", precision: 6, null: false
|
|
47
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
48
|
+
t.index ["account_id"], name: "index_qv_passwords_on_account_id"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
create_table "qv_recovery_codes", force: :cascade do |t|
|
|
52
|
+
t.bigint "account_id", null: false
|
|
53
|
+
t.string "code_digest", null: false
|
|
54
|
+
t.datetime "created_at", precision: 6, null: false
|
|
55
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
56
|
+
t.index ["account_id"], name: "index_qv_recovery_codes_on_account_id"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
create_table "qv_sessions", force: :cascade do |t|
|
|
60
|
+
t.bigint "account_id", null: false
|
|
61
|
+
t.string "ip", null: false
|
|
62
|
+
t.string "user_agent", null: false
|
|
63
|
+
t.datetime "lifetime_expires_at"
|
|
64
|
+
t.datetime "last_seen_at"
|
|
65
|
+
t.datetime "second_factor_at"
|
|
66
|
+
t.datetime "created_at", precision: 6, null: false
|
|
67
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
68
|
+
t.index ["account_id"], name: "index_qv_sessions_on_account_id"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
create_table "qv_totps", force: :cascade do |t|
|
|
72
|
+
t.bigint "account_id", null: false
|
|
73
|
+
t.string "key", null: false
|
|
74
|
+
t.integer "last_used_at", null: false
|
|
75
|
+
t.datetime "created_at", precision: 6, null: false
|
|
76
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
77
|
+
t.index ["account_id"], name: "index_qv_totps_on_account_id"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
create_table "users", force: :cascade do |t|
|
|
81
|
+
t.string "name", null: false
|
|
82
|
+
t.string "email", null: false
|
|
83
|
+
t.datetime "created_at", precision: 6, null: false
|
|
84
|
+
t.datetime "updated_at", precision: 6, null: false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
add_foreign_key "qv_logs", "qv_accounts", column: "account_id"
|
|
88
|
+
add_foreign_key "qv_passwords", "qv_accounts", column: "account_id"
|
|
89
|
+
add_foreign_key "qv_recovery_codes", "qv_accounts", column: "account_id"
|
|
90
|
+
add_foreign_key "qv_sessions", "qv_accounts", column: "account_id"
|
|
91
|
+
add_foreign_key "qv_totps", "qv_accounts", column: "account_id"
|
|
92
|
+
end
|