@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,112 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
/**
|
|
3
|
+
* Envio de e-mail default do host-kit, usando o mailer `default` do host via
|
|
4
|
+
* `@adonisjs/mail`. Permite que o dev não escreva nenhum hook: por padrão os
|
|
5
|
+
* e-mails de reset de senha / verificação são enviados pelo mailer já configurado
|
|
6
|
+
* no app, com HTML responsivo + branding (do `config/authkit.ts`) e fallback texto.
|
|
7
|
+
* Os hooks de `config/authkit.ts` (`mail.onPasswordReset` /
|
|
8
|
+
* `mail.onEmailVerification`), quando presentes, têm prioridade (override).
|
|
9
|
+
*
|
|
10
|
+
* Best-effort: se `@adonisjs/mail` não estiver instalado/configurado, cai no
|
|
11
|
+
* fallback de log (mesmo comportamento de antes) e NUNCA lança na request.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Service do `@adonisjs/mail` resolvido de forma preguiçosa. Tipado como `any` de
|
|
15
|
+
* propósito: a lib NÃO depende do mail em tempo de compilação (peer/opt-in).
|
|
16
|
+
*/
|
|
17
|
+
type MailService = any;
|
|
18
|
+
/**
|
|
19
|
+
* Permite reapontar/limpar o loader do mail (usado em testes).
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare function __setMailLoaderForTests(fn: (() => Promise<MailService | null>) | undefined): void;
|
|
23
|
+
/**
|
|
24
|
+
* Envia o e-mail de redefinição de senha pelo mailer default do host.
|
|
25
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sendPasswordResetEmail(ctx: HttpContext, data: {
|
|
28
|
+
email: string;
|
|
29
|
+
resetUrl: string;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Envia o e-mail de confirmação de TROCA de e-mail para o NOVO endereço.
|
|
33
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sendEmailChangeConfirmationEmail(ctx: HttpContext, data: {
|
|
36
|
+
email: string;
|
|
37
|
+
confirmUrl: string;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Envia o e-mail de alerta de NOVO acesso à conta (login de um IP novo).
|
|
41
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
42
|
+
*/
|
|
43
|
+
export declare function sendNewLoginEmail(ctx: HttpContext, data: {
|
|
44
|
+
email: string;
|
|
45
|
+
ip: string;
|
|
46
|
+
when: string;
|
|
47
|
+
}): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Envia o e-mail de alerta de NOVO DISPOSITIVO (login sem cookie de dispositivo
|
|
50
|
+
* confiável). Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
51
|
+
*/
|
|
52
|
+
export declare function sendNewDeviceLoginEmail(ctx: HttpContext, data: {
|
|
53
|
+
email: string;
|
|
54
|
+
ip?: string | null;
|
|
55
|
+
userAgent?: string | null;
|
|
56
|
+
when: string;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Envia o e-mail de magic link (login passwordless) pelo mailer default do host.
|
|
60
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
61
|
+
*/
|
|
62
|
+
export declare function sendMagicLinkEmail(ctx: HttpContext, data: {
|
|
63
|
+
email: string;
|
|
64
|
+
magicUrl: string;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Envia o e-mail de aviso de segurança ao e-mail ATUAL quando uma troca de
|
|
68
|
+
* e-mail é solicitada ("Alguém pediu troca para X — se não foi você...").
|
|
69
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
70
|
+
*/
|
|
71
|
+
export declare function sendEmailChangeNoticeEmail(ctx: HttpContext, data: {
|
|
72
|
+
email: string;
|
|
73
|
+
newEmail: string;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Envia o e-mail de aviso de segurança ao e-mail ANTIGO confirmando que a
|
|
77
|
+
* troca foi concluída ("Seu e-mail foi alterado de A para B — se não foi você...").
|
|
78
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
79
|
+
*/
|
|
80
|
+
export declare function sendEmailChangedCompletedEmail(ctx: HttpContext, data: {
|
|
81
|
+
oldEmail: string;
|
|
82
|
+
newEmail: string;
|
|
83
|
+
}): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Envia um e-mail de notificação de segurança para a conta (senha alterada,
|
|
86
|
+
* MFA habilitado/desabilitado, passkey adicionada/removida, e-mail alterado).
|
|
87
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
88
|
+
*/
|
|
89
|
+
export declare function sendSecurityNoticeEmail(ctx: HttpContext, data: {
|
|
90
|
+
email: string;
|
|
91
|
+
kind: 'password_changed' | 'mfa_enabled' | 'mfa_disabled' | 'passkey_added' | 'passkey_removed' | 'email_changed';
|
|
92
|
+
timestamp: string;
|
|
93
|
+
ip?: string | null;
|
|
94
|
+
metadata?: Record<string, string>;
|
|
95
|
+
}): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Envia o e-mail de desbloqueio do fator OTP (quando TOTP/recovery excede maxAttempts).
|
|
98
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
99
|
+
*/
|
|
100
|
+
export declare function sendOtpUnlockEmail(ctx: HttpContext, data: {
|
|
101
|
+
email: string;
|
|
102
|
+
unlockUrl: string;
|
|
103
|
+
}): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Envia o e-mail de verificação pelo mailer default do host.
|
|
106
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
107
|
+
*/
|
|
108
|
+
export declare function sendEmailVerificationEmail(ctx: HttpContext, data: {
|
|
109
|
+
email: string;
|
|
110
|
+
verifyUrl: string;
|
|
111
|
+
}): Promise<void>;
|
|
112
|
+
export {};
|
|
@@ -0,0 +1,417 @@
|
|
|
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
|
+
import { renderTransactionalEmail } from './email_templates.js';
|
|
10
|
+
import { resolveMessages, translate, } from './i18n.js';
|
|
11
|
+
let mailServicePromise;
|
|
12
|
+
/**
|
|
13
|
+
* Importa o service de mail do HOST de forma preguiçosa e fail-safe.
|
|
14
|
+
* Se `@adonisjs/mail` não estiver instalado, resolve `null`.
|
|
15
|
+
*/
|
|
16
|
+
async function loadMail() {
|
|
17
|
+
if (!mailServicePromise) {
|
|
18
|
+
// Indireção via variável: o `@adonisjs/mail` é peer/opcional e pode não estar
|
|
19
|
+
// instalado na lib, então o specifier não é resolvido em build-time.
|
|
20
|
+
const specifier = '@adonisjs/mail/services/main';
|
|
21
|
+
mailServicePromise = import(__rewriteRelativeImportExtension(specifier))
|
|
22
|
+
.then((mod) => mod.default ?? null)
|
|
23
|
+
.catch(() => null);
|
|
24
|
+
}
|
|
25
|
+
return mailServicePromise;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Permite reapontar/limpar o loader do mail (usado em testes).
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export function __setMailLoaderForTests(fn) {
|
|
32
|
+
if (fn) {
|
|
33
|
+
mailServicePromise = fn();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
mailServicePromise = undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Tenta descobrir o `from` default da config de mail do host. Se não houver,
|
|
41
|
+
* retorna `undefined` (deixa o @adonisjs/mail aplicar o default da própria config).
|
|
42
|
+
*/
|
|
43
|
+
function defaultFrom(ctx) {
|
|
44
|
+
try {
|
|
45
|
+
// Alcançamos a config de `mail` do HOST via o resolver do container. Esse
|
|
46
|
+
// formato é específico do app (a lib não conhece o shape da config de mail
|
|
47
|
+
// nem `containerResolver.app` é público), então tipamos apenas ESTE acesso
|
|
48
|
+
// como `unknown`/cast estreito — não o `HttpContext` inteiro.
|
|
49
|
+
const resolver = ctx.containerResolver;
|
|
50
|
+
const cfg = resolver.app?.config?.get?.('mail');
|
|
51
|
+
const from = cfg?.from;
|
|
52
|
+
if (from)
|
|
53
|
+
return from;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// sem config de mail resolvível — deixa o @adonisjs/mail decidir.
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a marca default a partir do `config/authkit.ts` (branding.default +
|
|
62
|
+
* company). Usada para o cabeçalho/cor de acento/rodapé dos e-mails. Cai num
|
|
63
|
+
* default neutro se a config não for resolvível.
|
|
64
|
+
*/
|
|
65
|
+
function resolveBrand(ctx) {
|
|
66
|
+
try {
|
|
67
|
+
const resolver = ctx.containerResolver;
|
|
68
|
+
const branding = resolver.app?.config?.get?.('authkit')?.branding;
|
|
69
|
+
if (branding) {
|
|
70
|
+
return {
|
|
71
|
+
appName: branding.default?.appName || branding.company || 'AuthKit',
|
|
72
|
+
accent: branding.default?.accent,
|
|
73
|
+
company: branding.company,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// sem config authkit resolvível — usa default neutro.
|
|
79
|
+
}
|
|
80
|
+
return { appName: 'AuthKit' };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve o catálogo de mensagens i18n a partir do `config/authkit.ts` (i18n).
|
|
84
|
+
* Cai no default (`en`) se a config não for resolvível. Usado para localizar
|
|
85
|
+
* os e-mails transacionais (assunto/cabeçalho/corpo).
|
|
86
|
+
*/
|
|
87
|
+
function resolveMailMessages(ctx) {
|
|
88
|
+
try {
|
|
89
|
+
const resolver = ctx.containerResolver;
|
|
90
|
+
const i18n = resolver.app?.config?.get?.('authkit')?.i18n;
|
|
91
|
+
return { messages: resolveMessages(i18n), locale: i18n?.locale ?? 'en' };
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// sem config authkit resolvível — usa o default `en`.
|
|
95
|
+
return { messages: resolveMessages(), locale: 'en' };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function sendEmail(ctx, to, content) {
|
|
99
|
+
const mail = await loadMail();
|
|
100
|
+
if (!mail)
|
|
101
|
+
return false;
|
|
102
|
+
const from = defaultFrom(ctx);
|
|
103
|
+
await mail.send((message) => {
|
|
104
|
+
if (from)
|
|
105
|
+
message.from(from);
|
|
106
|
+
message.to(to).subject(content.subject).html(content.html).text(content.text);
|
|
107
|
+
});
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Envia o e-mail de redefinição de senha pelo mailer default do host.
|
|
112
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
113
|
+
*/
|
|
114
|
+
export async function sendPasswordResetEmail(ctx, data) {
|
|
115
|
+
try {
|
|
116
|
+
const brand = resolveBrand(ctx);
|
|
117
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
118
|
+
const content = renderTransactionalEmail({
|
|
119
|
+
brand,
|
|
120
|
+
locale,
|
|
121
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
122
|
+
subject: translate(t, 'mail.reset.subject'),
|
|
123
|
+
heading: translate(t, 'mail.reset.heading'),
|
|
124
|
+
intro: translate(t, 'mail.reset.intro'),
|
|
125
|
+
ctaLabel: translate(t, 'mail.reset.cta'),
|
|
126
|
+
ctaUrl: data.resetUrl,
|
|
127
|
+
footnote: translate(t, 'mail.reset.fallback'),
|
|
128
|
+
});
|
|
129
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
130
|
+
if (!sent) {
|
|
131
|
+
ctx.logger.info({ resetUrl: data.resetUrl, email: data.email }, 'authkit: link de redefinição de senha (dev — @adonisjs/mail ausente)');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar e-mail de redefinição de senha');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Envia o e-mail de confirmação de TROCA de e-mail para o NOVO endereço.
|
|
140
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
141
|
+
*/
|
|
142
|
+
export async function sendEmailChangeConfirmationEmail(ctx, data) {
|
|
143
|
+
try {
|
|
144
|
+
const brand = resolveBrand(ctx);
|
|
145
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
146
|
+
const content = renderTransactionalEmail({
|
|
147
|
+
brand,
|
|
148
|
+
locale,
|
|
149
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
150
|
+
subject: translate(t, 'mail.email_change.subject'),
|
|
151
|
+
heading: translate(t, 'mail.email_change.heading'),
|
|
152
|
+
intro: translate(t, 'mail.email_change.intro'),
|
|
153
|
+
ctaLabel: translate(t, 'mail.email_change.cta'),
|
|
154
|
+
ctaUrl: data.confirmUrl,
|
|
155
|
+
footnote: translate(t, 'mail.email_change.fallback'),
|
|
156
|
+
});
|
|
157
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
158
|
+
if (!sent) {
|
|
159
|
+
ctx.logger.info({ confirmUrl: data.confirmUrl, email: data.email }, 'authkit: link de confirmação de troca de e-mail (dev — @adonisjs/mail ausente)');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar confirmação de troca de e-mail');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Envia o e-mail de alerta de NOVO acesso à conta (login de um IP novo).
|
|
168
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
169
|
+
*/
|
|
170
|
+
export async function sendNewLoginEmail(ctx, data) {
|
|
171
|
+
try {
|
|
172
|
+
const brand = resolveBrand(ctx);
|
|
173
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
174
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
175
|
+
const intro = [
|
|
176
|
+
translate(t, 'mail.new_login.intro'),
|
|
177
|
+
translate(t, 'mail.new_login.when', { date: data.when }),
|
|
178
|
+
translate(t, 'mail.new_login.ip', { ip: data.ip }),
|
|
179
|
+
].join(' ');
|
|
180
|
+
const content = renderTransactionalEmail({
|
|
181
|
+
brand,
|
|
182
|
+
locale,
|
|
183
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
184
|
+
subject: translate(t, 'mail.new_login.subject'),
|
|
185
|
+
heading: translate(t, 'mail.new_login.heading'),
|
|
186
|
+
intro,
|
|
187
|
+
ctaLabel: translate(t, 'account.security.title'),
|
|
188
|
+
ctaUrl: `${origin}/account/security`,
|
|
189
|
+
footnote: translate(t, 'mail.new_login.fallback'),
|
|
190
|
+
});
|
|
191
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
192
|
+
if (!sent) {
|
|
193
|
+
ctx.logger.info({ ip: data.ip, email: data.email }, 'authkit: alerta de novo acesso (dev — @adonisjs/mail ausente)');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar alerta de novo acesso');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Envia o e-mail de alerta de NOVO DISPOSITIVO (login sem cookie de dispositivo
|
|
202
|
+
* confiável). Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
203
|
+
*/
|
|
204
|
+
export async function sendNewDeviceLoginEmail(ctx, data) {
|
|
205
|
+
try {
|
|
206
|
+
const brand = resolveBrand(ctx);
|
|
207
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
208
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
209
|
+
const lines = [translate(t, 'mail.new_login.intro'), translate(t, 'mail.new_login.when', { date: data.when })];
|
|
210
|
+
if (data.userAgent)
|
|
211
|
+
lines.push(translate(t, 'mail.new_login.device', { device: data.userAgent }));
|
|
212
|
+
if (data.ip)
|
|
213
|
+
lines.push(translate(t, 'mail.new_login.ip', { ip: data.ip }));
|
|
214
|
+
const content = renderTransactionalEmail({
|
|
215
|
+
brand,
|
|
216
|
+
locale,
|
|
217
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
218
|
+
subject: translate(t, 'mail.new_login.subject'),
|
|
219
|
+
heading: translate(t, 'mail.new_login.heading'),
|
|
220
|
+
intro: lines.join(' '),
|
|
221
|
+
ctaLabel: translate(t, 'account.security.title'),
|
|
222
|
+
ctaUrl: `${origin}/account/security`,
|
|
223
|
+
footnote: translate(t, 'mail.new_login.fallback'),
|
|
224
|
+
});
|
|
225
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
226
|
+
if (!sent) {
|
|
227
|
+
ctx.logger.info({ ip: data.ip, email: data.email, userAgent: data.userAgent }, 'authkit: alerta de novo dispositivo (dev — @adonisjs/mail ausente)');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar alerta de novo dispositivo');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Envia o e-mail de magic link (login passwordless) pelo mailer default do host.
|
|
236
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
237
|
+
*/
|
|
238
|
+
export async function sendMagicLinkEmail(ctx, data) {
|
|
239
|
+
try {
|
|
240
|
+
const brand = resolveBrand(ctx);
|
|
241
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
242
|
+
const content = renderTransactionalEmail({
|
|
243
|
+
brand,
|
|
244
|
+
locale,
|
|
245
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
246
|
+
subject: translate(t, 'mail.magic_link.subject'),
|
|
247
|
+
heading: translate(t, 'mail.magic_link.heading'),
|
|
248
|
+
intro: translate(t, 'mail.magic_link.intro'),
|
|
249
|
+
ctaLabel: translate(t, 'mail.magic_link.cta'),
|
|
250
|
+
ctaUrl: data.magicUrl,
|
|
251
|
+
footnote: translate(t, 'mail.magic_link.fallback'),
|
|
252
|
+
});
|
|
253
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
254
|
+
if (!sent) {
|
|
255
|
+
ctx.logger.info({ magicUrl: data.magicUrl, email: data.email }, 'authkit: magic link de login (dev — @adonisjs/mail ausente)');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar magic link de login');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Envia o e-mail de aviso de segurança ao e-mail ATUAL quando uma troca de
|
|
264
|
+
* e-mail é solicitada ("Alguém pediu troca para X — se não foi você...").
|
|
265
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
266
|
+
*/
|
|
267
|
+
export async function sendEmailChangeNoticeEmail(ctx, data) {
|
|
268
|
+
try {
|
|
269
|
+
const brand = resolveBrand(ctx);
|
|
270
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
271
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
272
|
+
const content = renderTransactionalEmail({
|
|
273
|
+
brand,
|
|
274
|
+
locale,
|
|
275
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
276
|
+
subject: translate(t, 'mail.email_change_notice.subject'),
|
|
277
|
+
heading: translate(t, 'mail.email_change_notice.heading'),
|
|
278
|
+
intro: translate(t, 'mail.email_change_notice.intro', { newEmail: data.newEmail }),
|
|
279
|
+
ctaLabel: translate(t, 'mail.email_change_notice.cta'),
|
|
280
|
+
ctaUrl: `${origin}/account/security`,
|
|
281
|
+
footnote: translate(t, 'mail.email_change_notice.fallback'),
|
|
282
|
+
});
|
|
283
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
284
|
+
if (!sent) {
|
|
285
|
+
ctx.logger.info({ newEmail: data.newEmail, email: data.email }, 'authkit: aviso de troca de e-mail (dev — @adonisjs/mail ausente)');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar aviso de troca de e-mail');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Envia o e-mail de aviso de segurança ao e-mail ANTIGO confirmando que a
|
|
294
|
+
* troca foi concluída ("Seu e-mail foi alterado de A para B — se não foi você...").
|
|
295
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
296
|
+
*/
|
|
297
|
+
export async function sendEmailChangedCompletedEmail(ctx, data) {
|
|
298
|
+
try {
|
|
299
|
+
const brand = resolveBrand(ctx);
|
|
300
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
301
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
302
|
+
const content = renderTransactionalEmail({
|
|
303
|
+
brand,
|
|
304
|
+
locale,
|
|
305
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
306
|
+
subject: translate(t, 'mail.email_changed_completed.subject'),
|
|
307
|
+
heading: translate(t, 'mail.email_changed_completed.heading'),
|
|
308
|
+
intro: translate(t, 'mail.email_changed_completed.intro', {
|
|
309
|
+
oldEmail: data.oldEmail,
|
|
310
|
+
newEmail: data.newEmail,
|
|
311
|
+
}),
|
|
312
|
+
ctaLabel: translate(t, 'mail.email_changed_completed.cta'),
|
|
313
|
+
ctaUrl: `${origin}/account/security`,
|
|
314
|
+
footnote: translate(t, 'mail.email_changed_completed.fallback'),
|
|
315
|
+
});
|
|
316
|
+
const sent = await sendEmail(ctx, data.oldEmail, content);
|
|
317
|
+
if (!sent) {
|
|
318
|
+
ctx.logger.info({ oldEmail: data.oldEmail, newEmail: data.newEmail }, 'authkit: confirmação de troca de e-mail concluída (dev — @adonisjs/mail ausente)');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
ctx.logger.error({ err: error, email: data.oldEmail }, 'authkit: falha ao enviar confirmação de troca de e-mail concluída');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Envia um e-mail de notificação de segurança para a conta (senha alterada,
|
|
327
|
+
* MFA habilitado/desabilitado, passkey adicionada/removida, e-mail alterado).
|
|
328
|
+
* Best-effort: no fallback (sem mail) loga o evento; nunca lança.
|
|
329
|
+
*/
|
|
330
|
+
export async function sendSecurityNoticeEmail(ctx, data) {
|
|
331
|
+
try {
|
|
332
|
+
const brand = resolveBrand(ctx);
|
|
333
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
334
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
335
|
+
const kindKey = `mail.security_notice.kind_${data.kind}`;
|
|
336
|
+
const kindLabel = translate(t, kindKey);
|
|
337
|
+
const intro = [
|
|
338
|
+
translate(t, 'mail.security_notice.intro', { kind: kindLabel }),
|
|
339
|
+
translate(t, 'mail.security_notice.when', { date: data.timestamp }),
|
|
340
|
+
];
|
|
341
|
+
if (data.ip)
|
|
342
|
+
intro.push(translate(t, 'mail.security_notice.ip', { ip: data.ip }));
|
|
343
|
+
const content = renderTransactionalEmail({
|
|
344
|
+
brand,
|
|
345
|
+
locale,
|
|
346
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
347
|
+
subject: translate(t, 'mail.security_notice.subject', { kind: kindLabel }),
|
|
348
|
+
heading: translate(t, 'mail.security_notice.heading'),
|
|
349
|
+
intro: intro.join(' '),
|
|
350
|
+
ctaLabel: translate(t, 'account.security.title'),
|
|
351
|
+
ctaUrl: `${origin}/account/security`,
|
|
352
|
+
footnote: translate(t, 'mail.security_notice.fallback'),
|
|
353
|
+
});
|
|
354
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
355
|
+
if (!sent) {
|
|
356
|
+
ctx.logger.info({ kind: data.kind, email: data.email }, 'authkit: notificação de segurança (dev — @adonisjs/mail ausente)');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
ctx.logger.error({ err: error, email: data.email, kind: data.kind }, 'authkit: falha ao enviar notificação de segurança');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Envia o e-mail de desbloqueio do fator OTP (quando TOTP/recovery excede maxAttempts).
|
|
365
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
366
|
+
*/
|
|
367
|
+
export async function sendOtpUnlockEmail(ctx, data) {
|
|
368
|
+
try {
|
|
369
|
+
const brand = resolveBrand(ctx);
|
|
370
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
371
|
+
const content = renderTransactionalEmail({
|
|
372
|
+
brand,
|
|
373
|
+
locale,
|
|
374
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
375
|
+
subject: translate(t, 'mail.otp_unlock.subject'),
|
|
376
|
+
heading: translate(t, 'mail.otp_unlock.heading'),
|
|
377
|
+
intro: translate(t, 'mail.otp_unlock.intro'),
|
|
378
|
+
ctaLabel: translate(t, 'mail.otp_unlock.cta'),
|
|
379
|
+
ctaUrl: data.unlockUrl,
|
|
380
|
+
footnote: translate(t, 'mail.otp_unlock.fallback'),
|
|
381
|
+
});
|
|
382
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
383
|
+
if (!sent) {
|
|
384
|
+
ctx.logger.info({ unlockUrl: data.unlockUrl, email: data.email }, 'authkit: link de desbloqueio OTP (dev — @adonisjs/mail ausente)');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar e-mail de desbloqueio OTP');
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Envia o e-mail de verificação pelo mailer default do host.
|
|
393
|
+
* Best-effort: no fallback (sem mail) loga o link; nunca lança.
|
|
394
|
+
*/
|
|
395
|
+
export async function sendEmailVerificationEmail(ctx, data) {
|
|
396
|
+
try {
|
|
397
|
+
const brand = resolveBrand(ctx);
|
|
398
|
+
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
399
|
+
const content = renderTransactionalEmail({
|
|
400
|
+
brand,
|
|
401
|
+
locale,
|
|
402
|
+
linkFallback: translate(t, 'mail.common.link_fallback'),
|
|
403
|
+
subject: translate(t, 'mail.verify.subject'),
|
|
404
|
+
heading: translate(t, 'mail.verify.heading'),
|
|
405
|
+
intro: translate(t, 'mail.verify.intro'),
|
|
406
|
+
ctaLabel: translate(t, 'mail.verify.cta'),
|
|
407
|
+
ctaUrl: data.verifyUrl,
|
|
408
|
+
});
|
|
409
|
+
const sent = await sendEmail(ctx, data.email, content);
|
|
410
|
+
if (!sent) {
|
|
411
|
+
ctx.logger.info({ verifyUrl: data.verifyUrl, email: data.email }, 'authkit: link de verificação de e-mail (dev — @adonisjs/mail ausente)');
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar verificação de e-mail');
|
|
416
|
+
}
|
|
417
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { OidcService } from "../../provider/oidc_service.js";
|
|
2
|
+
import type { DeletionActor } from "../account_deletion_service.js";
|
|
3
|
+
/** Nome canônico do workflow durável de deleção de conta. */
|
|
4
|
+
export declare const ACCOUNT_DELETE_WORKFLOW = "authkit.account.delete";
|
|
5
|
+
/** Input do workflow `authkit.account.delete`. */
|
|
6
|
+
export interface AccountDeleteWorkflowInput {
|
|
7
|
+
accountId: string;
|
|
8
|
+
actor: DeletionActor;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Forma mínima do `ctx` durável que o corpo usa (um `ctx.step` checkpointado e
|
|
12
|
+
* idempotente). Tipada estruturalmente para NÃO acoplar o build do authkit ao
|
|
13
|
+
* pacote `@adonis-agora/durable` (peer OPCIONAL): o app passa o `engine.register`
|
|
14
|
+
* real e o ctx satisfaz esta interface em runtime.
|
|
15
|
+
*/
|
|
16
|
+
export interface DurableStepCtx {
|
|
17
|
+
step<T>(name: string, fn: (...args: any[]) => Promise<T>, options?: unknown): Promise<T>;
|
|
18
|
+
}
|
|
19
|
+
/** A assinatura do corpo do workflow (compatível com `engine.register`). */
|
|
20
|
+
export type WorkflowBody = (ctx: DurableStepCtx, input: AccountDeleteWorkflowInput) => Promise<unknown>;
|
|
21
|
+
/** Deps que o app injeta ao definir o workflow no seu próprio `WorkflowEngine`. */
|
|
22
|
+
export interface AccountDeletionWorkflowDeps {
|
|
23
|
+
/** Resolve o {@link OidcService} (de onde sai a config). Chamado DENTRO de um step. */
|
|
24
|
+
oidc: () => OidcService | Promise<OidcService>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Define a REGISTRAÇÃO do workflow durável `authkit.account.delete`.
|
|
28
|
+
*
|
|
29
|
+
* Retorna `{ name, version, body }` para o app registrar no seu `WorkflowEngine`:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { defineAccountDeletionWorkflow } from '@adonis-agora/authkit-server/durable'
|
|
33
|
+
* const wf = defineAccountDeletionWorkflow({ oidc: () => app.container.make('authkit.server') })
|
|
34
|
+
* engine.register(wf.name, wf.version, wf.body)
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* O corpo é FORWARD-ONLY (sem compensação — nunca des-deleta): cada etapa do
|
|
38
|
+
* cascade é um `ctx.step` checkpointado, com retry por-etapa e resumabilidade. A
|
|
39
|
+
* linha da conta é a ÚLTIMA etapa. Todos os efeitos colaterais ficam DENTRO de
|
|
40
|
+
* `ctx.step` (corpo determinístico: nada de Date.now()/random no corpo). A
|
|
41
|
+
* idempotência por `accountId` é feita pelo run-id no enqueue (ver
|
|
42
|
+
* `enqueueAccountDeletion`).
|
|
43
|
+
*/
|
|
44
|
+
export declare function defineAccountDeletionWorkflow(deps: AccountDeletionWorkflowDeps): {
|
|
45
|
+
name: string;
|
|
46
|
+
version: string;
|
|
47
|
+
body: WorkflowBody;
|
|
48
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { anonymizeAudit, auditDeleted, deleteAccountAvatar, deleteAccountRow, disableMfa, removeFromOrgs, removePasskeys, revokePats, revokeSessions, snapshotAccount, unlinkProviders, } from "../account_deletion_ops.js";
|
|
2
|
+
/** Nome canônico do workflow durável de deleção de conta. */
|
|
3
|
+
export const ACCOUNT_DELETE_WORKFLOW = "authkit.account.delete";
|
|
4
|
+
/** Estado inicial vazio do {@link DeletionResult} (acumulado etapa a etapa). */
|
|
5
|
+
function emptyResult() {
|
|
6
|
+
return {
|
|
7
|
+
ok: false,
|
|
8
|
+
sessions: 0,
|
|
9
|
+
grants: 0,
|
|
10
|
+
accessTokens: 0,
|
|
11
|
+
refreshTokens: 0,
|
|
12
|
+
pats: 0,
|
|
13
|
+
passkeys: 0,
|
|
14
|
+
providerIdentities: 0,
|
|
15
|
+
auditAnonymized: 0,
|
|
16
|
+
avatarDeleted: false,
|
|
17
|
+
orgMemberships: 0,
|
|
18
|
+
orgInvitations: 0,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Define a REGISTRAÇÃO do workflow durável `authkit.account.delete`.
|
|
23
|
+
*
|
|
24
|
+
* Retorna `{ name, version, body }` para o app registrar no seu `WorkflowEngine`:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { defineAccountDeletionWorkflow } from '@adonis-agora/authkit-server/durable'
|
|
28
|
+
* const wf = defineAccountDeletionWorkflow({ oidc: () => app.container.make('authkit.server') })
|
|
29
|
+
* engine.register(wf.name, wf.version, wf.body)
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* O corpo é FORWARD-ONLY (sem compensação — nunca des-deleta): cada etapa do
|
|
33
|
+
* cascade é um `ctx.step` checkpointado, com retry por-etapa e resumabilidade. A
|
|
34
|
+
* linha da conta é a ÚLTIMA etapa. Todos os efeitos colaterais ficam DENTRO de
|
|
35
|
+
* `ctx.step` (corpo determinístico: nada de Date.now()/random no corpo). A
|
|
36
|
+
* idempotência por `accountId` é feita pelo run-id no enqueue (ver
|
|
37
|
+
* `enqueueAccountDeletion`).
|
|
38
|
+
*/
|
|
39
|
+
export function defineAccountDeletionWorkflow(deps) {
|
|
40
|
+
const body = async (ctx, input) => {
|
|
41
|
+
const { accountId, actor } = input;
|
|
42
|
+
// Snapshot da conta ANTES de destruir (e-mail + avatar) — capturado num step
|
|
43
|
+
// para ser determinístico no replay. Se a conta não existe (ou já foi
|
|
44
|
+
// deletada num run anterior), encerra como no-op.
|
|
45
|
+
const snapshot = await ctx.step("snapshot", async () => {
|
|
46
|
+
const cfg = (await deps.oidc()).config;
|
|
47
|
+
return snapshotAccount(cfg, accountId);
|
|
48
|
+
});
|
|
49
|
+
if (!snapshot)
|
|
50
|
+
return emptyResult();
|
|
51
|
+
const result = emptyResult();
|
|
52
|
+
// 1) Audit `account.deleted` ANTES de qualquer destruição.
|
|
53
|
+
await ctx.step("audit.deleted", async () => {
|
|
54
|
+
const cfg = (await deps.oidc()).config;
|
|
55
|
+
await auditDeleted(cfg, snapshot, actor);
|
|
56
|
+
});
|
|
57
|
+
// 2) Sessões + grants (cascateia os tokens do oidc-provider).
|
|
58
|
+
const revoke = await ctx.step("revoke.sessions", async () => revokeSessions(await deps.oidc(), accountId));
|
|
59
|
+
result.sessions = revoke.sessions;
|
|
60
|
+
result.grants = revoke.grants;
|
|
61
|
+
result.accessTokens = revoke.accessTokens;
|
|
62
|
+
result.refreshTokens = revoke.refreshTokens;
|
|
63
|
+
// 3) Personal Access Tokens.
|
|
64
|
+
result.pats = (await ctx.step("revoke.pats", async () => revokePats((await deps.oidc()).config, accountId))).pats;
|
|
65
|
+
// 4) Passkeys / credenciais WebAuthn.
|
|
66
|
+
result.passkeys = (await ctx.step("remove.passkeys", async () => removePasskeys((await deps.oidc()).config, accountId))).passkeys;
|
|
67
|
+
// 5) MFA / TOTP.
|
|
68
|
+
await ctx.step("disable.mfa", async () => {
|
|
69
|
+
await disableMfa((await deps.oidc()).config, accountId);
|
|
70
|
+
});
|
|
71
|
+
// 6) Identidades de provider linkadas.
|
|
72
|
+
result.providerIdentities = (await ctx.step("unlink.providers", async () => unlinkProviders((await deps.oidc()).config, accountId))).providerIdentities;
|
|
73
|
+
// 6b) Organizations.
|
|
74
|
+
const orgResult = await ctx.step("remove.orgs", async () => removeFromOrgs((await deps.oidc()).config, accountId));
|
|
75
|
+
result.orgMemberships = orgResult.orgMemberships;
|
|
76
|
+
result.orgInvitations = orgResult.orgInvitations;
|
|
77
|
+
// 7) Avatar no drive.
|
|
78
|
+
result.avatarDeleted = (await ctx.step("delete.avatar", async () => deleteAccountAvatar((await deps.oidc()).config, snapshot.avatarUrl))).avatarDeleted;
|
|
79
|
+
// 8) Anonimiza o histórico de audit.
|
|
80
|
+
result.auditAnonymized = (await ctx.step("anonymize.audit", async () => anonymizeAudit((await deps.oidc()).config, accountId))).auditAnonymized;
|
|
81
|
+
// 9) Deleta a linha da conta (ÚLTIMA etapa, forward-only).
|
|
82
|
+
result.ok = (await ctx.step("delete.account", async () => deleteAccountRow((await deps.oidc()).config, accountId))).ok;
|
|
83
|
+
return result;
|
|
84
|
+
};
|
|
85
|
+
return { name: ACCOUNT_DELETE_WORKFLOW, version: "1", body };
|
|
86
|
+
}
|