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,59 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Onboardings
4
- module Transitions
5
- module Update
6
- class WebauthAuthenticationVerification
7
- include ::Booth::Concerns::Transition
8
-
9
- option :onboarding
10
-
11
- def self.applicable?(params:)
12
- params&.key?(:test_webauth) && params[:onboarding]&.key?(:rawId)
13
- end
14
-
15
- def call
16
- do_verify_response
17
- .on_success { do_persist_confirmation }
18
- end
19
-
20
- private
21
-
22
- def do_verify_response
23
- debug { 'Verifying challenge...' }
24
- # TODO: Replate with ::Booth::Webauth::AuthenticationVerification (?)
25
- webauth.verify(@onboarding.authenticator_challenge,
26
- public_key: @onboarding.authenticator_public_key,
27
- sign_count: @onboarding.authenticator_sign_count)
28
-
29
- Tron.success :challenge_response_correct
30
- rescue WebAuthn::Error => e
31
- debug { "Webauth Handshake failed: #{e.message}" }
32
- Tron.failure :invalid_challenge_response
33
- end
34
-
35
- def do_persist_confirmation
36
- debug { 'Updating succeeded sign count and authenticator confirmation...' }
37
- if onboarding.update(authenticator_sign_count: webauth.sign_count,
38
- authenticator_confirmed_at: Time.current)
39
-
40
- return Tron.success :webauth_authentication_verification_successful, public_json: {},
41
- http_status: :created
42
- end
43
-
44
- Tron.failure :storing_response_failed
45
- end
46
-
47
- def webauth
48
- @webauth ||= ::WebAuthn::Credential.from_get(onboarding_params)
49
- end
50
-
51
- def onboarding_params
52
- params.require(:onboarding).permit!
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,46 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Onboardings
4
- module Transitions
5
- module Update
6
- class WebauthRegistrationInitiation
7
- include ::Booth::Concerns::Transition
8
-
9
- option :onboarding
10
-
11
- def self.applicable?(params:)
12
- params&.key?(:register_webauth) && !params&.key?(:onboarding)
13
- end
14
-
15
- def call
16
- do_challenge
17
- end
18
-
19
- private
20
-
21
- def do_challenge
22
- debug { "Remembering registration challenge #{webauth.challenge.inspect}" }
23
-
24
- if onboarding.update authenticator_challenge: webauth.challenge
25
- return Tron.success :registration_challenge_created, public_json: webauth.as_json,
26
- http_status: :created
27
- end
28
-
29
- Tron.failure :storing_registration_challenge_failed
30
- end
31
-
32
- def webauth
33
- @webauth ||= ::Booth::Webauth::OptionsForCreate.call(
34
- webauthn_id: onboarding.webauthn_id,
35
- username: onboarding.credential.username,
36
- requires_user_verification: onboarding.requires_user_verification?
37
- # No need to exclude existing hardware keys.
38
- # You can not register more than one hardware key in this onboarding.
39
- )
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,56 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Onboardings
4
- module Transitions
5
- module Update
6
- class WebauthRegistrationVerification
7
- include ::Booth::Concerns::Transition
8
-
9
- option :onboarding
10
-
11
- def self.applicable?(params:)
12
- params&.key?(:register_webauth) && params[:onboarding]&.key?(:rawId)
13
- end
14
-
15
- def call
16
- do_verify_response
17
- .on_success { do_persist_keys }
18
- end
19
-
20
- private
21
-
22
- def do_verify_response
23
- debug { "Verifying challenge #{@onboarding.authenticator_challenge.inspect}" }
24
- webauth.verify(@onboarding.authenticator_challenge)
25
-
26
- Tron.success :challenge_response_correct
27
- rescue WebAuthn::Error => e
28
- debug { "Webauth Handshake failed: #{e.message}" }
29
- Tron.failure :invalid_challenge_response
30
- end
31
-
32
- def do_persist_keys
33
- debug { "Persisting authenticator information, the sign count is now at #{webauth.sign_count}..." }
34
- if onboarding.update(authenticator_id: ::Base64.strict_encode64(webauth.raw_id),
35
- authenticator_public_key: webauth.public_key,
36
- authenticator_sign_count: webauth.sign_count)
37
-
38
- return Tron.success :challenge_accepted, public_json: {}, http_status: :created
39
- end
40
-
41
- Tron.failure :storing_response_failed
42
- end
43
-
44
- def webauth
45
- @webauth ||= ::WebAuthn::Credential.from_create(onboarding_params)
46
- end
47
-
48
- def onboarding_params
49
- params.require(:onboarding).permit!
50
- end
51
- end
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,42 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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
- request.sudo.guard_with_otp { return _1 }
12
-
13
- do_require_eligible_credential
14
- .on_success { do_destroy }
15
- end
16
-
17
- private
18
-
19
- def do_require_eligible_credential
20
- return Tron.success :can_remove_otp if ::Booth::Credentials::Modes::OtpRemovable.call(credential)
21
-
22
- Tron.failure :credential_not_otpable, public_message: I18n.t('booth.otp_not_eligible')
23
- end
24
-
25
- def do_destroy
26
- if credential.mode_username_and_password!
27
- credential.otp_regenerate_secret
28
- credential.save # Not critical if this one fails
29
-
30
- return Tron.success :otp_removed, public_message: I18n.t('booth.otp_removed')
31
- end
32
-
33
- Tron.failure :otp_removal_failed
34
- end
35
-
36
- def credential
37
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,72 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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::Otps::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Otps::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_require_eligible_credential
16
- # .on_success { do_clear_previous_editing }
17
- .on_success { do_ensure_temporary_secret_key }
18
- .on_success { do_reveal_otp_secret }
19
- end
20
-
21
- private
22
-
23
- def do_require_eligible_credential
24
- return Tron.success :can_add_otp if ::Booth::Credentials::Modes::OtpAddable.call(credential)
25
- return Tron.success :can_change_otp if ::Booth::Credentials::Modes::OtpChangeable.call(credential)
26
-
27
- Tron.failure :credential_not_otpable, public_message: I18n.t('booth.otp_not_eligible')
28
- end
29
-
30
- # Hm, tests failed with this.
31
- # def do_clear_previous_editing
32
- # return Tron.success :no_previous_editing unless storage.secret_key_recently_changed?
33
- # return Tron.success :reset_not_requested unless request.params[:reset]
34
-
35
- # #storage.reset
36
- # Tron.success :previous_editing_cleared
37
- # end
38
-
39
- def do_ensure_temporary_secret_key
40
- return Tron.success :secret_key_exists if storage.secret_key
41
-
42
- storage.generate_secret_key!
43
- Tron.success :secret_generated
44
- end
45
-
46
- def do_reveal_otp_secret
47
- dummy = ::Booth::Models::Credential.new otp_secret_key: storage.secret_key, scope: scope
48
-
49
- Tron.success :register_otp, step:,
50
- otp_provisioning_svg: dummy.otp_provisioning_svg,
51
- otp_provisioning_url: dummy.otp_provisioning_url
52
- end
53
-
54
- def step
55
- return :successfully_changed if storage.secret_key_recently_changed?
56
-
57
- return :confirm if storage.secret_key_has_been_seen?
58
-
59
- :register
60
- end
61
-
62
- def storage
63
- request.storage.otp
64
- end
65
-
66
- def credential
67
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,21 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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::OtpManageable.call(credential)
13
-
14
- debug { 'OTP is not relevant to this credential' }
15
- yield Tron.failure :otp_not_configurable, public_message: I18n.t('booth.otp_unavailable')
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,23 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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_password?
14
- return if credential.mode_username_password_and_webauth?
15
- return if credential.mode_username_and_webauth?
16
-
17
- request.sudo.guard_with_otp { yield _1 }
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,36 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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::Otps::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Otps::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_show
16
- end
17
-
18
- private
19
-
20
- def do_show
21
- if credential.mode_username_password_and_otp?
22
- return Tron.success :current_otp, step: :show,
23
- otp_provisioning_svg: credential.otp_provisioning_svg,
24
- otp_provisioning_url: credential.otp_provisioning_url
25
- end
26
-
27
- Tron.success :otp_addable, step: :add
28
- end
29
-
30
- def credential
31
- @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,51 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
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_otp }
14
- .on_success { do_check_code }
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_otp
28
- return Tron.success :credential_has_otp if @credential.mode_username_password_and_otp?
29
-
30
- Tron.failure :credential_has_no_otp, public_message: I18n.t('booth.otp_unavailable')
31
- end
32
-
33
- def do_check_code
34
- ::Booth::Credentials::OtpAuthentication.call credential: @credential,
35
- code: code_param,
36
- ip: request.ip,
37
- agent: request.agent
38
- end
39
-
40
- def do_grant_sudo
41
- request.sudo.otp!
42
- Tron.success :otp_sudo_granted
43
- end
44
-
45
- def code_param
46
- params.require(:otp).permit(:otp)[:otp]
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,84 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
4
- module Transitions
5
- module Update
6
- class Confirm
7
- include ::Booth::Concerns::Transition
8
-
9
- def self.applicable?(params:)
10
- params.key?(:otp) && params[:otp].key?(:otp_confirmation)
11
- end
12
-
13
- def call
14
- do_check_secret_key
15
- .on_success { do_find_credential }
16
- .on_success { do_require_eligible_credential }
17
- .on_success { do_compare_code }
18
- .on_success { do_update_credential }
19
- .on_success { do_audit }
20
- end
21
-
22
- private
23
-
24
- def do_check_secret_key
25
- return Tron.success :secret_key_exists if storage.secret_key.present?
26
-
27
- Tron.failure :missing_secret_key
28
- end
29
-
30
- def do_find_credential
31
- @credential = ::Booth::Models::Credential.find(request.authentication.credential_id)
32
- return Tron.success :found_credential if @credential
33
-
34
- Tron.failure :missing_credential
35
- end
36
-
37
- def do_require_eligible_credential
38
- return Tron.success :can_add_otp if ::Booth::Credentials::Modes::OtpAddable.call(@credential)
39
- return Tron.success :can_change_otp if ::Booth::Credentials::Modes::OtpChangeable.call(@credential)
40
-
41
- Tron.failure :credential_not_otpable, public_message: I18n.t('booth.otp_not_eligible')
42
- end
43
-
44
- def do_compare_code
45
- @credential.otp_secret_key = storage.secret_key
46
- return Tron.success :correct_code if @credential.authenticate_otp(code_param)
47
-
48
- debug { "Provided code #{code_param} did not match expected code #{@credential.otp_code}" }
49
- Tron.failure :wrong_code, public_message: I18n.t('booth.wrong_otp')
50
- end
51
-
52
- def do_update_credential
53
- @credential.mode = :username_password_and_otp
54
-
55
- if @credential.save
56
- request.sudo.otp!
57
- debug { 'You confirmed your newly changed otp' }
58
- return Tron.success :otp_confirmed
59
- end
60
-
61
- debug { "The confirmation was correct but the update failed: #{@credential.errors.to_a.to_sentence}" }
62
- Tron.failure :correct_otp_confirmation_failed
63
- end
64
-
65
- def do_audit
66
- ::Booth::Audits::Register::ChangedOtp.call credential: @credential, ip: request.ip, agent: request.agent
67
- storage.secret_key_recently_changed!
68
-
69
- Tron.success :audit_created
70
- end
71
-
72
- def code_param
73
- params.require(:otp).permit(:otp_confirmation)[:otp_confirmation]
74
- end
75
-
76
- def storage
77
- request.storage.otp
78
- end
79
- end
80
- end
81
- end
82
- end
83
- end
84
- end
@@ -1,40 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
4
- module Transitions
5
- module Update
6
- class Register
7
- include ::Booth::Concerns::Transition
8
-
9
- def self.applicable?(params:)
10
- params&.key?(:register)
11
- end
12
-
13
- def call
14
- do_check_secret_key
15
- .on_success { do_register_otp }
16
- end
17
-
18
- private
19
-
20
- def do_check_secret_key
21
- return Tron.success :secret_key_exists if storage.secret_key.present?
22
-
23
- Tron.failure :missing_secret_key
24
- end
25
-
26
- def do_register_otp
27
- storage.secret_key_has_been_seen!
28
-
29
- Tron.success :otp_secret_registered
30
- end
31
-
32
- def storage
33
- request.storage.otp
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,31 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
4
- module Transitions
5
- module Update
6
- class Reset
7
- include ::Booth::Concerns::Transition
8
-
9
- def self.applicable?(params:)
10
- params.key?(:reset)
11
- end
12
-
13
- def call
14
- do_reset
15
- end
16
-
17
- private
18
-
19
- def do_reset
20
- storage.reset
21
- end
22
-
23
- def storage
24
- request.storage.otp
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,34 +0,0 @@
1
- module Booth
2
- module Userland
3
- module Otps
4
- class Update
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_patch!
9
- request.must_be_html!
10
- request.must_be_logged_in!
11
-
12
- ::Booth::Userland::Otps::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Otps::Guards::Sudo.call(request:, credential:) { return _1 }
14
-
15
- do_transition
16
- end
17
-
18
- private
19
-
20
- def transitions
21
- [
22
- ::Booth::Userland::Otps::Transitions::Update::Confirm,
23
- ::Booth::Userland::Otps::Transitions::Update::Register,
24
- ::Booth::Userland::Otps::Transitions::Update::Reset,
25
- ]
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,73 +0,0 @@
1
- module Booth
2
- module Userland
3
- module PasswordResets
4
- class Create
5
- include ::Booth::Concerns::Action
6
-
7
- def call
8
- request.must_be_post!
9
-
10
- do_check_logged_out
11
- .on_success { do_find_credential }
12
- .on_success { do_remember_email }
13
- .on_success { do_create_password_reset }
14
- end
15
-
16
- private
17
-
18
- delegate :username, to: :storage, private: true
19
-
20
- def do_check_logged_out
21
- unless request.authentication.logged_in?
22
- debug { "Good, nobody happens to be already logged in in scope #{request.scope}" }
23
- return Tron.success :not_logged_in
24
- end
25
-
26
- debug do
27
- "Logged in as user #{request.authentication.username.inspect} but trying to request password reset"
28
- end
29
- Tron.failure :logged_in_user_cannot_reset_password, public_message: I18n.t('booth.logged_in_user_cannot_reset_password')
30
- end
31
-
32
- def do_find_credential
33
- return Tron.success :known_credential if login_storage.credential_for_username
34
-
35
- Tron.failure :unknown_credential, public_message: I18n.t('booth.password_reset_needs_username')
36
- end
37
-
38
- def do_remember_email
39
- password_reset_storage.email = ::Booth::Syntaxes::Email.call(email_param).normalized_invalid_email
40
-
41
- Tron.success :remembered_email
42
- end
43
-
44
- def do_create_password_reset
45
- creation = ::Booth::PasswordResets::Create.call(
46
- credential: login_storage.credential_for_username,
47
- email: email_param,
48
- ip: request.ip,
49
- agent: request.agent
50
- )
51
-
52
- creation.on_success do
53
- password_reset_storage.email = nil
54
- end
55
-
56
- creation
57
- end
58
-
59
- def login_storage
60
- request.storage.login
61
- end
62
-
63
- def password_reset_storage
64
- request.storage.password_reset
65
- end
66
-
67
- def email_param
68
- params.require(:password_reset).permit(:email)[:email]
69
- end
70
- end
71
- end
72
- end
73
- end