quo_vadis 2.1.0 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +33 -28
  4. data/app/controllers/quo_vadis/password_resets_controller.rb +1 -1
  5. data/app/mailers/quo_vadis/mailer.rb +16 -16
  6. data/app/models/quo_vadis/account.rb +14 -0
  7. data/app/models/quo_vadis/log.rb +3 -1
  8. data/app/models/quo_vadis/password.rb +16 -0
  9. data/{test/dummy/app → app}/views/quo_vadis/confirmations/edit.html.erb +0 -0
  10. data/{test/dummy/app → app}/views/quo_vadis/confirmations/edit_email.html.erb +0 -0
  11. data/{test/dummy/app → app}/views/quo_vadis/confirmations/index.html.erb +0 -0
  12. data/{test/dummy/app → app}/views/quo_vadis/confirmations/new.html.erb +0 -0
  13. data/{test/dummy/app → app}/views/quo_vadis/logs/index.html.erb +0 -0
  14. data/{test/dummy/app → app}/views/quo_vadis/mailer/account_confirmation.text.erb +0 -0
  15. data/{test/dummy/app → app}/views/quo_vadis/mailer/email_change_notification.text.erb +0 -0
  16. data/{test/dummy/app → app}/views/quo_vadis/mailer/identifier_change_notification.text.erb +0 -0
  17. data/{test/dummy/app → app}/views/quo_vadis/mailer/password_change_notification.text.erb +0 -0
  18. data/{test/dummy/app → app}/views/quo_vadis/mailer/password_reset_notification.text.erb +0 -0
  19. data/{test/dummy/app → app}/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb +0 -0
  20. data/{test/dummy/app → app}/views/quo_vadis/mailer/reset_password.text.erb +0 -0
  21. data/{test/dummy/app → app}/views/quo_vadis/mailer/totp_reuse_notification.text.erb +0 -0
  22. data/{test/dummy/app → app}/views/quo_vadis/mailer/totp_setup_notification.text.erb +0 -0
  23. data/{test/dummy/app → app}/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb +0 -0
  24. data/{test/dummy/app → app}/views/quo_vadis/password_resets/edit.html.erb +0 -0
  25. data/{test/dummy/app → app}/views/quo_vadis/password_resets/index.html.erb +0 -0
  26. data/{test/dummy/app → app}/views/quo_vadis/password_resets/new.html.erb +0 -0
  27. data/{test/dummy/app → app}/views/quo_vadis/passwords/edit.html.erb +0 -0
  28. data/{test/dummy/app → app}/views/quo_vadis/recovery_codes/challenge.html.erb +0 -0
  29. data/{test/dummy/app → app}/views/quo_vadis/recovery_codes/index.html.erb +0 -0
  30. data/{test/dummy/app → app}/views/quo_vadis/sessions/index.html.erb +0 -0
  31. data/{test/dummy/app → app}/views/quo_vadis/sessions/new.html.erb +0 -0
  32. data/{test/dummy/app → app}/views/quo_vadis/totps/challenge.html.erb +0 -0
  33. data/{test/dummy/app → app}/views/quo_vadis/totps/new.html.erb +0 -0
  34. data/{test/dummy/app → app}/views/quo_vadis/twofas/show.html.erb +0 -0
  35. data/config/locales/quo_vadis.en.yml +1 -0
  36. data/config/routes.rb +4 -4
  37. data/lib/generators/quo_vadis/install_generator.rb +1 -1
  38. data/lib/quo_vadis/controller.rb +3 -3
  39. data/lib/quo_vadis/model.rb +4 -0
  40. data/lib/quo_vadis/version.rb +1 -1
  41. data/lib/quo_vadis.rb +6 -4
  42. data/test/integration/logging_test.rb +9 -0
  43. data/test/integration/password_reset_test.rb +1 -1
  44. data/test/mailers/mailer_test.rb +49 -32
  45. data/test/models/account_test.rb +24 -2
  46. data/test/models/model_test.rb +4 -1
  47. data/test/models/password_test.rb +13 -0
  48. data/test/models/recovery_code_test.rb +7 -1
  49. data/test/models/token_test.rb +1 -1
  50. metadata +29 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f8acc907c43d19fcc6f9be59854be5e848add025d427f78ec608b2e24677e73
4
- data.tar.gz: efab0ab6fc83535466f6bb6e31bb056016c5220ef227155629601e5c17aff5b6
3
+ metadata.gz: c0b470ad4482010d9774287306051d802625c95fa5e20675a12bf4537e71d939
4
+ data.tar.gz: 67574e42473e4c87dc112f7e7ced2104c8df54a8a02e7befcedad6e806d136a4
5
5
  SHA512:
6
- metadata.gz: 8d34c8922431d4234650c50718a29b71a328b070582bb5b7fac74d4b1e2b6847bc2b130a197d6dcc05d93d2c0dab882a90fecf9faa3e1620f36acb48b9be3778
7
- data.tar.gz: 4f471b97ff2a2dc0461ddac1f68c1e9f263ac5c188ab89daf2974f3c8f2e85c5e2b586da72b8c798d5f696acf3a2a7079aef57fb689f8f75f8113a38d56b2c2d
6
+ metadata.gz: debe3294db5262b56514b9ece8181464783521f475c4472a43dd4555739cd97fd81bea5fde66e700be8a75ada62ee554d4374aa196bfcb063bc9ecfcd989d1cf
7
+ data.tar.gz: 00f90c64fd56cec727ba364d784de3928e68e5d34eb5fca1fd56382c77289c0d6c5a4be7396687e1e175d5dc66c4473e00ae77b8b6f52c56def2496e0abeab40
data/CHANGELOG.md CHANGED
@@ -1,8 +1,30 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## HEAD
5
+
6
+
7
+ ## 2.1.3 (30 September 2021)
8
+
9
+ * Pass IP and timestamp as paramenters to mailer.
10
+
11
+
12
+ ## 2.1.2 (30 September 2021)
13
+
14
+ * Delete existing recovery codes when generating new ones.
15
+
16
+
17
+ ## 2.1.1 (8 July 2021)
18
+
19
+ * Remove unnecessary route names.
20
+ * Add user revocation.
21
+ * Ensure password is only updated via #change or #reset.
22
+ * Move views into gem's app/views/ directory.
23
+
24
+
4
25
  ## 2.1.0 (25 June 2021)
5
26
 
27
+ * Do not require password on create.
6
28
  * Fix incorrect assignment of built association.
7
29
  * Add i18n translations for log actions.
8
30
  * Use model instance in change-password form.
data/README.md CHANGED
@@ -119,7 +119,7 @@ end
119
119
 
120
120
  __`login(model, browser_session = true)`__
121
121
 
122
- To log in a user who has authenticated with a password, call `#login(model, browser_session = true)`. For the `browser_session` argument, pass `true` to log in for the duration of the browser session, or `false` to log in for `QuoVadis.session_lifetime` (which could be the browser session anyway).
122
+ To log in a user who has authenticated with a password, call `#login(model, browser_session = true, metadata: {})`. For the `browser_session` argument, optionally pass `true` to log in for the duration of the browser session, or `false` to log in for `QuoVadis.session_lifetime` (which could be the browser session anyway). Any metadata are stored in the log entry for the login.
123
123
 
124
124
  __`request_confirmation(model)`__
125
125
 
@@ -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/test/dummy/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.
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/test/dummy/app/views/quo_vadis/confirmations/index.html.erb)). It must be in `app/views/quo_vadis/confirmations/index.html.:format`.
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/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit.html.:format`.
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/test/dummy/app/views/quo_vadis/confirmations/edit_email.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit_email.html.:format`.
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/test/dummy/app/views/quo_vadis/confirmations/new.html.erb)). It must be in `app/views/quo_vadis/confirmations/new.html.:format`.
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/test/dummy/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).
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
 
@@ -292,7 +292,7 @@ After authenticating the user will be redirected to the first of these that exis
292
292
 
293
293
  If you do not want 2FA at all, set `QuoVadis.two_factor_authentication_mandatory false` in your configuration and skip the rest of this section.
294
294
 
295
- If you do want 2FA, you can choose whether it is optional or mandatory for your users by setting `QuoVadis.two_factor_authentication_mandatory <true|false>` in your configuration.
295
+ If you do want 2FA, you can choose whether it is mandatory or optional for your users by setting `QuoVadis.two_factor_authentication_mandatory <true|false>` in your configuration.
296
296
 
297
297
  Use `before_action :require_two_factor_authentication` in your controllers (which supersedes `:require_password_authentication`). This will require the user, after authenticating with their password, to authenticate with 2FA – when 2FA is mandatory, or when it is optional and the user has set up 2FA.
298
298
 
@@ -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/test/dummy/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.
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/test/dummy/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.
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/test/dummy/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.
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/test/dummy/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.
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/test/dummy/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.
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/test/dummy/app/views/quo_vadis/passwords/edit.html.erb)). It must be in `app/views/quo_vadis/passwords/edit.html.:format`.
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/test/dummy/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).
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/test/dummy/app/views/quo_vadis/password_resets/index.html.erb)). It must be in `app/views/quo_vadis/password_resets/index.html.:format`.
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/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.
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/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb)). It must be in `app/views/quo_vadis/password_resets/edit.html.:format`.
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/test/dummy/app/views/quo_vadis/sessions/index.html.erb)). It must be in `app/views/quo_vadis/sessions/index.html.:format`.
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/test/dummy/app/views/quo_vadis/logs/index.html.erb)). It must be in `app/views/quo_vadis/logs/index.html.:format`.
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/test/dummy/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/test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb))
392
- - change of password ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb))
393
- - reset of password ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb))
394
- - TOTP setup ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/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/test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb))
396
- - 2FA deactivated ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb))
397
- - recovery codes generated ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb))
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.edit_password_reset_url(token)
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')
@@ -14,52 +14,52 @@ module QuoVadis
14
14
  end
15
15
 
16
16
  def email_change_notification
17
- @timestamp = Time.now
18
- @ip = QuoVadis::CurrentRequestDetails.ip
17
+ @timestamp = params[:timestamp]
18
+ @ip = params[:ip]
19
19
  _mail params[:email], QuoVadis.translate('mailer.notification.email_change')
20
20
  end
21
21
 
22
22
  def identifier_change_notification
23
- @timestamp = Time.now
23
+ @timestamp = params[:timestamp]
24
24
  @identifier = params[:identifier]
25
- @ip = QuoVadis::CurrentRequestDetails.ip
25
+ @ip = params[:ip]
26
26
  _mail params[:email], QuoVadis.translate('mailer.notification.identifier_change',
27
27
  identifier: params[:identifier])
28
28
  end
29
29
 
30
30
  def password_change_notification
31
- @timestamp = Time.now
32
- @ip = QuoVadis::CurrentRequestDetails.ip
31
+ @timestamp = params[:timestamp]
32
+ @ip = params[:ip]
33
33
  _mail params[:email], QuoVadis.translate('mailer.notification.password_change')
34
34
  end
35
35
 
36
36
  def password_reset_notification
37
- @timestamp = Time.now
38
- @ip = QuoVadis::CurrentRequestDetails.ip
37
+ @timestamp = params[:timestamp]
38
+ @ip = params[:ip]
39
39
  _mail params[:email], QuoVadis.translate('mailer.notification.password_reset')
40
40
  end
41
41
 
42
42
  def totp_setup_notification
43
- @timestamp = Time.now
44
- @ip = QuoVadis::CurrentRequestDetails.ip
43
+ @timestamp = params[:timestamp]
44
+ @ip = params[:ip]
45
45
  _mail params[:email], QuoVadis.translate('mailer.notification.totp_setup')
46
46
  end
47
47
 
48
48
  def totp_reuse_notification
49
- @timestamp = Time.now
50
- @ip = QuoVadis::CurrentRequestDetails.ip
49
+ @timestamp = params[:timestamp]
50
+ @ip = params[:ip]
51
51
  _mail params[:email], QuoVadis.translate('mailer.notification.totp_reuse')
52
52
  end
53
53
 
54
54
  def twofa_deactivated_notification
55
- @timestamp = Time.now
56
- @ip = QuoVadis::CurrentRequestDetails.ip
55
+ @timestamp = params[:timestamp]
56
+ @ip = params[:ip]
57
57
  _mail params[:email], QuoVadis.translate('mailer.notification.twofa_deactivated')
58
58
  end
59
59
 
60
60
  def recovery_codes_generation_notification
61
- @timestamp = Time.now
62
- @ip = QuoVadis::CurrentRequestDetails.ip
61
+ @timestamp = params[:timestamp]
62
+ @ip = params[:ip]
63
63
  _mail params[:email], QuoVadis.translate('mailer.notification.recovery_codes_generation')
64
64
  end
65
65
 
@@ -32,9 +32,23 @@ module QuoVadis
32
32
 
33
33
  # Returns an array of the recovery codes' codes.
34
34
  def generate_recovery_codes
35
+ recovery_codes.delete_all
35
36
  Array.new(MAX_NUMBER_OF_RECOVERY_CODES) { recovery_codes.create }.map &:code
36
37
  end
37
38
 
39
+ def revoke
40
+ password&.destroy
41
+ totp&.destroy
42
+ recovery_codes.destroy_all
43
+ sessions.destroy_all
44
+
45
+ Log.create(
46
+ account: self,
47
+ action: Log::REVOKE,
48
+ ip: (CurrentRequestDetails.ip || '')
49
+ )
50
+ end
51
+
38
52
  private
39
53
 
40
54
  def log_identifier_change
@@ -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
@@ -74,6 +74,7 @@ en:
74
74
  logout:
75
75
  self: Logged out
76
76
  other: Logged out session remotely
77
+ revoke: Revoked access
77
78
  activerecord:
78
79
  errors:
79
80
  models:
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', as: 'edit_password_reset'
16
- put '/pwd-reset/:token', to: 'password_resets#update', as: 'password_reset'
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', as: 'edit_confirmation'
26
- put '/confirm/:token', to: 'confirmations#update', as: 'confirmation'
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__) / '..' / '..' / '..' / 'test' / 'dummy' / 'app' / 'views' / 'quo_vadis'
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
@@ -36,8 +36,8 @@ module QuoVadis
36
36
  #
37
37
  # browser_session - true: login only for duration of browser session
38
38
  # false: login for QuoVadis.session_lifetime (which may be browser session anyway)
39
- def login(model, browser_session = true)
40
- qv.log model.qv_account, Log::LOGIN_SUCCESS
39
+ def login(model, browser_session = true, metadata: {})
40
+ qv.log model.qv_account, Log::LOGIN_SUCCESS, metadata
41
41
 
42
42
  qv.prevent_rails_session_fixation
43
43
 
@@ -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.edit_confirmation_url(token)
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'
@@ -53,6 +53,10 @@ module QuoVadis
53
53
  (qv_account.password || qv_account.build_password).password_confirmation = val
54
54
  end
55
55
 
56
+ def revoke_authentication_credentials
57
+ qv_account.revoke
58
+ end
59
+
56
60
  private
57
61
 
58
62
  def qv_copy_password_errors
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QuoVadis
4
- VERSION = '2.1.0'
4
+ VERSION = '2.1.4'
5
5
  end
data/lib/quo_vadis.rb CHANGED
@@ -73,12 +73,14 @@ module QuoVadis
73
73
  end
74
74
 
75
75
  def notify(action, params)
76
- QuoVadis::Mailer.with(params).send(action).deliver_later
76
+ deliver(action, params, later: true)
77
77
  end
78
78
 
79
- def deliver(action, params)
80
- mail = QuoVadis::Mailer.with(params).send(action)
81
- QuoVadis.enqueue_transactional_emails ?
79
+ def deliver(action, params, later: QuoVadis.enqueue_transactional_emails)
80
+ mail = QuoVadis::Mailer
81
+ .with(params.merge(ip: QuoVadis::CurrentRequestDetails.ip, timestamp: Time.now))
82
+ .send(action)
83
+ later ?
82
84
  mail.deliver_later :
83
85
  mail.deliver_now
84
86
  end
@@ -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.edit_password_reset_url(extract_token_from_email)
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
@@ -44,14 +44,16 @@ class MailerTest < ActionMailer::TestCase
44
44
 
45
45
 
46
46
  test 'email change notification' do
47
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').email_change_notification
47
+ email = QuoVadis::Mailer.with(
48
+ email: 'Foo <foo@example.com>',
49
+ ip: '1.2.3.4',
50
+ timestamp: Time.now
51
+ ).email_change_notification
48
52
 
49
53
  # freeze_time
50
54
 
51
55
  assert_emails 1 do
52
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
53
- email.deliver_now
54
- end
56
+ email.deliver_now
55
57
  end
56
58
 
57
59
  assert_equal ['foo@example.com'], email.to
@@ -62,14 +64,17 @@ class MailerTest < ActionMailer::TestCase
62
64
 
63
65
 
64
66
  test 'identifier change notification' do
65
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>', identifier: 'email').identifier_change_notification
67
+ email = QuoVadis::Mailer.with(
68
+ email: 'Foo <foo@example.com>',
69
+ identifier: 'email',
70
+ ip: '1.2.3.4',
71
+ timestamp: Time.now
72
+ ).identifier_change_notification
66
73
 
67
74
  # freeze_time
68
75
 
69
76
  assert_emails 1 do
70
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
71
- email.deliver_now
72
- end
77
+ email.deliver_now
73
78
  end
74
79
 
75
80
  assert_equal ['foo@example.com'], email.to
@@ -80,14 +85,16 @@ class MailerTest < ActionMailer::TestCase
80
85
 
81
86
 
82
87
  test 'password change notification' do
83
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').password_change_notification
88
+ email = QuoVadis::Mailer.with(
89
+ email: 'Foo <foo@example.com>',
90
+ ip: '1.2.3.4',
91
+ timestamp: Time.now
92
+ ).password_change_notification
84
93
 
85
94
  # freeze_time
86
95
 
87
96
  assert_emails 1 do
88
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
89
- email.deliver_now
90
- end
97
+ email.deliver_now
91
98
  end
92
99
 
93
100
  assert_equal ['foo@example.com'], email.to
@@ -98,14 +105,16 @@ class MailerTest < ActionMailer::TestCase
98
105
 
99
106
 
100
107
  test 'password reset notification' do
101
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').password_reset_notification
108
+ email = QuoVadis::Mailer.with(
109
+ email: 'Foo <foo@example.com>',
110
+ ip: '1.2.3.4',
111
+ timestamp: Time.now
112
+ ).password_reset_notification
102
113
 
103
114
  # freeze_time
104
115
 
105
116
  assert_emails 1 do
106
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
107
- email.deliver_now
108
- end
117
+ email.deliver_now
109
118
  end
110
119
 
111
120
  assert_equal ['foo@example.com'], email.to
@@ -116,14 +125,16 @@ class MailerTest < ActionMailer::TestCase
116
125
 
117
126
 
118
127
  test 'totp setup notification' do
119
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').totp_setup_notification
128
+ email = QuoVadis::Mailer.with(
129
+ email: 'Foo <foo@example.com>',
130
+ ip: '1.2.3.4',
131
+ timestamp: Time.now
132
+ ).totp_setup_notification
120
133
 
121
134
  # freeze_time
122
135
 
123
136
  assert_emails 1 do
124
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
125
- email.deliver_now
126
- end
137
+ email.deliver_now
127
138
  end
128
139
 
129
140
  assert_equal ['foo@example.com'], email.to
@@ -134,14 +145,16 @@ class MailerTest < ActionMailer::TestCase
134
145
 
135
146
 
136
147
  test 'totp reuse notification' do
137
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').totp_reuse_notification
148
+ email = QuoVadis::Mailer.with(
149
+ email: 'Foo <foo@example.com>',
150
+ ip: '1.2.3.4',
151
+ timestamp: Time.now
152
+ ).totp_reuse_notification
138
153
 
139
154
  # freeze_time
140
155
 
141
156
  assert_emails 1 do
142
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
143
- email.deliver_now
144
- end
157
+ email.deliver_now
145
158
  end
146
159
 
147
160
  assert_equal ['foo@example.com'], email.to
@@ -152,14 +165,16 @@ class MailerTest < ActionMailer::TestCase
152
165
 
153
166
 
154
167
  test '2fa deactivated notification' do
155
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').twofa_deactivated_notification
168
+ email = QuoVadis::Mailer.with(
169
+ email: 'Foo <foo@example.com>',
170
+ ip: '1.2.3.4',
171
+ timestamp: Time.now
172
+ ).twofa_deactivated_notification
156
173
 
157
174
  # freeze_time
158
175
 
159
176
  assert_emails 1 do
160
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
161
- email.deliver_now
162
- end
177
+ email.deliver_now
163
178
  end
164
179
 
165
180
  assert_equal ['foo@example.com'], email.to
@@ -170,14 +185,16 @@ class MailerTest < ActionMailer::TestCase
170
185
 
171
186
 
172
187
  test 'recovery codes generation notification' do
173
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').recovery_codes_generation_notification
188
+ email = QuoVadis::Mailer.with(
189
+ email: 'Foo <foo@example.com>',
190
+ ip: '1.2.3.4',
191
+ timestamp: Time.now
192
+ ).recovery_codes_generation_notification
174
193
 
175
194
  # freeze_time
176
195
 
177
196
  assert_emails 1 do
178
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
179
- email.deliver_now
180
- end
197
+ email.deliver_now
181
198
  end
182
199
 
183
200
  assert_equal ['foo@example.com'], email.to
@@ -13,8 +13,11 @@ class AccountTest < ActiveSupport::TestCase
13
13
 
14
14
 
15
15
  test 'notifies on identifier change when notifier is not email' do
16
+ freeze_time
16
17
  p = Person.create! username: 'bob', email: 'bob@example.com', password: 'secretsecret'
17
- assert_enqueued_email_with QuoVadis::Mailer, :identifier_change_notification, args: {email: 'bob@example.com', identifier: 'username'} do
18
+ assert_enqueued_email_with QuoVadis::Mailer,
19
+ :identifier_change_notification,
20
+ args: {email: 'bob@example.com', identifier: 'username', ip: nil, timestamp: Time.now} do
18
21
  assert_enqueued_emails 1 do
19
22
  p.update username: 'robert@example.com'
20
23
  end
@@ -23,12 +26,31 @@ class AccountTest < ActiveSupport::TestCase
23
26
 
24
27
 
25
28
  test 'does not notify on identifier change when notifier is email' do
29
+ freeze_time
26
30
  u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
27
- assert_enqueued_email_with QuoVadis::Mailer, :email_change_notification, args: {email: 'bob@example.com'} do
31
+ assert_enqueued_email_with QuoVadis::Mailer,
32
+ :email_change_notification,
33
+ args: {email: 'bob@example.com', ip: nil, timestamp: Time.now} do
28
34
  assert_enqueued_emails 1 do
29
35
  u.update email: 'robert@example.com'
30
36
  end
31
37
  end
32
38
  end
33
39
 
40
+
41
+ test 'revoke' do
42
+ u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
43
+ account = u.qv_account
44
+ account.create_totp last_used_at: 1.minute.ago
45
+ account.generate_recovery_codes
46
+
47
+ u.revoke_authentication_credentials
48
+ account.reload
49
+
50
+ assert_nil account.password
51
+ assert_nil account.totp
52
+ assert_empty account.recovery_codes
53
+ assert_empty account.sessions
54
+ end
55
+
34
56
  end
@@ -58,8 +58,11 @@ class ModelTest < ActiveSupport::TestCase
58
58
 
59
59
 
60
60
  test 'notifies on email change' do
61
+ freeze_time
61
62
  u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
62
- assert_enqueued_email_with QuoVadis::Mailer, :email_change_notification, args: {email: 'bob@example.com'} do
63
+ assert_enqueued_email_with QuoVadis::Mailer,
64
+ :email_change_notification,
65
+ args: {email: 'bob@example.com', ip: nil, timestamp: Time.now} do
63
66
  u.update email: 'robert@example.com'
64
67
  end
65
68
  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?
@@ -42,13 +42,19 @@ class RecoveryCodeTest < ActiveSupport::TestCase
42
42
  test 'generate a fresh set of codes' do
43
43
  account = @user.qv_account
44
44
  codes = []
45
- assert_difference 'QuoVadis::RecoveryCode.count', 5 do
45
+ assert_difference 'QuoVadis::RecoveryCode.count', (-1 + 5) do
46
46
  codes = account.generate_recovery_codes
47
47
  end
48
48
  assert_equal 5, codes.length
49
+ assert_equal 5, account.recovery_codes.count
49
50
  codes.each do |code|
50
51
  assert_instance_of String, code
51
52
  end
53
+
54
+ new_codes = account.generate_recovery_codes
55
+ assert_equal 5, new_codes.length
56
+ assert_equal 5, account.recovery_codes.count
57
+ refute_equal new_codes, codes
52
58
  end
53
59
 
54
60
  end
@@ -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.update password: 'secretsecret'
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.0
4
+ version: 2.1.4
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-06-25 00:00:00.000000000 Z
11
+ date: 2021-10-02 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.4
227
+ rubygems_version: 3.1.2
228
228
  signing_key:
229
229
  specification_version: 4
230
230
  summary: Multifactor authentication for Rails 6.