quo_vadis 2.1.0 → 2.1.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/CHANGELOG.md +12 -0
- data/README.md +31 -26
- data/app/controllers/quo_vadis/password_resets_controller.rb +1 -1
- data/app/models/quo_vadis/account.rb +13 -0
- data/app/models/quo_vadis/log.rb +3 -1
- data/app/models/quo_vadis/password.rb +16 -0
- data/{test/dummy/app → app}/views/quo_vadis/confirmations/edit.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/confirmations/edit_email.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/confirmations/index.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/confirmations/new.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/logs/index.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/account_confirmation.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/email_change_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/identifier_change_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/password_change_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/password_reset_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/reset_password.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/totp_reuse_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/totp_setup_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/password_resets/edit.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/password_resets/index.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/password_resets/new.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/passwords/edit.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/recovery_codes/challenge.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/recovery_codes/index.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/sessions/index.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/sessions/new.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/totps/challenge.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/totps/new.html.erb +0 -0
- data/{test/dummy/app → app}/views/quo_vadis/twofas/show.html.erb +0 -0
- data/config/locales/quo_vadis.en.yml +1 -0
- data/config/routes.rb +4 -4
- data/lib/generators/quo_vadis/install_generator.rb +1 -1
- data/lib/quo_vadis/controller.rb +1 -1
- data/lib/quo_vadis/model.rb +4 -0
- data/lib/quo_vadis/version.rb +1 -1
- data/test/integration/logging_test.rb +9 -0
- data/test/integration/password_reset_test.rb +1 -1
- data/test/models/account_test.rb +16 -0
- data/test/models/password_test.rb +13 -0
- data/test/models/token_test.rb +1 -1
- metadata +29 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 455075dcaacc7b730c0834edec721467fd36aed73ab25d55980f2db6baa5226c
|
4
|
+
data.tar.gz: 463eafcb85b1da5a09ebf990d38729f9e4a52e60856e83350df1f57fccbdd439
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3113487a82c77378bec401e4c721923d2de127a0ad790cb96e754e83794dc236e2a8042f33305114f1b85b021ad12d08f9724e1338c3f0f4c1e536853482e93b
|
7
|
+
data.tar.gz: 0c03c57428c0642fbd29d0b9ad150e01d72a3bd4ef5eab35243584b4621a6d35aaba218af90b13cb7ef8a66f0ded8c0f02a842899c2ef3561d7b0279f5864a23
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,20 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
3
|
|
4
|
+
## HEAD
|
5
|
+
|
6
|
+
|
7
|
+
## 2.1.1 (8 July 2021)
|
8
|
+
|
9
|
+
* Remove unnecessary route names.
|
10
|
+
* Add user revocation.
|
11
|
+
* Ensure password is only updated via #change or #reset.
|
12
|
+
* Move views into gem's app/views/ directory.
|
13
|
+
|
14
|
+
|
4
15
|
## 2.1.0 (25 June 2021)
|
5
16
|
|
17
|
+
* Do not require password on create.
|
6
18
|
* Fix incorrect assignment of built association.
|
7
19
|
* Add i18n translations for log actions.
|
8
20
|
* Use model instance in change-password form.
|
data/README.md
CHANGED
@@ -246,19 +246,19 @@ class UsersController < ApplicationController
|
|
246
246
|
end
|
247
247
|
```
|
248
248
|
|
249
|
-
QuoVadis will send the user an email with a link. Write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/
|
249
|
+
QuoVadis will send the user an email with a link. Write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/account_confirmation.text.erb)). It must be in `app/views/quo_vadis/mailer/account_confirmation.{text,html}.erb` and output the `@url` variable.
|
250
250
|
|
251
251
|
See the Configuration section below for how to set QuoVadis's emails' from addresses, headers, etc.
|
252
252
|
|
253
|
-
Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/
|
253
|
+
Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/confirmations/index.html.erb)). It must be in `app/views/quo_vadis/confirmations/index.html.:format`.
|
254
254
|
|
255
255
|
On that page you can show the user the address the email was sent to, enable them to update their email address if they make a mistake on the sign-up form, and provide a button to resend another email directly. If the sign-up occurred in a different browser session, you can instead link to `new_confirmation_path` where the user can request another email if need be.
|
256
256
|
|
257
|
-
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/
|
257
|
+
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/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/
|
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/app/views/quo_vadis/confirmations/edit_email.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit_email.html.:format`.
|
260
260
|
|
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/
|
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/app/views/quo_vadis/confirmations/new.html.erb)). It must be in `app/views/quo_vadis/confirmations/new.html.:format`.
|
262
262
|
|
263
263
|
After the user has confirmed their account, they will be logged in and redirected to the first of these that exists:
|
264
264
|
|
@@ -272,7 +272,7 @@ So add whichever works best for you.
|
|
272
272
|
|
273
273
|
Use `before_action :require_password_authentication` or `before_action :require_authentication` in your controllers.
|
274
274
|
|
275
|
-
Write the login view ([example](https://github.com/airblade/quo_vadis/blob/master/
|
275
|
+
Write the login view ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/sessions/new.html.erb)). Your login form must be in `app/views/quo_vadis/sessions/new.html.:format`. Note it must capture the user's identifier (not email, unless the identifier is email).
|
276
276
|
|
277
277
|
If you include a `remember` checkbox in your login form:
|
278
278
|
|
@@ -312,22 +312,22 @@ In your views, have a link where users can manage their 2FA:
|
|
312
312
|
link_to '2FA', quo_vadis.twofa_path
|
313
313
|
```
|
314
314
|
|
315
|
-
Write the 2FA overview page ([example](https://github.com/airblade/quo_vadis/blob/master/
|
315
|
+
Write the 2FA overview page ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/twofas/show.html.erb)). It must be in `app/views/quo_vadis/twofas/show.html.:format`. This page allows the user to set up 2FA, deactivate or reset it, and generate new recovery codes.
|
316
316
|
|
317
|
-
Next, write the TOTP setup page ([example](https://github.com/airblade/quo_vadis/blob/master/
|
317
|
+
Next, write the TOTP setup page ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/totps/new.html.erb)). It must be in `app/views/quo_vadis/totps/new.html.:format`. This page shows the user a QR code (and the key as text) which they scan with their authenticator.
|
318
318
|
|
319
|
-
Next, write the recovery codes page ([example](https://github.com/airblade/quo_vadis/blob/master/
|
319
|
+
Next, write the recovery codes page ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/recovery_codes/index.html.erb)). It must be in `app/views/quo_vadis/recovery_codes/index.html.:format`. This shows the recovery codes immediately after TOTP is setup, and immediately after generating fresh recovery codes, but not otherwise.
|
320
320
|
|
321
|
-
Next, write the TOTP challenge page where a user inputs their 6-digit TOTP ([example](https://github.com/airblade/quo_vadis/blob/master/
|
321
|
+
Next, write the TOTP challenge page where a user inputs their 6-digit TOTP ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/totps/challenge.html.erb)). It must be in `app/views/quo_vadis/totps/challenge.html.:format`. It's a good idea to link to the recovery code page (`challenge_recovery_codes_path`) for any user who has lost their authenticator.
|
322
322
|
|
323
|
-
Finally, write the recovery code challenge page where a user inputs one of their recovery codes ([example](https://github.com/airblade/quo_vadis/blob/master/
|
323
|
+
Finally, write the recovery code challenge page where a user inputs one of their recovery codes ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/recovery_codes/challenge.html.erb)). It must be in `app/views/quo_vadis/recovery_codes/challenge.html.:format`. A recovery code can only be used once, and using one deactivates TOTP – so the user will have to set it up again next time.
|
324
324
|
|
325
325
|
|
326
326
|
### Change password
|
327
327
|
|
328
328
|
To change their password, the user must provide their current one as well as the new one.
|
329
329
|
|
330
|
-
Write the change-password form ([example](https://github.com/airblade/quo_vadis/blob/master/
|
330
|
+
Write the change-password form ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/passwords/edit.html.erb)). It must be in `app/views/quo_vadis/passwords/edit.html.:format`.
|
331
331
|
|
332
332
|
After the password has been changed, the user is redirected to the first of:
|
333
333
|
|
@@ -347,17 +347,17 @@ The user can reset their password if they lose it. The flow is:
|
|
347
347
|
4. [Password-reset confirmation page] The user enters their new password and clicks a button.
|
348
348
|
5. QuoVadis sets the user's password and logs them in.
|
349
349
|
|
350
|
-
First, write the page where the user requests a password-reset ([example](https://github.com/airblade/quo_vadis/blob/master/
|
350
|
+
First, write the page where the user requests a password-reset ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/password_resets/new.html.erb)). It must be in `app/views/quo_vadis/password_resets/new.html.:format`. Note it must capture the user's identifier (not email, unless the identifier is email).
|
351
351
|
|
352
352
|
See the Configuration section below for how to set QuoVadis's emails' from addresses, headers, etc.
|
353
353
|
|
354
|
-
Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/
|
354
|
+
Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/password_resets/index.html.erb)). It must be in `app/views/quo_vadis/password_resets/index.html.:format`.
|
355
355
|
|
356
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.
|
357
357
|
|
358
|
-
Now write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/
|
358
|
+
Now write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/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.
|
359
359
|
|
360
|
-
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/
|
360
|
+
Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/password_resets/edit.html.erb)). It must be in `app/views/quo_vadis/password_resets/edit.html.:format`.
|
361
361
|
|
362
362
|
After the user has reset their password, they will be logged in and redirected to the first of these that exists:
|
363
363
|
|
@@ -371,14 +371,14 @@ A logged-in session lasts for either the browser session or `QuoVadis.session_li
|
|
371
371
|
|
372
372
|
A user can view their active sessions and log out of any of them.
|
373
373
|
|
374
|
-
Write the view showing the sessions ([example](https://github.com/airblade/quo_vadis/blob/master/
|
374
|
+
Write the view showing the sessions ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/sessions/index.html.erb)). It must be in `app/views/quo_vadis/sessions/index.html.:format`.
|
375
375
|
|
376
376
|
|
377
377
|
### Audit trail
|
378
378
|
|
379
379
|
An audit trail is kept of authentication events. You can see the full list in the [`Log`](https://github.com/airblade/quo_vadis/blob/master/app/models/quo_vadis/log.rb) class.
|
380
380
|
|
381
|
-
Write the view showing the events ([example](https://github.com/airblade/quo_vadis/blob/master/
|
381
|
+
Write the view showing the events ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/logs/index.html.erb)). It must be in `app/views/quo_vadis/logs/index.html.:format`.
|
382
382
|
|
383
383
|
|
384
384
|
### Notifications
|
@@ -387,18 +387,23 @@ QuoVadis notifies users by email whenever their authentication details are chang
|
|
387
387
|
|
388
388
|
Write the corresponding mailer views:
|
389
389
|
|
390
|
-
- change of email ([example](https://github.com/airblade/quo_vadis/blob/master/
|
391
|
-
- change of identifier (unless the identifier is email) ([example](https://github.com/airblade/quo_vadis/blob/master/
|
392
|
-
- change of password ([example](https://github.com/airblade/quo_vadis/blob/master/
|
393
|
-
- reset of password ([example](https://github.com/airblade/quo_vadis/blob/master/
|
394
|
-
- TOTP setup ([example](https://github.com/airblade/quo_vadis/blob/master/
|
395
|
-
- TOTP code used a second time ([example](https://github.com/airblade/quo_vadis/blob/master/
|
396
|
-
- 2FA deactivated ([example](https://github.com/airblade/quo_vadis/blob/master/
|
397
|
-
- recovery codes generated ([example](https://github.com/airblade/quo_vadis/blob/master/
|
390
|
+
- change of email ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/email_change_notification.text.erb))
|
391
|
+
- change of identifier (unless the identifier is email) ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/identifier_change_notification.text.erb))
|
392
|
+
- change of password ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/password_change_notification.text.erb))
|
393
|
+
- reset of password ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/password_reset_notification.text.erb))
|
394
|
+
- TOTP setup ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/totp_setup_notification.text.erb))
|
395
|
+
- TOTP code used a second time ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb))
|
396
|
+
- 2FA deactivated ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb))
|
397
|
+
- recovery codes generated ([example](https://github.com/airblade/quo_vadis/blob/master/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb))
|
398
398
|
|
399
399
|
They must be in `app/views/quo_vadis/mailer/NAME.{text,html}.erb`.
|
400
400
|
|
401
401
|
|
402
|
+
### Revocation
|
403
|
+
|
404
|
+
You can revoke a user's access by calling `#revoke_authentication_credentials` on the model instance. This deletes the user's password, TOTP credential, recovery codes, and active sessions. Their authentication logs, or audit trail, are preserved.
|
405
|
+
|
406
|
+
|
402
407
|
## Configuration
|
403
408
|
|
404
409
|
This is QuoVadis' [default configuration](https://github.com/airblade/quo_vadis/blob/master/lib/quo_vadis/defaults.rb):
|
@@ -17,7 +17,7 @@ module QuoVadis
|
|
17
17
|
|
18
18
|
if account
|
19
19
|
token = QuoVadis::PasswordResetToken.generate account
|
20
|
-
QuoVadis.deliver :reset_password, email: account.model.email, url: quo_vadis.
|
20
|
+
QuoVadis.deliver :reset_password, email: account.model.email, url: quo_vadis.password_reset_url(token)
|
21
21
|
end
|
22
22
|
|
23
23
|
redirect_to password_resets_path, notice: QuoVadis.translate('flash.password_reset.create')
|
@@ -35,6 +35,19 @@ module QuoVadis
|
|
35
35
|
Array.new(MAX_NUMBER_OF_RECOVERY_CODES) { recovery_codes.create }.map &:code
|
36
36
|
end
|
37
37
|
|
38
|
+
def revoke
|
39
|
+
password&.destroy
|
40
|
+
totp&.destroy
|
41
|
+
recovery_codes.destroy_all
|
42
|
+
sessions.destroy_all
|
43
|
+
|
44
|
+
Log.create(
|
45
|
+
account: self,
|
46
|
+
action: Log::REVOKE,
|
47
|
+
ip: (CurrentRequestDetails.ip || '')
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
38
51
|
private
|
39
52
|
|
40
53
|
def log_identifier_change
|
data/app/models/quo_vadis/log.rb
CHANGED
@@ -22,6 +22,7 @@ module QuoVadis
|
|
22
22
|
ACCOUNT_CONFIRMATION = 'account.confirmation'
|
23
23
|
LOGOUT_OTHER = 'logout.other'
|
24
24
|
LOGOUT = 'logout.self'
|
25
|
+
REVOKE = 'revoke'
|
25
26
|
|
26
27
|
ACTIONS = [
|
27
28
|
LOGIN_SUCCESS,
|
@@ -41,7 +42,8 @@ module QuoVadis
|
|
41
42
|
PASSWORD_RESET,
|
42
43
|
ACCOUNT_CONFIRMATION,
|
43
44
|
LOGOUT_OTHER,
|
44
|
-
LOGOUT
|
45
|
+
LOGOUT,
|
46
|
+
REVOKE
|
45
47
|
]
|
46
48
|
|
47
49
|
belongs_to :account, optional: true # optional only for LOGIN_UNKNOWN
|
@@ -7,6 +7,7 @@ module QuoVadis
|
|
7
7
|
has_secure_password
|
8
8
|
|
9
9
|
validates_length_of :password, minimum: QuoVadis.password_minimum_length, allow_blank: true
|
10
|
+
validate :password_updated_legitimately, on: :update
|
10
11
|
|
11
12
|
attr_accessor :new_password
|
12
13
|
|
@@ -48,5 +49,20 @@ module QuoVadis
|
|
48
49
|
save
|
49
50
|
end
|
50
51
|
|
52
|
+
private
|
53
|
+
|
54
|
+
def password_updated_legitimately
|
55
|
+
return unless password_digest_changed?
|
56
|
+
|
57
|
+
unless change_or_reset_called?
|
58
|
+
errors.add :password, 'must be updated via #change or #reset'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def change_or_reset_called?
|
63
|
+
caller_locations.any? { |loc|
|
64
|
+
['change', 'reset'].include?(loc.label) && Pathname.new(loc.path).basename.to_s == 'password.rb'
|
65
|
+
}
|
66
|
+
end
|
51
67
|
end
|
52
68
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/{test/dummy/app → app}/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/config/routes.rb
CHANGED
@@ -12,8 +12,8 @@ QuoVadis::Engine.routes.draw do
|
|
12
12
|
resource :password, only: [:edit, :update]
|
13
13
|
|
14
14
|
resources :password_resets, only: [:new, :create, :index]
|
15
|
-
get '/pwd-reset/:token', to: 'password_resets#edit',
|
16
|
-
put '/pwd-reset/:token', to: 'password_resets#update'
|
15
|
+
get '/pwd-reset/:token', to: 'password_resets#edit', as: 'password_reset'
|
16
|
+
put '/pwd-reset/:token', to: 'password_resets#update'
|
17
17
|
|
18
18
|
resources :confirmations, only: [:new, :create, :index] do
|
19
19
|
collection do
|
@@ -22,8 +22,8 @@ QuoVadis::Engine.routes.draw do
|
|
22
22
|
post :resend
|
23
23
|
end
|
24
24
|
end
|
25
|
-
get '/confirm/:token', to: 'confirmations#edit',
|
26
|
-
put '/confirm/:token', to: 'confirmations#update'
|
25
|
+
get '/confirm/:token', to: 'confirmations#edit', as: 'confirmation'
|
26
|
+
put '/confirm/:token', to: 'confirmations#update'
|
27
27
|
|
28
28
|
resources :totps, only: [:new, :create] do
|
29
29
|
collection do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module QuoVadis
|
2
2
|
class InstallGenerator < Rails::Generators::Base
|
3
|
-
source_root Pathname.new(__dir__) / '..' / '..' / '..' / '
|
3
|
+
source_root Pathname.new(__dir__) / '..' / '..' / '..' / 'app' / 'views' / 'quo_vadis'
|
4
4
|
|
5
5
|
desc "Copy QuoVadis' views into your app."
|
6
6
|
def copy_views
|
data/lib/quo_vadis/controller.rb
CHANGED
@@ -87,7 +87,7 @@ module QuoVadis
|
|
87
87
|
|
88
88
|
def request_confirmation(model)
|
89
89
|
token = QuoVadis::AccountConfirmationToken.generate model.qv_account
|
90
|
-
QuoVadis.deliver :account_confirmation, email: model.email, url: quo_vadis.
|
90
|
+
QuoVadis.deliver :account_confirmation, email: model.email, url: quo_vadis.confirmation_url(token)
|
91
91
|
session[:account_pending_confirmation] = model.qv_account.id
|
92
92
|
|
93
93
|
flash[:notice] = QuoVadis.translate 'flash.confirmation.create'
|
data/lib/quo_vadis/model.rb
CHANGED
data/lib/quo_vadis/version.rb
CHANGED
@@ -201,6 +201,15 @@ class LoggingTest < IntegrationTest
|
|
201
201
|
end
|
202
202
|
|
203
203
|
|
204
|
+
test 'revoke' do
|
205
|
+
login_new_session
|
206
|
+
assert_log QuoVadis::Log::REVOKE do
|
207
|
+
QuoVadis::CurrentRequestDetails.ip = '127.0.0.1' # fake out the IP assertion
|
208
|
+
@account.revoke
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
204
213
|
private
|
205
214
|
|
206
215
|
def assert_log(action, metadata = {}, account = @account, &block)
|
@@ -56,7 +56,7 @@ class PasswordResetTest < IntegrationTest
|
|
56
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
|
-
get quo_vadis.
|
59
|
+
get quo_vadis.password_reset_url(extract_token_from_email)
|
60
60
|
assert_redirected_to quo_vadis.new_password_reset_path
|
61
61
|
assert_equal 'Either the link has expired or you have already reset your password.', flash[:alert]
|
62
62
|
end
|
data/test/models/account_test.rb
CHANGED
@@ -31,4 +31,20 @@ class AccountTest < ActiveSupport::TestCase
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
|
35
|
+
test 'revoke' do
|
36
|
+
u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
|
37
|
+
account = u.qv_account
|
38
|
+
account.create_totp last_used_at: 1.minute.ago
|
39
|
+
account.generate_recovery_codes
|
40
|
+
|
41
|
+
u.revoke_authentication_credentials
|
42
|
+
account.reload
|
43
|
+
|
44
|
+
assert_nil account.password
|
45
|
+
assert_nil account.totp
|
46
|
+
assert_empty account.recovery_codes
|
47
|
+
assert_empty account.sessions
|
48
|
+
end
|
49
|
+
|
34
50
|
end
|
@@ -120,6 +120,19 @@ class PasswordTest < ActiveSupport::TestCase
|
|
120
120
|
end
|
121
121
|
|
122
122
|
|
123
|
+
test 'passwords can only be updated via #change and #reset' do
|
124
|
+
user = User.create! name: 'bob', email: 'bob@example.com', password: VALID_PASSWORD
|
125
|
+
pw = user.qv_account.password
|
126
|
+
|
127
|
+
refute pw.update password: 'secretsecret'
|
128
|
+
assert_equal ["must be updated via #change or #reset"], pw.errors[:password]
|
129
|
+
|
130
|
+
pw.password = VALID_PASSWORD
|
131
|
+
refute pw.save
|
132
|
+
assert_equal ["must be updated via #change or #reset"], pw.errors[:password]
|
133
|
+
end
|
134
|
+
|
135
|
+
|
123
136
|
test 'cascade destroy' do
|
124
137
|
user = User.create! name: 'bob', email: 'bob@example.com', password: VALID_PASSWORD
|
125
138
|
assert user.qv_account.persisted?
|
data/test/models/token_test.rb
CHANGED
@@ -52,7 +52,7 @@ class TokenTest < ActiveSupport::TestCase
|
|
52
52
|
|
53
53
|
test 'password reset already done' do
|
54
54
|
token = QuoVadis::PasswordResetToken.generate @account
|
55
|
-
@account.password.
|
55
|
+
@account.password.reset 'secretsecret', 'secretsecret'
|
56
56
|
assert_nil QuoVadis::PasswordResetToken.find_account(token)
|
57
57
|
end
|
58
58
|
|
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.1.
|
4
|
+
version: 2.1.1
|
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-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -97,6 +97,32 @@ files:
|
|
97
97
|
- app/models/quo_vadis/session.rb
|
98
98
|
- app/models/quo_vadis/token.rb
|
99
99
|
- app/models/quo_vadis/totp.rb
|
100
|
+
- app/views/quo_vadis/confirmations/edit.html.erb
|
101
|
+
- app/views/quo_vadis/confirmations/edit_email.html.erb
|
102
|
+
- app/views/quo_vadis/confirmations/index.html.erb
|
103
|
+
- app/views/quo_vadis/confirmations/new.html.erb
|
104
|
+
- app/views/quo_vadis/logs/index.html.erb
|
105
|
+
- app/views/quo_vadis/mailer/account_confirmation.text.erb
|
106
|
+
- app/views/quo_vadis/mailer/email_change_notification.text.erb
|
107
|
+
- app/views/quo_vadis/mailer/identifier_change_notification.text.erb
|
108
|
+
- app/views/quo_vadis/mailer/password_change_notification.text.erb
|
109
|
+
- app/views/quo_vadis/mailer/password_reset_notification.text.erb
|
110
|
+
- app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb
|
111
|
+
- app/views/quo_vadis/mailer/reset_password.text.erb
|
112
|
+
- app/views/quo_vadis/mailer/totp_reuse_notification.text.erb
|
113
|
+
- app/views/quo_vadis/mailer/totp_setup_notification.text.erb
|
114
|
+
- app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb
|
115
|
+
- app/views/quo_vadis/password_resets/edit.html.erb
|
116
|
+
- app/views/quo_vadis/password_resets/index.html.erb
|
117
|
+
- app/views/quo_vadis/password_resets/new.html.erb
|
118
|
+
- app/views/quo_vadis/passwords/edit.html.erb
|
119
|
+
- app/views/quo_vadis/recovery_codes/challenge.html.erb
|
120
|
+
- app/views/quo_vadis/recovery_codes/index.html.erb
|
121
|
+
- app/views/quo_vadis/sessions/index.html.erb
|
122
|
+
- app/views/quo_vadis/sessions/new.html.erb
|
123
|
+
- app/views/quo_vadis/totps/challenge.html.erb
|
124
|
+
- app/views/quo_vadis/totps/new.html.erb
|
125
|
+
- app/views/quo_vadis/twofas/show.html.erb
|
100
126
|
- bin/console
|
101
127
|
- bin/rails
|
102
128
|
- bin/setup
|
@@ -131,32 +157,6 @@ files:
|
|
131
157
|
- test/dummy/app/views/articles/secret.html.erb
|
132
158
|
- test/dummy/app/views/articles/very_secret.html.erb
|
133
159
|
- test/dummy/app/views/layouts/application.html.erb
|
134
|
-
- test/dummy/app/views/quo_vadis/confirmations/edit.html.erb
|
135
|
-
- test/dummy/app/views/quo_vadis/confirmations/edit_email.html.erb
|
136
|
-
- test/dummy/app/views/quo_vadis/confirmations/index.html.erb
|
137
|
-
- test/dummy/app/views/quo_vadis/confirmations/new.html.erb
|
138
|
-
- test/dummy/app/views/quo_vadis/logs/index.html.erb
|
139
|
-
- test/dummy/app/views/quo_vadis/mailer/account_confirmation.text.erb
|
140
|
-
- test/dummy/app/views/quo_vadis/mailer/email_change_notification.text.erb
|
141
|
-
- test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb
|
142
|
-
- test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb
|
143
|
-
- test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb
|
144
|
-
- test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb
|
145
|
-
- test/dummy/app/views/quo_vadis/mailer/reset_password.text.erb
|
146
|
-
- test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb
|
147
|
-
- test/dummy/app/views/quo_vadis/mailer/totp_setup_notification.text.erb
|
148
|
-
- test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb
|
149
|
-
- test/dummy/app/views/quo_vadis/password_resets/edit.html.erb
|
150
|
-
- test/dummy/app/views/quo_vadis/password_resets/index.html.erb
|
151
|
-
- test/dummy/app/views/quo_vadis/password_resets/new.html.erb
|
152
|
-
- test/dummy/app/views/quo_vadis/passwords/edit.html.erb
|
153
|
-
- test/dummy/app/views/quo_vadis/recovery_codes/challenge.html.erb
|
154
|
-
- test/dummy/app/views/quo_vadis/recovery_codes/index.html.erb
|
155
|
-
- test/dummy/app/views/quo_vadis/sessions/index.html.erb
|
156
|
-
- test/dummy/app/views/quo_vadis/sessions/new.html.erb
|
157
|
-
- test/dummy/app/views/quo_vadis/totps/challenge.html.erb
|
158
|
-
- test/dummy/app/views/quo_vadis/totps/new.html.erb
|
159
|
-
- test/dummy/app/views/quo_vadis/twofas/show.html.erb
|
160
160
|
- test/dummy/app/views/sign_ups/new.html.erb
|
161
161
|
- test/dummy/app/views/sign_ups/show.html.erb
|
162
162
|
- test/dummy/app/views/users/new.html.erb
|
@@ -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.2
|
228
228
|
signing_key:
|
229
229
|
specification_version: 4
|
230
230
|
summary: Multifactor authentication for Rails 6.
|