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,57 +0,0 @@
1
- module Booth
2
- module Syntaxes
3
- class Otp
4
- include ::Booth::Logging
5
- include ::Booth::MethodObject
6
-
7
- param :input
8
-
9
- def call
10
- check_blank.on_success { check_characters }
11
- .on_success { check_length }
12
- end
13
-
14
- private
15
-
16
- def check_blank
17
- return Tron.success :otp_present if input.present?
18
-
19
- debug { "OTP #{input.inspect} is blank." }
20
- Tron.failure :blank_otp,
21
- normalized_otp: nil,
22
- public_message: I18n.t('booth.blank_otp')
23
- end
24
-
25
- def check_characters
26
- return Tron.success :otp_consists_of_digits if input_without_spaces.match?(allowed_regexp)
27
-
28
- debug { "OTP #{input.inspect} contains invalid characters" }
29
- Tron.failure :invalid_otp_format,
30
- normalized_otp: nil,
31
- public_message: I18n.t('booth.invalid_otp_format')
32
- end
33
-
34
- def check_length
35
- if input_without_spaces.to_s.length == ::Booth.config.otp_digits
36
- return Tron.success :valid_otp_syntax,
37
- normalized_otp: input_without_spaces
38
- end
39
-
40
- debug { "OTP #{input.inspect} is not #{::Booth.config.otp_digits} characters long." }
41
- Tron.failure :wrong_otp_length,
42
- normalized_otp: nil,
43
- public_message: I18n.t('booth.wrong_otp_length', digits: ::Booth.config.otp_digits)
44
- end
45
-
46
- # Helpers
47
-
48
- def input_without_spaces
49
- input.to_s.delete(' ')
50
- end
51
-
52
- def allowed_regexp
53
- /\A\d+\z/
54
- end
55
- end
56
- end
57
- end
@@ -1,28 +0,0 @@
1
- module Booth
2
- module Syntaxes
3
- class ScopeComparison
4
- include ::Booth::Logging
5
- include ::Booth::MethodObject
6
-
7
- option :this, as: :raw_this
8
- option :that, as: :raw_that
9
-
10
- def call
11
- return Tron.success(:identical_scopes) if this == that
12
-
13
- debug { "The requested scope #{this.inspect} does not match what's on record #{that.inspect}" }
14
- Tron.failure :mismatching_scopes, this:, that:
15
- end
16
-
17
- private
18
-
19
- def this
20
- ::Booth::Syntaxes::Scope.call(raw_this).normalized_scope
21
- end
22
-
23
- def that
24
- ::Booth::Syntaxes::Scope.call(raw_that).normalized_scope
25
- end
26
- end
27
- end
28
- end
@@ -1,63 +0,0 @@
1
- require 'active_support/testing/time_helpers'
2
-
3
- require_relative 'support/assert_all_partials_were_covered'
4
- require_relative 'support/assert_logged_in'
5
- require_relative 'support/assert_logged_out'
6
- require_relative 'support/assert_partial'
7
- require_relative 'support/get_session_value'
8
- require_relative 'support/otp_code_from_session'
9
- require_relative 'support/soft_reset_session'
10
- require_relative 'webauthn/disable'
11
- require_relative 'webauthn/enable'
12
- require_relative 'webauthn/virtual_authenticators/create'
13
- require_relative 'webauthn/virtual_authenticators/destroy'
14
-
15
- module Booth
16
- module Test
17
- module Helpers
18
- extend ActiveSupport::Concern
19
-
20
- included do
21
- include ActiveSupport::Testing::TimeHelpers
22
- end
23
-
24
- def assert_logged_out
25
- ::Booth::Test::Support::AssertLoggedOut.call(page:, scope:)
26
- end
27
-
28
- def assert_logged_in(credential:)
29
- ::Booth::Test::Support::AssertLoggedIn.call(page:, scope:, credential:)
30
- end
31
-
32
- def assert_userland_partial(controller:, step:)
33
- ::Booth::Test::Support::AssertPartial.call(page:, namespace: :userland, controller:, step:)
34
- end
35
-
36
- def extract_otp_secret_key_and_generate_code
37
- secret_key = page.body.split('?secret=').last.split('&').first
38
- raise 'Expected an OTP secret but found none' if secret_key.blank?
39
-
40
- code = ::Booth::Models::Credential.new(otp_secret_key: secret_key).otp_code
41
- Booth.config.logger&.debug(to_s) { "Extracted OTP secret #{secret_key} and derived the code #{code}" }
42
- code
43
- end
44
-
45
- def soft_reset_session
46
- ::Booth::Test::Support::SoftResetSession.call(page:)
47
- end
48
-
49
- def setup_virtual_authenticator_environment
50
- # For some reason, the Chrome Virtual Authenticator Environment often leaks from one test to the next.
51
- # All kinds of errors in Webauth only cause one single generic `NotAllowedError` for privacy reasons
52
- # So it's impossible to debug the actual cause. I just found out after many hours that disabling first, works.
53
- ::Booth::Test::Webauthn::Disable.call devtools: page.driver.browser.devtools
54
- ::Booth::Test::Webauthn::Enable.call devtools: page.driver.browser.devtools
55
- end
56
-
57
- def create_virtual_authenticator(has_user_verification: true)
58
- setup_virtual_authenticator_environment
59
- ::Booth::Test::Webauthn::VirtualAuthenticators::Create.call(page:, has_user_verification:)
60
- end
61
- end
62
- end
63
- end
@@ -1,63 +0,0 @@
1
- module Booth
2
- module Test
3
- module Support
4
- class AssertAllPartialsWereCovered
5
- include ::Booth::MethodObject
6
-
7
- def call
8
- return if missing_partials.empty?
9
-
10
- raise "Expected these partials to be covered: #{missing_partials}"
11
- end
12
-
13
- private
14
-
15
- def missing_partials
16
- (expected_partials - covered_partials)
17
- end
18
-
19
- def expected_partials # rubocop:disable Metrics/MethodLength
20
- %w[
21
- userland/login/enter_otp
22
- userland/login/enter_password
23
- userland/login/enter_username
24
- userland/login/enter_webauth
25
- userland/login/needs_onboarding
26
- userland/login/no_authenticators
27
- userland/login/remote_session_available
28
- userland/onboarding/already_logged_in
29
- userland/onboarding/choose_password
30
- userland/onboarding/choose_webauth_nickname
31
- userland/onboarding/completed
32
- userland/onboarding/confirm_otp
33
- userland/onboarding/confirm_password
34
- userland/onboarding/confirm_webauth
35
- userland/onboarding/register_otp
36
- userland/onboarding/register_webauth
37
- userland/onboarding/timed_out
38
- userland/otp/add
39
- userland/otp/confirm
40
- userland/otp/register
41
- userland/otp/show
42
- userland/otp/successfully_changed
43
- userland/otp/sudo
44
- userland/password_reset/check_your_mail
45
- userland/password_reset/choose_password
46
- userland/password_reset/completed
47
- userland/password_reset/confirm_password
48
- userland/password_reset/logout_first
49
- userland/password_reset/new
50
- userland/password_reset/revoked
51
- userland/password_reset/throttled
52
- userland/password_reset/timed_out
53
- userland/password_reset/wrong_user_logged_in
54
- ]
55
- end
56
-
57
- def covered_partials
58
- Booth::Test::Support::AssertPartial.asserted_partials.to_a
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,49 +0,0 @@
1
- module Booth
2
- module Test
3
- module Support
4
- class AssertLoggedIn
5
- class AssertionFailedError < StandardError; end
6
-
7
- include ::Booth::MethodObject
8
- include ::Booth::Logging
9
-
10
- option :page
11
- option :scope
12
- option :credential
13
-
14
- def call
15
- tries ||= 0
16
- ::Capybara::Lockstep.synchronize
17
-
18
- active_sessions.each do |session|
19
- browser_session_id = ::Booth::Test::Support::GetSessionValue.call(page:, key:)
20
- return true if browser_session_id == session.id.to_s
21
- end
22
-
23
- raise AssertionFailedError, "Expected Credential `#{credential.id}` to be logged in with a session of: #{active_sessions.map(&:id)}"
24
-
25
- # With the Webauth pingpong it sometimes takes a little longer.
26
- # And Capybara Lockstep doesn't seem to be able to detect that.
27
- rescue AssertionFailedError
28
- if (tries += 1) < 3
29
- debug { 'Trying again...' }
30
- sleep 1
31
- retry
32
- end
33
-
34
- raise
35
- end
36
-
37
- private
38
-
39
- def active_sessions
40
- credential.sessions.active_scope.sorted_scope
41
- end
42
-
43
- def key
44
- "warden.user.#{scope}.key"
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,29 +0,0 @@
1
- module Booth
2
- module Test
3
- module Support
4
- class AssertPartial
5
- include ::Booth::MethodObject
6
-
7
- cattr_accessor :asserted_partials, instance_accessor: false, default: Set.new
8
-
9
- option :page
10
- option :namespace
11
- option :controller
12
- option :step
13
-
14
- def call
15
- ::Capybara::Lockstep.synchronize
16
-
17
- page.find "[data-booth='#{partial}']", visible: :all
18
-
19
- self.class.asserted_partials << partial
20
- nil
21
- end
22
-
23
- def partial
24
- "#{namespace}/#{controller}/#{step}"
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,30 +0,0 @@
1
- module Booth
2
- module Test
3
- module Support
4
- class OtpCodeFromSession
5
- include ::Booth::MethodObject
6
-
7
- option :page
8
- option :scope
9
-
10
- def call
11
- secret_key = load_secret_key
12
- raise 'No OTP secret key found in session' if secret_key.blank?
13
-
14
- dummy = ::Booth::Models::Credential.new otp_secret_key: secret_key
15
- dummy.otp_code
16
- end
17
-
18
- private
19
-
20
- def load_secret_key
21
- ::Booth::Test::Support::GetSessionValue.call(page:, key:)
22
- end
23
-
24
- def key
25
- "booth.#{scope}.otp.secret_key"
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,22 +0,0 @@
1
- module Booth
2
- module Test
3
- module Support
4
- # Essentially resets the session cookie, but without removing
5
- # Chrome's Virtual Authenticator Enviroment.
6
- class SoftResetSession
7
- include ::Booth::MethodObject
8
-
9
- option :page
10
-
11
- def call
12
- ::Capybara::Lockstep.synchronize
13
-
14
- keys = page.get_rack_session.keys
15
- nilified_keys = keys.index_with { nil }
16
-
17
- page.set_rack_session(**nilified_keys)
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,72 +0,0 @@
1
- module Booth
2
- module Test
3
- module Userland
4
- module Logins
5
- class MissingAuthenticators
6
- include ::Booth::MethodObject
7
- include ::Booth::Test::Helpers
8
-
9
- option :page
10
- option :scope
11
- option :show_onboarding_path
12
- option :new_login_path
13
-
14
- def call
15
- credential = ::Booth::Models::Credential.create!(
16
- username: 'alice',
17
- password: 'qwrasfyxv',
18
- scope:,
19
- mode: :username_and_webauth,
20
- allowed_modes: [:username_and_webauth]
21
- )
22
-
23
- onboarding = ::Booth::Models::Onboarding.create!(
24
- credential_id: credential.id,
25
- mode: :username_and_webauth
26
- )
27
-
28
- page.visit show_onboarding_path.sub('ID', onboarding.secret_key)
29
-
30
- create_virtual_authenticator
31
-
32
- assert_userland_partial controller: :onboarding, step: :register_webauth
33
-
34
- page.click_on :register
35
-
36
- assert_userland_partial controller: :onboarding, step: :choose_webauth_nickname
37
-
38
- page.fill_in :nickname, with: 'Yubikey'
39
- page.click_on :submit
40
-
41
- assert_userland_partial controller: :onboarding, step: :confirm_webauth
42
-
43
- page.click_on :authenticate
44
-
45
- assert_userland_partial controller: :onboarding, step: :completed
46
- assert_logged_in credential: credential
47
-
48
- soft_reset_session
49
- assert_logged_out
50
-
51
- credential.authenticators.delete_all
52
-
53
- # Login
54
-
55
- page.visit new_login_path
56
-
57
- assert_userland_partial controller: :login, step: :enter_username
58
-
59
- page.fill_in :username, with: 'alice'
60
- page.click_on :submit
61
-
62
- assert_userland_partial controller: :login, step: :remote_session_available
63
-
64
- page.click_on :skip
65
-
66
- assert_userland_partial controller: :login, step: :no_authenticators
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,35 +0,0 @@
1
- module Booth
2
- module Test
3
- module Userland
4
- module Logins
5
- class MissingOnboarding
6
- include ::Booth::MethodObject
7
- include ::Booth::Test::Helpers
8
-
9
- option :page
10
- option :scope
11
- option :new_login_path
12
-
13
- def call
14
- ::Booth::Models::Credential.create!(
15
- username: 'alice',
16
- password: 'qwrasfyxv',
17
- scope:,
18
- mode: :first_time,
19
- allowed_modes: [:username_and_password]
20
- )
21
-
22
- page.visit new_login_path
23
-
24
- assert_userland_partial controller: :login, step: :enter_username
25
-
26
- page.fill_in :username, with: 'alice'
27
- page.click_on :submit
28
-
29
- assert_userland_partial controller: :login, step: :needs_onboarding
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,40 +0,0 @@
1
- module Booth
2
- module Test
3
- module Userland
4
- module Logins
5
- class UsernameAndPassword
6
- include ::Booth::MethodObject
7
- include ::Booth::Test::Helpers
8
-
9
- option :page
10
- option :scope
11
- option :new_login_path
12
-
13
- def call
14
- credential = ::Booth::Models::Credential.create!(
15
- username: 'alice',
16
- password: 'qwrasfyxv',
17
- scope:,
18
- mode: :username_and_password,
19
- allowed_modes: [:username_and_password]
20
- )
21
-
22
- page.visit new_login_path
23
-
24
- assert_userland_partial controller: :login, step: :enter_username
25
-
26
- page.fill_in :username, with: 'alice'
27
- page.click_on :submit
28
-
29
- assert_userland_partial controller: :login, step: :enter_password
30
-
31
- page.fill_in :password, with: 'qwrasfyxv'
32
- page.click_on :submit
33
-
34
- assert_logged_in credential:
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,75 +0,0 @@
1
- module Booth
2
- module Test
3
- module Userland
4
- module Logins
5
- class UsernameAndWebauth
6
- include ::Booth::MethodObject
7
- include ::Booth::Test::Helpers
8
-
9
- option :page
10
- option :scope
11
- option :show_onboarding_path
12
- option :new_login_path
13
- option :after_credential, default: -> {}
14
-
15
- def call
16
- credential = ::Booth::Models::Credential.create!(
17
- username: 'alice',
18
- password: 'qwrasfyxv',
19
- scope:,
20
- mode: :username_and_webauth,
21
- allowed_modes: [:username_and_webauth]
22
- )
23
- after_credential&.call(credential.id)
24
-
25
- onboarding = ::Booth::Models::Onboarding.create!(
26
- credential_id: credential.id,
27
- mode: :username_and_webauth
28
- )
29
-
30
- page.visit show_onboarding_path.sub('ID', onboarding.secret_key)
31
- create_virtual_authenticator
32
-
33
- assert_userland_partial controller: :onboarding, step: :register_webauth
34
-
35
- page.click_on :register
36
-
37
- assert_userland_partial controller: :onboarding, step: :choose_webauth_nickname
38
-
39
- page.fill_in :nickname, with: 'Yubikey'
40
- page.click_on :submit
41
-
42
- assert_userland_partial controller: :onboarding, step: :confirm_webauth
43
-
44
- page.click_on :authenticate
45
-
46
- assert_userland_partial controller: :onboarding, step: :completed
47
- assert_logged_in credential: credential
48
-
49
- soft_reset_session
50
- assert_logged_out
51
-
52
- # Login
53
-
54
- page.visit new_login_path
55
-
56
- assert_userland_partial controller: :login, step: :enter_username
57
-
58
- page.fill_in :username, with: 'alice'
59
- page.click_on :submit
60
-
61
- assert_userland_partial controller: :login, step: :remote_session_available
62
-
63
- page.click_on :skip
64
-
65
- assert_userland_partial controller: :login, step: :enter_webauth
66
-
67
- page.click_on :authenticate
68
-
69
- assert_logged_in credential:
70
- end
71
- end
72
- end
73
- end
74
- end
75
- end
@@ -1,45 +0,0 @@
1
- module Booth
2
- module Test
3
- module Userland
4
- module Logins
5
- class UsernamePasswordAndOtp
6
- include ::Booth::MethodObject
7
- include ::Booth::Test::Helpers
8
-
9
- option :page
10
- option :scope
11
- option :new_login_path
12
-
13
- def call
14
- credential = ::Booth::Models::Credential.create!(
15
- username: 'alice',
16
- password: 'qwrasfyxv',
17
- scope:,
18
- mode: :username_password_and_otp,
19
- allowed_modes: [:username_password_and_otp]
20
- )
21
-
22
- page.visit new_login_path
23
-
24
- assert_userland_partial controller: :login, step: :enter_username
25
-
26
- page.fill_in :username, with: 'alice'
27
- page.click_on :submit
28
-
29
- assert_userland_partial controller: :login, step: :enter_password
30
-
31
- page.fill_in :password, with: 'qwrasfyxv'
32
- page.click_on :submit
33
-
34
- assert_userland_partial controller: :login, step: :enter_otp
35
-
36
- page.fill_in :code, with: credential.otp_code
37
- page.click_on :submit
38
-
39
- assert_logged_in credential:
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end