quo_vadis 2.0.2 → 2.1.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 +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.
|