@adonis-agora/authkit-server 0.34.0
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.
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/build/assets/grafana/authkit-dashboard.json +118 -0
- package/build/commands/clients_create.d.ts +27 -0
- package/build/commands/clients_create.js +121 -0
- package/build/commands/commands.json +292 -0
- package/build/commands/configure.d.ts +2 -0
- package/build/commands/configure.js +45 -0
- package/build/commands/doctor.d.ts +10 -0
- package/build/commands/doctor.js +113 -0
- package/build/commands/eject.d.ts +11 -0
- package/build/commands/eject.js +96 -0
- package/build/commands/expire_scan.d.ts +28 -0
- package/build/commands/expire_scan.js +92 -0
- package/build/commands/import_users.d.ts +17 -0
- package/build/commands/import_users.js +80 -0
- package/build/commands/keys_rotate.d.ts +21 -0
- package/build/commands/keys_rotate.js +126 -0
- package/build/commands/main.d.ts +12 -0
- package/build/commands/main.js +38 -0
- package/build/commands/settings_get.d.ts +18 -0
- package/build/commands/settings_get.js +43 -0
- package/build/commands/settings_list.d.ts +17 -0
- package/build/commands/settings_list.js +39 -0
- package/build/commands/settings_set.d.ts +20 -0
- package/build/commands/settings_set.js +55 -0
- package/build/commands/settings_unset.d.ts +18 -0
- package/build/commands/settings_unset.js +46 -0
- package/build/commands/ui_preset.d.ts +4 -0
- package/build/commands/ui_preset.js +32 -0
- package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
- package/build/database/migrations/make_authkit_oidc_table.js +19 -0
- package/build/host/ui/admin.html +29 -0
- package/build/host/views/account/apps.edge +59 -0
- package/build/host/views/account/confirm.edge +70 -0
- package/build/host/views/account/email-confirmed.edge +16 -0
- package/build/host/views/account/login.edge +33 -0
- package/build/host/views/account/mfa.edge +152 -0
- package/build/host/views/account/orgs.edge +58 -0
- package/build/host/views/account/security.edge +215 -0
- package/build/host/views/account/tokens.edge +75 -0
- package/build/host/views/consent.edge +20 -0
- package/build/host/views/forgot.edge +43 -0
- package/build/host/views/login.edge +251 -0
- package/build/host/views/maintenance.edge +32 -0
- package/build/host/views/mfa-challenge.edge +107 -0
- package/build/host/views/otp-unlock.edge +40 -0
- package/build/host/views/partials/styles.edge +2 -0
- package/build/host/views/reset.edge +30 -0
- package/build/host/views/signup.edge +62 -0
- package/build/host/views/verify-email.edge +17 -0
- package/build/index.d.ts +115 -0
- package/build/index.js +76 -0
- package/build/password/common_passwords.txt +10000 -0
- package/build/providers/authkit_server_provider.d.ts +27 -0
- package/build/providers/authkit_server_provider.js +242 -0
- package/build/src/accounts/account_store.d.ts +578 -0
- package/build/src/accounts/account_store.js +60 -0
- package/build/src/accounts/lucid_account_store.d.ts +156 -0
- package/build/src/accounts/lucid_account_store.js +294 -0
- package/build/src/accounts/lucid_store/core.d.ts +9 -0
- package/build/src/accounts/lucid_store/core.js +306 -0
- package/build/src/accounts/lucid_store/mfa.d.ts +15 -0
- package/build/src/accounts/lucid_store/mfa.js +108 -0
- package/build/src/accounts/lucid_store/organizations.d.ts +13 -0
- package/build/src/accounts/lucid_store/organizations.js +294 -0
- package/build/src/accounts/lucid_store/password_hygiene.d.ts +20 -0
- package/build/src/accounts/lucid_store/password_hygiene.js +130 -0
- package/build/src/accounts/lucid_store/provider_identity.d.ts +8 -0
- package/build/src/accounts/lucid_store/provider_identity.js +59 -0
- package/build/src/accounts/lucid_store/shared.d.ts +113 -0
- package/build/src/accounts/lucid_store/shared.js +130 -0
- package/build/src/accounts/lucid_store/status_profile.d.ts +34 -0
- package/build/src/accounts/lucid_store/status_profile.js +100 -0
- package/build/src/accounts/lucid_store/webauthn.d.ts +8 -0
- package/build/src/accounts/lucid_store/webauthn.js +140 -0
- package/build/src/accounts/lucid_stores.d.ts +45 -0
- package/build/src/accounts/lucid_stores.js +30 -0
- package/build/src/adapters/adapter_contract.d.ts +37 -0
- package/build/src/adapters/adapter_contract.js +1 -0
- package/build/src/adapters/database_adapter.d.ts +21 -0
- package/build/src/adapters/database_adapter.js +79 -0
- package/build/src/adapters/factory.d.ts +30 -0
- package/build/src/adapters/factory.js +43 -0
- package/build/src/adapters/redis_adapter.d.ts +24 -0
- package/build/src/adapters/redis_adapter.js +122 -0
- package/build/src/audit/audit_sink.d.ts +63 -0
- package/build/src/audit/audit_sink.js +1 -0
- package/build/src/audit/lucid_audit_sink.d.ts +10 -0
- package/build/src/audit/lucid_audit_sink.js +99 -0
- package/build/src/commands/expire_scan_command.d.ts +60 -0
- package/build/src/commands/expire_scan_command.js +229 -0
- package/build/src/commands/import_clients.d.ts +40 -0
- package/build/src/commands/import_clients.js +79 -0
- package/build/src/commands/import_users.d.ts +51 -0
- package/build/src/commands/import_users.js +94 -0
- package/build/src/commands/resolve_config.d.ts +13 -0
- package/build/src/commands/resolve_config.js +18 -0
- package/build/src/commands/settings_commands.d.ts +47 -0
- package/build/src/commands/settings_commands.js +270 -0
- package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
- package/build/src/controllers/oidc_callback_controller.js +33 -0
- package/build/src/define_config.d.ts +772 -0
- package/build/src/define_config.js +351 -0
- package/build/src/doctor/checks.d.ts +197 -0
- package/build/src/doctor/checks.js +858 -0
- package/build/src/events/dispatcher.d.ts +45 -0
- package/build/src/events/dispatcher.js +117 -0
- package/build/src/host/account_api/account_api_controller.d.ts +245 -0
- package/build/src/host/account_api/account_api_controller.js +827 -0
- package/build/src/host/account_deletion_ops.d.ts +80 -0
- package/build/src/host/account_deletion_ops.js +118 -0
- package/build/src/host/account_deletion_service.d.ts +63 -0
- package/build/src/host/account_deletion_service.js +133 -0
- package/build/src/host/account_export_service.d.ts +76 -0
- package/build/src/host/account_export_service.js +140 -0
- package/build/src/host/account_home.d.ts +11 -0
- package/build/src/host/account_home.js +11 -0
- package/build/src/host/account_lockout.d.ts +86 -0
- package/build/src/host/account_lockout.js +185 -0
- package/build/src/host/active_org_cookie.d.ts +28 -0
- package/build/src/host/active_org_cookie.js +47 -0
- package/build/src/host/admin_api/admin_api_guard.d.ts +16 -0
- package/build/src/host/admin_api/admin_api_guard.js +59 -0
- package/build/src/host/admin_api/admin_orgs_service.d.ts +125 -0
- package/build/src/host/admin_api/admin_orgs_service.js +324 -0
- package/build/src/host/admin_api/admin_users_service.d.ts +163 -0
- package/build/src/host/admin_api/admin_users_service.js +308 -0
- package/build/src/host/admin_api/api_clients_controller.d.ts +54 -0
- package/build/src/host/admin_api/api_clients_controller.js +89 -0
- package/build/src/host/admin_api/api_keys_controller.d.ts +19 -0
- package/build/src/host/admin_api/api_keys_controller.js +36 -0
- package/build/src/host/admin_api/api_misc_controller.d.ts +19 -0
- package/build/src/host/admin_api/api_misc_controller.js +44 -0
- package/build/src/host/admin_api/api_orgs_controller.d.ts +108 -0
- package/build/src/host/admin_api/api_orgs_controller.js +189 -0
- package/build/src/host/admin_api/api_settings_controller.d.ts +55 -0
- package/build/src/host/admin_api/api_settings_controller.js +134 -0
- package/build/src/host/admin_api/api_users_controller.d.ts +108 -0
- package/build/src/host/admin_api/api_users_controller.js +187 -0
- package/build/src/host/admin_api/dto.d.ts +131 -0
- package/build/src/host/admin_api/dto.js +122 -0
- package/build/src/host/admin_api/token_verify_service.d.ts +34 -0
- package/build/src/host/admin_api/token_verify_service.js +74 -0
- package/build/src/host/admin_clients_service.d.ts +88 -0
- package/build/src/host/admin_clients_service.js +181 -0
- package/build/src/host/admin_console/admin_shell_controller.d.ts +27 -0
- package/build/src/host/admin_console/admin_shell_controller.js +167 -0
- package/build/src/host/admin_console/console_audit_controller.d.ts +17 -0
- package/build/src/host/admin_console/console_audit_controller.js +25 -0
- package/build/src/host/admin_console/console_clients_controller.d.ts +53 -0
- package/build/src/host/admin_console/console_clients_controller.js +102 -0
- package/build/src/host/admin_console/console_impersonation_controller.d.ts +23 -0
- package/build/src/host/admin_console/console_impersonation_controller.js +45 -0
- package/build/src/host/admin_console/console_keys_controller.d.ts +24 -0
- package/build/src/host/admin_console/console_keys_controller.js +41 -0
- package/build/src/host/admin_console/console_orgs_controller.d.ts +96 -0
- package/build/src/host/admin_console/console_orgs_controller.js +238 -0
- package/build/src/host/admin_console/console_overview_controller.d.ts +27 -0
- package/build/src/host/admin_console/console_overview_controller.js +44 -0
- package/build/src/host/admin_console/console_roles_controller.d.ts +31 -0
- package/build/src/host/admin_console/console_roles_controller.js +108 -0
- package/build/src/host/admin_console/console_sessions_controller.d.ts +91 -0
- package/build/src/host/admin_console/console_sessions_controller.js +125 -0
- package/build/src/host/admin_console/console_settings_controller.d.ts +47 -0
- package/build/src/host/admin_console/console_settings_controller.js +115 -0
- package/build/src/host/admin_console/console_users_controller.d.ts +110 -0
- package/build/src/host/admin_console/console_users_controller.js +212 -0
- package/build/src/host/admin_prefix.d.ts +50 -0
- package/build/src/host/admin_prefix.js +77 -0
- package/build/src/host/admin_sessions_service.d.ts +119 -0
- package/build/src/host/admin_sessions_service.js +284 -0
- package/build/src/host/admin_stats_service.d.ts +44 -0
- package/build/src/host/admin_stats_service.js +130 -0
- package/build/src/host/admin_validators.d.ts +247 -0
- package/build/src/host/admin_validators.js +197 -0
- package/build/src/host/augmentations.d.ts +12 -0
- package/build/src/host/augmentations.js +1 -0
- package/build/src/host/auth_host_config.d.ts +22 -0
- package/build/src/host/auth_host_config.js +13 -0
- package/build/src/host/avatar_storage.d.ts +68 -0
- package/build/src/host/avatar_storage.js +166 -0
- package/build/src/host/bot_protection.d.ts +187 -0
- package/build/src/host/bot_protection.js +132 -0
- package/build/src/host/branding.d.ts +19 -0
- package/build/src/host/branding.js +8 -0
- package/build/src/host/config_locks.d.ts +38 -0
- package/build/src/host/config_locks.js +70 -0
- package/build/src/host/console_session.d.ts +27 -0
- package/build/src/host/console_session.js +36 -0
- package/build/src/host/controllers/account_apps_controller.d.ts +15 -0
- package/build/src/host/controllers/account_apps_controller.js +61 -0
- package/build/src/host/controllers/account_confirm_controller.d.ts +24 -0
- package/build/src/host/controllers/account_confirm_controller.js +144 -0
- package/build/src/host/controllers/account_mfa_controller.d.ts +28 -0
- package/build/src/host/controllers/account_mfa_controller.js +208 -0
- package/build/src/host/controllers/account_orgs_controller.d.ts +80 -0
- package/build/src/host/controllers/account_orgs_controller.js +401 -0
- package/build/src/host/controllers/account_security_controller.d.ts +43 -0
- package/build/src/host/controllers/account_security_controller.js +546 -0
- package/build/src/host/controllers/account_session_controller.d.ts +21 -0
- package/build/src/host/controllers/account_session_controller.js +113 -0
- package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
- package/build/src/host/controllers/account_tokens_controller.js +67 -0
- package/build/src/host/controllers/interaction_controller.d.ts +125 -0
- package/build/src/host/controllers/interaction_controller.js +981 -0
- package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
- package/build/src/host/controllers/pat_introspection_controller.js +46 -0
- package/build/src/host/controllers/registration_controller.d.ts +18 -0
- package/build/src/host/controllers/registration_controller.js +382 -0
- package/build/src/host/controllers/social_controller.d.ts +8 -0
- package/build/src/host/controllers/social_controller.js +89 -0
- package/build/src/host/csrf.d.ts +29 -0
- package/build/src/host/csrf.js +14 -0
- package/build/src/host/default_mailer.d.ts +112 -0
- package/build/src/host/default_mailer.js +417 -0
- package/build/src/host/durable/account_deletion_workflow.d.ts +48 -0
- package/build/src/host/durable/account_deletion_workflow.js +86 -0
- package/build/src/host/durable/account_export_workflow.d.ts +68 -0
- package/build/src/host/durable/account_export_workflow.js +93 -0
- package/build/src/host/durable/index.d.ts +68 -0
- package/build/src/host/durable/index.js +77 -0
- package/build/src/host/email_templates.d.ts +39 -0
- package/build/src/host/email_templates.js +69 -0
- package/build/src/host/geo.d.ts +22 -0
- package/build/src/host/geo.js +39 -0
- package/build/src/host/i18n.d.ts +1416 -0
- package/build/src/host/i18n.js +1583 -0
- package/build/src/host/impersonation.d.ts +25 -0
- package/build/src/host/impersonation.js +31 -0
- package/build/src/host/key_rotation.d.ts +14 -0
- package/build/src/host/key_rotation.js +27 -0
- package/build/src/host/key_rotation_actions.d.ts +42 -0
- package/build/src/host/key_rotation_actions.js +27 -0
- package/build/src/host/login_attempt.d.ts +98 -0
- package/build/src/host/login_attempt.js +211 -0
- package/build/src/host/login_notify.d.ts +27 -0
- package/build/src/host/login_notify.js +142 -0
- package/build/src/host/middleware/account_auth.d.ts +7 -0
- package/build/src/host/middleware/account_auth.js +11 -0
- package/build/src/host/otp_lockout.d.ts +103 -0
- package/build/src/host/otp_lockout.js +221 -0
- package/build/src/host/rate_limit.d.ts +39 -0
- package/build/src/host/rate_limit.js +94 -0
- package/build/src/host/register_auth_host.d.ts +97 -0
- package/build/src/host/register_auth_host.js +466 -0
- package/build/src/host/renderers/edge_renderer.d.ts +12 -0
- package/build/src/host/renderers/edge_renderer.js +38 -0
- package/build/src/host/renderers/inertia_renderer.d.ts +70 -0
- package/build/src/host/renderers/inertia_renderer.js +54 -0
- package/build/src/host/runtime_settings.d.ts +181 -0
- package/build/src/host/runtime_settings.js +307 -0
- package/build/src/host/runtime_toggles.d.ts +807 -0
- package/build/src/host/runtime_toggles.js +784 -0
- package/build/src/host/security_notice_service.d.ts +36 -0
- package/build/src/host/security_notice_service.js +87 -0
- package/build/src/host/session_context.d.ts +23 -0
- package/build/src/host/session_context.js +89 -0
- package/build/src/host/sudo_mode.d.ts +56 -0
- package/build/src/host/sudo_mode.js +99 -0
- package/build/src/host/svg_chart.d.ts +15 -0
- package/build/src/host/svg_chart.js +45 -0
- package/build/src/host/trusted_device.d.ts +61 -0
- package/build/src/host/trusted_device.js +65 -0
- package/build/src/host/ui-dist/assets/index-CRWcmsex.js +137 -0
- package/build/src/host/ui-dist/assets/index-DTSmD4RU.css +1 -0
- package/build/src/host/ui-dist/index.html +17 -0
- package/build/src/host/user_agent.d.ts +18 -0
- package/build/src/host/user_agent.js +50 -0
- package/build/src/host/validators.d.ts +127 -0
- package/build/src/host/validators.js +53 -0
- package/build/src/keys/jwks_manager.d.ts +6 -0
- package/build/src/keys/jwks_manager.js +11 -0
- package/build/src/keys/keystore.d.ts +52 -0
- package/build/src/keys/keystore.js +68 -0
- package/build/src/keys/keystore_codec.d.ts +20 -0
- package/build/src/keys/keystore_codec.js +42 -0
- package/build/src/keys/keystore_crypto.d.ts +9 -0
- package/build/src/keys/keystore_crypto.js +27 -0
- package/build/src/keys/keystore_manager.d.ts +43 -0
- package/build/src/keys/keystore_manager.js +104 -0
- package/build/src/keys/keystore_vault.d.ts +113 -0
- package/build/src/keys/keystore_vault.js +265 -0
- package/build/src/mixins/json_column.d.ts +33 -0
- package/build/src/mixins/json_column.js +38 -0
- package/build/src/mixins/with_audit_log.d.ts +19 -0
- package/build/src/mixins/with_audit_log.js +39 -0
- package/build/src/mixins/with_auth_user.d.ts +24 -0
- package/build/src/mixins/with_auth_user.js +46 -0
- package/build/src/mixins/with_credentials.d.ts +20 -0
- package/build/src/mixins/with_credentials.js +29 -0
- package/build/src/mixins/with_mfa.d.ts +35 -0
- package/build/src/mixins/with_mfa.js +21 -0
- package/build/src/mixins/with_personal_access_token.d.ts +19 -0
- package/build/src/mixins/with_personal_access_token.js +42 -0
- package/build/src/mixins/with_provider_identity.d.ts +20 -0
- package/build/src/mixins/with_provider_identity.js +32 -0
- package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
- package/build/src/mixins/with_webauthn_credential.js +46 -0
- package/build/src/observability/diagnostics_bridge.d.ts +6 -0
- package/build/src/observability/diagnostics_bridge.js +27 -0
- package/build/src/observability/metrics_controller.d.ts +5 -0
- package/build/src/observability/metrics_controller.js +24 -0
- package/build/src/observability/metrics_service.d.ts +2 -0
- package/build/src/observability/metrics_service.js +7 -0
- package/build/src/observability/otel_recorder.d.ts +10 -0
- package/build/src/observability/otel_recorder.js +59 -0
- package/build/src/observability/telescope/data_providers.d.ts +24 -0
- package/build/src/observability/telescope/data_providers.js +235 -0
- package/build/src/observability/telescope/extension.d.ts +29 -0
- package/build/src/observability/telescope/extension.js +167 -0
- package/build/src/observability/telescope/index.d.ts +8 -0
- package/build/src/observability/telescope/index.js +8 -0
- package/build/src/observability/wire_provider_events.d.ts +12 -0
- package/build/src/observability/wire_provider_events.js +30 -0
- package/build/src/password/common_passwords.d.ts +31 -0
- package/build/src/password/common_passwords.js +73 -0
- package/build/src/password/password_manager.d.ts +163 -0
- package/build/src/password/password_manager.js +191 -0
- package/build/src/password/policy.d.ts +71 -0
- package/build/src/password/policy.js +55 -0
- package/build/src/password/pwned.d.ts +36 -0
- package/build/src/password/pwned.js +52 -0
- package/build/src/pat/lucid_pat_store.d.ts +6 -0
- package/build/src/pat/lucid_pat_store.js +62 -0
- package/build/src/pat/pat_store.d.ts +31 -0
- package/build/src/pat/pat_store.js +1 -0
- package/build/src/pat/pat_tokens.d.ts +4 -0
- package/build/src/pat/pat_tokens.js +9 -0
- package/build/src/provider/build_provider.d.ts +45 -0
- package/build/src/provider/build_provider.js +219 -0
- package/build/src/provider/device_sources.d.ts +6 -0
- package/build/src/provider/device_sources.js +65 -0
- package/build/src/provider/interaction_actions.d.ts +36 -0
- package/build/src/provider/interaction_actions.js +55 -0
- package/build/src/provider/key_rotation_scheduler.d.ts +28 -0
- package/build/src/provider/key_rotation_scheduler.js +40 -0
- package/build/src/provider/keystore_reload.d.ts +21 -0
- package/build/src/provider/keystore_reload.js +39 -0
- package/build/src/provider/logout_sources.d.ts +13 -0
- package/build/src/provider/logout_sources.js +64 -0
- package/build/src/provider/oidc_service.d.ts +81 -0
- package/build/src/provider/oidc_service.js +254 -0
- package/build/src/provider/single_flight_lock.d.ts +18 -0
- package/build/src/provider/single_flight_lock.js +31 -0
- package/build/src/provider/token_exchange.d.ts +21 -0
- package/build/src/provider/token_exchange.js +124 -0
- package/build/src/register_routes.d.ts +16 -0
- package/build/src/register_routes.js +21 -0
- package/build/src/schema/ensure.d.ts +41 -0
- package/build/src/schema/ensure.js +262 -0
- package/build/stubs/config/authkit.stub +20 -0
- package/build/stubs/config/authkit_react.stub +52 -0
- package/build/stubs/main.d.ts +1 -0
- package/build/stubs/main.js +2 -0
- package/build/stubs/models/auth_user.stub +22 -0
- package/build/stubs/ui/edge/views/consent.edge +13 -0
- package/build/stubs/ui/edge/views/login.edge +19 -0
- package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/build/stubs/ui/react/pages/account/login.tsx +56 -0
- package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/build/stubs/ui/react/pages/consent.tsx +39 -0
- package/build/stubs/ui/react/pages/forgot.tsx +44 -0
- package/build/stubs/ui/react/pages/login.tsx +171 -0
- package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/build/stubs/ui/react/pages/reset.tsx +58 -0
- package/build/stubs/ui/react/pages/signup.tsx +78 -0
- package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
- package/build/types.d.ts +7 -0
- package/build/types.js +1 -0
- package/package.json +147 -0
- package/stubs/config/authkit.stub +20 -0
- package/stubs/config/authkit_react.stub +52 -0
- package/stubs/main.ts +2 -0
- package/stubs/models/auth_user.stub +22 -0
- package/stubs/ui/edge/views/consent.edge +13 -0
- package/stubs/ui/edge/views/login.edge +19 -0
- package/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/stubs/ui/react/pages/account/login.tsx +56 -0
- package/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/stubs/ui/react/pages/consent.tsx +39 -0
- package/stubs/ui/react/pages/forgot.tsx +44 -0
- package/stubs/ui/react/pages/login.tsx +171 -0
- package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/stubs/ui/react/pages/reset.tsx +58 -0
- package/stubs/ui/react/pages/signup.tsx +78 -0
- package/stubs/ui/react/pages/verify-email.tsx +24 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
let driveServicePromise;
|
|
10
|
+
/**
|
|
11
|
+
* Importa o service de drive do HOST de forma preguiçosa e fail-safe.
|
|
12
|
+
* Se `@adonisjs/drive` não estiver instalado, resolve `null`.
|
|
13
|
+
*/
|
|
14
|
+
async function loadDrive() {
|
|
15
|
+
if (!driveServicePromise) {
|
|
16
|
+
// Indireção via variável: o `@adonisjs/drive` é peer/opcional e pode não estar
|
|
17
|
+
// instalado na lib, então o specifier não é resolvido em build-time.
|
|
18
|
+
const specifier = '@adonisjs/drive/services/main';
|
|
19
|
+
driveServicePromise = import(__rewriteRelativeImportExtension(specifier))
|
|
20
|
+
.then((mod) => mod.default ?? null)
|
|
21
|
+
.catch(() => null);
|
|
22
|
+
}
|
|
23
|
+
return driveServicePromise;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Permite reapontar/limpar o loader do drive (usado em testes).
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export function __setDriveLoaderForTests(fn) {
|
|
30
|
+
if (fn) {
|
|
31
|
+
driveServicePromise = fn();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
driveServicePromise = undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Extensões aceitas para o avatar (imagem raster comum). */
|
|
38
|
+
const ALLOWED_EXTNAMES = ['jpg', 'jpeg', 'png', 'webp'];
|
|
39
|
+
/** Erro de validação do upload (mensagem já localizada no controller). */
|
|
40
|
+
export class AvatarUploadError extends Error {
|
|
41
|
+
reason;
|
|
42
|
+
constructor(reason, message) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.reason = reason;
|
|
45
|
+
this.name = 'AvatarUploadError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Indica se o drive do app está disponível (para a view decidir mostrar o input
|
|
50
|
+
* de arquivo). Best-effort: nunca lança.
|
|
51
|
+
*/
|
|
52
|
+
export async function isDriveAvailable() {
|
|
53
|
+
return (await loadDrive()) !== null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve a extensão validada do arquivo enviado.
|
|
57
|
+
* Lança {@link AvatarUploadError} se ext/size forem inválidos.
|
|
58
|
+
*/
|
|
59
|
+
function validate(file, cfg, messages) {
|
|
60
|
+
const ext = (file.extname ?? '').toLowerCase().replace(/^\./, '');
|
|
61
|
+
if (!ALLOWED_EXTNAMES.includes(ext)) {
|
|
62
|
+
throw new AvatarUploadError('extname', messages.extname);
|
|
63
|
+
}
|
|
64
|
+
const maxBytes = cfg.avatars.maxSizeMb * 1024 * 1024;
|
|
65
|
+
if (typeof file.size === 'number' && file.size > maxBytes) {
|
|
66
|
+
throw new AvatarUploadError('size', messages.size);
|
|
67
|
+
}
|
|
68
|
+
return ext;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gera uma chave única para o avatar dentro do diretório configurado.
|
|
72
|
+
* `${directory}/${accountId}-${random}.${ext}`
|
|
73
|
+
*/
|
|
74
|
+
function buildKey(cfg, accountId, ext) {
|
|
75
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
76
|
+
return `${cfg.avatars.directory}/${accountId}-${random}.${ext}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Armazena o avatar no drive do host e retorna a URL pública.
|
|
80
|
+
*
|
|
81
|
+
* - Valida extensão (jpg/jpeg/png/webp) e tamanho (≤ maxSizeMb) — lança
|
|
82
|
+
* {@link AvatarUploadError} se inválido (o controller traduz/flasha).
|
|
83
|
+
* - Usa o disk configurado em `uploads.avatars.disk` ou o disk DEFAULT do app.
|
|
84
|
+
* - Se o drive estiver ausente/não-configurado → retorna `null` (degrada para URL).
|
|
85
|
+
*
|
|
86
|
+
* Nunca lança por causa de drive ausente; só lança em validação.
|
|
87
|
+
*/
|
|
88
|
+
export async function storeAvatar(_ctx, cfg, file, accountId, messages) {
|
|
89
|
+
const drive = await loadDrive();
|
|
90
|
+
if (!drive)
|
|
91
|
+
return null;
|
|
92
|
+
const ext = validate(file, cfg, messages);
|
|
93
|
+
// Resolve o disk: o configurado, ou o DEFAULT do drive do app.
|
|
94
|
+
let disk;
|
|
95
|
+
try {
|
|
96
|
+
disk = cfg.avatars.disk ? drive.use(cfg.avatars.disk) : drive.use();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// disk inválido/não-configurado — degrada para URL.
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (!disk)
|
|
103
|
+
return null;
|
|
104
|
+
const key = buildKey(cfg, accountId || 'account', ext);
|
|
105
|
+
// API @adonisjs/drive v3+: o file de multipart move-se direto para o disk.
|
|
106
|
+
// `moveToDisk` lê do tmpPath e usa o disk informado (ou o default da config).
|
|
107
|
+
if (typeof file.moveToDisk === 'function') {
|
|
108
|
+
await file.moveToDisk(key, cfg.avatars.disk ? { disk: cfg.avatars.disk } : undefined);
|
|
109
|
+
}
|
|
110
|
+
else if (file.tmpPath) {
|
|
111
|
+
// Fallback: lê do tmpPath e escreve via putStream no disk resolvido.
|
|
112
|
+
const fs = await import('node:fs');
|
|
113
|
+
await disk.putStream(key, fs.createReadStream(file.tmpPath));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
return await disk.getUrl(key);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// disk sem getUrl público — retorna a key como referência relativa.
|
|
123
|
+
return key;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Deleta (best-effort, fail-safe) o avatar de uma conta no drive do host, a partir
|
|
128
|
+
* da URL/key armazenada. Usado pela deleção de conta (LGPD): apaga o arquivo se
|
|
129
|
+
* conseguirmos derivar a key dentro do diretório configurado.
|
|
130
|
+
*
|
|
131
|
+
* NUNCA lança: drive ausente, key não reconhecida ou erro de I/O → no-op. A key é
|
|
132
|
+
* derivada da `storedUrlOrKey` pegando o trecho a partir de `directory/` (cobre
|
|
133
|
+
* tanto uma key relativa quanto uma URL pública que contenha o caminho).
|
|
134
|
+
*/
|
|
135
|
+
export async function deleteAvatar(cfg, storedUrlOrKey) {
|
|
136
|
+
if (!storedUrlOrKey)
|
|
137
|
+
return false;
|
|
138
|
+
const drive = await loadDrive();
|
|
139
|
+
if (!drive)
|
|
140
|
+
return false;
|
|
141
|
+
// Deriva a key: trecho a partir de `<directory>/`. Se não bater, aborta (não
|
|
142
|
+
// arriscamos deletar algo fora do nosso diretório).
|
|
143
|
+
const dir = cfg.avatars.directory.replace(/\/+$/, '');
|
|
144
|
+
const marker = `${dir}/`;
|
|
145
|
+
const idx = storedUrlOrKey.indexOf(marker);
|
|
146
|
+
if (idx < 0)
|
|
147
|
+
return false;
|
|
148
|
+
// Remove querystring/fragment de uma URL pública.
|
|
149
|
+
const key = storedUrlOrKey.slice(idx).split(/[?#]/)[0];
|
|
150
|
+
let disk;
|
|
151
|
+
try {
|
|
152
|
+
disk = cfg.avatars.disk ? drive.use(cfg.avatars.disk) : drive.use();
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (!disk || typeof disk.delete !== 'function')
|
|
158
|
+
return false;
|
|
159
|
+
try {
|
|
160
|
+
await disk.delete(key);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { ResolvedServerConfig } from '../define_config.js';
|
|
3
|
+
import type { SettingsCapability } from './runtime_settings.js';
|
|
4
|
+
/**
|
|
5
|
+
* Bot protection plugável (CAPTCHA / challenge), agnóstica de vendor.
|
|
6
|
+
*
|
|
7
|
+
* O HOST fornece o verificador (`verify`); a lib só ORQUESTRA: injeta o widget
|
|
8
|
+
* nas telas afetadas (login/signup/reset) e, no POST correspondente, extrai o
|
|
9
|
+
* token do body e chama `verify` ANTES de processar credenciais. Nenhuma
|
|
10
|
+
* dependência de Cloudflare Turnstile / hCaptcha / reCAPTCHA é trazida pela lib —
|
|
11
|
+
* o host escreve o `verify` (um fetch ao endpoint do provedor) no `config/authkit.ts`.
|
|
12
|
+
*
|
|
13
|
+
* Decisão de disponibilidade (FAIL-SAFE): se `verify` LANÇAR ou estourar o
|
|
14
|
+
* timeout, o fluxo PROSSEGUE (a verificação é tratada como "passou") e um warning
|
|
15
|
+
* é logado. Disponibilidade > proteção: um provedor de CAPTCHA fora do ar não pode
|
|
16
|
+
* derrubar o login de todo mundo. Apenas um `verify` que retorna `false`
|
|
17
|
+
* explicitamente rejeita a request.
|
|
18
|
+
*
|
|
19
|
+
* @example Cloudflare Turnstile (código do HOST, sem dependência nova na lib):
|
|
20
|
+
* ```ts
|
|
21
|
+
* // config/authkit.ts
|
|
22
|
+
* botProtection: {
|
|
23
|
+
* on: ['login', 'signup', 'reset'],
|
|
24
|
+
* widget: {
|
|
25
|
+
* scriptUrl: 'https://challenges.cloudflare.com/turnstile/v0/api.js',
|
|
26
|
+
* // Container renderizado nas telas; o script do Turnstile o "hidrata".
|
|
27
|
+
* html: '<div class="cf-turnstile" data-sitekey="0xAAAA..."></div>',
|
|
28
|
+
* },
|
|
29
|
+
* async verify({ token, ip }) {
|
|
30
|
+
* if (!token) return false
|
|
31
|
+
* const res = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
|
|
32
|
+
* method: 'POST',
|
|
33
|
+
* headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
34
|
+
* body: new URLSearchParams({
|
|
35
|
+
* secret: process.env.TURNSTILE_SECRET!,
|
|
36
|
+
* response: token,
|
|
37
|
+
* ...(ip ? { remoteip: ip } : {}),
|
|
38
|
+
* }),
|
|
39
|
+
* })
|
|
40
|
+
* const data = (await res.json()) as { success: boolean }
|
|
41
|
+
* return data.success === true
|
|
42
|
+
* },
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example hCaptcha (código do HOST):
|
|
47
|
+
* ```ts
|
|
48
|
+
* botProtection: {
|
|
49
|
+
* tokenFields: ['h-captcha-response'], // sobrescreve a lista default
|
|
50
|
+
* widget: {
|
|
51
|
+
* scriptUrl: 'https://js.hcaptcha.com/1/api.js',
|
|
52
|
+
* html: '<div class="h-captcha" data-sitekey="YOUR_SITE_KEY"></div>',
|
|
53
|
+
* },
|
|
54
|
+
* async verify({ token, ip }) {
|
|
55
|
+
* if (!token) return false
|
|
56
|
+
* const res = await fetch('https://api.hcaptcha.com/siteverify', {
|
|
57
|
+
* method: 'POST',
|
|
58
|
+
* headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
59
|
+
* body: new URLSearchParams({
|
|
60
|
+
* secret: process.env.HCAPTCHA_SECRET!,
|
|
61
|
+
* response: token,
|
|
62
|
+
* ...(ip ? { remoteip: ip } : {}),
|
|
63
|
+
* }),
|
|
64
|
+
* })
|
|
65
|
+
* const data = (await res.json()) as { success: boolean }
|
|
66
|
+
* return data.success === true
|
|
67
|
+
* },
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
/** Ação protegida pelo bot protection (mapeia 1:1 com as telas/POSTs sensíveis). */
|
|
72
|
+
export type BotProtectionAction = 'login' | 'signup' | 'reset';
|
|
73
|
+
/** Contexto passado ao `verify` do host. */
|
|
74
|
+
export interface BotProtectionVerifyInput {
|
|
75
|
+
/** Token do widget extraído do body (null quando ausente). */
|
|
76
|
+
token: string | null;
|
|
77
|
+
/** IP da request (best-effort; pode ser undefined). */
|
|
78
|
+
ip?: string;
|
|
79
|
+
/** Ação que disparou a verificação. */
|
|
80
|
+
action: BotProtectionAction;
|
|
81
|
+
}
|
|
82
|
+
/** Markup/script do widget injetado nas telas (Turnstile, hCaptcha, etc.). */
|
|
83
|
+
export interface BotProtectionWidget {
|
|
84
|
+
/** URL do script externo do provedor (carregado uma vez, async). */
|
|
85
|
+
scriptUrl: string;
|
|
86
|
+
/**
|
|
87
|
+
* HTML do container do widget (renderizado RAW no form). Tipicamente um
|
|
88
|
+
* `<div>` com a classe/atributos do provedor (ex.: `class="cf-turnstile"
|
|
89
|
+
* data-sitekey="..."`). Como é config-trusted (do host), é injetado sem escape.
|
|
90
|
+
*/
|
|
91
|
+
html: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Campos de body onde o token do widget costuma vir. Cobre os provedores comuns
|
|
95
|
+
* por padrão; o host pode sobrescrever via `tokenFields`.
|
|
96
|
+
* - `cf-turnstile-response` (Cloudflare Turnstile)
|
|
97
|
+
* - `h-captcha-response` (hCaptcha)
|
|
98
|
+
* - `g-recaptcha-response` (Google reCAPTCHA)
|
|
99
|
+
* - `authkit-bot-token` (genérico, p/ widgets custom)
|
|
100
|
+
*/
|
|
101
|
+
export declare const DEFAULT_BOT_TOKEN_FIELDS: readonly ["cf-turnstile-response", "h-captcha-response", "g-recaptcha-response", "authkit-bot-token"];
|
|
102
|
+
/** Config de entrada do bot protection (em `config/authkit.ts`). */
|
|
103
|
+
export interface BotProtectionConfigInput {
|
|
104
|
+
/**
|
|
105
|
+
* Verificador fornecido pelo HOST. Recebe o token do widget + contexto e
|
|
106
|
+
* resolve `true` (humano/ok) ou `false` (bot/rejeitar). LANÇAR/timeout é
|
|
107
|
+
* tratado como FAIL-SAFE (permite + warning) — ver {@link verifyBotProtection}.
|
|
108
|
+
*/
|
|
109
|
+
verify: (input: BotProtectionVerifyInput) => Promise<boolean>;
|
|
110
|
+
/** Ações protegidas. Default: `['login', 'signup']`. */
|
|
111
|
+
on?: BotProtectionAction[];
|
|
112
|
+
/** Widget injetado nas telas (script + container). Opcional. */
|
|
113
|
+
widget?: BotProtectionWidget;
|
|
114
|
+
/**
|
|
115
|
+
* Nomes de campo de body onde procurar o token, em ordem. Default:
|
|
116
|
+
* {@link DEFAULT_BOT_TOKEN_FIELDS}. O host pode passar uma lista própria.
|
|
117
|
+
*/
|
|
118
|
+
tokenFields?: string[];
|
|
119
|
+
/**
|
|
120
|
+
* Timeout (ms) do `verify`. Estourar = FAIL-SAFE (permite). Default: 5000.
|
|
121
|
+
*/
|
|
122
|
+
timeoutMs?: number;
|
|
123
|
+
}
|
|
124
|
+
/** Config resolvida do bot protection (sempre com defaults aplicados). */
|
|
125
|
+
export interface ResolvedBotProtectionConfig {
|
|
126
|
+
verify: (input: BotProtectionVerifyInput) => Promise<boolean>;
|
|
127
|
+
on: BotProtectionAction[];
|
|
128
|
+
widget?: BotProtectionWidget;
|
|
129
|
+
tokenFields: string[];
|
|
130
|
+
timeoutMs: number;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resolve a config do bot protection aplicando os defaults. Retorna `undefined`
|
|
134
|
+
* quando o host não configura `botProtection` (feature totalmente desligada).
|
|
135
|
+
*/
|
|
136
|
+
export declare function resolveBotProtection(input?: BotProtectionConfigInput): ResolvedBotProtectionConfig | undefined;
|
|
137
|
+
/** `true` se o bot protection está ligado para `action`. */
|
|
138
|
+
export declare function botProtectionApplies(cfg: ResolvedBotProtectionConfig | undefined, action: BotProtectionAction): boolean;
|
|
139
|
+
/** Extrai o token do widget do body, testando os campos configurados em ordem. */
|
|
140
|
+
export declare function extractBotToken(ctx: HttpContext, fields: string[]): string | null;
|
|
141
|
+
/**
|
|
142
|
+
* Roda o `verify` do host com timeout e semântica FAIL-SAFE:
|
|
143
|
+
* - `verify` resolve `false` → `false` (rejeitar a request).
|
|
144
|
+
* - `verify` resolve `true` → `true` (prosseguir).
|
|
145
|
+
* - `verify` LANÇA → `true` (FAIL-SAFE) + warning.
|
|
146
|
+
* - `verify` estoura o timeout→ `true` (FAIL-SAFE) + warning.
|
|
147
|
+
*
|
|
148
|
+
* NUNCA lança para o caminho da request. Disponibilidade > proteção.
|
|
149
|
+
*/
|
|
150
|
+
export declare function verifyBotProtection(ctx: HttpContext, cfg: ResolvedBotProtectionConfig, action: BotProtectionAction): Promise<boolean>;
|
|
151
|
+
/**
|
|
152
|
+
* Verifica o bot protection para `action` e, em rejeição, AUDITA
|
|
153
|
+
* `bot_protection.rejected` (sem o token). Retorna `false` quando a request deve
|
|
154
|
+
* ser bloqueada (bot detectado). Best-effort: usado pelos controllers antes de
|
|
155
|
+
* processar credenciais. Quando a feature não se aplica à ação, retorna `true`.
|
|
156
|
+
*/
|
|
157
|
+
export declare function guardBotProtection(ctx: HttpContext, cfg: ResolvedServerConfig, action: BotProtectionAction, meta?: {
|
|
158
|
+
email?: string | null;
|
|
159
|
+
clientId?: string | null;
|
|
160
|
+
}): Promise<boolean>;
|
|
161
|
+
/** Shape da setting `bot_protection` em `auth_settings`. */
|
|
162
|
+
export interface BotProtectionSetting {
|
|
163
|
+
/** Liga/desliga em runtime. */
|
|
164
|
+
enabled: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Ações protegidas. Se omitido, herda do config. Só é considerado
|
|
167
|
+
* quando `enabled: true`.
|
|
168
|
+
*/
|
|
169
|
+
on?: BotProtectionAction[];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve a config EFETIVA do bot protection considerando o runtime setting
|
|
173
|
+
* armazenado em `auth_settings` (via `RuntimeSettings` / `SettingsCapability`).
|
|
174
|
+
*
|
|
175
|
+
* Regras:
|
|
176
|
+
* - config ausente (host não configurou `botProtection`) → `undefined` sempre
|
|
177
|
+
* (a feature não existe; settings são ignoradas).
|
|
178
|
+
* - config presente + setting ausente/erro → retorna `config` intacto.
|
|
179
|
+
* - config presente + setting `{ enabled: false }` → retorna `undefined`
|
|
180
|
+
* (desligado em runtime).
|
|
181
|
+
* - config presente + setting `{ enabled: true }` → retorna config com
|
|
182
|
+
* `on` substituído pelo `setting.on` (se definido) ou pelo `config.on`.
|
|
183
|
+
* - O `verify` NUNCA vem da setting (é código do host, não serializável).
|
|
184
|
+
*
|
|
185
|
+
* FAIL-SAFE: se `getSetting` retornar null (tabela ausente/erro), usa o config.
|
|
186
|
+
*/
|
|
187
|
+
export declare function resolveEffectiveBotProtection(config: ResolvedBotProtectionConfig | undefined, settings: SettingsCapability): Promise<ResolvedBotProtectionConfig | undefined>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Campos de body onde o token do widget costuma vir. Cobre os provedores comuns
|
|
3
|
+
* por padrão; o host pode sobrescrever via `tokenFields`.
|
|
4
|
+
* - `cf-turnstile-response` (Cloudflare Turnstile)
|
|
5
|
+
* - `h-captcha-response` (hCaptcha)
|
|
6
|
+
* - `g-recaptcha-response` (Google reCAPTCHA)
|
|
7
|
+
* - `authkit-bot-token` (genérico, p/ widgets custom)
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_BOT_TOKEN_FIELDS = [
|
|
10
|
+
'cf-turnstile-response',
|
|
11
|
+
'h-captcha-response',
|
|
12
|
+
'g-recaptcha-response',
|
|
13
|
+
'authkit-bot-token',
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a config do bot protection aplicando os defaults. Retorna `undefined`
|
|
17
|
+
* quando o host não configura `botProtection` (feature totalmente desligada).
|
|
18
|
+
*/
|
|
19
|
+
export function resolveBotProtection(input) {
|
|
20
|
+
if (!input)
|
|
21
|
+
return undefined;
|
|
22
|
+
const on = input.on && input.on.length > 0 ? input.on : ['login', 'signup'];
|
|
23
|
+
const tokenFields = input.tokenFields && input.tokenFields.length > 0
|
|
24
|
+
? input.tokenFields
|
|
25
|
+
: [...DEFAULT_BOT_TOKEN_FIELDS];
|
|
26
|
+
return {
|
|
27
|
+
verify: input.verify,
|
|
28
|
+
on,
|
|
29
|
+
widget: input.widget,
|
|
30
|
+
tokenFields,
|
|
31
|
+
timeoutMs: input.timeoutMs && input.timeoutMs > 0 ? input.timeoutMs : 5000,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** `true` se o bot protection está ligado para `action`. */
|
|
35
|
+
export function botProtectionApplies(cfg, action) {
|
|
36
|
+
return !!cfg && cfg.on.includes(action);
|
|
37
|
+
}
|
|
38
|
+
/** Extrai o token do widget do body, testando os campos configurados em ordem. */
|
|
39
|
+
export function extractBotToken(ctx, fields) {
|
|
40
|
+
for (const field of fields) {
|
|
41
|
+
const value = ctx.request.input(field);
|
|
42
|
+
if (typeof value === 'string' && value.length > 0)
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Roda o `verify` do host com timeout e semântica FAIL-SAFE:
|
|
49
|
+
* - `verify` resolve `false` → `false` (rejeitar a request).
|
|
50
|
+
* - `verify` resolve `true` → `true` (prosseguir).
|
|
51
|
+
* - `verify` LANÇA → `true` (FAIL-SAFE) + warning.
|
|
52
|
+
* - `verify` estoura o timeout→ `true` (FAIL-SAFE) + warning.
|
|
53
|
+
*
|
|
54
|
+
* NUNCA lança para o caminho da request. Disponibilidade > proteção.
|
|
55
|
+
*/
|
|
56
|
+
export async function verifyBotProtection(ctx, cfg, action) {
|
|
57
|
+
const token = extractBotToken(ctx, cfg.tokenFields);
|
|
58
|
+
const ip = ctx.request.ip?.() ?? undefined;
|
|
59
|
+
let timer;
|
|
60
|
+
const timeout = new Promise((resolve) => {
|
|
61
|
+
timer = setTimeout(() => resolve(true), cfg.timeoutMs);
|
|
62
|
+
});
|
|
63
|
+
try {
|
|
64
|
+
const result = await Promise.race([cfg.verify({ token, ip, action }), timeout]);
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// FAIL-SAFE: erro no verificador do host NÃO bloqueia o login.
|
|
69
|
+
ctx.logger.warn({ err: error, action }, 'authkit: bot protection verify lançou — fail-safe (request permitida)');
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
if (timer)
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Verifica o bot protection para `action` e, em rejeição, AUDITA
|
|
79
|
+
* `bot_protection.rejected` (sem o token). Retorna `false` quando a request deve
|
|
80
|
+
* ser bloqueada (bot detectado). Best-effort: usado pelos controllers antes de
|
|
81
|
+
* processar credenciais. Quando a feature não se aplica à ação, retorna `true`.
|
|
82
|
+
*/
|
|
83
|
+
export async function guardBotProtection(ctx, cfg, action, meta) {
|
|
84
|
+
const bot = cfg.botProtection;
|
|
85
|
+
if (!botProtectionApplies(bot, action))
|
|
86
|
+
return true;
|
|
87
|
+
const ok = await verifyBotProtection(ctx, bot, action);
|
|
88
|
+
if (ok)
|
|
89
|
+
return true;
|
|
90
|
+
// Rejeitado: audita SEM o token (apenas action + ip + contexto mínimo).
|
|
91
|
+
await cfg.audit?.record({
|
|
92
|
+
type: 'bot_protection.rejected',
|
|
93
|
+
email: meta?.email ?? null,
|
|
94
|
+
ip: ctx.request.ip?.() ?? null,
|
|
95
|
+
clientId: meta?.clientId ?? null,
|
|
96
|
+
metadata: { action },
|
|
97
|
+
});
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve a config EFETIVA do bot protection considerando o runtime setting
|
|
102
|
+
* armazenado em `auth_settings` (via `RuntimeSettings` / `SettingsCapability`).
|
|
103
|
+
*
|
|
104
|
+
* Regras:
|
|
105
|
+
* - config ausente (host não configurou `botProtection`) → `undefined` sempre
|
|
106
|
+
* (a feature não existe; settings são ignoradas).
|
|
107
|
+
* - config presente + setting ausente/erro → retorna `config` intacto.
|
|
108
|
+
* - config presente + setting `{ enabled: false }` → retorna `undefined`
|
|
109
|
+
* (desligado em runtime).
|
|
110
|
+
* - config presente + setting `{ enabled: true }` → retorna config com
|
|
111
|
+
* `on` substituído pelo `setting.on` (se definido) ou pelo `config.on`.
|
|
112
|
+
* - O `verify` NUNCA vem da setting (é código do host, não serializável).
|
|
113
|
+
*
|
|
114
|
+
* FAIL-SAFE: se `getSetting` retornar null (tabela ausente/erro), usa o config.
|
|
115
|
+
*/
|
|
116
|
+
export async function resolveEffectiveBotProtection(config, settings) {
|
|
117
|
+
if (!config)
|
|
118
|
+
return undefined;
|
|
119
|
+
const raw = await settings.getSetting('bot_protection');
|
|
120
|
+
if (raw === null || raw === undefined)
|
|
121
|
+
return config;
|
|
122
|
+
// Valida a shape mínima da setting.
|
|
123
|
+
if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
|
|
124
|
+
return config; // shape inválida → fallback
|
|
125
|
+
}
|
|
126
|
+
const setting = raw;
|
|
127
|
+
if (!setting.enabled)
|
|
128
|
+
return undefined; // runtime off
|
|
129
|
+
// enabled: true — on pode sobrescrever
|
|
130
|
+
const on = Array.isArray(setting.on) && setting.on.length > 0 ? setting.on : config.on;
|
|
131
|
+
return { ...config, on };
|
|
132
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ClientBrand {
|
|
2
|
+
/** Client id (OIDC) que iniciou o fluxo — chave estável pra escolher tema/tela por produto. */
|
|
3
|
+
clientId?: string;
|
|
4
|
+
appName: string;
|
|
5
|
+
accent: string;
|
|
6
|
+
accentSoft: string;
|
|
7
|
+
tagline: string;
|
|
8
|
+
company?: string;
|
|
9
|
+
audienceLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface BrandingConfig {
|
|
12
|
+
company: string;
|
|
13
|
+
clients: Record<string, Omit<ClientBrand, 'company' | 'audienceLabel'>>;
|
|
14
|
+
default: Omit<ClientBrand, 'company' | 'audienceLabel'>;
|
|
15
|
+
firstParty: string[];
|
|
16
|
+
audienceLabels?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function isFirstParty(cfg: BrandingConfig, clientId: string | undefined): boolean;
|
|
19
|
+
export declare function brandFor(cfg: BrandingConfig, clientId: string | undefined, audience?: string): ClientBrand;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function isFirstParty(cfg, clientId) {
|
|
2
|
+
return !!clientId && cfg.firstParty.includes(clientId);
|
|
3
|
+
}
|
|
4
|
+
export function brandFor(cfg, clientId, audience) {
|
|
5
|
+
const base = (clientId && cfg.clients[clientId]) || cfg.default;
|
|
6
|
+
const label = audience ? cfg.audienceLabels?.[audience] : undefined;
|
|
7
|
+
return { ...base, clientId, company: cfg.company, ...(label ? { audienceLabel: label } : {}) };
|
|
8
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config locks — quando uma feature/política é definida explicitamente no
|
|
3
|
+
* `defineConfig`, ela fica TRAVADA: o valor do config manda e a UI/Admin API NÃO
|
|
4
|
+
* pode mais alterá-la em runtime. Quando NÃO está no config, a UI controla
|
|
5
|
+
* livremente o valor (runtime setting em `auth_settings`).
|
|
6
|
+
*
|
|
7
|
+
* Mecânica (elegante, sem tocar nos ~20 resolvers):
|
|
8
|
+
* - `RuntimeSettings.getSetting` retorna `null` para keys travadas → cada
|
|
9
|
+
* `resolveEffective*` cai no `configDefault` (= o valor do config). Logo, config vence.
|
|
10
|
+
* - `RuntimeSettings.setSetting`/`deleteSetting` lançam {@link SettingLockedError}
|
|
11
|
+
* para keys travadas → o write path da Admin API/console rejeita com 423.
|
|
12
|
+
* - A UI lê a lista de keys travadas (`lockedSettingKeys()`) e desabilita o
|
|
13
|
+
* controle + mostra o aviso "definido via defineConfig".
|
|
14
|
+
*
|
|
15
|
+
* O registro é MODULE-LEVEL e setado uma vez no boot do provider — o IdP é um por
|
|
16
|
+
* processo e os locks vêm de config estático (imutável pós-boot).
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Deriva as keys de `auth_settings` travadas a partir dos campos EXPLICITAMENTE
|
|
20
|
+
* presentes no input do `defineConfig`. Só mapeia keys que têm contraparte tanto
|
|
21
|
+
* em config quanto na UI (runtime setting); features sem campo de config nunca
|
|
22
|
+
* travam (UI sempre controla).
|
|
23
|
+
*/
|
|
24
|
+
export declare function deriveLockedSettingKeys(config: Record<string, any>): string[];
|
|
25
|
+
/** Erro lançado ao tentar gravar/remover uma setting travada via `defineConfig`. */
|
|
26
|
+
export declare class SettingLockedError extends Error {
|
|
27
|
+
readonly code = "E_SETTING_LOCKED";
|
|
28
|
+
readonly key: string;
|
|
29
|
+
constructor(key: string);
|
|
30
|
+
}
|
|
31
|
+
/** Define o conjunto de keys travadas (chamado uma vez no boot do provider). */
|
|
32
|
+
export declare function setLockedSettingKeys(keys: Iterable<string>): void;
|
|
33
|
+
/** Limpa os locks — uso em testes. */
|
|
34
|
+
export declare function resetLockedSettingKeys(): void;
|
|
35
|
+
/** A setting `key` está travada por config? */
|
|
36
|
+
export declare function isSettingLocked(key: string): boolean;
|
|
37
|
+
/** Lista (snapshot) das keys travadas — consumida pelo read path da UI. */
|
|
38
|
+
export declare function lockedSettingKeys(): string[];
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config locks — quando uma feature/política é definida explicitamente no
|
|
3
|
+
* `defineConfig`, ela fica TRAVADA: o valor do config manda e a UI/Admin API NÃO
|
|
4
|
+
* pode mais alterá-la em runtime. Quando NÃO está no config, a UI controla
|
|
5
|
+
* livremente o valor (runtime setting em `auth_settings`).
|
|
6
|
+
*
|
|
7
|
+
* Mecânica (elegante, sem tocar nos ~20 resolvers):
|
|
8
|
+
* - `RuntimeSettings.getSetting` retorna `null` para keys travadas → cada
|
|
9
|
+
* `resolveEffective*` cai no `configDefault` (= o valor do config). Logo, config vence.
|
|
10
|
+
* - `RuntimeSettings.setSetting`/`deleteSetting` lançam {@link SettingLockedError}
|
|
11
|
+
* para keys travadas → o write path da Admin API/console rejeita com 423.
|
|
12
|
+
* - A UI lê a lista de keys travadas (`lockedSettingKeys()`) e desabilita o
|
|
13
|
+
* controle + mostra o aviso "definido via defineConfig".
|
|
14
|
+
*
|
|
15
|
+
* O registro é MODULE-LEVEL e setado uma vez no boot do provider — o IdP é um por
|
|
16
|
+
* processo e os locks vêm de config estático (imutável pós-boot).
|
|
17
|
+
*/
|
|
18
|
+
import { SETTING_KEYS } from './runtime_toggles.js';
|
|
19
|
+
/**
|
|
20
|
+
* Deriva as keys de `auth_settings` travadas a partir dos campos EXPLICITAMENTE
|
|
21
|
+
* presentes no input do `defineConfig`. Só mapeia keys que têm contraparte tanto
|
|
22
|
+
* em config quanto na UI (runtime setting); features sem campo de config nunca
|
|
23
|
+
* travam (UI sempre controla).
|
|
24
|
+
*/
|
|
25
|
+
export function deriveLockedSettingKeys(config) {
|
|
26
|
+
const locked = [];
|
|
27
|
+
const add = (present, key) => {
|
|
28
|
+
if (present)
|
|
29
|
+
locked.push(key);
|
|
30
|
+
};
|
|
31
|
+
add(config.registration !== undefined, SETTING_KEYS.REGISTRATION);
|
|
32
|
+
add(config.login?.requireVerifiedEmail !== undefined, SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
|
|
33
|
+
add(config.lockout !== undefined, SETTING_KEYS.LOCKOUT);
|
|
34
|
+
add(config.rateLimit !== undefined, SETTING_KEYS.RATE_LIMIT);
|
|
35
|
+
add(config.trustedDevices !== undefined, SETTING_KEYS.TRUSTED_DEVICES);
|
|
36
|
+
add(config.botProtection !== undefined, SETTING_KEYS.BOT_PROTECTION);
|
|
37
|
+
add(config.organizations !== undefined, SETTING_KEYS.ORGANIZATIONS_POLICY);
|
|
38
|
+
add(config.admin?.impersonation !== undefined, SETTING_KEYS.ADMIN_IMPERSONATION);
|
|
39
|
+
add(config.ttl !== undefined, SETTING_KEYS.TOKEN_TTL);
|
|
40
|
+
return locked;
|
|
41
|
+
}
|
|
42
|
+
/** Erro lançado ao tentar gravar/remover uma setting travada via `defineConfig`. */
|
|
43
|
+
export class SettingLockedError extends Error {
|
|
44
|
+
code = 'E_SETTING_LOCKED';
|
|
45
|
+
key;
|
|
46
|
+
constructor(key) {
|
|
47
|
+
super(`A setting "${key}" foi definida via defineConfig() e está travada — ` +
|
|
48
|
+
`não pode ser alterada em runtime (console/Admin API). ` +
|
|
49
|
+
`Remova-a do defineConfig para liberar a edição pela UI.`);
|
|
50
|
+
this.name = 'SettingLockedError';
|
|
51
|
+
this.key = key;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let lockedKeys = new Set();
|
|
55
|
+
/** Define o conjunto de keys travadas (chamado uma vez no boot do provider). */
|
|
56
|
+
export function setLockedSettingKeys(keys) {
|
|
57
|
+
lockedKeys = new Set(keys);
|
|
58
|
+
}
|
|
59
|
+
/** Limpa os locks — uso em testes. */
|
|
60
|
+
export function resetLockedSettingKeys() {
|
|
61
|
+
lockedKeys = new Set();
|
|
62
|
+
}
|
|
63
|
+
/** A setting `key` está travada por config? */
|
|
64
|
+
export function isSettingLocked(key) {
|
|
65
|
+
return lockedKeys.has(key);
|
|
66
|
+
}
|
|
67
|
+
/** Lista (snapshot) das keys travadas — consumida pelo read path da UI. */
|
|
68
|
+
export function lockedSettingKeys() {
|
|
69
|
+
return [...lockedKeys];
|
|
70
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
/**
|
|
3
|
+
* Helpers públicos para integrar a sessão do console do AuthKit com
|
|
4
|
+
* qualquer coisa fora do pacote (ex.: proteger o dashboard do
|
|
5
|
+
* adonis-telescope, rotas administrativas próprias, etc).
|
|
6
|
+
*
|
|
7
|
+
* Use estes helpers em vez de ler `ctx.session` com a key interna —
|
|
8
|
+
* eles são contrato público e continuam funcionando se o mecanismo de
|
|
9
|
+
* sessão mudar.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Retorna o id da conta logada no console (ou `null` quando não há
|
|
13
|
+
* sessão).
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAccountId(ctx: HttpContext): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* `true` quando o request carrega uma sessão de conta do console.
|
|
18
|
+
*/
|
|
19
|
+
export declare function hasAccountSession(ctx: HttpContext): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* URL do login do console, com `return_to` opcional de volta ao destino
|
|
22
|
+
* original após autenticar.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* consoleLoginUrl('/telescope') // => '/account/login?return_to=%2Ftelescope'
|
|
26
|
+
*/
|
|
27
|
+
export declare function consoleLoginUrl(returnTo?: string): string;
|