quo_vadis 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|