booth 0.0.1 → 0.0.2

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.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE.md +1 -2
  4. data/README.md +37 -6
  5. data/app/assets/images/booth/browsers/README.md +1 -2
  6. data/app/assets/images/booth/browsers/chrome.svg +1 -1
  7. data/app/assets/images/booth/browsers/edge.svg +1 -1
  8. data/app/assets/images/booth/browsers/firefox.svg +1 -1
  9. data/app/assets/images/booth/browsers/opera.svg +1 -1
  10. data/app/assets/images/booth/browsers/safari.svg +1 -1
  11. data/app/assets/images/booth/fido/passkey_mark_a.svg +10 -0
  12. data/app/assets/images/booth/fido/passkey_mark_a_black.svg +32 -0
  13. data/app/assets/images/booth/fido/passkey_mark_a_reverse.svg +33 -0
  14. data/app/assets/images/booth/fido/passkey_mark_a_white.svg +32 -0
  15. data/app/assets/images/booth/fido/passkey_mark_b_black.svg +1 -0
  16. data/app/assets/images/booth/platforms/android.svg +1 -6
  17. data/app/assets/images/booth/platforms/apple.svg +1 -6
  18. data/app/assets/images/booth/platforms/linux.svg +1 -6
  19. data/app/assets/images/booth/platforms/windows.svg +1 -6
  20. data/app/assets/javascripts/booth/authentication.js +29 -0
  21. data/app/assets/javascripts/booth/authentication.js.map +1 -0
  22. data/app/assets/javascripts/booth/error.js +38 -0
  23. data/app/assets/javascripts/booth/error.js.map +1 -0
  24. data/app/assets/javascripts/booth/form.js +78 -0
  25. data/app/assets/javascripts/booth/form.js.map +1 -0
  26. data/app/assets/javascripts/booth/gui.js +53 -0
  27. data/app/assets/javascripts/booth/gui.js.map +1 -0
  28. data/app/assets/javascripts/booth/registration.js +29 -0
  29. data/app/assets/javascripts/booth/registration.js.map +1 -0
  30. data/app/assets/javascripts/booth/setup.js +14 -0
  31. data/app/assets/javascripts/booth/verification.js +49 -0
  32. data/app/assets/javascripts/booth/verification.js.map +1 -0
  33. data/app/assets/javascripts/declarations/authentication.d.ts +6 -0
  34. data/app/assets/javascripts/declarations/error.d.ts +36 -0
  35. data/app/assets/javascripts/declarations/form.d.ts +8 -0
  36. data/app/assets/javascripts/declarations/gui.d.ts +4 -0
  37. data/app/assets/javascripts/declarations/registration.d.ts +6 -0
  38. data/app/assets/javascripts/declarations/setup.d.ts +3 -0
  39. data/app/assets/javascripts/declarations/verification.d.ts +6 -0
  40. data/app/assets/javascripts/src/authentication.ts +41 -0
  41. data/app/assets/javascripts/src/error.ts +35 -0
  42. data/app/assets/javascripts/src/form.ts +90 -0
  43. data/app/assets/javascripts/src/gui.ts +59 -0
  44. data/app/assets/javascripts/src/registration.ts +44 -0
  45. data/app/assets/javascripts/src/verification.ts +61 -0
  46. data/app/assets/stylesheets/booth/booth.css +3 -0
  47. data/config/importmap.rb +11 -0
  48. data/config/locales/de.yml +14 -38
  49. data/config/locales/en.yml +17 -36
  50. data/data/combined_aaguid.json +1 -0
  51. data/lib/booth/adminland/credentials/create.rb +10 -12
  52. data/lib/booth/adminland/credentials/index.rb +31 -0
  53. data/lib/booth/adminland/onboardings/create.rb +24 -15
  54. data/lib/booth/adminland/onboardings/destroy.rb +8 -4
  55. data/lib/booth/adminland/onboardings/find.rb +52 -45
  56. data/lib/booth/adminland/onboardings/find_unconsumed.rb +61 -0
  57. data/lib/booth/adminland/onboardings/index.rb +6 -3
  58. data/lib/booth/adminland/periodic_cleanup.rb +7 -2
  59. data/lib/booth/adminland.rb +17 -18
  60. data/lib/booth/coercers/domain.rb +11 -0
  61. data/lib/booth/coercers/request.rb +51 -0
  62. data/lib/booth/coercers/scope.rb +11 -0
  63. data/lib/booth/comparisons/domain.rb +38 -0
  64. data/lib/booth/comparisons/scope.rb +38 -0
  65. data/lib/booth/concerns/action.rb +25 -13
  66. data/lib/booth/concerns/transition.rb +5 -2
  67. data/lib/booth/configuration.rb +14 -73
  68. data/lib/booth/configure.rb +3 -10
  69. data/lib/booth/{audits/register → core/audit}/completed_onboarding.rb +8 -6
  70. data/lib/booth/core/audit/credential_created.rb +24 -0
  71. data/lib/booth/core/audit/logout.rb +24 -0
  72. data/lib/booth/core/authenticators/confirm.rb +30 -0
  73. data/lib/booth/core/authenticators/step.rb +24 -0
  74. data/lib/booth/core/cooldowns/distance_of_time.rb +50 -0
  75. data/lib/booth/core/cooldowns/strategies/exponential.rb +88 -0
  76. data/lib/booth/core/cooldowns/strategies/global.rb +66 -0
  77. data/lib/booth/core/cooldowns/strategies/result.rb +27 -0
  78. data/lib/booth/core/credentials/create.rb +32 -0
  79. data/lib/booth/core/credentials/find_by_username.rb +63 -0
  80. data/lib/booth/core/credentials/index.rb +15 -0
  81. data/lib/booth/core/credentials/webauth_challenge.rb +37 -0
  82. data/lib/booth/core/geolocation.rb +25 -0
  83. data/lib/booth/core/onboardings/find.rb +92 -0
  84. data/lib/booth/core/onboardings/step.rb +19 -0
  85. data/lib/booth/core/remotes/get.rb +45 -0
  86. data/lib/booth/core/remotes/respond.rb +82 -0
  87. data/lib/booth/core/remotes/set_for_login.rb +31 -0
  88. data/lib/booth/core/sessions/create_and_login.rb +63 -0
  89. data/lib/booth/core/sessions/historical_locations.rb +22 -0
  90. data/lib/booth/core/sessions/index.rb +66 -0
  91. data/lib/booth/core/sessions/revoke.rb +59 -0
  92. data/lib/booth/core/sessions/revoke_all_others.rb +49 -0
  93. data/lib/booth/core/sessions/to_passport.rb +35 -0
  94. data/lib/booth/core/webauth/authentication_verification.rb +76 -0
  95. data/lib/booth/core/webauth/options_for_create.rb +56 -0
  96. data/lib/booth/core/webauth/options_for_get.rb +30 -0
  97. data/lib/booth/core/webauth/provider.rb +36 -0
  98. data/lib/booth/core/webauth/registration_verification.rb +100 -0
  99. data/lib/booth/credential.rb +35 -0
  100. data/lib/booth/engine.rb +15 -4
  101. data/lib/booth/errors.rb +2 -0
  102. data/lib/booth/hooks/after_fetch.rb +14 -6
  103. data/lib/booth/hooks/before_logout.rb +5 -3
  104. data/lib/booth/hooks/serialize_from_session.rb +13 -5
  105. data/lib/booth/hooks/serialize_into_session.rb +6 -3
  106. data/lib/booth/logging.rb +13 -42
  107. data/lib/booth/models/application_record.rb +3 -0
  108. data/lib/booth/models/audit.rb +10 -11
  109. data/lib/booth/models/authenticator.rb +6 -9
  110. data/lib/booth/models/credential.rb +17 -20
  111. data/lib/booth/models/onboarding.rb +16 -39
  112. data/lib/booth/models/{contest.rb → remote.rb} +13 -14
  113. data/lib/booth/models/remotes/scopes/recently_created.rb +26 -0
  114. data/lib/booth/models/remotes/scopes/recently_responded.rb +35 -0
  115. data/lib/booth/models/session.rb +15 -10
  116. data/lib/booth/models/user_agent.rb +2 -0
  117. data/lib/booth/request.rb +43 -22
  118. data/lib/booth/requests/agent.rb +3 -1
  119. data/lib/booth/requests/authentication.rb +15 -5
  120. data/lib/booth/requests/ip.rb +4 -2
  121. data/lib/booth/requests/return_path.rb +4 -2
  122. data/lib/booth/requests/session.rb +6 -4
  123. data/lib/booth/requests/storage.rb +5 -31
  124. data/lib/booth/requests/storages/login.rb +35 -29
  125. data/lib/booth/requests/storages/registration.rb +2 -0
  126. data/lib/booth/requests/storages/webauth.rb +3 -0
  127. data/lib/booth/requests/sudo.rb +6 -50
  128. data/lib/booth/routes/userland.rb +13 -59
  129. data/lib/booth/syntaxes/domain.rb +46 -0
  130. data/lib/booth/syntaxes/email.rb +11 -8
  131. data/lib/booth/syntaxes/ip.rb +6 -4
  132. data/lib/booth/syntaxes/remote_code.rb +60 -0
  133. data/lib/booth/syntaxes/scope.rb +7 -3
  134. data/lib/booth/syntaxes/secret_key.rb +8 -6
  135. data/lib/booth/syntaxes/username.rb +23 -10
  136. data/lib/booth/syntaxes/uuid.rb +3 -1
  137. data/lib/booth/test.rb +27 -22
  138. data/lib/booth/testing/incorporation_test_case.rb +29 -0
  139. data/lib/booth/testing/shortcuts.rb +77 -0
  140. data/lib/booth/testing/support/assert_all_partials_were_covered.rb +69 -0
  141. data/lib/booth/testing/support/assert_logged_in.rb +68 -0
  142. data/lib/booth/{test → testing}/support/assert_logged_out.rb +7 -4
  143. data/lib/booth/testing/support/assert_partial.rb +56 -0
  144. data/lib/booth/{test → testing}/support/force_login.rb +10 -4
  145. data/lib/booth/{test → testing}/support/get_session_value.rb +8 -6
  146. data/lib/booth/testing/support/scenario.rb +23 -0
  147. data/lib/booth/testing/support/shortcuts/create_and_onboard.rb +56 -0
  148. data/lib/booth/testing/support/shortcuts/login_with_passkey.rb +55 -0
  149. data/lib/booth/testing/support/shortcuts/register_new_passkey.rb +51 -0
  150. data/lib/booth/testing/support/soft_reset_session.rb +24 -0
  151. data/lib/booth/testing/support/virtual_authenticators/create.rb +34 -0
  152. data/lib/booth/testing/support/virtual_authenticators/destroy.rb +20 -0
  153. data/lib/booth/testing/support/virtual_authenticators/enable.rb +24 -0
  154. data/lib/booth/testing/support/virtual_authenticators/load.rb +38 -0
  155. data/lib/booth/testing/support/virtual_authenticators/manager.rb +124 -0
  156. data/lib/booth/testing/support/visit.rb +62 -0
  157. data/lib/booth/testing/userland/login_remotely.rb +100 -0
  158. data/lib/booth/testing/userland/onboarding_first_time.rb +81 -0
  159. data/lib/booth/testing/userland/onboarding_to_reset_passkeys.rb +129 -0
  160. data/lib/booth/testing/userland/registration_with_passkey.rb +93 -0
  161. data/lib/booth/testing/userland/registration_without_passkey.rb +101 -0
  162. data/lib/booth/testing/userland/sessions_manage_behavior.rb +68 -0
  163. data/lib/booth/testing/userland/sessions_revoke_all_others.rb +17 -0
  164. data/lib/booth/testing/userland/sessions_revoke_one.rb +17 -0
  165. data/lib/booth/testing/userland.rb +36 -0
  166. data/lib/booth/to_struct.rb +9 -2
  167. data/lib/booth/userland/extract_flash_messages.rb +10 -3
  168. data/lib/booth/userland/logins/create.rb +8 -6
  169. data/lib/booth/userland/logins/destroy.rb +23 -6
  170. data/lib/booth/userland/logins/new.rb +23 -25
  171. data/lib/booth/userland/logins/transitions/create/choose_username.rb +62 -27
  172. data/lib/booth/userland/logins/transitions/create/skip_remotes.rb +18 -14
  173. data/lib/booth/userland/logins/transitions/create/webauth_authentication_initiation.rb +54 -48
  174. data/lib/booth/userland/logins/transitions/create/webauth_authentication_verification.rb +62 -58
  175. data/lib/booth/userland/logins/transitions/new/already_logged_in.rb +4 -3
  176. data/lib/booth/userland/logins/transitions/new/fallible.rb +4 -0
  177. data/lib/booth/userland/logins/transitions/new/{mode_username_and_password.rb → missing_authenticators.rb} +5 -4
  178. data/lib/booth/userland/logins/transitions/new/mode_username_and_webauth.rb +6 -4
  179. data/lib/booth/userland/logins/transitions/new/no_username_chosen.rb +3 -1
  180. data/lib/booth/userland/logins/transitions/new/remote_session_available.rb +20 -13
  181. data/lib/booth/userland/logins/transitions/new/timed_out.rb +3 -1
  182. data/lib/booth/userland/onboardings/show.rb +65 -39
  183. data/lib/booth/userland/onboardings/update.rb +46 -38
  184. data/lib/booth/userland/registrations/create.rb +51 -20
  185. data/lib/booth/userland/registrations/new.rb +6 -7
  186. data/lib/booth/userland/remotes/show.rb +56 -0
  187. data/lib/booth/userland/{personal_contests → remotes}/update.rb +5 -3
  188. data/lib/booth/userland/sessions/destroy_one_or_other.rb +3 -16
  189. data/lib/booth/userland/sessions/index.rb +4 -2
  190. data/lib/booth/userland/sessions/show.rb +5 -6
  191. data/lib/booth/userland/sessions/transitions/destroy/enter_webauth.rb +8 -6
  192. data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_initiation.rb +8 -6
  193. data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_verification.rb +7 -5
  194. data/lib/booth/userland/sessions/transitions/show/enter_webauth.rb +8 -6
  195. data/lib/booth/userland/webauths/create.rb +20 -17
  196. data/lib/booth/userland/webauths/destroy.rb +6 -16
  197. data/lib/booth/userland/webauths/guards/sudo.rb +10 -5
  198. data/lib/booth/userland/webauths/index.rb +4 -2
  199. data/lib/booth/userland/webauths/new.rb +7 -22
  200. data/lib/booth/userland/webauths/sudo.rb +3 -1
  201. data/lib/booth/userland/webauths/transitions/create/authentication_initiation.rb +8 -11
  202. data/lib/booth/userland/webauths/transitions/create/authentication_verification.rb +11 -13
  203. data/lib/booth/userland/webauths/transitions/create/choose_nickname.rb +8 -5
  204. data/lib/booth/userland/webauths/transitions/create/registration_initiation.rb +15 -14
  205. data/lib/booth/userland/webauths/transitions/create/registration_verification.rb +34 -28
  206. data/lib/booth/userland/webauths/transitions/create/reset.rb +2 -0
  207. data/lib/booth/userland/webauths/transitions/new/step.rb +3 -1
  208. data/lib/booth/userland/webauths/transitions/sudo/authentication_initiation.rb +5 -10
  209. data/lib/booth/userland/webauths/transitions/sudo/authentication_verification.rb +4 -2
  210. data/lib/booth/userland.rb +53 -109
  211. data/lib/booth/version.rb +3 -1
  212. data/lib/booth.rb +6 -236
  213. data/lib/generators/booth/migration/migration_generator.rb +2 -1
  214. data/lib/generators/booth/migration/templates/add_credential_to_users.erb +6 -4
  215. data/lib/generators/booth/migration/templates/create_booth_tables.erb +61 -72
  216. metadata +124 -571
  217. data/app/assets/config/booth_manifest.js +0 -15
  218. data/app/assets/images/booth/browsers/internet_explorer.svg +0 -1
  219. data/app/assets/javascripts/booth/all.js +0 -162
  220. data/app/assets/javascripts/booth/all.js.map +0 -1
  221. data/app/assets/javascripts/booth/booth.ts +0 -194
  222. data/app/assets/javascripts/booth/webauthn-json.ts +0 -99
  223. data/lib/booth/adminland/recoveries/consume.rb +0 -70
  224. data/lib/booth/audits/register/added_otp.rb +0 -22
  225. data/lib/booth/audits/register/changed_otp.rb +0 -22
  226. data/lib/booth/audits/register/correct_otp.rb +0 -42
  227. data/lib/booth/audits/register/correct_password.rb +0 -43
  228. data/lib/booth/audits/register/logout.rb +0 -22
  229. data/lib/booth/audits/register/requested_password_reset.rb +0 -22
  230. data/lib/booth/audits/register/wrong_otp.rb +0 -22
  231. data/lib/booth/audits/register/wrong_password.rb +0 -25
  232. data/lib/booth/authenticators/confirm.rb +0 -34
  233. data/lib/booth/authenticators/credential_mode_after_confirmation.rb +0 -25
  234. data/lib/booth/authenticators/step.rb +0 -19
  235. data/lib/booth/contests/get.rb +0 -36
  236. data/lib/booth/contests/respond.rb +0 -78
  237. data/lib/booth/contests/set_for_login.rb +0 -28
  238. data/lib/booth/cooldowns/distance_of_time.rb +0 -46
  239. data/lib/booth/cooldowns/otp.rb +0 -22
  240. data/lib/booth/cooldowns/password.rb +0 -44
  241. data/lib/booth/cooldowns/password_reset.rb +0 -24
  242. data/lib/booth/cooldowns/strategies/exponential.rb +0 -82
  243. data/lib/booth/cooldowns/strategies/global.rb +0 -62
  244. data/lib/booth/cooldowns/strategies/result.rb +0 -22
  245. data/lib/booth/credentials/create.rb +0 -28
  246. data/lib/booth/credentials/create_with_onboarding.rb +0 -26
  247. data/lib/booth/credentials/find_by_username.rb +0 -45
  248. data/lib/booth/credentials/mode.rb +0 -69
  249. data/lib/booth/credentials/modes/otp_addable.rb +0 -23
  250. data/lib/booth/credentials/modes/otp_changeable.rb +0 -23
  251. data/lib/booth/credentials/modes/otp_manageable.rb +0 -17
  252. data/lib/booth/credentials/modes/otp_removable.rb +0 -23
  253. data/lib/booth/credentials/modes/password_addable.rb +0 -29
  254. data/lib/booth/credentials/modes/password_changeable.rb +0 -31
  255. data/lib/booth/credentials/modes/password_manageable.rb +0 -17
  256. data/lib/booth/credentials/modes/password_removable.rb +0 -24
  257. data/lib/booth/credentials/modes/password_removal_requires_user_verifiable_webauth.rb +0 -16
  258. data/lib/booth/credentials/modes/webauth_addable.rb +0 -26
  259. data/lib/booth/credentials/modes/webauth_manageable.rb +0 -16
  260. data/lib/booth/credentials/modes/webauth_removable.rb +0 -25
  261. data/lib/booth/credentials/otp_authentication.rb +0 -59
  262. data/lib/booth/credentials/password_authentication.rb +0 -72
  263. data/lib/booth/credentials/webauth_challenge.rb +0 -28
  264. data/lib/booth/geolocation.rb +0 -20
  265. data/lib/booth/logger.rb +0 -41
  266. data/lib/booth/method_object.rb +0 -73
  267. data/lib/booth/mode.rb +0 -22
  268. data/lib/booth/models/concerns/modeable.rb +0 -50
  269. data/lib/booth/models/concerns/otpable.rb +0 -37
  270. data/lib/booth/models/concerns/passwordable.rb +0 -58
  271. data/lib/booth/models/contests/scopes/recently_created.rb +0 -23
  272. data/lib/booth/models/contests/scopes/recently_responded.rb +0 -32
  273. data/lib/booth/models/password_reset.rb +0 -41
  274. data/lib/booth/models/recovery.rb +0 -32
  275. data/lib/booth/models/registration.rb +0 -10
  276. data/lib/booth/modes/base.rb +0 -25
  277. data/lib/booth/modes/username_and_password.rb +0 -7
  278. data/lib/booth/modes/username_and_webauth.rb +0 -7
  279. data/lib/booth/modes/username_password_and_otp.rb +0 -7
  280. data/lib/booth/modes/username_password_and_webauth.rb +0 -7
  281. data/lib/booth/onboardings/find.rb +0 -35
  282. data/lib/booth/onboardings/propagate_to_credential.rb +0 -63
  283. data/lib/booth/onboardings/step.rb +0 -68
  284. data/lib/booth/password_resets/create.rb +0 -57
  285. data/lib/booth/password_resets/find.rb +0 -36
  286. data/lib/booth/password_resets/propagate_to_credential.rb +0 -36
  287. data/lib/booth/password_resets/step.rb +0 -18
  288. data/lib/booth/recoveries/create.rb +0 -45
  289. data/lib/booth/requests/storages/otp.rb +0 -54
  290. data/lib/booth/requests/storages/password.rb +0 -49
  291. data/lib/booth/requests/storages/password_reset.rb +0 -35
  292. data/lib/booth/requests/storages/recovery.rb +0 -35
  293. data/lib/booth/sessions/create_and_login.rb +0 -46
  294. data/lib/booth/sessions/historical_locations.rb +0 -18
  295. data/lib/booth/sessions/index.rb +0 -59
  296. data/lib/booth/sessions/revoke.rb +0 -51
  297. data/lib/booth/sessions/revoke_all_others.rb +0 -43
  298. data/lib/booth/sessions/to_passport.rb +0 -51
  299. data/lib/booth/syntaxes/contest_code.rb +0 -58
  300. data/lib/booth/syntaxes/otp.rb +0 -57
  301. data/lib/booth/syntaxes/scope_comparison.rb +0 -28
  302. data/lib/booth/test/helpers.rb +0 -63
  303. data/lib/booth/test/support/assert_all_partials_were_covered.rb +0 -63
  304. data/lib/booth/test/support/assert_logged_in.rb +0 -49
  305. data/lib/booth/test/support/assert_partial.rb +0 -29
  306. data/lib/booth/test/support/otp_code_from_session.rb +0 -30
  307. data/lib/booth/test/support/soft_reset_session.rb +0 -22
  308. data/lib/booth/test/userland/logins/missing_authenticators.rb +0 -72
  309. data/lib/booth/test/userland/logins/missing_onboarding.rb +0 -35
  310. data/lib/booth/test/userland/logins/username_and_password.rb +0 -40
  311. data/lib/booth/test/userland/logins/username_and_webauth.rb +0 -75
  312. data/lib/booth/test/userland/logins/username_password_and_otp.rb +0 -45
  313. data/lib/booth/test/userland/logins/username_password_and_webauth.rb +0 -86
  314. data/lib/booth/test/userland/onboardings/already_logged_in.rb +0 -64
  315. data/lib/booth/test/userland/onboardings/otp.rb +0 -63
  316. data/lib/booth/test/userland/onboardings/password.rb +0 -49
  317. data/lib/booth/test/userland/onboardings/timeout.rb +0 -47
  318. data/lib/booth/test/userland/otps/manage.rb +0 -86
  319. data/lib/booth/test/userland/password_resets/reset.rb +0 -102
  320. data/lib/booth/test/userland.rb +0 -38
  321. data/lib/booth/test/webauthn/disable.rb +0 -17
  322. data/lib/booth/test/webauthn/enable.rb +0 -19
  323. data/lib/booth/test/webauthn/virtual_authenticators/create.rb +0 -38
  324. data/lib/booth/test/webauthn/virtual_authenticators/destroy.rb +0 -20
  325. data/lib/booth/userland/logins/transitions/create/enter_otp.rb +0 -70
  326. data/lib/booth/userland/logins/transitions/create/verify_password.rb +0 -70
  327. data/lib/booth/userland/logins/transitions/new/mode_first_time.rb +0 -20
  328. data/lib/booth/userland/logins/transitions/new/mode_username_password_and_otp.rb +0 -24
  329. data/lib/booth/userland/logins/transitions/new/mode_username_password_and_webauth.rb +0 -24
  330. data/lib/booth/userland/onboardings/transitions/update/choose_mode.rb +0 -58
  331. data/lib/booth/userland/onboardings/transitions/update/choose_password.rb +0 -41
  332. data/lib/booth/userland/onboardings/transitions/update/choose_webauth_nickname.rb +0 -50
  333. data/lib/booth/userland/onboardings/transitions/update/confirm_otp.rb +0 -58
  334. data/lib/booth/userland/onboardings/transitions/update/confirm_password.rb +0 -49
  335. data/lib/booth/userland/onboardings/transitions/update/register_otp.rb +0 -31
  336. data/lib/booth/userland/onboardings/transitions/update/reset_otp.rb +0 -40
  337. data/lib/booth/userland/onboardings/transitions/update/reset_password.rb +0 -35
  338. data/lib/booth/userland/onboardings/transitions/update/reset_webauth.rb +0 -46
  339. data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_initiation.rb +0 -40
  340. data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_verification.rb +0 -59
  341. data/lib/booth/userland/onboardings/transitions/update/webauth_registration_initiation.rb +0 -46
  342. data/lib/booth/userland/onboardings/transitions/update/webauth_registration_verification.rb +0 -56
  343. data/lib/booth/userland/otps/destroy.rb +0 -42
  344. data/lib/booth/userland/otps/edit.rb +0 -72
  345. data/lib/booth/userland/otps/guards/manageable.rb +0 -21
  346. data/lib/booth/userland/otps/guards/sudo.rb +0 -23
  347. data/lib/booth/userland/otps/show.rb +0 -36
  348. data/lib/booth/userland/otps/sudo.rb +0 -51
  349. data/lib/booth/userland/otps/transitions/update/confirm.rb +0 -84
  350. data/lib/booth/userland/otps/transitions/update/register.rb +0 -40
  351. data/lib/booth/userland/otps/transitions/update/reset.rb +0 -31
  352. data/lib/booth/userland/otps/update.rb +0 -34
  353. data/lib/booth/userland/password_resets/create.rb +0 -73
  354. data/lib/booth/userland/password_resets/guards/logged_out.rb +0 -21
  355. data/lib/booth/userland/password_resets/new.rb +0 -57
  356. data/lib/booth/userland/password_resets/show.rb +0 -77
  357. data/lib/booth/userland/password_resets/transitions/update/choose_password.rb +0 -48
  358. data/lib/booth/userland/password_resets/transitions/update/confirm_password.rb +0 -54
  359. data/lib/booth/userland/password_resets/transitions/update/reset_password.rb +0 -29
  360. data/lib/booth/userland/password_resets/update.rb +0 -65
  361. data/lib/booth/userland/passwords/destroy.rb +0 -41
  362. data/lib/booth/userland/passwords/edit.rb +0 -54
  363. data/lib/booth/userland/passwords/guards/manageable.rb +0 -21
  364. data/lib/booth/userland/passwords/guards/removable.rb +0 -21
  365. data/lib/booth/userland/passwords/guards/sudo.rb +0 -21
  366. data/lib/booth/userland/passwords/remove.rb +0 -34
  367. data/lib/booth/userland/passwords/show.rb +0 -32
  368. data/lib/booth/userland/passwords/sudo.rb +0 -55
  369. data/lib/booth/userland/passwords/transitions/remove/step.rb +0 -27
  370. data/lib/booth/userland/passwords/transitions/update/choose_password.rb +0 -62
  371. data/lib/booth/userland/passwords/transitions/update/confirm_password.rb +0 -82
  372. data/lib/booth/userland/passwords/update.rb +0 -33
  373. data/lib/booth/userland/personal_contests/show.rb +0 -60
  374. data/lib/booth/userland/recoveries/create.rb +0 -48
  375. data/lib/booth/userland/recoveries/new.rb +0 -35
  376. data/lib/booth/userland/sessions/transitions/destroy/enter_password.rb +0 -50
  377. data/lib/booth/userland/sessions/transitions/destroy/verify_password.rb +0 -83
  378. data/lib/booth/userland/webauths/guards/manageable.rb +0 -21
  379. data/lib/booth/webauth/authentication_verification.rb +0 -68
  380. data/lib/booth/webauth/demand_user_verification.rb +0 -29
  381. data/lib/booth/webauth/options_for_create.rb +0 -46
  382. data/lib/booth/webauth/options_for_get.rb +0 -29
  383. data/lib/generators/booth/migration/templates/create_booth_mode_types.erb +0 -20
@@ -1,21 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- module Guards
5
- class LoggedOut
6
- include ::Booth::MethodObject
7
- include ::Booth::Logging
8
-
9
- option :request
10
-
11
- def call
12
- return Tron.success :not_logged_in unless request.authentication.logged_in?
13
-
14
- debug { "Logged in as user #{request.authentication.username.inspect} but trying to password reset" }
15
- yield Tron.success :logged_in_user_cannot_reset_password, step: :logout_first
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,57 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- class New
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_get!
9
- request.must_be_html!
10
-
11
- ::Booth::Userland::PasswordResets::Guards::LoggedOut.call(request:) { return _1 }
12
-
13
- do_find_credential
14
- .on_success { do_prepare_reset_form }
15
- end
16
-
17
- private
18
-
19
- delegate :username, to: :storage, private: true
20
-
21
- def do_find_credential
22
- return Tron.success :known_credential if login_storage.credential_for_username
23
-
24
- debug { "I don't know the username for a password reset" }
25
- Tron.failure :unknown_credential, public_message: I18n.t('booth.password_reset_needs_username')
26
- end
27
-
28
- def do_prepare_reset_form
29
- creation = ::Booth::PasswordResets::Create.call(
30
- credential: login_storage.credential_for_username,
31
- email: nil,
32
- ip: request.ip,
33
- agent: request.agent
34
- )
35
-
36
- if creation.failure == :blank_email
37
- debug { 'Password reset is possible, once email was provided' }
38
- return Tron.success :email_address_needed, username: login_storage.username,
39
- email: password_reset_storage.email,
40
- step: :new
41
- end
42
-
43
- # Because we did not pass in an email, this will never be successful.
44
- creation
45
- end
46
-
47
- def login_storage
48
- request.storage.login
49
- end
50
-
51
- def password_reset_storage
52
- request.storage.password_reset
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,77 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- class Show
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_get!
9
- request.must_be_html!
10
-
11
- do_find_password_reset
12
- .on_success { do_check_scope }
13
- .on_success { do_check_logged_out }
14
- .on_success { do_access_password_reset }
15
- end
16
-
17
- def do_find_password_reset
18
- finding = ::Booth::PasswordResets::Find.call(secret_key: secret_key_param)
19
- return finding if finding.failure?
20
-
21
- @password_reset = finding.password_reset
22
- finding
23
- end
24
-
25
- def do_check_scope
26
- ::Booth::Syntaxes::ScopeComparison.call this: request.scope, that: @password_reset.credential.scope
27
- end
28
-
29
- def do_check_logged_out
30
- unless request.authentication.logged_in?
31
- debug { "Good, nobody happens to be already logged in in scope #{request.scope}" }
32
- return Tron.success :not_logged_in
33
- end
34
-
35
- if request.authentication.logged_in_as?(credential: @password_reset.credential)
36
- debug { "#{@password_reset.credential.username} is already logged in in scope #{request.scope}" }
37
- return Tron.success :logged_in_as_same_credential
38
- end
39
-
40
- # This is not a security issue (the reset link status is checked elsewhere),
41
- # but we should not ask the user to logout knowing that password reset is unavailble.
42
- if %i[completed timed_out].include?(@password_reset.step)
43
- return Tron.failure :wrong_user_and_reset_unavailable, step: @password_reset.step
44
- end
45
-
46
- debug do
47
- "Logged in as user #{request.authentication.username.inspect} but trying to reset password as #{@password_reset.credential.username.inspect}"
48
- end
49
- Tron.failure :wrong_user_logged_in, step: :wrong_user_logged_in,
50
- secret_key: @password_reset.secret_key,
51
- username: @password_reset.credential.username
52
- end
53
-
54
- def do_access_password_reset
55
- # Storing the consumer IP for now, since we already have it.
56
- if @password_reset.accessed_at.blank?
57
- @password_reset.update!(accessed_at: Time.current, consumer_ip: request.ip)
58
- end
59
-
60
- debug do
61
- "Accessed PasswordReset with ID #{@password_reset.id.inspect} and Credential ID #{@password_reset.credential_id.inspect}"
62
- end
63
- Tron.success :password_reset_accessed, credential_id: @password_reset.credential.id,
64
- step: @password_reset.step,
65
- username: @password_reset.credential.username,
66
- secret_key: @password_reset.secret_key,
67
- minlength: @password_reset.class.password_minlength,
68
- passwordrules: @password_reset.class.passwordrules
69
- end
70
-
71
- def secret_key_param
72
- params[:id]
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,48 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- module Transitions
5
- module Update
6
- class ChoosePassword
7
- include ::Booth::Concerns::Transition
8
-
9
- option :password_reset
10
-
11
- def self.applicable?(params:)
12
- params&.key?(:password_reset) && params[:password_reset]&.key?(:password)
13
- end
14
-
15
- def call
16
- do_check_password_reset
17
- .on_success { do_update_password }
18
- end
19
-
20
- private
21
-
22
- def do_check_password_reset
23
- return Tron.failure :missing_password_reset unless password_reset.is_a?(::Booth::Models::PasswordReset)
24
-
25
- Tron.success :password_reset_exists
26
- end
27
-
28
- def do_update_password
29
- if password_reset.update password: password,
30
- password_chosen_at: Time.current
31
- debug { 'You chose a password' }
32
- Tron.success :password_chosen
33
- else
34
- public_message = password_reset.errors.to_a.to_sentence
35
- debug { "Could not choose password: #{public_message}" }
36
- Tron.failure :password_update_failed, public_message:
37
- end
38
- end
39
-
40
- def password
41
- params&.require(:password_reset)&.permit(:password)&.[](:password)
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,54 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- module Transitions
5
- module Update
6
- class ConfirmPassword
7
- include ::Booth::Concerns::Transition
8
-
9
- option :password_reset
10
-
11
- def self.applicable?(params:)
12
- params.key?(:password_reset) && params[:password_reset].key?(:password_confirmation)
13
- end
14
-
15
- def call
16
- do_compare_password
17
- .on_success { do_update_password }
18
- end
19
-
20
- private
21
-
22
- def do_compare_password
23
- return Tron.success :passwords_match if @password_reset.authenticate_password(password_param)
24
-
25
- @password_reset.errors.add :password_confirmation, :confirmation
26
- public_message = password_reset.errors.to_a.to_sentence
27
- debug { "Could not confirm password: #{public_message}" }
28
- Tron.failure :password_did_not_match, public_message:
29
- end
30
-
31
- def do_update_password
32
- if @password_reset.update(password_confirmed_at: Time.current, consumer_ip: request.ip)
33
- debug { 'You confirmed your password' }
34
- ::Booth::PasswordResets::PropagateToCredential.call(@password_reset)
35
- Tron.success :password_confirmed,
36
- public_message: I18n.t('booth.password_successfully_reset')
37
-
38
- else
39
- debug do
40
- "The confirmation was correct but the update failed: #{password_reset.errors.to_a.to_sentence}"
41
- end
42
- Tron.failure :correct_password_confirmation_failed
43
- end
44
- end
45
-
46
- def password_param
47
- params.require(:password_reset).permit(:password_confirmation)[:password_confirmation]
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,29 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- module Transitions
5
- module Update
6
- class ResetPassword
7
- include ::Booth::Concerns::Transition
8
-
9
- option :password_reset
10
-
11
- def self.applicable?(params:)
12
- params.key?(:reset_password)
13
- end
14
-
15
- def call
16
- if password_reset.update password_chosen_at: nil, password_confirmed_at: nil
17
- debug { 'The PasswordReset password was reset.' }
18
- Tron.success :password_reset
19
- else
20
- debug { "Could not reset password: #{password_reset.errors.to_a.to_sentence}" }
21
- Tron.failure :password_reset_failed
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,65 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- class Update
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_patch!
9
-
10
- do_find_password_reset
11
- .on_success { do_check_scope }
12
- .on_success { do_check_logged_out }
13
- .on_success { do_transition }
14
- end
15
-
16
- private
17
-
18
- def do_find_password_reset
19
- finding = ::Booth::PasswordResets::Find.call(secret_key: params[:id])
20
- return finding if finding.failure?
21
-
22
- @password_reset = finding.password_reset
23
- finding
24
- end
25
-
26
- def do_check_scope
27
- ::Booth::Syntaxes::ScopeComparison.call this: scope, that: @password_reset.credential.scope
28
- end
29
-
30
- def do_check_logged_out
31
- unless request.authentication.logged_in?
32
- debug { "Good, nobody happens to be already logged in in scope #{scope}" }
33
- return Tron.success :not_logged_in
34
- end
35
-
36
- debug { "When updating a new password, nobody should be logged in its scope #{scope.inspect}" }
37
- Tron.failure :currently_logged_in
38
- end
39
-
40
- def after_transition
41
- @password_reset.reload # Ensure the `password_reset` instance is in a valid state after a failed update
42
- debug { "PasswordReset updated, now in status #{@password_reset.step}" }
43
-
44
- # If (and only if!) this account is protected *only* by a password...
45
- return unless @password_reset.completed? && @password_reset.credential.mode_username_and_password?
46
-
47
- # ...then we log in right away.
48
- ::Booth::Sessions::CreateAndLogin.call(credential: @password_reset.credential, request:)
49
- end
50
-
51
- def initialize_transition
52
- transition.call(password_reset: @password_reset, request:)
53
- end
54
-
55
- def transitions
56
- [
57
- ::Booth::Userland::PasswordResets::Transitions::Update::ChoosePassword,
58
- ::Booth::Userland::PasswordResets::Transitions::Update::ConfirmPassword,
59
- ::Booth::Userland::PasswordResets::Transitions::Update::ResetPassword,
60
- ]
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,41 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- class Destroy
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_delete!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- ::Booth::Userland::Passwords::Guards::Sudo.call(request:, credential:) { return _1 }
13
-
14
- do_require_eligible_credential
15
- .on_success { do_destroy }
16
- end
17
-
18
- private
19
-
20
- def do_require_eligible_credential
21
- return Tron.success :can_remove_password if ::Booth::Credentials::Modes::PasswordRemovable.call(credential)
22
-
23
- Tron.failure :credential_not_passwordable, public_message: I18n.t('booth.password_not_eligible')
24
- end
25
-
26
- def do_destroy
27
- if credential.mode_username_and_webauth!
28
- debug { 'Password has been removed from this credential' }
29
- return Tron.success :password_removed, public_message: I18n.t('booth.password_removed')
30
- end
31
-
32
- Tron.failure :password_removal_failed
33
- end
34
-
35
- def credential
36
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,54 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- class Edit
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_get!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- ::Booth::Userland::Passwords::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Passwords::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_clear_timed_out_sudo
16
- .on_success { do_edit_password }
17
- end
18
-
19
- private
20
-
21
- delegate :sudo, :authentication, to: :request
22
-
23
- def do_clear_timed_out_sudo
24
- return Tron.success :sudo_still_granted if sudo.password?
25
-
26
- # If you had chosen a new password and your sudo ran out,
27
- # then we should also clear the chosen password again. Simply start all over.
28
- storage.password_digest = nil
29
- Tron.success :cleared_password_digest
30
- end
31
-
32
- def do_edit_password
33
- Tron.success :editing_password, step:
34
- end
35
-
36
- def step
37
- return :successfully_changed if storage.password_recently_changed?
38
- return :enter_old_password unless sudo.password?
39
- return :choose_new_password if storage.password_digest.blank?
40
-
41
- :confirm_new_password
42
- end
43
-
44
- def storage
45
- request.storage.password
46
- end
47
-
48
- def credential
49
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,21 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- module Guards
5
- class Manageable
6
- include ::Booth::Logging
7
- include ::Booth::MethodObject
8
-
9
- option :credential
10
-
11
- def call
12
- return if ::Booth::Credentials::Modes::PasswordManageable.call(credential)
13
-
14
- debug { 'Password is not relevant to this credential' }
15
- yield Tron.failure :password_not_configurable, public_message: I18n.t('booth.password_unavailable')
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- module Guards
5
- class Removable
6
- include ::Booth::Logging
7
- include ::Booth::MethodObject
8
-
9
- option :credential
10
-
11
- def call
12
- return if ::Booth::Credentials::Modes::PasswordRemovable.call(credential)
13
-
14
- debug { 'Password is not removable from this credential' }
15
- yield Tron.failure :password_not_removable, public_message: I18n.t('booth.password_unavailable')
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- module Guards
5
- class Sudo
6
- include ::Booth::MethodObject
7
-
8
- option :request
9
- option :credential
10
-
11
- def call
12
- return if credential.mode_first_time?
13
- return if credential.mode_username_and_webauth?
14
-
15
- request.sudo.guard_with_password { yield _1 }
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,34 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- class Remove
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_get!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- ::Booth::Userland::Passwords::Guards::Removable.call(credential:) { return _1 }
13
- ::Booth::Userland::Passwords::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_render
16
- end
17
-
18
- private
19
-
20
- def do_render
21
- Tron.success :todo, step:
22
- end
23
-
24
- def step
25
- ::Booth::Userland::Passwords::Transitions::Remove::Step.call(credential:)
26
- end
27
-
28
- def credential
29
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,32 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- class Show
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_get!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- ::Booth::Userland::Passwords::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Passwords::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_show
16
- end
17
-
18
- private
19
-
20
- def do_show
21
- return Tron.success(:otp_addable, step: :add) if credential.mode_username_and_webauth?
22
-
23
- Tron.success :manage_password, step: :show
24
- end
25
-
26
- def credential
27
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,55 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- class Sudo
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_post!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- do_find_credential
13
- .on_success { do_require_credential_has_password }
14
- .on_success { do_check_password }
15
- .on_success { do_grant_sudo }
16
- end
17
-
18
- private
19
-
20
- def do_find_credential
21
- @credential = ::Booth::Models::Credential.find(request.authentication.credential_id)
22
- return Tron.success :found_credential if @credential
23
-
24
- Tron.failure :missing_credential
25
- end
26
-
27
- def do_require_credential_has_password
28
- return Tron.success :credential_has_only_password if @credential.mode_username_and_password?
29
- return Tron.success :credential_has_password_and_otp if @credential.mode_username_password_and_otp?
30
- return Tron.success :credential_has_password_and_webauth if @credential.mode_username_password_and_webauth?
31
-
32
- Tron.failure :credential_has_no_password, public_message: I18n.t('booth.password_not_configured')
33
- end
34
-
35
- def do_check_password
36
- ::Booth::Credentials::PasswordAuthentication.call(
37
- credential: @credential,
38
- password: password_param,
39
- ip: request.ip,
40
- agent: request.agent
41
- )
42
- end
43
-
44
- def do_grant_sudo
45
- request.sudo.password!
46
- Tron.success :password_sudo_granted
47
- end
48
-
49
- def password_param
50
- params.require(:password).permit(:password)[:password]
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,27 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Passwords
4
- module Transitions
5
- module Remove
6
- class Step
7
- include ::Booth::MethodObject
8
-
9
- option :credential
10
-
11
- def call
12
- return :add_authenticator if authenticators.none?(&:supports_user_verification)
13
-
14
- :remove
15
- end
16
-
17
- private
18
-
19
- def authenticators
20
- credential.authenticators.registered_scope
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end