quo_vadis 2.1.11 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +50 -99
- data/app/controllers/quo_vadis/confirmations_controller.rb +26 -61
- data/app/controllers/quo_vadis/password_resets_controller.rb +64 -32
- data/app/controllers/quo_vadis/sessions_controller.rb +0 -5
- data/app/mailers/quo_vadis/mailer.rb +2 -2
- data/app/models/quo_vadis/account.rb +32 -0
- data/app/models/quo_vadis/password.rb +6 -1
- data/app/views/quo_vadis/confirmations/new.html.erb +19 -7
- data/app/views/quo_vadis/mailer/account_confirmation.text.erb +2 -3
- data/app/views/quo_vadis/mailer/reset_password.text.erb +2 -2
- data/app/views/quo_vadis/password_resets/edit.html.erb +13 -1
- data/app/views/quo_vadis/password_resets/new.html.erb +1 -1
- data/config/locales/quo_vadis.en.yml +9 -7
- data/config/routes.rb +4 -12
- data/lib/quo_vadis/controller.rb +20 -10
- data/lib/quo_vadis/defaults.rb +2 -2
- data/lib/quo_vadis/version.rb +1 -1
- data/lib/quo_vadis.rb +2 -2
- data/test/dummy/app/controllers/sign_ups_controller.rb +2 -11
- data/test/fixtures/quo_vadis/mailer/account_confirmation.text +2 -3
- data/test/fixtures/quo_vadis/mailer/reset_password.text +2 -2
- data/test/integration/account_confirmation_test.rb +42 -86
- data/test/integration/controller_test.rb +8 -8
- data/test/integration/logging_test.rb +31 -7
- data/test/integration/password_login_test.rb +1 -1
- data/test/integration/password_reset_test.rb +89 -54
- data/test/mailers/mailer_test.rb +2 -2
- data/test/models/account_test.rb +48 -0
- data/test/models/session_test.rb +4 -0
- metadata +2 -10
- data/app/models/quo_vadis/account_confirmation_token.rb +0 -17
- data/app/models/quo_vadis/password_reset_token.rb +0 -17
- data/app/models/quo_vadis/token.rb +0 -42
- data/app/views/quo_vadis/confirmations/edit.html.erb +0 -10
- data/app/views/quo_vadis/confirmations/edit_email.html.erb +0 -14
- data/app/views/quo_vadis/confirmations/index.html.erb +0 -14
- data/app/views/quo_vadis/password_resets/index.html.erb +0 -5
- data/test/models/token_test.rb +0 -70
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rotp'
|
4
|
+
|
3
5
|
module QuoVadis
|
4
6
|
class Account < ActiveRecord::Base
|
5
7
|
|
@@ -18,6 +20,26 @@ module QuoVadis
|
|
18
20
|
after_update :log_identifier_change, if: :saved_change_to_identifier?
|
19
21
|
after_update :notify_identifier_change, if: :saved_change_to_identifier?
|
20
22
|
|
23
|
+
scope :unconfirmed, -> { where confirmed_at: nil }
|
24
|
+
|
25
|
+
def otp_for_confirmation(counter)
|
26
|
+
hotp_for_confirmation.at(counter)
|
27
|
+
end
|
28
|
+
|
29
|
+
# If the `otp` is valid for the `counter`, confirms the account and returns truthy.
|
30
|
+
# Otherwise returns falsey.
|
31
|
+
def confirm(otp, counter)
|
32
|
+
hotp_for_confirmation.verify(otp, counter) && confirmed!
|
33
|
+
end
|
34
|
+
|
35
|
+
def otp_for_password_reset(counter)
|
36
|
+
hotp_for_password_reset.at(counter)
|
37
|
+
end
|
38
|
+
|
39
|
+
def verify_password_reset(otp, counter)
|
40
|
+
hotp_for_password_reset.verify(otp, counter)
|
41
|
+
end
|
42
|
+
|
21
43
|
def confirmed?
|
22
44
|
confirmed_at.present?
|
23
45
|
end
|
@@ -51,6 +73,16 @@ module QuoVadis
|
|
51
73
|
|
52
74
|
private
|
53
75
|
|
76
|
+
def hotp_for_confirmation
|
77
|
+
key = ROTP::Base32.encode("#{id}-#{Rails.application.secret_key_base}")
|
78
|
+
ROTP::HOTP.new(key)
|
79
|
+
end
|
80
|
+
|
81
|
+
def hotp_for_password_reset
|
82
|
+
key = ROTP::Base32.encode("#{id}-#{password.password_digest}")
|
83
|
+
ROTP::HOTP.new(key)
|
84
|
+
end
|
85
|
+
|
54
86
|
def log_identifier_change
|
55
87
|
from, to = saved_change_to_identifier
|
56
88
|
Log.create(
|
@@ -46,7 +46,12 @@ module QuoVadis
|
|
46
46
|
|
47
47
|
self.password = new_plaintext
|
48
48
|
self.password_confirmation = new_plaintext_confirmation
|
49
|
-
save
|
49
|
+
if save
|
50
|
+
# Logout account's sessions because password has changed.
|
51
|
+
# Assumes model is not logged in.
|
52
|
+
account.sessions.destroy_all
|
53
|
+
true
|
54
|
+
end
|
50
55
|
end
|
51
56
|
|
52
57
|
private
|
@@ -1,16 +1,28 @@
|
|
1
|
-
<h1>
|
1
|
+
<h1>Account confirmation</h1>
|
2
2
|
|
3
|
-
|
3
|
+
<p>We have sent a confirmation code to <%= @account.model.email %>.</p>
|
4
4
|
|
5
|
-
|
5
|
+
<!-- flash could go here -->
|
6
6
|
|
7
|
-
<%= form_with url:
|
7
|
+
<%= form_with url: confirm_path, method: :post do %>
|
8
8
|
<p>
|
9
|
-
|
10
|
-
|
9
|
+
<label for="otp">Your confirmation code:</label>
|
10
|
+
<input
|
11
|
+
name="otp"
|
12
|
+
id="otp"
|
13
|
+
type="text"
|
14
|
+
inputmode="numeric"
|
15
|
+
pattern="\d*"
|
16
|
+
autofocus="true"
|
17
|
+
autocomplete="one-time-password"
|
18
|
+
maxlength="6">
|
11
19
|
</p>
|
12
20
|
|
13
21
|
<p>
|
14
|
-
|
22
|
+
<button type="submit">Confirm me!</button>
|
15
23
|
</p>
|
16
24
|
<% end %>
|
25
|
+
|
26
|
+
<p>
|
27
|
+
<%= button_to "Send me a new confirmation code", send_confirmation_path %>
|
28
|
+
</p>
|
@@ -1,6 +1,18 @@
|
|
1
1
|
<h1>Reset password</h1>
|
2
2
|
|
3
|
-
<%= form_with model: @password, url: password_reset_path
|
3
|
+
<%= form_with model: @password, url: password_reset_path, method: :put do |f| %>
|
4
|
+
<p>
|
5
|
+
<%= f.label :otp, 'Your password reset code' %>
|
6
|
+
<%= f.text_field :otp,
|
7
|
+
value: params.dig(:password, :otp),
|
8
|
+
inputmode: 'numeric',
|
9
|
+
pattern: '\d*',
|
10
|
+
autofocus: true,
|
11
|
+
autocomplete: 'one-time-password',
|
12
|
+
maxlength: 6 %>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
|
4
16
|
<p>
|
5
17
|
<%= f.label :password %>
|
6
18
|
<%= f.password_field :password, autocomplete: 'new-password' %>
|
@@ -11,15 +11,17 @@ en:
|
|
11
11
|
password:
|
12
12
|
update: Your password has been changed.
|
13
13
|
password_reset:
|
14
|
-
create:
|
15
|
-
unknown:
|
14
|
+
create: Please check your email for your reset code.
|
15
|
+
unknown: Please check your email for your reset code.
|
16
|
+
expired: Your reset code has expired. Please request another one.
|
17
|
+
invalid: Sorry, the code was incorrect. Please try again.
|
16
18
|
reset: Your password has been changed and you are logged in.
|
17
19
|
confirmation:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
confirmed: Thanks for confirming your account.
|
20
|
+
unknown: You have already confirmed your account.
|
21
|
+
sent: Please check your email for your confirmation code.
|
22
|
+
expired: Your confirmation code has expired. Please request another one.
|
23
|
+
invalid: Sorry, the code was incorrect. Please try again.
|
24
|
+
confirmed: Thanks for confirming your account.
|
23
25
|
totp:
|
24
26
|
unverified: Sorry, the code was incorrect. Please check your system clock is correct and try again.
|
25
27
|
setup: Please set up two factor authentication.
|
data/config/routes.rb
CHANGED
@@ -11,19 +11,11 @@ QuoVadis::Engine.routes.draw do
|
|
11
11
|
|
12
12
|
resource :password, only: [:edit, :update]
|
13
13
|
|
14
|
-
|
15
|
-
get '/pwd-reset/:token', to: 'password_resets#edit', as: 'password_reset'
|
16
|
-
put '/pwd-reset/:token', to: 'password_resets#update'
|
14
|
+
resource :password_reset, only: [:new, :create, :edit, :update]
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
put :update_email
|
22
|
-
post :resend
|
23
|
-
end
|
24
|
-
end
|
25
|
-
get '/confirm/:token', to: 'confirmations#edit', as: 'confirmation'
|
26
|
-
put '/confirm/:token', to: 'confirmations#update'
|
16
|
+
get '/confirm', to: 'confirmations#new'
|
17
|
+
post '/confirm', to: 'confirmations#create'
|
18
|
+
post '/confirm/send', to: 'confirmations#resend', as: 'send_confirmation'
|
27
19
|
|
28
20
|
resources :totps, only: [:new, :create] do
|
29
21
|
collection do
|
data/lib/quo_vadis/controller.rb
CHANGED
@@ -16,7 +16,13 @@ module QuoVadis
|
|
16
16
|
|
17
17
|
|
18
18
|
def require_password_authentication
|
19
|
-
|
19
|
+
if logged_in?
|
20
|
+
if QuoVadis.accounts_require_confirmation && !authenticated_model.qv_account.confirmed?
|
21
|
+
qv.request_confirmation authenticated_model
|
22
|
+
redirect_to quo_vadis.confirm_path
|
23
|
+
end
|
24
|
+
return
|
25
|
+
end
|
20
26
|
session[:qv_bookmark] = request.original_fullpath
|
21
27
|
redirect_to quo_vadis.login_path, notice: QuoVadis.translate('flash.require_authentication')
|
22
28
|
end
|
@@ -85,15 +91,6 @@ module QuoVadis
|
|
85
91
|
end
|
86
92
|
|
87
93
|
|
88
|
-
def request_confirmation(model)
|
89
|
-
token = QuoVadis::AccountConfirmationToken.generate model.qv_account
|
90
|
-
QuoVadis.deliver :account_confirmation, {email: model.email, url: quo_vadis.confirmation_url(token)}
|
91
|
-
session[:account_pending_confirmation] = model.qv_account.id
|
92
|
-
|
93
|
-
flash[:notice] = QuoVadis.translate 'flash.confirmation.create'
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
94
|
def qv
|
98
95
|
@qv_wrapper ||= QuoVadisWrapper.new self
|
99
96
|
end
|
@@ -143,6 +140,19 @@ module QuoVadis
|
|
143
140
|
old_session.each { |k,v| rails_session[k] = v }
|
144
141
|
end
|
145
142
|
|
143
|
+
def request_confirmation(model)
|
144
|
+
rails_session[:account_pending_confirmation] = model.qv_account.id
|
145
|
+
|
146
|
+
expiration = QuoVadis.account_confirmation_otp_lifetime.from_now.to_i
|
147
|
+
rails_session[:account_confirmation_expires_at] = expiration
|
148
|
+
|
149
|
+
otp = model.qv_account.otp_for_confirmation(expiration)
|
150
|
+
|
151
|
+
QuoVadis.deliver :account_confirmation, {email: model.email, otp: otp}
|
152
|
+
|
153
|
+
controller.flash[:notice] = QuoVadis.translate 'flash.confirmation.sent'
|
154
|
+
end
|
155
|
+
|
146
156
|
# Assumes user is logged in.
|
147
157
|
def second_factor_required?
|
148
158
|
QuoVadis.two_factor_authentication_mandatory || authenticated_model.qv_account.has_two_factors?
|
data/lib/quo_vadis/defaults.rb
CHANGED
@@ -7,9 +7,9 @@ QuoVadis.configure do
|
|
7
7
|
session_lifetime :session
|
8
8
|
session_lifetime_extend_to_end_of_day false
|
9
9
|
session_idle_timeout :lifetime
|
10
|
-
|
10
|
+
password_reset_otp_lifetime 10.minutes
|
11
11
|
accounts_require_confirmation false
|
12
|
-
|
12
|
+
account_confirmation_otp_lifetime 10.minutes
|
13
13
|
mailer_superclass 'ApplicationMailer'
|
14
14
|
mail_headers ({ from: 'Example App <support@example.com>' })
|
15
15
|
enqueue_transactional_emails true
|
data/lib/quo_vadis/version.rb
CHANGED
data/lib/quo_vadis.rb
CHANGED
@@ -24,11 +24,11 @@ module QuoVadis
|
|
24
24
|
:session_lifetime, # :session | ActiveSupport::Duration | [integer] seconds
|
25
25
|
:session_lifetime_extend_to_end_of_day,# true | false
|
26
26
|
:session_idle_timeout, # :lifetime | ActiveSupport::Duration | [integer] seconds
|
27
|
-
:
|
27
|
+
:password_reset_otp_lifetime, # ActiveSupport::Duration | [integer] seconds
|
28
28
|
:mailer_superclass, # string
|
29
29
|
:mail_headers, # hash
|
30
30
|
:accounts_require_confirmation, # true | false
|
31
|
-
:
|
31
|
+
:account_confirmation_otp_lifetime, # ActiveSupport::Duration | [integer] seconds
|
32
32
|
:enqueue_transactional_emails, # true | false
|
33
33
|
:app_name, # string
|
34
34
|
:two_factor_authentication_mandatory, # true | false
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# To test sign-ups with confirmation (activation / verification)
|
2
2
|
class SignUpsController < ApplicationController
|
3
3
|
|
4
|
-
around_action :toggle_confirmation
|
5
|
-
|
6
4
|
def new
|
7
5
|
@user = User.new
|
8
6
|
end
|
@@ -11,9 +9,9 @@ class SignUpsController < ApplicationController
|
|
11
9
|
def create
|
12
10
|
@user = User.new user_params
|
13
11
|
if @user.save
|
12
|
+
login @user
|
14
13
|
if QuoVadis.accounts_require_confirmation
|
15
|
-
|
16
|
-
redirect_to quo_vadis.confirmations_path
|
14
|
+
redirect_to secret_articles_path
|
17
15
|
else
|
18
16
|
redirect_to articles_path
|
19
17
|
end
|
@@ -37,11 +35,4 @@ class SignUpsController < ApplicationController
|
|
37
35
|
params.require(:user).permit(:name, :email, :password, :password_confirmation)
|
38
36
|
end
|
39
37
|
|
40
|
-
def toggle_confirmation
|
41
|
-
QuoVadis.accounts_require_confirmation true
|
42
|
-
yield
|
43
|
-
ensure
|
44
|
-
QuoVadis.accounts_require_confirmation false
|
45
|
-
end
|
46
|
-
|
47
38
|
end
|
@@ -14,136 +14,92 @@ class AccountConfirmationTest < IntegrationTest
|
|
14
14
|
test 'new signup requiring confirmation' do
|
15
15
|
assert_emails 1 do
|
16
16
|
post sign_ups_path(user: {name: 'Bob', email: 'bob@example.com', password: '123456789abc'})
|
17
|
+
refute QuoVadis::Account.last.confirmed?
|
18
|
+
assert controller.logged_in?
|
19
|
+
|
20
|
+
# verify response
|
21
|
+
assert_redirected_to '/articles/secret'
|
22
|
+
follow_redirect!
|
23
|
+
assert_redirected_to '/confirm'
|
24
|
+
follow_redirect!
|
25
|
+
assert_equal 'Please check your email for your confirmation code.', flash[:notice]
|
17
26
|
end
|
18
|
-
refute QuoVadis::Account.last.confirmed?
|
19
|
-
|
20
|
-
# verify response
|
21
|
-
assert_response :redirect
|
22
|
-
follow_redirect!
|
23
|
-
assert_equal 'A link to confirm your account has been emailed to you.', flash[:notice]
|
24
27
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
assert_response :success
|
29
|
-
action_path = extract_path_from_email
|
30
|
-
assert_select "form[action='#{action_path}']"
|
31
|
-
|
32
|
-
# click button on confirmation page
|
33
|
-
put action_path
|
28
|
+
# type in confirmation code from email
|
29
|
+
code = extract_code_from_email
|
30
|
+
post quo_vadis.confirm_path(otp: code)
|
34
31
|
|
35
32
|
# verify logged in
|
36
33
|
assert_redirected_to '/sign_ups/confirmed'
|
37
34
|
follow_redirect!
|
38
35
|
assert_redirected_to '/articles/secret'
|
39
|
-
assert_equal 'Thanks for confirming your account.
|
40
|
-
assert controller.logged_in?
|
36
|
+
assert_equal 'Thanks for confirming your account.', flash[:notice]
|
41
37
|
assert QuoVadis::Account.last.confirmed?
|
42
38
|
end
|
43
39
|
|
44
40
|
|
45
|
-
test '
|
46
|
-
assert_emails 1 do
|
47
|
-
post sign_ups_path(user: {name: 'Bob', email: 'bob@example.com', password: '123456789abc'})
|
48
|
-
end
|
49
|
-
|
50
|
-
get quo_vadis.edit_email_confirmations_path
|
51
|
-
assert_response :success
|
52
|
-
|
53
|
-
# First email: changed-email notifier sent to original address
|
54
|
-
# Second email: confirmation email sent to new address
|
55
|
-
assert_emails 2 do
|
56
|
-
put quo_vadis.update_email_confirmations_path(email: 'bobby@example.com')
|
57
|
-
end
|
58
|
-
assert_equal ['bobby@example.com'], ActionMailer::Base.deliveries.last.to
|
59
|
-
assert_redirected_to quo_vadis.confirmations_path
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
test 'resend confirmation email in same session' do
|
41
|
+
test 'resend confirmation email' do
|
64
42
|
assert_emails 1 do
|
65
43
|
post sign_ups_path(user: {name: 'Bob', email: 'bob@example.com', password: '123456789abc'})
|
44
|
+
assert_redirected_to '/articles/secret'
|
45
|
+
follow_redirect!
|
66
46
|
end
|
67
47
|
|
68
48
|
assert_emails 1 do
|
69
|
-
post quo_vadis.
|
49
|
+
post quo_vadis.send_confirmation_path
|
70
50
|
end
|
71
51
|
end
|
72
52
|
|
73
53
|
|
74
|
-
test '
|
75
|
-
User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
76
|
-
|
77
|
-
get quo_vadis.new_confirmation_path
|
78
|
-
assert_response :success
|
79
|
-
|
80
|
-
assert_emails 1 do
|
81
|
-
post quo_vadis.confirmations_path(email: 'bob@example.com')
|
82
|
-
end
|
83
|
-
|
84
|
-
assert_redirected_to '/confirmations'
|
85
|
-
assert_equal 'A link to confirm your account has been emailed to you.', flash[:notice]
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
test 'resend confirmation email: unknown identifier' do
|
90
|
-
assert_no_emails do
|
91
|
-
post quo_vadis.confirmations_path(email: 'bob@example.com')
|
92
|
-
end
|
93
|
-
|
94
|
-
assert_redirected_to quo_vadis.new_confirmation_path
|
95
|
-
assert_equal 'Sorry, your account could not be found. Please try again.', flash[:alert]
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
test 'reusing a token' do
|
54
|
+
test 'cannot reuse a confirmation code' do
|
100
55
|
assert_emails 1 do
|
101
56
|
post sign_ups_path(user: {name: 'Bob', email: 'bob@example.com', password: '123456789abc'})
|
57
|
+
follow_redirect!
|
102
58
|
end
|
103
59
|
|
104
|
-
|
60
|
+
code = extract_code_from_email
|
61
|
+
post quo_vadis.confirm_path(otp: code)
|
62
|
+
assert QuoVadis::Account.last.confirmed?
|
63
|
+
assert_equal 'Thanks for confirming your account.', flash[:notice]
|
105
64
|
|
65
|
+
post quo_vadis.confirm_path(otp: code)
|
66
|
+
assert_equal 'You have already confirmed your account.', flash[:alert]
|
106
67
|
assert_redirected_to '/sign_ups/confirmed'
|
107
|
-
follow_redirect!
|
108
|
-
assert_redirected_to '/articles/secret'
|
109
|
-
assert_equal 'Thanks for confirming your account. You are now logged in.', flash[:notice]
|
110
|
-
|
111
|
-
put extract_path_from_email
|
112
|
-
assert_redirected_to quo_vadis.new_confirmation_path
|
113
|
-
assert_equal 'Either the link has expired or your account has already been confirmed.', flash[:alert]
|
114
68
|
end
|
115
69
|
|
116
70
|
|
117
|
-
test '
|
71
|
+
test 'confirmation code expired' do
|
118
72
|
assert_emails 1 do
|
119
73
|
post sign_ups_path(user: {name: 'Bob', email: 'bob@example.com', password: '123456789abc'})
|
74
|
+
follow_redirect!
|
120
75
|
end
|
121
76
|
|
122
|
-
travel QuoVadis.
|
123
|
-
get extract_url_from_email
|
77
|
+
travel QuoVadis.account_confirmation_otp_lifetime + 1.minute
|
124
78
|
|
125
|
-
|
126
|
-
|
79
|
+
code = extract_code_from_email
|
80
|
+
post quo_vadis.confirm_path(otp: code)
|
81
|
+
refute QuoVadis::Account.last.confirmed?
|
82
|
+
assert_equal 'Your confirmation code has expired. Please request another one.', flash[:alert]
|
83
|
+
assert_redirected_to quo_vadis.confirm_path
|
127
84
|
end
|
128
85
|
|
129
86
|
|
130
|
-
test 'accounts requiring confirmation
|
87
|
+
test 'accounts requiring confirmation can log in but have to confirm' do
|
131
88
|
User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
132
89
|
post quo_vadis.login_path(email: 'bob@example.com', password: '123456789abc')
|
133
|
-
assert_redirected_to
|
134
|
-
|
135
|
-
|
90
|
+
assert_redirected_to '/articles/secret'
|
91
|
+
follow_redirect!
|
92
|
+
assert_redirected_to quo_vadis.confirm_path
|
93
|
+
follow_redirect!
|
94
|
+
assert controller.logged_in?
|
95
|
+
assert_equal 'Please check your email for your confirmation code.', flash[:notice]
|
136
96
|
end
|
137
97
|
|
138
98
|
|
139
99
|
private
|
140
100
|
|
141
|
-
def
|
142
|
-
ActionMailer::Base.deliveries.last.decoded[%r{
|
143
|
-
end
|
144
|
-
|
145
|
-
def extract_path_from_email
|
146
|
-
extract_url_from_email.sub 'http://www.example.com', ''
|
101
|
+
def extract_code_from_email
|
102
|
+
ActionMailer::Base.deliveries.last.decoded[%r{\d{6}}, 0]
|
147
103
|
end
|
148
104
|
|
149
105
|
end
|
@@ -206,14 +206,14 @@ class ControllerTest < IntegrationTest
|
|
206
206
|
end
|
207
207
|
|
208
208
|
|
209
|
-
test 'request_confirmation' do
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
end
|
209
|
+
# test 'request_confirmation' do
|
210
|
+
# get articles_path
|
211
|
+
|
212
|
+
# assert_emails 1 do
|
213
|
+
# controller.request_confirmation User.last
|
214
|
+
# end
|
215
|
+
# assert_equal 'A link to confirm your account has been emailed to you.', flash[:notice]
|
216
|
+
# end
|
217
217
|
|
218
218
|
|
219
219
|
test 'session lifetime exceeded' do
|
@@ -163,22 +163,42 @@ class LoggingTest < IntegrationTest
|
|
163
163
|
|
164
164
|
|
165
165
|
test 'password.reset' do
|
166
|
+
assert_emails 1 do
|
167
|
+
post quo_vadis.password_reset_path(email: 'bob@example.com')
|
168
|
+
follow_redirect!
|
169
|
+
end
|
170
|
+
|
166
171
|
assert_difference 'QuoVadis::Log.count', 2 do
|
167
|
-
|
168
|
-
|
172
|
+
put quo_vadis.password_reset_path(password: {
|
173
|
+
otp: extract_code_from_email,
|
174
|
+
password: 'secretsecret',
|
175
|
+
password_confirmation: 'secretsecret',
|
176
|
+
})
|
169
177
|
end
|
178
|
+
|
170
179
|
assert_equal QuoVadis::Log::PASSWORD_RESET, QuoVadis::Log.first.action
|
171
180
|
assert_equal QuoVadis::Log::LOGIN_SUCCESS, log.action
|
172
181
|
end
|
173
182
|
|
174
183
|
|
175
184
|
test 'account.confirmation' do
|
176
|
-
|
177
|
-
|
178
|
-
|
185
|
+
QuoVadis.accounts_require_confirmation true
|
186
|
+
|
187
|
+
assert_emails 1 do
|
188
|
+
login
|
189
|
+
assert_redirected_to '/articles/secret'
|
190
|
+
follow_redirect!
|
191
|
+
assert_redirected_to '/confirm'
|
192
|
+
follow_redirect!
|
179
193
|
end
|
180
|
-
|
181
|
-
|
194
|
+
|
195
|
+
assert_difference 'QuoVadis::Log.count' do
|
196
|
+
post quo_vadis.confirm_path(otp: extract_code_from_email)
|
197
|
+
end
|
198
|
+
|
199
|
+
assert_equal QuoVadis::Log::ACCOUNT_CONFIRMATION, log.action
|
200
|
+
ensure
|
201
|
+
QuoVadis.accounts_require_confirmation false
|
182
202
|
end
|
183
203
|
|
184
204
|
|
@@ -241,4 +261,8 @@ class LoggingTest < IntegrationTest
|
|
241
261
|
end
|
242
262
|
end
|
243
263
|
|
264
|
+
def extract_code_from_email
|
265
|
+
ActionMailer::Base.deliveries.last.decoded[%r{\d{6}}, 0]
|
266
|
+
end
|
267
|
+
|
244
268
|
end
|