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,22 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
5
+ # A WebAuthn Passkey.
3
6
  class Authenticator < ::Booth::Models::ApplicationRecord
4
- include ::Booth::Logging
5
-
6
7
  self.table_name = 'booth_authenticators'
7
8
 
8
- belongs_to :credential, class_name: '::Booth::Models::Credential'
9
+ belongs_to :credential
9
10
 
10
11
  validates :credential_id, uniqueness: { scope: :webauthn_id }
11
12
  validates :webauthn_id, presence: true, uniqueness: true
12
13
  validates :nickname, length: { minimum: 3, maximum: 40 }, allow_blank: true
14
+ validates :rp_id, presence: true
13
15
 
14
16
  before_validation :ensure_webauthn_id
15
- # before_validation :derive_registration_challenge
16
- # before_destroy :keep_at_least_one_authenticator
17
17
 
18
18
  scope :registered_scope, -> { where.not(confirmed_at: nil) }
19
- scope :supports_user_verification_scope, -> { where(supports_user_verification: true) }
20
19
  scope :sorted_scope, -> { order(:nickname) }
21
20
 
22
21
  def generate_webauth_id
@@ -28,13 +27,11 @@ module Booth
28
27
  end
29
28
 
30
29
  def step
31
- ::Booth::Authenticators::Step.call(self)
30
+ ::Booth::Core::Authenticators::Step.call(self)
32
31
  end
33
32
 
34
33
  private
35
34
 
36
- # delegate :recommended_user_verification, to: :credential
37
-
38
35
  def ensure_webauthn_id
39
36
  return if webauthn_id.present?
40
37
 
@@ -1,41 +1,38 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
5
+ # Essentially the username for logging in.
3
6
  class Credential < ::Booth::Models::ApplicationRecord
4
- include ::Booth::Models::Concerns::Modeable
5
- include ::Booth::Models::Concerns::Passwordable
6
- include ::Booth::Models::Concerns::Otpable
7
-
8
7
  self.table_name = 'booth_credentials'
9
8
 
10
- has_one :contest, dependent: :destroy
11
9
  has_one :onboarding, dependent: :destroy
10
+ has_one :remote, dependent: :destroy
12
11
 
13
12
  has_many :audits, dependent: :destroy
14
13
  has_many :authenticators, dependent: :destroy
15
- has_many :password_resets, dependent: :destroy
16
14
  has_many :sessions, dependent: :destroy
17
15
 
16
+ before_validation :normalize_domain
18
17
  before_validation :normalize_username
19
18
  before_validation :normalize_scope
20
- before_validation :stringify_allowed_modes
21
19
 
22
- validates :username, :scope, :allowed_modes, :mode, presence: true
23
- validates :username, uniqueness: { scope: :scope }
20
+ validates :domain, :scope, :username, presence: true
21
+ validates :username, uniqueness: true
24
22
 
25
- validates_each :allowed_modes do |record, attr, value|
26
- record.errors.add(attr, 'is invalid') unless value.all? { modes.keys.include?(_1) }
23
+ scope :sorted_scope, -> { order(:username) }
24
+
25
+ def blocked?
26
+ blocked_at.present?
27
27
  end
28
28
 
29
29
  def remote_session_available?
30
30
  sessions.active_scope.any?
31
31
  end
32
32
 
33
- def applicable_for_password_reset?
34
- mode_username_and_password? ||
35
- mode_username_password_and_otp? ||
36
- mode_username_password_and_webauth?
33
+ def registered_authenticators?
34
+ registered_authenticator_ids.any?
37
35
  end
38
- alias passworded? applicable_for_password_reset?
39
36
 
40
37
  def registered_authenticator_ids
41
38
  authenticators.registered_scope
@@ -45,16 +42,16 @@ module Booth
45
42
 
46
43
  private
47
44
 
48
- def normalize_username
49
- self.username = ::Booth::Syntaxes::Username.call(username).normalized_username
45
+ def normalize_domain
46
+ self.domain = ::Booth::Syntaxes::Domain.call(domain).valid_domain
50
47
  end
51
48
 
52
49
  def normalize_scope
53
50
  self.scope = ::Booth::Syntaxes::Scope.call(scope).normalized_scope
54
51
  end
55
52
 
56
- def stringify_allowed_modes
57
- self.allowed_modes = Array(allowed_modes).map(&:to_s)
53
+ def normalize_username
54
+ self.username = ::Booth::Syntaxes::Username.call(username).normalized_username
58
55
  end
59
56
  end
60
57
  end
@@ -1,60 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
5
+ # Log in via a special URL, forcing you to delete all your existing authenticators.
3
6
  class Onboarding < ::Booth::Models::ApplicationRecord
4
- include ::Booth::Logging
5
- include ::Booth::Models::Concerns::Modeable
6
- include ::Booth::Models::Concerns::Passwordable
7
- include ::Booth::Models::Concerns::Otpable
8
-
9
7
  self.table_name = 'booth_onboardings'
10
8
 
11
- belongs_to :credential, class_name: '::Booth::Models::Credential'
9
+ belongs_to :credential
12
10
 
13
11
  validates :credential_id, uniqueness: true
14
- validates :webauthn_id, presence: true
15
- validates :authenticator_nickname, length: { minimum: 3, maximum: 40 }, allow_blank: true
16
-
17
- before_validation :ensure_webauthn_id
18
12
 
19
13
  # See https://github.com/rails/rails/blob/main/activerecord/lib/active_record/secure_token.rb
20
14
  has_secure_token :secret_key, length: 30
21
- delegate :allowed_modes, :scope, :username, to: :credential
22
-
23
- attr_accessor :otp_confirmation
15
+ delegate :domain, :scope, :username, to: :credential
24
16
 
25
17
  scope :includes_scope, -> { includes(:credential) }
26
18
  scope :sorted_scope, -> { order(:created_at) }
27
19
 
28
- def step
29
- ::Booth::Onboardings::Step.call(self)
30
- end
31
-
32
- def lifetime
33
- ::Booth.config.onboarding_window
34
- end
35
-
36
- def completed?
37
- step == :completed
38
- end
39
-
40
- def authenticator?
41
- authenticator_public_key.present?
20
+ # Distinguish "first time onboarding" from high-stakes "I lost my authenticator".
21
+ def lifespan
22
+ if credential.authenticators.any?
23
+ 12.hours
24
+ else
25
+ 1.week
26
+ end
42
27
  end
43
28
 
44
- def propagated?
45
- propagated_at.present?
29
+ def consumed?
30
+ consumed_at.present?
46
31
  end
47
32
 
48
- def recently_created?
49
- created_at > lifetime.ago
50
- end
51
-
52
- private
53
-
54
- def ensure_webauthn_id
55
- return if webauthn_id.present?
56
-
57
- self.webauthn_id = ::WebAuthn.generate_user_id
33
+ def timed_out?
34
+ created_at < lifespan.ago
58
35
  end
59
36
  end
60
37
  end
@@ -1,21 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
3
- class Contest < ::Booth::Models::ApplicationRecord
4
- self.table_name = 'booth_contests'
5
+ # Login remotely by entering a code in the browser of an existing session.
6
+ class Remote < ::Booth::Models::ApplicationRecord
7
+ self.table_name = 'booth_remotes'
5
8
 
6
9
  belongs_to :credential
7
10
 
8
11
  before_validation :ensure_code
9
12
  before_validation :update_location
10
13
 
11
- validates :credential_id, :code, :ip, presence: true
12
14
  validates :credential_id, uniqueness: true
13
- validates :reason, presence: true, inclusion: %w[login support]
15
+ validates :code, :ip, presence: true
14
16
 
15
- scope :recently_created_scope, -> { ::Booth::Models::Contests::Scopes::RecentlyCreated.scope(self) }
16
- scope :recently_responded_scope, -> { ::Booth::Models::Contests::Scopes::RecentlyResponded.scope(self) }
17
+ scope :recently_created_scope, -> { ::Booth::Models::Remotes::Scopes::RecentlyCreated.scope(self) }
17
18
 
18
- delegate :browser_name, :platform_name, :browser_image_path, :platform_image_path, to: :user_agent
19
+ delegate :browser_name, :platform_name, :browser_image_path, :platform_image_path,
20
+ to: :user_agent
21
+ delegate :lifespan, to: :class
19
22
 
20
23
  def self.lifespan
21
24
  ::Booth.config.interaction_timeout
@@ -26,15 +29,11 @@ module Booth
26
29
  end
27
30
 
28
31
  def recently_created?
29
- ::Booth::Models::Contests::Scopes::RecentlyCreated.call(self)
32
+ ::Booth::Models::Remotes::Scopes::RecentlyCreated.call(self)
30
33
  end
31
34
 
32
35
  def recently_responded?
33
- ::Booth::Models::Contests::Scopes::RecentlyResponded.call(self)
34
- end
35
-
36
- def lifespan
37
- self.class.lifespan
36
+ ::Booth::Models::Remotes::Scopes::RecentlyResponded.call(self)
38
37
  end
39
38
 
40
39
  private
@@ -44,7 +43,7 @@ module Booth
44
43
  end
45
44
 
46
45
  def update_location
47
- self.location = ::Booth::Geolocation.lookup(ip)
46
+ self.location = ::Booth::Core::Geolocation.lookup(ip)
48
47
  end
49
48
 
50
49
  def user_agent
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Booth
4
+ module Models
5
+ module Remotes
6
+ module Scopes
7
+ # Determines if a Remote was created recently.
8
+ class RecentlyCreated
9
+ include Calls
10
+
11
+ param :remote
12
+
13
+ def self.scope(base)
14
+ base.where.not(created_at: nil)
15
+ .where('created_at > ?', ::Booth::Models::Remote.lifespan.ago)
16
+ end
17
+
18
+ def call
19
+ remote.created_at.present? &&
20
+ remote.created_at > ::Booth::Models::Remote.lifespan.ago
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Booth
4
+ module Models
5
+ module Remotes
6
+ module Scopes
7
+ class RecentlyResponded
8
+ include Calls
9
+
10
+ param :remote
11
+
12
+ def self.scope(base)
13
+ base.where.not(created_at: nil)
14
+ .where.not(responded_at: nil)
15
+ .where('created_at > ?', lifespan.ago)
16
+ .where('responded_at > ?', lifespan.ago)
17
+ end
18
+
19
+ def call
20
+ remote.created_at.present? &&
21
+ remote.responded_at.present? &&
22
+ remote.created_at > lifespan.ago &&
23
+ remote.responded_at > lifespan.ago
24
+ end
25
+
26
+ private
27
+
28
+ def lifespan
29
+ remote.class.lifespan
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,28 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
5
+ # Essentially the session Cookie in one Browser.
3
6
  class Session < ::Booth::Models::ApplicationRecord
4
7
  self.table_name = :booth_sessions
5
8
 
6
- def self.lifetime
7
- ::Booth.config.session_inactivity_lifetime
8
- end
9
-
10
- belongs_to :credential, class_name: '::Booth::Models::Credential'
9
+ belongs_to :credential
11
10
 
12
11
  before_create :ensure_activity_at
13
12
  before_create :denormalize_and_geolocate_ip
14
13
 
15
14
  # First of all it has to be not deleted, but also it must not be way too old.
16
- scope :active_scope, -> { where(revoked_at: nil).where('activity_at > ?', lifetime.ago) }
15
+ scope :active_scope, -> { where(revoked_at: nil).where('activity_at > ?', lifespan.ago) }
17
16
  scope :owned_by_scope, lambda { |credential_id:|
18
17
  active_scope.where('credential_id = ? OR incognito_credential_id = ?', credential_id, credential_id)
19
18
  }
19
+ scope :includes_scope, -> { includes(:credential) }
20
20
  scope :sorted_scope, -> { order(activity_at: :desc) }
21
21
 
22
- delegate :browser_name, :platform_name, :browser_image_path, :platform_image_path, to: :user_agent
22
+ delegate :browser_name, :platform_name, :browser_image_path, :platform_image_path,
23
+ to: :user_agent
24
+
25
+ def self.lifespan
26
+ ::Booth.config.session_inactivity_lifetime
27
+ end
23
28
 
24
29
  def historical_location_names
25
- ::Booth::Sessions::HistoricalLocations.call(self)
30
+ ::Booth::Core::Sessions::HistoricalLocations.call(self)
26
31
  end
27
32
 
28
33
  private
@@ -31,10 +36,10 @@ module Booth
31
36
  self.activity_at = Time.current
32
37
  end
33
38
 
34
- # These attributes are later updated via SQL.
39
+ # These attributes are later set via SQL.
35
40
  # This method here only sets the initial state.
36
41
  def denormalize_and_geolocate_ip
37
- self.location = ::Booth::Geolocation.lookup(most_recent_ip)
42
+ self.location = ::Booth::Core::Geolocation.lookup(most_recent_ip)
38
43
  self.historical_locations = { most_recent_ip => location }
39
44
  self.historical_ips = { most_recent_ip => Time.current.to_i }
40
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Models
3
5
  class UserAgent
data/lib/booth/request.rb CHANGED
@@ -1,30 +1,55 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
- # Convenience wrapper for `Rack::Request`.
4
+ # Convenience wrapper for Rack::Request.
3
5
  class Request
4
6
  include ::Booth::Logging
5
-
6
- # Can be used as a DRY::Initializer Coercer.
7
- # See https://dry-rb.org/gems/dry-initializer/master/type-constraints/#back-references
8
- def self.call(request, initializer)
9
- # `request` is an `ActionDispatch::Request` or a `Rack::Request`.
10
- # But if it already has been coerced, just return it immediately.
11
- # This makes it easier to pass the request from one MethodObject to another.
12
- return request if request.is_a?(self)
13
-
14
- # `initializer` is an instance that is trying to coerce one of its params into a `Booth::Request`.
15
- # By convention, that's where we assume the scope to be specified. So we take it from there.
16
- new(request:, scope: initializer.scope)
17
- end
18
-
7
+ # Initializes a new Booth::Request instance.
8
+ #
9
+ # **Parameters:**
10
+ #
11
+ # - `:request` - The request object (`ActionDispatch::Request`, `Rack::Request`, or
12
+ # +Booth::Request+).
13
+ #
14
+ # - `scope` - The controller scope identifier (Symbol).
19
15
  def initialize(request:, scope:)
20
- request = ActionDispatch::Request.new(request.env) if request.is_a?(Rack::Request)
16
+ # Sometimes we pass the request instance from one `Calls` object to another.
17
+ # In that case, unwrap the underlying request and take that as basis.
18
+ # if request.is_a?(::Booth::Request)
19
+ # return request if request.scope == scope
20
+ # #request = request.send(:request)
21
+ # end
22
+
23
+ # The underlying `request` is an `ActionDispatch::Request` or a `Rack::Request`.
24
+ # For consistency, we always convert to the more rich interface provided by Rails.
25
+ request = ActionDispatch::Request.new(request.env) if request.is_a?(::Rack::Request)
21
26
 
22
27
  @request = request
23
28
  @scope = ::Booth::Syntaxes::Scope.call(scope).normalized_scope
24
29
  end
25
30
 
31
+ # A Controller that logs the user in, needs to know in which scope to login to.
32
+ # The +scope+ is an authoritative way for the Rails developer to specify a dedicated area.
33
+ #
34
+ # For example:
35
+ #
36
+ # ```ruby
37
+ # Booth::Userland.new_login(scope: :admin, ...)
38
+ # Booth::Userland.new_login(scope: :guest, ...)
39
+ # ```
40
+ #
41
+ # The implementation could then check if a user is already logged in in that
42
+ # +scope+, while ignoring other scopes.
43
+ #
44
+ # For convenience, we store the authoritative controller +scope+ here, in the request wrapper.
26
45
  attr_reader :scope
27
46
 
47
+ delegate :port, to: :request
48
+
49
+ def host
50
+ ::Booth::Syntaxes::Domain.call(request.host).valid_domain
51
+ end
52
+
28
53
  def agent
29
54
  ::Booth::Requests::Agent.call(request:)
30
55
  end
@@ -34,7 +59,7 @@ module Booth
34
59
  end
35
60
 
36
61
  def location
37
- ::Booth::Geolocation.lookup(ip)
62
+ ::Booth::Core::Geolocation.lookup(ip)
38
63
  end
39
64
 
40
65
  def authentication
@@ -64,14 +89,10 @@ module Booth
64
89
  ::Booth::Requests::ReturnPath.call(params:)
65
90
  end
66
91
 
67
- # ------------
68
- # Requirements
69
- # ------------
70
-
71
92
  def must_be_logged_in!
72
93
  return if authentication.logged_in?
73
94
 
74
- debug { "Expected someone to be logged in in scope #{scope.inspect}" }
95
+ log { "Expected someone to be logged in in scope #{scope.inspect}" }
75
96
  raise ::Booth::Errors::NotAuthenticated
76
97
  end
77
98
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  class Agent
4
- include ::Booth::MethodObject
6
+ include Calls
5
7
 
6
8
  option :request
7
9
 
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  # Convenience wrapper for `Warden::Manager`.
4
6
  class Authentication
7
+ include ::Booth::Logging
8
+
5
9
  delegate :username, :credential_id, :mode,
6
10
  to: :passport,
7
11
  allow_nil: true
@@ -12,17 +16,23 @@ module Booth
12
16
  end
13
17
 
14
18
  def login(session:)
15
- # Whatever instance we pass in to Warden,
16
- # it needs to be that, which we also want do get out.
17
- # Because serialization only takes place for the *next* request.
19
+ log { "Persisting Session in Cookie for scope #{scope}" }
20
+ # Warden's serialization mechanism only takes place for the *next* request.
18
21
  # In the *same* request, whatever we pass in, is returned back as it is.
19
- warden.set_user ::Booth::Sessions::ToPassport.call(session), scope:
22
+ # That's why we don't pass in some ID here, but the entire Passport object
23
+ # (which is that what we normally would receive by Warden's deserialization).
24
+ warden.set_user ::Booth::Core::Sessions::ToPassport.call(session), scope:
20
25
  end
21
26
 
22
27
  def logged_in?
28
+ log { "Checking whether logged in in scope #{scope}" }
23
29
  warden.authenticated?(scope)
24
30
  end
25
31
 
32
+ def logged_out?
33
+ !logged_in?
34
+ end
35
+
26
36
  def logged_in_as?(credential:)
27
37
  logged_in? && credential.id == credential_id
28
38
  end
@@ -32,7 +42,7 @@ module Booth
32
42
  end
33
43
 
34
44
  def session_id
35
- passport&.id
45
+ passport&.session_id
36
46
  end
37
47
 
38
48
  private
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  class Ip
4
- include ::Booth::MethodObject
6
+ include Calls
5
7
 
6
8
  option :request
7
9
  option :raise_if_invalid, default: -> { true }
@@ -10,7 +12,7 @@ module Booth
10
12
  check = ::Booth::Syntaxes::Ip.call(raw_ip)
11
13
  check.on_success { return check.normalized_ip }
12
14
 
13
- raise ArgumentError "Invalid IP: #{raw_ip.inspect}" if raise_if_invalid
15
+ raise ArgumentError, "Invalid IP: #{raw_ip.inspect}" if raise_if_invalid
14
16
 
15
17
  check
16
18
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  class ReturnPath
4
- include ::Booth::MethodObject
6
+ include Calls
5
7
  include ::Booth::Logging
6
8
 
7
9
  option :params
@@ -20,7 +22,7 @@ module Booth
20
22
  # We always assume it is a full path and fix any missing beginning slash.
21
23
  result.starts_with?('/') ? result : result.prepend('/')
22
24
  rescue URI::InvalidURIError
23
- debug { "Invalid return path: #{raw_return_path.inspect}" } if raw_return_path
25
+ log { "Invalid return path: #{raw_return_path.inspect}" } if raw_return_path
24
26
  nil
25
27
  end
26
28
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  # Convenience wrapper for `ActionDispatch::Session::CookieStore`.
@@ -41,11 +43,11 @@ module Booth
41
43
  end
42
44
 
43
45
  def reset
44
- debug { "Resetting #{namespace.inspect} cookie data in scope #{scope.inspect}" }
46
+ log { "Resetting #{namespace.inspect} cookie data in scope #{scope.inspect}" }
45
47
 
46
48
  # There is no `#delete_if` in a `ActionDispatch::Request::Session`.
47
- keys_to_delete = session.keys.select { _1.to_s.start_with?(path(nil)) }
48
- keys_to_delete.each { session.delete(_1) }
49
+ keys_to_delete = session.keys.select { it.to_s.start_with?(path(nil)) }
50
+ keys_to_delete.each { session.delete(it) }
49
51
  end
50
52
 
51
53
  # -----
@@ -89,7 +91,7 @@ module Booth
89
91
  def reset_if_too_old!
90
92
  return if seconds_until_auto_reset.positive?
91
93
 
92
- debug do
94
+ log do
93
95
  "Timeout-resetting #{namespace.inspect} cookie data in scope #{scope.inspect} " \
94
96
  "because it is older than #{lifespan} seconds"
95
97
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Requests
3
5
  class Storage
@@ -10,53 +12,25 @@ module Booth
10
12
 
11
13
  def login
12
14
  @login ||= ::Booth::Requests::Storages::Login.new(
13
- session: request.session(namespace: :login)
14
- )
15
- end
16
-
17
- def otp
18
- @otp ||= ::Booth::Requests::Storages::Otp.new(
19
- session: request.session(namespace: :otp)
15
+ session: request.session(namespace: :login),
20
16
  )
21
17
  end
22
18
 
23
19
  def webauth
24
20
  @webauth ||= ::Booth::Requests::Storages::Webauth.new(
25
- session: request.session(namespace: :webauth)
26
- )
27
- end
28
-
29
- def password
30
- @password ||= ::Booth::Requests::Storages::Password.new(
31
- session: request.session(namespace: :password)
32
- )
33
- end
34
-
35
- def password_reset
36
- @password_reset ||= ::Booth::Requests::Storages::PasswordReset.new(
37
- session: request.session(namespace: :password_reset)
38
- )
39
- end
40
-
41
- def recovery
42
- @recovery ||= ::Booth::Requests::Storages::Recovery.new(
43
- session: request.session(namespace: :recovery)
21
+ session: request.session(namespace: :webauth),
44
22
  )
45
23
  end
46
24
 
47
25
  def registration
48
26
  @registration ||= ::Booth::Requests::Storages::Registration.new(
49
- session: request.session(namespace: :registration)
27
+ session: request.session(namespace: :registration),
50
28
  )
51
29
  end
52
30
 
53
31
  private
54
32
 
55
33
  attr_reader :scope, :request
56
-
57
- def session
58
- request.session(namespace: :sudo)
59
- end
60
34
  end
61
35
  end
62
36
  end