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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE.md +1 -2
- data/README.md +37 -6
- data/app/assets/images/booth/browsers/README.md +1 -2
- data/app/assets/images/booth/browsers/chrome.svg +1 -1
- data/app/assets/images/booth/browsers/edge.svg +1 -1
- data/app/assets/images/booth/browsers/firefox.svg +1 -1
- data/app/assets/images/booth/browsers/opera.svg +1 -1
- data/app/assets/images/booth/browsers/safari.svg +1 -1
- data/app/assets/images/booth/fido/passkey_mark_a.svg +10 -0
- data/app/assets/images/booth/fido/passkey_mark_a_black.svg +32 -0
- data/app/assets/images/booth/fido/passkey_mark_a_reverse.svg +33 -0
- data/app/assets/images/booth/fido/passkey_mark_a_white.svg +32 -0
- data/app/assets/images/booth/fido/passkey_mark_b_black.svg +1 -0
- data/app/assets/images/booth/platforms/android.svg +1 -6
- data/app/assets/images/booth/platforms/apple.svg +1 -6
- data/app/assets/images/booth/platforms/linux.svg +1 -6
- data/app/assets/images/booth/platforms/windows.svg +1 -6
- data/app/assets/javascripts/booth/authentication.js +29 -0
- data/app/assets/javascripts/booth/authentication.js.map +1 -0
- data/app/assets/javascripts/booth/error.js +38 -0
- data/app/assets/javascripts/booth/error.js.map +1 -0
- data/app/assets/javascripts/booth/form.js +78 -0
- data/app/assets/javascripts/booth/form.js.map +1 -0
- data/app/assets/javascripts/booth/gui.js +53 -0
- data/app/assets/javascripts/booth/gui.js.map +1 -0
- data/app/assets/javascripts/booth/registration.js +29 -0
- data/app/assets/javascripts/booth/registration.js.map +1 -0
- data/app/assets/javascripts/booth/setup.js +14 -0
- data/app/assets/javascripts/booth/verification.js +49 -0
- data/app/assets/javascripts/booth/verification.js.map +1 -0
- data/app/assets/javascripts/declarations/authentication.d.ts +6 -0
- data/app/assets/javascripts/declarations/error.d.ts +36 -0
- data/app/assets/javascripts/declarations/form.d.ts +8 -0
- data/app/assets/javascripts/declarations/gui.d.ts +4 -0
- data/app/assets/javascripts/declarations/registration.d.ts +6 -0
- data/app/assets/javascripts/declarations/setup.d.ts +3 -0
- data/app/assets/javascripts/declarations/verification.d.ts +6 -0
- data/app/assets/javascripts/src/authentication.ts +41 -0
- data/app/assets/javascripts/src/error.ts +35 -0
- data/app/assets/javascripts/src/form.ts +90 -0
- data/app/assets/javascripts/src/gui.ts +59 -0
- data/app/assets/javascripts/src/registration.ts +44 -0
- data/app/assets/javascripts/src/verification.ts +61 -0
- data/app/assets/stylesheets/booth/booth.css +3 -0
- data/config/importmap.rb +11 -0
- data/config/locales/de.yml +14 -38
- data/config/locales/en.yml +17 -36
- data/data/combined_aaguid.json +1 -0
- data/lib/booth/adminland/credentials/create.rb +10 -12
- data/lib/booth/adminland/credentials/index.rb +31 -0
- data/lib/booth/adminland/onboardings/create.rb +24 -15
- data/lib/booth/adminland/onboardings/destroy.rb +8 -4
- data/lib/booth/adminland/onboardings/find.rb +52 -45
- data/lib/booth/adminland/onboardings/find_unconsumed.rb +61 -0
- data/lib/booth/adminland/onboardings/index.rb +6 -3
- data/lib/booth/adminland/periodic_cleanup.rb +7 -2
- data/lib/booth/adminland.rb +17 -18
- data/lib/booth/coercers/domain.rb +11 -0
- data/lib/booth/coercers/request.rb +51 -0
- data/lib/booth/coercers/scope.rb +11 -0
- data/lib/booth/comparisons/domain.rb +38 -0
- data/lib/booth/comparisons/scope.rb +38 -0
- data/lib/booth/concerns/action.rb +25 -13
- data/lib/booth/concerns/transition.rb +5 -2
- data/lib/booth/configuration.rb +14 -73
- data/lib/booth/configure.rb +3 -10
- data/lib/booth/{audits/register → core/audit}/completed_onboarding.rb +8 -6
- data/lib/booth/core/audit/credential_created.rb +24 -0
- data/lib/booth/core/audit/logout.rb +24 -0
- data/lib/booth/core/authenticators/confirm.rb +30 -0
- data/lib/booth/core/authenticators/step.rb +24 -0
- data/lib/booth/core/cooldowns/distance_of_time.rb +50 -0
- data/lib/booth/core/cooldowns/strategies/exponential.rb +88 -0
- data/lib/booth/core/cooldowns/strategies/global.rb +66 -0
- data/lib/booth/core/cooldowns/strategies/result.rb +27 -0
- data/lib/booth/core/credentials/create.rb +32 -0
- data/lib/booth/core/credentials/find_by_username.rb +63 -0
- data/lib/booth/core/credentials/index.rb +15 -0
- data/lib/booth/core/credentials/webauth_challenge.rb +37 -0
- data/lib/booth/core/geolocation.rb +25 -0
- data/lib/booth/core/onboardings/find.rb +92 -0
- data/lib/booth/core/onboardings/step.rb +19 -0
- data/lib/booth/core/remotes/get.rb +45 -0
- data/lib/booth/core/remotes/respond.rb +82 -0
- data/lib/booth/core/remotes/set_for_login.rb +31 -0
- data/lib/booth/core/sessions/create_and_login.rb +63 -0
- data/lib/booth/core/sessions/historical_locations.rb +22 -0
- data/lib/booth/core/sessions/index.rb +66 -0
- data/lib/booth/core/sessions/revoke.rb +59 -0
- data/lib/booth/core/sessions/revoke_all_others.rb +49 -0
- data/lib/booth/core/sessions/to_passport.rb +35 -0
- data/lib/booth/core/webauth/authentication_verification.rb +76 -0
- data/lib/booth/core/webauth/options_for_create.rb +56 -0
- data/lib/booth/core/webauth/options_for_get.rb +30 -0
- data/lib/booth/core/webauth/provider.rb +36 -0
- data/lib/booth/core/webauth/registration_verification.rb +100 -0
- data/lib/booth/credential.rb +35 -0
- data/lib/booth/engine.rb +15 -4
- data/lib/booth/errors.rb +2 -0
- data/lib/booth/hooks/after_fetch.rb +14 -6
- data/lib/booth/hooks/before_logout.rb +5 -3
- data/lib/booth/hooks/serialize_from_session.rb +13 -5
- data/lib/booth/hooks/serialize_into_session.rb +6 -3
- data/lib/booth/logging.rb +13 -42
- data/lib/booth/models/application_record.rb +3 -0
- data/lib/booth/models/audit.rb +10 -11
- data/lib/booth/models/authenticator.rb +6 -9
- data/lib/booth/models/credential.rb +17 -20
- data/lib/booth/models/onboarding.rb +16 -39
- data/lib/booth/models/{contest.rb → remote.rb} +13 -14
- data/lib/booth/models/remotes/scopes/recently_created.rb +26 -0
- data/lib/booth/models/remotes/scopes/recently_responded.rb +35 -0
- data/lib/booth/models/session.rb +15 -10
- data/lib/booth/models/user_agent.rb +2 -0
- data/lib/booth/request.rb +43 -22
- data/lib/booth/requests/agent.rb +3 -1
- data/lib/booth/requests/authentication.rb +15 -5
- data/lib/booth/requests/ip.rb +4 -2
- data/lib/booth/requests/return_path.rb +4 -2
- data/lib/booth/requests/session.rb +6 -4
- data/lib/booth/requests/storage.rb +5 -31
- data/lib/booth/requests/storages/login.rb +35 -29
- data/lib/booth/requests/storages/registration.rb +2 -0
- data/lib/booth/requests/storages/webauth.rb +3 -0
- data/lib/booth/requests/sudo.rb +6 -50
- data/lib/booth/routes/userland.rb +13 -59
- data/lib/booth/syntaxes/domain.rb +46 -0
- data/lib/booth/syntaxes/email.rb +11 -8
- data/lib/booth/syntaxes/ip.rb +6 -4
- data/lib/booth/syntaxes/remote_code.rb +60 -0
- data/lib/booth/syntaxes/scope.rb +7 -3
- data/lib/booth/syntaxes/secret_key.rb +8 -6
- data/lib/booth/syntaxes/username.rb +23 -10
- data/lib/booth/syntaxes/uuid.rb +3 -1
- data/lib/booth/test.rb +27 -22
- data/lib/booth/testing/incorporation_test_case.rb +29 -0
- data/lib/booth/testing/shortcuts.rb +77 -0
- data/lib/booth/testing/support/assert_all_partials_were_covered.rb +69 -0
- data/lib/booth/testing/support/assert_logged_in.rb +68 -0
- data/lib/booth/{test → testing}/support/assert_logged_out.rb +7 -4
- data/lib/booth/testing/support/assert_partial.rb +56 -0
- data/lib/booth/{test → testing}/support/force_login.rb +10 -4
- data/lib/booth/{test → testing}/support/get_session_value.rb +8 -6
- data/lib/booth/testing/support/scenario.rb +23 -0
- data/lib/booth/testing/support/shortcuts/create_and_onboard.rb +56 -0
- data/lib/booth/testing/support/shortcuts/login_with_passkey.rb +55 -0
- data/lib/booth/testing/support/shortcuts/register_new_passkey.rb +51 -0
- data/lib/booth/testing/support/soft_reset_session.rb +24 -0
- data/lib/booth/testing/support/virtual_authenticators/create.rb +34 -0
- data/lib/booth/testing/support/virtual_authenticators/destroy.rb +20 -0
- data/lib/booth/testing/support/virtual_authenticators/enable.rb +24 -0
- data/lib/booth/testing/support/virtual_authenticators/load.rb +38 -0
- data/lib/booth/testing/support/virtual_authenticators/manager.rb +124 -0
- data/lib/booth/testing/support/visit.rb +62 -0
- data/lib/booth/testing/userland/login_remotely.rb +100 -0
- data/lib/booth/testing/userland/onboarding_first_time.rb +81 -0
- data/lib/booth/testing/userland/onboarding_to_reset_passkeys.rb +129 -0
- data/lib/booth/testing/userland/registration_with_passkey.rb +93 -0
- data/lib/booth/testing/userland/registration_without_passkey.rb +101 -0
- data/lib/booth/testing/userland/sessions_manage_behavior.rb +68 -0
- data/lib/booth/testing/userland/sessions_revoke_all_others.rb +17 -0
- data/lib/booth/testing/userland/sessions_revoke_one.rb +17 -0
- data/lib/booth/testing/userland.rb +36 -0
- data/lib/booth/to_struct.rb +9 -2
- data/lib/booth/userland/extract_flash_messages.rb +10 -3
- data/lib/booth/userland/logins/create.rb +8 -6
- data/lib/booth/userland/logins/destroy.rb +23 -6
- data/lib/booth/userland/logins/new.rb +23 -25
- data/lib/booth/userland/logins/transitions/create/choose_username.rb +62 -27
- data/lib/booth/userland/logins/transitions/create/skip_remotes.rb +18 -14
- data/lib/booth/userland/logins/transitions/create/webauth_authentication_initiation.rb +54 -48
- data/lib/booth/userland/logins/transitions/create/webauth_authentication_verification.rb +62 -58
- data/lib/booth/userland/logins/transitions/new/already_logged_in.rb +4 -3
- data/lib/booth/userland/logins/transitions/new/fallible.rb +4 -0
- data/lib/booth/userland/logins/transitions/new/{mode_username_and_password.rb → missing_authenticators.rb} +5 -4
- data/lib/booth/userland/logins/transitions/new/mode_username_and_webauth.rb +6 -4
- data/lib/booth/userland/logins/transitions/new/no_username_chosen.rb +3 -1
- data/lib/booth/userland/logins/transitions/new/remote_session_available.rb +20 -13
- data/lib/booth/userland/logins/transitions/new/timed_out.rb +3 -1
- data/lib/booth/userland/onboardings/show.rb +65 -39
- data/lib/booth/userland/onboardings/update.rb +46 -38
- data/lib/booth/userland/registrations/create.rb +51 -20
- data/lib/booth/userland/registrations/new.rb +6 -7
- data/lib/booth/userland/remotes/show.rb +56 -0
- data/lib/booth/userland/{personal_contests → remotes}/update.rb +5 -3
- data/lib/booth/userland/sessions/destroy_one_or_other.rb +3 -16
- data/lib/booth/userland/sessions/index.rb +4 -2
- data/lib/booth/userland/sessions/show.rb +5 -6
- data/lib/booth/userland/sessions/transitions/destroy/enter_webauth.rb +8 -6
- data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_initiation.rb +8 -6
- data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_verification.rb +7 -5
- data/lib/booth/userland/sessions/transitions/show/enter_webauth.rb +8 -6
- data/lib/booth/userland/webauths/create.rb +20 -17
- data/lib/booth/userland/webauths/destroy.rb +6 -16
- data/lib/booth/userland/webauths/guards/sudo.rb +10 -5
- data/lib/booth/userland/webauths/index.rb +4 -2
- data/lib/booth/userland/webauths/new.rb +7 -22
- data/lib/booth/userland/webauths/sudo.rb +3 -1
- data/lib/booth/userland/webauths/transitions/create/authentication_initiation.rb +8 -11
- data/lib/booth/userland/webauths/transitions/create/authentication_verification.rb +11 -13
- data/lib/booth/userland/webauths/transitions/create/choose_nickname.rb +8 -5
- data/lib/booth/userland/webauths/transitions/create/registration_initiation.rb +15 -14
- data/lib/booth/userland/webauths/transitions/create/registration_verification.rb +34 -28
- data/lib/booth/userland/webauths/transitions/create/reset.rb +2 -0
- data/lib/booth/userland/webauths/transitions/new/step.rb +3 -1
- data/lib/booth/userland/webauths/transitions/sudo/authentication_initiation.rb +5 -10
- data/lib/booth/userland/webauths/transitions/sudo/authentication_verification.rb +4 -2
- data/lib/booth/userland.rb +53 -109
- data/lib/booth/version.rb +3 -1
- data/lib/booth.rb +6 -236
- data/lib/generators/booth/migration/migration_generator.rb +2 -1
- data/lib/generators/booth/migration/templates/add_credential_to_users.erb +6 -4
- data/lib/generators/booth/migration/templates/create_booth_tables.erb +61 -72
- metadata +124 -571
- data/app/assets/config/booth_manifest.js +0 -15
- data/app/assets/images/booth/browsers/internet_explorer.svg +0 -1
- data/app/assets/javascripts/booth/all.js +0 -162
- data/app/assets/javascripts/booth/all.js.map +0 -1
- data/app/assets/javascripts/booth/booth.ts +0 -194
- data/app/assets/javascripts/booth/webauthn-json.ts +0 -99
- data/lib/booth/adminland/recoveries/consume.rb +0 -70
- data/lib/booth/audits/register/added_otp.rb +0 -22
- data/lib/booth/audits/register/changed_otp.rb +0 -22
- data/lib/booth/audits/register/correct_otp.rb +0 -42
- data/lib/booth/audits/register/correct_password.rb +0 -43
- data/lib/booth/audits/register/logout.rb +0 -22
- data/lib/booth/audits/register/requested_password_reset.rb +0 -22
- data/lib/booth/audits/register/wrong_otp.rb +0 -22
- data/lib/booth/audits/register/wrong_password.rb +0 -25
- data/lib/booth/authenticators/confirm.rb +0 -34
- data/lib/booth/authenticators/credential_mode_after_confirmation.rb +0 -25
- data/lib/booth/authenticators/step.rb +0 -19
- data/lib/booth/contests/get.rb +0 -36
- data/lib/booth/contests/respond.rb +0 -78
- data/lib/booth/contests/set_for_login.rb +0 -28
- data/lib/booth/cooldowns/distance_of_time.rb +0 -46
- data/lib/booth/cooldowns/otp.rb +0 -22
- data/lib/booth/cooldowns/password.rb +0 -44
- data/lib/booth/cooldowns/password_reset.rb +0 -24
- data/lib/booth/cooldowns/strategies/exponential.rb +0 -82
- data/lib/booth/cooldowns/strategies/global.rb +0 -62
- data/lib/booth/cooldowns/strategies/result.rb +0 -22
- data/lib/booth/credentials/create.rb +0 -28
- data/lib/booth/credentials/create_with_onboarding.rb +0 -26
- data/lib/booth/credentials/find_by_username.rb +0 -45
- data/lib/booth/credentials/mode.rb +0 -69
- data/lib/booth/credentials/modes/otp_addable.rb +0 -23
- data/lib/booth/credentials/modes/otp_changeable.rb +0 -23
- data/lib/booth/credentials/modes/otp_manageable.rb +0 -17
- data/lib/booth/credentials/modes/otp_removable.rb +0 -23
- data/lib/booth/credentials/modes/password_addable.rb +0 -29
- data/lib/booth/credentials/modes/password_changeable.rb +0 -31
- data/lib/booth/credentials/modes/password_manageable.rb +0 -17
- data/lib/booth/credentials/modes/password_removable.rb +0 -24
- data/lib/booth/credentials/modes/password_removal_requires_user_verifiable_webauth.rb +0 -16
- data/lib/booth/credentials/modes/webauth_addable.rb +0 -26
- data/lib/booth/credentials/modes/webauth_manageable.rb +0 -16
- data/lib/booth/credentials/modes/webauth_removable.rb +0 -25
- data/lib/booth/credentials/otp_authentication.rb +0 -59
- data/lib/booth/credentials/password_authentication.rb +0 -72
- data/lib/booth/credentials/webauth_challenge.rb +0 -28
- data/lib/booth/geolocation.rb +0 -20
- data/lib/booth/logger.rb +0 -41
- data/lib/booth/method_object.rb +0 -73
- data/lib/booth/mode.rb +0 -22
- data/lib/booth/models/concerns/modeable.rb +0 -50
- data/lib/booth/models/concerns/otpable.rb +0 -37
- data/lib/booth/models/concerns/passwordable.rb +0 -58
- data/lib/booth/models/contests/scopes/recently_created.rb +0 -23
- data/lib/booth/models/contests/scopes/recently_responded.rb +0 -32
- data/lib/booth/models/password_reset.rb +0 -41
- data/lib/booth/models/recovery.rb +0 -32
- data/lib/booth/models/registration.rb +0 -10
- data/lib/booth/modes/base.rb +0 -25
- data/lib/booth/modes/username_and_password.rb +0 -7
- data/lib/booth/modes/username_and_webauth.rb +0 -7
- data/lib/booth/modes/username_password_and_otp.rb +0 -7
- data/lib/booth/modes/username_password_and_webauth.rb +0 -7
- data/lib/booth/onboardings/find.rb +0 -35
- data/lib/booth/onboardings/propagate_to_credential.rb +0 -63
- data/lib/booth/onboardings/step.rb +0 -68
- data/lib/booth/password_resets/create.rb +0 -57
- data/lib/booth/password_resets/find.rb +0 -36
- data/lib/booth/password_resets/propagate_to_credential.rb +0 -36
- data/lib/booth/password_resets/step.rb +0 -18
- data/lib/booth/recoveries/create.rb +0 -45
- data/lib/booth/requests/storages/otp.rb +0 -54
- data/lib/booth/requests/storages/password.rb +0 -49
- data/lib/booth/requests/storages/password_reset.rb +0 -35
- data/lib/booth/requests/storages/recovery.rb +0 -35
- data/lib/booth/sessions/create_and_login.rb +0 -46
- data/lib/booth/sessions/historical_locations.rb +0 -18
- data/lib/booth/sessions/index.rb +0 -59
- data/lib/booth/sessions/revoke.rb +0 -51
- data/lib/booth/sessions/revoke_all_others.rb +0 -43
- data/lib/booth/sessions/to_passport.rb +0 -51
- data/lib/booth/syntaxes/contest_code.rb +0 -58
- data/lib/booth/syntaxes/otp.rb +0 -57
- data/lib/booth/syntaxes/scope_comparison.rb +0 -28
- data/lib/booth/test/helpers.rb +0 -63
- data/lib/booth/test/support/assert_all_partials_were_covered.rb +0 -63
- data/lib/booth/test/support/assert_logged_in.rb +0 -49
- data/lib/booth/test/support/assert_partial.rb +0 -29
- data/lib/booth/test/support/otp_code_from_session.rb +0 -30
- data/lib/booth/test/support/soft_reset_session.rb +0 -22
- data/lib/booth/test/userland/logins/missing_authenticators.rb +0 -72
- data/lib/booth/test/userland/logins/missing_onboarding.rb +0 -35
- data/lib/booth/test/userland/logins/username_and_password.rb +0 -40
- data/lib/booth/test/userland/logins/username_and_webauth.rb +0 -75
- data/lib/booth/test/userland/logins/username_password_and_otp.rb +0 -45
- data/lib/booth/test/userland/logins/username_password_and_webauth.rb +0 -86
- data/lib/booth/test/userland/onboardings/already_logged_in.rb +0 -64
- data/lib/booth/test/userland/onboardings/otp.rb +0 -63
- data/lib/booth/test/userland/onboardings/password.rb +0 -49
- data/lib/booth/test/userland/onboardings/timeout.rb +0 -47
- data/lib/booth/test/userland/otps/manage.rb +0 -86
- data/lib/booth/test/userland/password_resets/reset.rb +0 -102
- data/lib/booth/test/userland.rb +0 -38
- data/lib/booth/test/webauthn/disable.rb +0 -17
- data/lib/booth/test/webauthn/enable.rb +0 -19
- data/lib/booth/test/webauthn/virtual_authenticators/create.rb +0 -38
- data/lib/booth/test/webauthn/virtual_authenticators/destroy.rb +0 -20
- data/lib/booth/userland/logins/transitions/create/enter_otp.rb +0 -70
- data/lib/booth/userland/logins/transitions/create/verify_password.rb +0 -70
- data/lib/booth/userland/logins/transitions/new/mode_first_time.rb +0 -20
- data/lib/booth/userland/logins/transitions/new/mode_username_password_and_otp.rb +0 -24
- data/lib/booth/userland/logins/transitions/new/mode_username_password_and_webauth.rb +0 -24
- data/lib/booth/userland/onboardings/transitions/update/choose_mode.rb +0 -58
- data/lib/booth/userland/onboardings/transitions/update/choose_password.rb +0 -41
- data/lib/booth/userland/onboardings/transitions/update/choose_webauth_nickname.rb +0 -50
- data/lib/booth/userland/onboardings/transitions/update/confirm_otp.rb +0 -58
- data/lib/booth/userland/onboardings/transitions/update/confirm_password.rb +0 -49
- data/lib/booth/userland/onboardings/transitions/update/register_otp.rb +0 -31
- data/lib/booth/userland/onboardings/transitions/update/reset_otp.rb +0 -40
- data/lib/booth/userland/onboardings/transitions/update/reset_password.rb +0 -35
- data/lib/booth/userland/onboardings/transitions/update/reset_webauth.rb +0 -46
- data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_initiation.rb +0 -40
- data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_verification.rb +0 -59
- data/lib/booth/userland/onboardings/transitions/update/webauth_registration_initiation.rb +0 -46
- data/lib/booth/userland/onboardings/transitions/update/webauth_registration_verification.rb +0 -56
- data/lib/booth/userland/otps/destroy.rb +0 -42
- data/lib/booth/userland/otps/edit.rb +0 -72
- data/lib/booth/userland/otps/guards/manageable.rb +0 -21
- data/lib/booth/userland/otps/guards/sudo.rb +0 -23
- data/lib/booth/userland/otps/show.rb +0 -36
- data/lib/booth/userland/otps/sudo.rb +0 -51
- data/lib/booth/userland/otps/transitions/update/confirm.rb +0 -84
- data/lib/booth/userland/otps/transitions/update/register.rb +0 -40
- data/lib/booth/userland/otps/transitions/update/reset.rb +0 -31
- data/lib/booth/userland/otps/update.rb +0 -34
- data/lib/booth/userland/password_resets/create.rb +0 -73
- data/lib/booth/userland/password_resets/guards/logged_out.rb +0 -21
- data/lib/booth/userland/password_resets/new.rb +0 -57
- data/lib/booth/userland/password_resets/show.rb +0 -77
- data/lib/booth/userland/password_resets/transitions/update/choose_password.rb +0 -48
- data/lib/booth/userland/password_resets/transitions/update/confirm_password.rb +0 -54
- data/lib/booth/userland/password_resets/transitions/update/reset_password.rb +0 -29
- data/lib/booth/userland/password_resets/update.rb +0 -65
- data/lib/booth/userland/passwords/destroy.rb +0 -41
- data/lib/booth/userland/passwords/edit.rb +0 -54
- data/lib/booth/userland/passwords/guards/manageable.rb +0 -21
- data/lib/booth/userland/passwords/guards/removable.rb +0 -21
- data/lib/booth/userland/passwords/guards/sudo.rb +0 -21
- data/lib/booth/userland/passwords/remove.rb +0 -34
- data/lib/booth/userland/passwords/show.rb +0 -32
- data/lib/booth/userland/passwords/sudo.rb +0 -55
- data/lib/booth/userland/passwords/transitions/remove/step.rb +0 -27
- data/lib/booth/userland/passwords/transitions/update/choose_password.rb +0 -62
- data/lib/booth/userland/passwords/transitions/update/confirm_password.rb +0 -82
- data/lib/booth/userland/passwords/update.rb +0 -33
- data/lib/booth/userland/personal_contests/show.rb +0 -60
- data/lib/booth/userland/recoveries/create.rb +0 -48
- data/lib/booth/userland/recoveries/new.rb +0 -35
- data/lib/booth/userland/sessions/transitions/destroy/enter_password.rb +0 -50
- data/lib/booth/userland/sessions/transitions/destroy/verify_password.rb +0 -83
- data/lib/booth/userland/webauths/guards/manageable.rb +0 -21
- data/lib/booth/webauth/authentication_verification.rb +0 -68
- data/lib/booth/webauth/demand_user_verification.rb +0 -29
- data/lib/booth/webauth/options_for_create.rb +0 -46
- data/lib/booth/webauth/options_for_get.rb +0 -29
- data/lib/generators/booth/migration/templates/create_booth_mode_types.erb +0 -20
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module Shortcuts
|
|
7
|
+
class LoginWithPasskey
|
|
8
|
+
include ::Calls
|
|
9
|
+
include ::Capybara::DSL
|
|
10
|
+
include ::Booth::Logging
|
|
11
|
+
|
|
12
|
+
option :routing_namespace
|
|
13
|
+
option :scope
|
|
14
|
+
option :username
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
log { 'Initiating Test Shortcut for logging in with passkey' }
|
|
18
|
+
::Booth::Testing::Support::Visit.call(routing_namespace:,
|
|
19
|
+
controller: :logins,
|
|
20
|
+
action: :new)
|
|
21
|
+
|
|
22
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
23
|
+
controller: :logins,
|
|
24
|
+
step: :enter_username)
|
|
25
|
+
|
|
26
|
+
fill_in :username, with: username
|
|
27
|
+
click_on :submit
|
|
28
|
+
|
|
29
|
+
# Wait for HTML to be loaded before checking its <template>
|
|
30
|
+
assert_selector 'template', visible: false
|
|
31
|
+
|
|
32
|
+
if page.html.include?('userland/logins/remote_session_available')
|
|
33
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
34
|
+
controller: :logins,
|
|
35
|
+
step: :remote_session_available)
|
|
36
|
+
click_on :skip
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
40
|
+
controller: :logins,
|
|
41
|
+
step: :enter_webauth)
|
|
42
|
+
|
|
43
|
+
click_on :authenticate
|
|
44
|
+
|
|
45
|
+
AssertLoggedIn.call(scope:, username:)
|
|
46
|
+
|
|
47
|
+
log { 'Shortcut to login with passkey succeeded' }
|
|
48
|
+
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module Shortcuts
|
|
7
|
+
class RegisterNewPasskey
|
|
8
|
+
include ::Calls
|
|
9
|
+
include ::Capybara::DSL
|
|
10
|
+
|
|
11
|
+
option :routing_namespace
|
|
12
|
+
option :scope
|
|
13
|
+
option :username
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
::Booth::Testing::Support::Visit.call(routing_namespace:,
|
|
17
|
+
controller: :webauths,
|
|
18
|
+
action: :new)
|
|
19
|
+
|
|
20
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
21
|
+
controller: :webauths,
|
|
22
|
+
step: :register)
|
|
23
|
+
|
|
24
|
+
click_on :register
|
|
25
|
+
|
|
26
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
27
|
+
controller: :webauths,
|
|
28
|
+
step: :choose_nickname)
|
|
29
|
+
|
|
30
|
+
fill_in :nickname, with: 'Latchkey'
|
|
31
|
+
click_on :submit
|
|
32
|
+
|
|
33
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
34
|
+
controller: :webauths,
|
|
35
|
+
step: :confirm)
|
|
36
|
+
|
|
37
|
+
click_on :test
|
|
38
|
+
|
|
39
|
+
::Booth::Testing::Support::AssertPartial.call(namespace: :userland,
|
|
40
|
+
controller: :webauths,
|
|
41
|
+
step: :completed)
|
|
42
|
+
|
|
43
|
+
AssertLoggedIn.call(scope:, username:)
|
|
44
|
+
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
# Essentially resets the session cookie, but without removing
|
|
7
|
+
# Chrome's Virtual Authenticator Enviroment. Like a force logout.
|
|
8
|
+
class SoftResetSession
|
|
9
|
+
include ::Calls
|
|
10
|
+
include ::Capybara::DSL
|
|
11
|
+
include ::Booth::Logging
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
::Capybara::Lockstep.synchronize
|
|
15
|
+
|
|
16
|
+
keys = page.get_rack_session.keys
|
|
17
|
+
keys_with_nil_values = keys.index_with { nil }
|
|
18
|
+
|
|
19
|
+
page.set_rack_session(**keys_with_nil_values)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module VirtualAuthenticators
|
|
7
|
+
class Create
|
|
8
|
+
include ::Calls
|
|
9
|
+
include ::Capybara::DSL
|
|
10
|
+
include ::Booth::Logging
|
|
11
|
+
|
|
12
|
+
option :has_user_verification
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
log { "Adding Virtual Authenticator... #{options.as_json}" }
|
|
16
|
+
page.driver.browser.add_virtual_authenticator(options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
# See `bundle open selenium-webdriver`
|
|
22
|
+
# See https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/#type-VirtualAuthenticatorOptions
|
|
23
|
+
def options
|
|
24
|
+
::Selenium::WebDriver::VirtualAuthenticatorOptions.new.tap do |instance|
|
|
25
|
+
instance.user_verification = has_user_verification
|
|
26
|
+
instance.user_verified = true
|
|
27
|
+
# instance.attestation = 'direct' # or 'indirect'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module VirtualAuthenticators
|
|
6
|
+
class Destroy
|
|
7
|
+
include ::Booth::Logging
|
|
8
|
+
include Calls
|
|
9
|
+
|
|
10
|
+
option :devtools
|
|
11
|
+
option :id
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
log { "Removing Virtual Authenticator with ID #{id}" }
|
|
15
|
+
devtools.send_cmd 'WebAuthn.removeVirtualAuthenticator', authenticatorId: id
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module VirtualAuthenticators
|
|
7
|
+
# Start the Virtual Authenticator Environment in Chrome.
|
|
8
|
+
class Enable
|
|
9
|
+
include ::Calls
|
|
10
|
+
include ::Capybara::DSL
|
|
11
|
+
include ::Booth::Logging
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
log { 'Ensuring enabled Chrome Virtual Authenticator Environment...' }
|
|
15
|
+
# The Environment *randomly* leaks from test to test, disabling it first works.
|
|
16
|
+
# All you'll see is `NotAllowedError` in the JS console if you miss this.
|
|
17
|
+
page.driver.browser.devtools.send_cmd 'WebAuthn.disable'
|
|
18
|
+
page.driver.browser.devtools.send_cmd 'WebAuthn.enable'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module VirtualAuthenticators
|
|
7
|
+
class Load
|
|
8
|
+
include ::Calls
|
|
9
|
+
include ::Capybara::DSL
|
|
10
|
+
include ::Booth::Logging
|
|
11
|
+
|
|
12
|
+
option :virtual_authenticator
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
credential = virtual_authenticator.credentials.first
|
|
16
|
+
|
|
17
|
+
# p 'A' * 100
|
|
18
|
+
# pp credential.instance_variable_get(:@sign_count)
|
|
19
|
+
# p Booth::Models::Authenticator.sole.sign_count
|
|
20
|
+
# p 'B' * 100
|
|
21
|
+
|
|
22
|
+
instance = ::Booth::Testing::Support::VirtualAuthenticators::Create.call(
|
|
23
|
+
has_user_verification: true,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
log do
|
|
27
|
+
"Attaching Virtual Authenticator Secrets to #{virtual_authenticator.instance_variable_get(:@id)}"
|
|
28
|
+
end
|
|
29
|
+
instance.add_credential(credential)
|
|
30
|
+
# virtual_authenticator.instance_variable_set(:@id, instance.instance_variable_get(:@sign_count))
|
|
31
|
+
|
|
32
|
+
instance
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
module VirtualAuthenticators
|
|
7
|
+
# Capybara handles multiple separate Chrome sessions (like separate browsers).
|
|
8
|
+
# In Chrome each of those sessions is completely distinct and nows nothing about the others.
|
|
9
|
+
# To "simulate" having the *same* passkey in "two browsers", we need to clone and sync it.
|
|
10
|
+
# This means transferring the secret key, and synchronizing the sign count.
|
|
11
|
+
# This class holds a state of all browser sessions to easier facilitate transfer and sync.
|
|
12
|
+
class Manager
|
|
13
|
+
include ::Capybara::DSL
|
|
14
|
+
include ::Booth::Logging
|
|
15
|
+
|
|
16
|
+
# Creates a brand new passkey.
|
|
17
|
+
def create(has_user_verification: true)
|
|
18
|
+
::Booth::Testing::Support::VirtualAuthenticators::Enable.call
|
|
19
|
+
|
|
20
|
+
new_device = ::Booth::Testing::Support::VirtualAuthenticators::Create.call(
|
|
21
|
+
has_user_verification:,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
this_session[new_device.instance_variable_get(:@id)] = new_device
|
|
25
|
+
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Takes a passkey from (the) other browser and injects it into this browser.
|
|
30
|
+
def clone_from_other_session
|
|
31
|
+
new_device = ::Booth::Testing::Support::VirtualAuthenticators::Create.call(
|
|
32
|
+
has_user_verification: true,
|
|
33
|
+
)
|
|
34
|
+
new_device.add_credential(other_credential)
|
|
35
|
+
|
|
36
|
+
this_session[new_device.instance_variable_get(:@id)] = new_device
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Inspects a passkey in (the) other browser and syncs the passkey here if needed.
|
|
41
|
+
def refresh_from_other_session
|
|
42
|
+
this_sign_count = this_credential.instance_variable_get(:@sign_count)
|
|
43
|
+
other_sign_count = other_credential.instance_variable_get(:@sign_count)
|
|
44
|
+
|
|
45
|
+
if this_sign_count == other_sign_count
|
|
46
|
+
log { "Sign count of both Virtual Keys is #{this_sign_count}" }
|
|
47
|
+
return
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
log { "Changing Virtual Key sign count from #{this_sign_count} to #{other_sign_count}" }
|
|
51
|
+
|
|
52
|
+
new_credential = this_credential
|
|
53
|
+
# This only affects the Credential here in our Ruby instance.
|
|
54
|
+
new_credential.instance_variable_set(:@sign_count, other_sign_count)
|
|
55
|
+
|
|
56
|
+
# So let us send our Ruby instance to the browser by replacing the key there.
|
|
57
|
+
this_device.remove_all_credentials
|
|
58
|
+
this_device.add_credential(new_credential)
|
|
59
|
+
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def this_credential
|
|
66
|
+
these_credentials = this_device.credentials
|
|
67
|
+
|
|
68
|
+
unless these_credentials.size == 1
|
|
69
|
+
raise "Don't know which other Virtual Credential to pick: #{these_credentials}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
these_credentials.first
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def other_credential
|
|
76
|
+
other_credentials = other_device.credentials
|
|
77
|
+
|
|
78
|
+
unless other_credentials.size == 1
|
|
79
|
+
raise "Don't know which Virtual Credential of mine to pick: #{other_credentials}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
other_credentials.first
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def this_device
|
|
86
|
+
unless this_session.size == 1
|
|
87
|
+
raise "Don't know which Virtual Authenticator of mine to pick: #{this_session.keys}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
this_session.values.first
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def other_device
|
|
94
|
+
unless other_session.size == 1
|
|
95
|
+
raise "Don't know which other Virtual Authenticator to pick: #{other_session.keys}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
other_session.values.first
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def this_session
|
|
102
|
+
sessions[Capybara.session_name]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def other_session
|
|
106
|
+
other_session_keys = sessions.keys.reject { it == Capybara.session_name }
|
|
107
|
+
|
|
108
|
+
unless other_session_keys.size == 1
|
|
109
|
+
raise "Cannot determine #{sessions.keys} as alternative to #{Capybara.session_name}"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
sessions[other_session_keys.first]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def sessions
|
|
116
|
+
@sessions ||= {}
|
|
117
|
+
@sessions[Capybara.session_name] ||= {}
|
|
118
|
+
@sessions
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Support
|
|
6
|
+
class Visit
|
|
7
|
+
include ::Calls
|
|
8
|
+
include ::Capybara::DSL
|
|
9
|
+
include ::Booth::Logging
|
|
10
|
+
|
|
11
|
+
option :routing_namespace # :community
|
|
12
|
+
option :controller # :registrations
|
|
13
|
+
option :action # :new
|
|
14
|
+
option :params, default: -> { {} } # { id: 42 }
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
log { "-----> Visiting #{controller}/#{action} #{params.presence} on #{subdomain}.localhost" }
|
|
18
|
+
visit ::Rails.application.routes.url_helpers.url_for(options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# The `url_for` helper dissects options into three categories:
|
|
24
|
+
#
|
|
25
|
+
# Path Params
|
|
26
|
+
# - :controller
|
|
27
|
+
# - :action
|
|
28
|
+
# - :anchor
|
|
29
|
+
#
|
|
30
|
+
# URL Params
|
|
31
|
+
# - :protocol
|
|
32
|
+
# - :port
|
|
33
|
+
# - :domain
|
|
34
|
+
# - :subdomain
|
|
35
|
+
# - :host (shortcut for :domain + :subdomain)
|
|
36
|
+
# - :only_path
|
|
37
|
+
#
|
|
38
|
+
# Query Params (everything not absorbed by the other to categories)
|
|
39
|
+
#
|
|
40
|
+
def options
|
|
41
|
+
params.merge subdomain:,
|
|
42
|
+
domain: 'localhost',
|
|
43
|
+
controller: namespaced_controller,
|
|
44
|
+
action:
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def subdomain
|
|
48
|
+
uri = URI.parse(Capybara.app_host) # 'http://one.two.localhost'
|
|
49
|
+
host_parts = uri.host.to_s.split('.') # ['one', 'two']
|
|
50
|
+
host_parts[0...-1].join('.') # 'one.two'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def namespaced_controller
|
|
54
|
+
raise "Controller names must be plural (#{controller})" unless controller.end_with?('s')
|
|
55
|
+
return controller if routing_namespace.blank?
|
|
56
|
+
|
|
57
|
+
"#{routing_namespace}/#{controller}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Userland
|
|
6
|
+
class LoginRemotely < ::Booth::Testing::IncorporationTestCase
|
|
7
|
+
def call
|
|
8
|
+
before_test&.call
|
|
9
|
+
|
|
10
|
+
create_and_onboard(username: 'alice')
|
|
11
|
+
virtual_authenticators.create
|
|
12
|
+
register_new_passkey(username: 'alice')
|
|
13
|
+
|
|
14
|
+
visit_namespaced controller: :remote_logins, action: :show
|
|
15
|
+
|
|
16
|
+
# ---------------- SIGNIFICANT TEST ------------------
|
|
17
|
+
# Can only enter a code when there is a pending Remote
|
|
18
|
+
# ----------------------------------------------------
|
|
19
|
+
assert_userland_view controller: :remote_logins, step: :no_remote
|
|
20
|
+
|
|
21
|
+
code = nil
|
|
22
|
+
using_session(:other_device) do
|
|
23
|
+
# Login on other device
|
|
24
|
+
|
|
25
|
+
visit_namespaced controller: :logins, action: :new
|
|
26
|
+
|
|
27
|
+
assert_userland_view controller: :logins, step: :enter_username
|
|
28
|
+
|
|
29
|
+
fill_in :username, with: 'alice'
|
|
30
|
+
click_on :submit
|
|
31
|
+
|
|
32
|
+
assert_userland_view controller: :logins, step: :remote_session_available
|
|
33
|
+
|
|
34
|
+
code = find('[data-booth="code"]').text
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Redeem remote code
|
|
38
|
+
|
|
39
|
+
visit_namespaced controller: :remote_logins, action: :show
|
|
40
|
+
|
|
41
|
+
assert_userland_view controller: :remote_logins, step: :remote_login
|
|
42
|
+
|
|
43
|
+
fill_in :code, with: code
|
|
44
|
+
click_on :submit
|
|
45
|
+
|
|
46
|
+
# ------ SIGNIFICANT TEST ------
|
|
47
|
+
# Remote logins can be redeemed.
|
|
48
|
+
# ------------------------------
|
|
49
|
+
assert_userland_view controller: :remote_logins, step: :remote_solved
|
|
50
|
+
|
|
51
|
+
using_session(:other_device) do
|
|
52
|
+
visit_namespaced controller: :webauths, action: :index
|
|
53
|
+
|
|
54
|
+
# ------------ SIGNIFICANT TEST --------------
|
|
55
|
+
# Webauth sudo is required after remote login.
|
|
56
|
+
# --------------------------------------------
|
|
57
|
+
assert_userland_view controller: :webauths, step: :sudo
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
using_session(:yet_another_device) do
|
|
61
|
+
visit_namespaced controller: :logins, action: :new
|
|
62
|
+
|
|
63
|
+
assert_userland_view controller: :logins, step: :enter_username
|
|
64
|
+
|
|
65
|
+
fill_in :username, with: 'alice'
|
|
66
|
+
click_on :submit
|
|
67
|
+
|
|
68
|
+
assert_userland_view controller: :logins, step: :remote_session_available
|
|
69
|
+
|
|
70
|
+
::Booth::Models::Remote.sole.update!(created_at: 21.minutes.ago)
|
|
71
|
+
|
|
72
|
+
visit_namespaced controller: :logins, action: :new
|
|
73
|
+
|
|
74
|
+
assert_userland_view controller: :logins, step: :remote_session_expired
|
|
75
|
+
|
|
76
|
+
travel 19.minutes
|
|
77
|
+
|
|
78
|
+
visit_namespaced controller: :logins, action: :new
|
|
79
|
+
|
|
80
|
+
# --- SIGNIFICANT TEST ----
|
|
81
|
+
# Remote logins can expire.
|
|
82
|
+
# -------------------------
|
|
83
|
+
assert_userland_view controller: :logins, step: :remote_session_expired
|
|
84
|
+
|
|
85
|
+
travel 2.minutes
|
|
86
|
+
|
|
87
|
+
visit_namespaced controller: :logins, action: :new
|
|
88
|
+
|
|
89
|
+
assert_userland_view controller: :logins, step: :enter_username
|
|
90
|
+
|
|
91
|
+
# ---------- SIGNIFICANT TEST -----------
|
|
92
|
+
# Login procedures as a whole can expire.
|
|
93
|
+
# ---------------------------------------
|
|
94
|
+
assert_text(/20 min/i) # Flash message
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Booth
|
|
4
|
+
module Testing
|
|
5
|
+
module Userland
|
|
6
|
+
class OnboardingFirstTime < ::Booth::Testing::IncorporationTestCase
|
|
7
|
+
def call
|
|
8
|
+
before_test&.call
|
|
9
|
+
|
|
10
|
+
alice = ::Booth::Models::Credential.create!(
|
|
11
|
+
domain: ::Capybara.app_host.remove('http://'),
|
|
12
|
+
username: 'alice',
|
|
13
|
+
scope:,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
after_credential&.call(credential_id: alice.id)
|
|
17
|
+
|
|
18
|
+
bobby = ::Booth::Models::Credential.create!(
|
|
19
|
+
domain: ::Capybara.app_host.remove('http://'),
|
|
20
|
+
username: 'bobby',
|
|
21
|
+
scope:,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
after_credential&.call(credential_id: bobby.id)
|
|
25
|
+
|
|
26
|
+
alices_onboarding = ::Booth::Models::Onboarding.create!(
|
|
27
|
+
credential_id: alice.id,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
bobbys_onboarding = ::Booth::Models::Onboarding.create!(
|
|
31
|
+
credential_id: bobby.id,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Onboard via URL
|
|
35
|
+
|
|
36
|
+
visit_namespaced controller: :onboardings, action: :show,
|
|
37
|
+
params: { id: alices_onboarding.secret_key }
|
|
38
|
+
|
|
39
|
+
assert_userland_view controller: :onboardings, step: :redeem
|
|
40
|
+
|
|
41
|
+
click_on :submit
|
|
42
|
+
|
|
43
|
+
# ------------------------ SIGNIFICANT TEST --------------------------------
|
|
44
|
+
# Re-visiting the Onboarding later, shows the success of having redeemed it.
|
|
45
|
+
# --------------------------------------------------------------------------
|
|
46
|
+
assert_userland_view controller: :onboardings, step: :success
|
|
47
|
+
|
|
48
|
+
visit_namespaced controller: :webauths, action: :index
|
|
49
|
+
|
|
50
|
+
# ----- SIGNIFICANT TEST -----
|
|
51
|
+
# Onboarding logs the user in.
|
|
52
|
+
# ----------------------------
|
|
53
|
+
assert_userland_view controller: :webauths, step: :index
|
|
54
|
+
|
|
55
|
+
visit_namespaced controller: :onboardings, action: :show,
|
|
56
|
+
params: { id: alices_onboarding.secret_key }
|
|
57
|
+
|
|
58
|
+
assert_userland_view controller: :onboardings, step: :success
|
|
59
|
+
|
|
60
|
+
visit_namespaced controller: :onboardings, action: :show,
|
|
61
|
+
params: { id: bobbys_onboarding.secret_key }
|
|
62
|
+
|
|
63
|
+
# -------------------- SIGNIFICANT TEST -------------------
|
|
64
|
+
# Cannot onboard while the wrong user is already logged in.
|
|
65
|
+
# ---------------------------------------------------------
|
|
66
|
+
assert_userland_view controller: :onboardings, step: :wrong_user
|
|
67
|
+
|
|
68
|
+
soft_reset_session
|
|
69
|
+
|
|
70
|
+
visit_namespaced controller: :onboardings, action: :show,
|
|
71
|
+
params: { id: alices_onboarding.secret_key }
|
|
72
|
+
|
|
73
|
+
# ------------ SIGNIFICANT TEST ---------------
|
|
74
|
+
# Cannot redeem an already consumed Onboarding.
|
|
75
|
+
# ---------------------------------------------
|
|
76
|
+
assert_userland_view controller: :onboardings, step: :already_used
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|