quo_vadis 2.0.2 → 2.1.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 +10 -1
- data/README.md +8 -6
- data/app/controllers/quo_vadis/password_resets_controller.rb +11 -8
- data/app/controllers/quo_vadis/passwords_controller.rb +4 -2
- data/app/controllers/quo_vadis/recovery_codes_controller.rb +1 -1
- data/app/controllers/quo_vadis/sessions_controller.rb +2 -2
- data/app/controllers/quo_vadis/totps_controller.rb +1 -1
- data/app/models/quo_vadis/log.rb +1 -1
- data/config/locales/quo_vadis.en.yml +29 -1
- data/lib/quo_vadis/controller.rb +1 -2
- data/lib/quo_vadis/defaults.rb +1 -1
- data/lib/quo_vadis/model.rb +4 -11
- data/lib/quo_vadis/version.rb +1 -1
- data/test/dummy/app/views/quo_vadis/logs/index.html.erb +3 -1
- data/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb +1 -9
- data/test/dummy/app/views/quo_vadis/passwords/edit.html.erb +1 -9
- data/test/dummy/config/initializers/quo_vadis.rb +0 -4
- data/test/integration/logging_test.rb +4 -4
- data/test/integration/password_change_test.rb +16 -10
- data/test/integration/password_login_test.rb +14 -2
- data/test/integration/password_reset_test.rb +5 -5
- data/test/integration/totps_test.rb +1 -1
- data/test/models/password_test.rb +3 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f8acc907c43d19fcc6f9be59854be5e848add025d427f78ec608b2e24677e73
|
4
|
+
data.tar.gz: efab0ab6fc83535466f6bb6e31bb056016c5220ef227155629601e5c17aff5b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d34c8922431d4234650c50718a29b71a328b070582bb5b7fac74d4b1e2b6847bc2b130a197d6dcc05d93d2c0dab882a90fecf9faa3e1620f36acb48b9be3778
|
7
|
+
data.tar.gz: 4f471b97ff2a2dc0461ddac1f68c1e9f263ac5c188ab89daf2974f3c8f2e85c5e2b586da72b8c798d5f696acf3a2a7079aef57fb689f8f75f8113a38d56b2c2d
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
3
|
|
4
|
-
##
|
4
|
+
## 2.1.0 (25 June 2021)
|
5
|
+
|
6
|
+
* Fix incorrect assignment of built association.
|
7
|
+
* Add i18n translations for log actions.
|
8
|
+
* Use model instance in change-password form.
|
9
|
+
* Ensure password-reset flash notice not displayed when emailed link is clicked.
|
10
|
+
* Use model instance in password-reset form.
|
11
|
+
* Give no indication of unknown account on request of password reset email.
|
12
|
+
* Use 422 status code for form submission error responses.
|
13
|
+
* Make default cookie name depend on Rails environment.
|
5
14
|
|
6
15
|
|
7
16
|
## 2.0.2 (24 May 2021)
|
data/README.md
CHANGED
@@ -86,9 +86,9 @@ class Person < ApplicationRecord
|
|
86
86
|
end
|
87
87
|
```
|
88
88
|
|
89
|
-
When
|
89
|
+
You can create and update your models as before. When you want to set a password for the first time, just include `:password` and, optionally, `:password_confirmation` in the attributes to `#create` or `#update`.
|
90
90
|
|
91
|
-
|
91
|
+
If you want to change an existing password, use the Change Password feature (see below). If you update a model (that already has a password) with a `:password` attribute, it will raise a `QuoVadis::PasswordExistsError`.
|
92
92
|
|
93
93
|
The minimum password length is configured by `QuoVadis.password_minimum_length` (12 by default).
|
94
94
|
|
@@ -256,6 +256,8 @@ On that page you can show the user the address the email was sent to, enable the
|
|
256
256
|
|
257
257
|
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit.html.:format`.
|
258
258
|
|
259
|
+
Next, write the page where the user can amend their email address if they made a mistake when signing up ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/edit_email.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit_email.html.:format`.
|
260
|
+
|
259
261
|
Finally, write the page where people can put in their identifier (not their email, unless the identifier is email) again to request another confirmation email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/new.html.erb)). It must be in `app/views/quo_vadis/confirmations/new.html.:format`.
|
260
262
|
|
261
263
|
After the user has confirmed their account, they will be logged in and redirected to the first of these that exists:
|
@@ -353,9 +355,9 @@ Now write the page to where the user is redirected while they wait for the email
|
|
353
355
|
|
354
356
|
It's a good idea for that page to link to `new_password_reset_path` where the user can request another email if need be.
|
355
357
|
|
356
|
-
|
358
|
+
Now write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/reset_password.text.erb)). It must be in `app/views/quo_vadis/mailer/reset_password.{text,html}.erb` and output the `@url` variable.
|
357
359
|
|
358
|
-
|
360
|
+
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb)). It must be in `app/views/quo_vadis/password_resets/edit.html.:format`.
|
359
361
|
|
360
362
|
After the user has reset their password, they will be logged in and redirected to the first of these that exists:
|
361
363
|
|
@@ -405,7 +407,7 @@ This is QuoVadis' [default configuration](https://github.com/airblade/quo_vadis/
|
|
405
407
|
QuoVadis.configure do
|
406
408
|
password_minimum_length 12
|
407
409
|
mask_ips false
|
408
|
-
cookie_name '__Host-qv'
|
410
|
+
cookie_name (Rails.env.production? ? '__Host-qv' : 'qv')
|
409
411
|
session_lifetime :session
|
410
412
|
session_lifetime_extend_to_end_of_day false
|
411
413
|
session_idle_timeout :lifetime
|
@@ -436,7 +438,7 @@ Masking means setting the last octet (IPv4) or the last 80 bits (IPv6) to 0.
|
|
436
438
|
|
437
439
|
__`cookie_name`__ (string)
|
438
440
|
|
439
|
-
The name of the cookie QuoVadis uses to store the session identifier. The `__Host-` prefix is [recommended](https://developer.mozilla.org/en-US/docs/Web/API/document/cookie).
|
441
|
+
The name of the cookie QuoVadis uses to store the session identifier. The `__Host-` prefix is [recommended](https://developer.mozilla.org/en-US/docs/Web/API/document/cookie) in an SSL environment (but cannot be used in a non-SSL environment).
|
440
442
|
|
441
443
|
__`session_lifetime`__ (`:session` | `ActiveSupport::Duration` | integer)
|
442
444
|
|
@@ -13,15 +13,14 @@ module QuoVadis
|
|
13
13
|
|
14
14
|
|
15
15
|
def create
|
16
|
-
flash[:notice] = QuoVadis.translate 'flash.password_reset.create'
|
17
|
-
|
18
16
|
account = QuoVadis.find_account_by_identifier_in_params params
|
19
|
-
return unless account
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
if account
|
19
|
+
token = QuoVadis::PasswordResetToken.generate account
|
20
|
+
QuoVadis.deliver :reset_password, email: account.model.email, url: quo_vadis.edit_password_reset_url(token)
|
21
|
+
end
|
23
22
|
|
24
|
-
redirect_to password_resets_path
|
23
|
+
redirect_to password_resets_path, notice: QuoVadis.translate('flash.password_reset.create')
|
25
24
|
end
|
26
25
|
|
27
26
|
|
@@ -33,6 +32,10 @@ module QuoVadis
|
|
33
32
|
redirect_to new_password_reset_path, alert: QuoVadis.translate('flash.password_reset.unknown') and return
|
34
33
|
end
|
35
34
|
|
35
|
+
# Ensure the flash notice set in the create action does not appear when the user clicks the
|
36
|
+
# link in the email they were sent.
|
37
|
+
flash.delete :notice
|
38
|
+
|
36
39
|
@password = QuoVadis::Password.new
|
37
40
|
end
|
38
41
|
|
@@ -46,7 +49,7 @@ module QuoVadis
|
|
46
49
|
end
|
47
50
|
|
48
51
|
@password = account.password
|
49
|
-
if @password.reset params[:password], params[:password_confirmation]
|
52
|
+
if @password.reset params[:password][:password], params[:password][:password_confirmation]
|
50
53
|
# Logout account's sessions because password has changed.
|
51
54
|
# Note model is not logged in here.
|
52
55
|
@password.account.sessions.destroy_all
|
@@ -57,7 +60,7 @@ module QuoVadis
|
|
57
60
|
login @password.account.model, true
|
58
61
|
redirect_to qv.path_after_authentication, notice: QuoVadis.translate('flash.password_reset.reset')
|
59
62
|
else
|
60
|
-
render :edit
|
63
|
+
render :edit, status: :unprocessable_entity
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
@@ -11,14 +11,16 @@ module QuoVadis
|
|
11
11
|
|
12
12
|
def update
|
13
13
|
@password = authenticated_model.qv_account.password
|
14
|
-
if @password.change
|
14
|
+
if @password.change(params[:password][:password],
|
15
|
+
params[:password][:new_password],
|
16
|
+
params[:password][:new_password_confirmation])
|
15
17
|
qv.log authenticated_model.qv_account, Log::PASSWORD_CHANGE
|
16
18
|
QuoVadis.notify :password_change_notification, email: authenticated_model.email
|
17
19
|
qv.logout_other_sessions
|
18
20
|
qv.replace_session
|
19
21
|
redirect_to qv.path_after_password_change, notice: QuoVadis.translate('flash.password.update')
|
20
22
|
else
|
21
|
-
render :edit
|
23
|
+
render :edit, status: :unprocessable_entity
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
@@ -23,14 +23,14 @@ module QuoVadis
|
|
23
23
|
unless account
|
24
24
|
qv.log nil, Log::LOGIN_UNKNOWN, identifier: QuoVadis.identifier_value_in_params(params)
|
25
25
|
flash.now[:alert] = QuoVadis.translate 'flash.login.failed'
|
26
|
-
render :new
|
26
|
+
render :new, status: :unprocessable_entity
|
27
27
|
return
|
28
28
|
end
|
29
29
|
|
30
30
|
unless account.password.authenticate params[:password]
|
31
31
|
qv.log account, Log::LOGIN_FAILURE
|
32
32
|
flash.now[:alert] = QuoVadis.translate 'flash.login.failed'
|
33
|
-
render :new
|
33
|
+
render :new, status: :unprocessable_entity
|
34
34
|
return
|
35
35
|
end
|
36
36
|
|
data/app/models/quo_vadis/log.rb
CHANGED
@@ -31,7 +31,6 @@ en:
|
|
31
31
|
other: You have %{count} recovery codes left.
|
32
32
|
2fa:
|
33
33
|
invalidated: You have invalidated your 2FA credentials and recovery codes.
|
34
|
-
|
35
34
|
mailer:
|
36
35
|
password_reset:
|
37
36
|
subject: Change your password
|
@@ -46,6 +45,35 @@ en:
|
|
46
45
|
totp_reuse: Your two-factor authentication code was reused just now
|
47
46
|
twofa_deactivated: Two-factor authentication was deactivated just now
|
48
47
|
recovery_codes_generation: Recovery codes have been generated for your account
|
48
|
+
log:
|
49
|
+
action:
|
50
|
+
login:
|
51
|
+
success: Logged in
|
52
|
+
failure: Failed login attempt (incorrect password)
|
53
|
+
unknown: Failed login attempt (unknown identifier)
|
54
|
+
totp:
|
55
|
+
setup: TOTP set up for 2FA
|
56
|
+
success: Authenticated via TOTP
|
57
|
+
failure: Failed authentication attempt via TOTP
|
58
|
+
reuse: Failed attempt to reuse TOTP code
|
59
|
+
recovery_code:
|
60
|
+
success: Authenticated via 2FA recovery code
|
61
|
+
failure: Failed authentication attempt via 2FA recovery code
|
62
|
+
generate: Generated new 2FA recovery codes
|
63
|
+
2fa:
|
64
|
+
deactivated: Deactivated 2FA
|
65
|
+
identifier:
|
66
|
+
change: Changed identifier
|
67
|
+
email:
|
68
|
+
change: Changed email address
|
69
|
+
password:
|
70
|
+
change: Changed password
|
71
|
+
reset: Reset password
|
72
|
+
account:
|
73
|
+
confirmation: Confirmed account
|
74
|
+
logout:
|
75
|
+
self: Logged out
|
76
|
+
other: Logged out session remotely
|
49
77
|
activerecord:
|
50
78
|
errors:
|
51
79
|
models:
|
data/lib/quo_vadis/controller.rb
CHANGED
@@ -17,9 +17,8 @@ module QuoVadis
|
|
17
17
|
|
18
18
|
def require_password_authentication
|
19
19
|
return if logged_in?
|
20
|
-
flash[:notice] = QuoVadis.translate 'flash.require_authentication'
|
21
20
|
session[:qv_bookmark] = request.original_fullpath
|
22
|
-
redirect_to quo_vadis.login_path
|
21
|
+
redirect_to quo_vadis.login_path, notice: QuoVadis.translate('flash.require_authentication')
|
23
22
|
end
|
24
23
|
alias_method :require_authentication, :require_password_authentication
|
25
24
|
|
data/lib/quo_vadis/defaults.rb
CHANGED
@@ -3,7 +3,7 @@ require 'active_support/core_ext'
|
|
3
3
|
QuoVadis.configure do
|
4
4
|
password_minimum_length 12
|
5
5
|
mask_ips false
|
6
|
-
cookie_name '__Host-qv'
|
6
|
+
cookie_name (Rails.env.production? ? '__Host-qv' : 'qv')
|
7
7
|
session_lifetime :session
|
8
8
|
session_lifetime_extend_to_end_of_day false
|
9
9
|
session_idle_timeout :lifetime
|
data/lib/quo_vadis/model.rb
CHANGED
@@ -14,11 +14,9 @@ module QuoVadis
|
|
14
14
|
|
15
15
|
has_one :qv_account, as: :model, class_name: 'QuoVadis::Account', dependent: :destroy, autosave: true
|
16
16
|
|
17
|
-
before_validation :
|
18
|
-
before_validation :qv_copy_identifier_to_account
|
17
|
+
before_validation :qv_copy_identifier_to_account, if: Proc.new { |m| m.qv_account }
|
19
18
|
|
20
|
-
|
21
|
-
validate :qv_copy_password_errors, on: :create
|
19
|
+
validate :qv_copy_password_errors, if: Proc.new { |m| m.qv_account&.password }
|
22
20
|
|
23
21
|
unless validators_on(identifier).any? { |v| ActiveRecord::Validations::UniquenessValidator === v }
|
24
22
|
raise NotImplementedError, <<~END
|
@@ -44,24 +42,19 @@ module QuoVadis
|
|
44
42
|
|
45
43
|
def password=(val)
|
46
44
|
@password = val
|
47
|
-
|
45
|
+
build_qv_account unless qv_account
|
48
46
|
raise PasswordExistsError if qv_account.password&.persisted?
|
49
47
|
(qv_account.password || qv_account.build_password).password = val
|
50
48
|
end
|
51
49
|
|
52
50
|
def password_confirmation=(val)
|
53
51
|
@password_confirmation = val
|
54
|
-
|
52
|
+
build_qv_account unless qv_account
|
55
53
|
(qv_account.password || qv_account.build_password).password_confirmation = val
|
56
54
|
end
|
57
55
|
|
58
56
|
private
|
59
57
|
|
60
|
-
def qv_build_account_and_password
|
61
|
-
self.qv_account ||= build_qv_account
|
62
|
-
qv_account.password || qv_account.build_password
|
63
|
-
end
|
64
|
-
|
65
58
|
def qv_copy_password_errors
|
66
59
|
qv_account.password.valid? # force qv_account.password to validate
|
67
60
|
qv_account.password.errors[:password ].each { |message| errors.add :password, message }
|
data/lib/quo_vadis/version.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
<table>
|
4
4
|
<thead>
|
5
5
|
<tr>
|
6
|
+
<th>Timestamp</th>
|
6
7
|
<th>Action</th>
|
7
8
|
<th>IP</th>
|
8
9
|
<th>Metadata</th>
|
@@ -11,7 +12,8 @@
|
|
11
12
|
<tbody>
|
12
13
|
<% @logs.each do |log| %>
|
13
14
|
<tr>
|
14
|
-
<td><%= log.
|
15
|
+
<td><%= log.created_at %></td>
|
16
|
+
<td><%= QuoVadis.translate "log.action.#{log.action}" %></td>
|
15
17
|
<td><%= log.ip %></td>
|
16
18
|
<td><%= log.metadata.empty? ? '' : log.metadata.map {|k,v| "#{k}: #{v}"}.join(', ') %></td>
|
17
19
|
</tr>
|
@@ -1,14 +1,6 @@
|
|
1
1
|
<h1>Reset password</h1>
|
2
2
|
|
3
|
-
|
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| %>
|
3
|
+
<%= form_with model: @password, url: password_reset_path(params[:token]), method: :put do |f| %>
|
12
4
|
<p>
|
13
5
|
<%= f.label :password %>
|
14
6
|
<%= f.password_field :password, autocomplete: 'new-password' %>
|
@@ -1,14 +1,6 @@
|
|
1
1
|
<h1>Change password</h1>
|
2
2
|
|
3
|
-
|
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| %>
|
3
|
+
<%= form_with model: @password, url: password_path, method: :put do |f| %>
|
12
4
|
<p>
|
13
5
|
<%= f.label :password %>
|
14
6
|
<%= f.password_field :password, autocomplete: 'current-password' %>
|
@@ -15,13 +15,13 @@ class LoggingTest < IntegrationTest
|
|
15
15
|
assert_response :success
|
16
16
|
|
17
17
|
assert_select 'tbody tr' do
|
18
|
-
assert_select 'td', 'password
|
18
|
+
assert_select 'td', 'Changed password'
|
19
19
|
assert_select 'td', '1.2.3.4'
|
20
20
|
assert_select 'td', 'foo: bar, baz: qux'
|
21
21
|
end
|
22
22
|
|
23
23
|
assert_select 'tbody tr' do
|
24
|
-
assert_select 'td', '
|
24
|
+
assert_select 'td', 'Logged in'
|
25
25
|
assert_select 'td', '127.0.0.1'
|
26
26
|
assert_select 'td', ''
|
27
27
|
end
|
@@ -157,7 +157,7 @@ class LoggingTest < IntegrationTest
|
|
157
157
|
test 'password.change' do
|
158
158
|
login
|
159
159
|
assert_log QuoVadis::Log::PASSWORD_CHANGE do
|
160
|
-
put quo_vadis.password_path(password: '123456789abc', new_password: 'xxxxxxxxxxxx', new_password_confirmation: 'xxxxxxxxxxxx')
|
160
|
+
put quo_vadis.password_path(password: {password: '123456789abc', new_password: 'xxxxxxxxxxxx', new_password_confirmation: 'xxxxxxxxxxxx'})
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -165,7 +165,7 @@ class LoggingTest < IntegrationTest
|
|
165
165
|
test 'password.reset' do
|
166
166
|
assert_difference 'QuoVadis::Log.count', 2 do
|
167
167
|
token = QuoVadis::PasswordResetToken.generate @account
|
168
|
-
put quo_vadis.password_reset_path(token, password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx')
|
168
|
+
put quo_vadis.password_reset_path(token, password: {password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx'})
|
169
169
|
end
|
170
170
|
assert_equal QuoVadis::Log::PASSWORD_RESET, QuoVadis::Log.first.action
|
171
171
|
assert_equal QuoVadis::Log::LOGIN_SUCCESS, log.action
|
@@ -18,29 +18,31 @@ class PasswordChangeTest < IntegrationTest
|
|
18
18
|
|
19
19
|
|
20
20
|
test 'incorrect password' do
|
21
|
-
put quo_vadis.password_path(password: 'x')
|
22
|
-
assert_response :
|
21
|
+
put quo_vadis.password_path(password: {password: 'x'})
|
22
|
+
assert_response :unprocessable_entity
|
23
23
|
assert_equal ['is incorrect'], password_instance.errors[:password]
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
27
|
test 'new password empty' do
|
28
|
-
put quo_vadis.password_path(password: '123456789abc', new_password: '')
|
29
|
-
assert_response :
|
28
|
+
put quo_vadis.password_path(password: {password: '123456789abc', new_password: ''})
|
29
|
+
assert_response :unprocessable_entity
|
30
30
|
assert_equal ["can't be blank"], password_instance.errors[:new_password]
|
31
31
|
end
|
32
32
|
|
33
33
|
|
34
34
|
test 'new password too short' do
|
35
|
-
put quo_vadis.password_path(password: '123456789abc', new_password: 'x')
|
36
|
-
assert_response :
|
35
|
+
put quo_vadis.password_path(password: {password: '123456789abc', new_password: 'x'})
|
36
|
+
assert_response :unprocessable_entity
|
37
37
|
assert_equal ["is too short (minimum is #{QuoVadis.password_minimum_length} characters)"], password_instance.errors[:new_password]
|
38
38
|
end
|
39
39
|
|
40
40
|
|
41
41
|
test 'new password confirmation does not match' do
|
42
|
-
put quo_vadis.password_path(password:
|
43
|
-
|
42
|
+
put quo_vadis.password_path(password: {
|
43
|
+
password: '123456789abc', new_password: 'xxxxxxxxxxxx', new_password_confirmation: 'y'
|
44
|
+
})
|
45
|
+
assert_response :unprocessable_entity
|
44
46
|
assert_equal ["doesn't match Password"], password_instance.errors[:new_password_confirmation]
|
45
47
|
end
|
46
48
|
|
@@ -48,7 +50,9 @@ class PasswordChangeTest < IntegrationTest
|
|
48
50
|
test 'success' do
|
49
51
|
assert_emails 1 do
|
50
52
|
assert_session_replaced do
|
51
|
-
put quo_vadis.password_path(password:
|
53
|
+
put quo_vadis.password_path(password: {
|
54
|
+
password: '123456789abc', new_password: 'xxxxxxxxxxxx', new_password_confirmation: 'xxxxxxxxxxxx'
|
55
|
+
})
|
52
56
|
assert_response :redirect
|
53
57
|
assert_equal 'Your password has been changed.', flash[:notice]
|
54
58
|
end
|
@@ -60,7 +64,9 @@ class PasswordChangeTest < IntegrationTest
|
|
60
64
|
desktop = session_login
|
61
65
|
phone = session_login
|
62
66
|
|
63
|
-
desktop.put quo_vadis.password_path(password:
|
67
|
+
desktop.put quo_vadis.password_path(password: {
|
68
|
+
password: '123456789abc', new_password: 'xxxxxxxxxxxx', new_password_confirmation: 'xxxxxxxxxxxx'
|
69
|
+
})
|
64
70
|
desktop.follow_redirect!
|
65
71
|
assert desktop.controller.logged_in?
|
66
72
|
|
@@ -21,6 +21,7 @@ class PasswordLoginTest < IntegrationTest
|
|
21
21
|
|
22
22
|
test 'successful login redirects to original path' do
|
23
23
|
get also_secret_articles_path
|
24
|
+
refute_nil session[:qv_bookmark]
|
24
25
|
|
25
26
|
User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
26
27
|
post quo_vadis.login_path(email: 'bob@example.com', password: '123456789abc')
|
@@ -30,11 +31,22 @@ class PasswordLoginTest < IntegrationTest
|
|
30
31
|
end
|
31
32
|
|
32
33
|
|
34
|
+
test 'successful login does not redirect to login path' do
|
35
|
+
get quo_vadis.login_path
|
36
|
+
assert_nil session[:qv_bookmark]
|
37
|
+
|
38
|
+
User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
39
|
+
post quo_vadis.login_path(email: 'bob@example.com', password: '123456789abc')
|
40
|
+
|
41
|
+
assert_redirected_to after_login_path
|
42
|
+
end
|
43
|
+
|
44
|
+
|
33
45
|
test 'failed login' do
|
34
46
|
User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
35
47
|
post quo_vadis.login_path(email: 'bob@example.com', password: 'wrong')
|
36
48
|
|
37
|
-
assert_response :
|
49
|
+
assert_response :unprocessable_entity
|
38
50
|
assert_equal quo_vadis.login_path, path
|
39
51
|
end
|
40
52
|
|
@@ -42,7 +54,7 @@ class PasswordLoginTest < IntegrationTest
|
|
42
54
|
test 'unknown login' do
|
43
55
|
post quo_vadis.login_path(email: 'bob@example.com', password: 'wrong')
|
44
56
|
|
45
|
-
assert_response :
|
57
|
+
assert_response :unprocessable_entity
|
46
58
|
assert_equal quo_vadis.login_path, path
|
47
59
|
end
|
48
60
|
|
@@ -15,7 +15,7 @@ class PasswordResetTest < IntegrationTest
|
|
15
15
|
|
16
16
|
test 'unknown identifier' do
|
17
17
|
post quo_vadis.password_resets_path(email: 'foo@example.com')
|
18
|
-
|
18
|
+
assert_redirected_to quo_vadis.password_resets_path
|
19
19
|
assert_equal 'A link to change your password has been emailed to you.', flash[:notice]
|
20
20
|
end
|
21
21
|
|
@@ -53,7 +53,7 @@ class PasswordResetTest < IntegrationTest
|
|
53
53
|
assert_emails 1 do
|
54
54
|
post quo_vadis.password_resets_path(email: 'bob@example.com')
|
55
55
|
end
|
56
|
-
put quo_vadis.password_reset_path(extract_token_from_email, password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx')
|
56
|
+
put quo_vadis.password_reset_path(extract_token_from_email, password: {password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx'})
|
57
57
|
assert controller.logged_in?
|
58
58
|
|
59
59
|
get quo_vadis.edit_password_reset_url(extract_token_from_email)
|
@@ -70,11 +70,11 @@ class PasswordResetTest < IntegrationTest
|
|
70
70
|
end
|
71
71
|
|
72
72
|
assert_no_difference 'QuoVadis::Session.count' do
|
73
|
-
put quo_vadis.password_reset_path(extract_token_from_email, password: '', password_confirmation: '')
|
73
|
+
put quo_vadis.password_reset_path(extract_token_from_email, password: {password: '', password_confirmation: ''})
|
74
74
|
end
|
75
75
|
|
76
76
|
assert_equal digest, @user.qv_account.password.reload.password_digest
|
77
|
-
assert_response :
|
77
|
+
assert_response :unprocessable_entity
|
78
78
|
assert_equal quo_vadis.password_reset_path(extract_token_from_email), path
|
79
79
|
end
|
80
80
|
|
@@ -95,7 +95,7 @@ class PasswordResetTest < IntegrationTest
|
|
95
95
|
end
|
96
96
|
|
97
97
|
assert_difference 'QuoVadis::Session.count', (- 2 + 1) do
|
98
|
-
put quo_vadis.password_reset_path(extract_token_from_email, password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx')
|
98
|
+
put quo_vadis.password_reset_path(extract_token_from_email, password: {password: 'xxxxxxxxxxxx', password_confirmation: 'xxxxxxxxxxxx'})
|
99
99
|
end
|
100
100
|
|
101
101
|
assert controller.logged_in?
|
@@ -74,7 +74,7 @@ class TotpsTest < IntegrationTest
|
|
74
74
|
|
75
75
|
post quo_vadis.authenticate_totps_path(totp: '123456')
|
76
76
|
refute QuoVadis::Session.last.second_factor_authenticated?
|
77
|
-
assert_response :
|
77
|
+
assert_response :unprocessable_entity
|
78
78
|
assert_equal 'Sorry, the code was incorrect. Please check your system clock is correct and try again.', flash[:alert]
|
79
79
|
end
|
80
80
|
|
@@ -46,6 +46,9 @@ class PasswordTest < ActiveSupport::TestCase
|
|
46
46
|
|
47
47
|
test 'model passes through password to quo_vadis' do
|
48
48
|
user = User.new name: 'bob', email: 'bob@example.com'
|
49
|
+
assert user.valid?
|
50
|
+
|
51
|
+
user = User.new name: 'bob', email: 'bob@example.com', password: ''
|
49
52
|
refute user.valid?
|
50
53
|
refute_empty user.errors[:password]
|
51
54
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quo_vadis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Stewart
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -224,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
224
|
- !ruby/object:Gem::Version
|
225
225
|
version: '0'
|
226
226
|
requirements: []
|
227
|
-
rubygems_version: 3.1.
|
227
|
+
rubygems_version: 3.1.4
|
228
228
|
signing_key:
|
229
229
|
specification_version: 4
|
230
230
|
summary: Multifactor authentication for Rails 6.
|