@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,215 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('account.security.page_title') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
</head>
|
|
5
|
+
<body class="min-h-screen bg-gray-100 p-4">
|
|
6
|
+
<div class="mx-auto max-w-2xl">
|
|
7
|
+
<div class="flex items-center justify-between py-6">
|
|
8
|
+
<div>
|
|
9
|
+
<div class="text-xs font-semibold uppercase tracking-widest text-gray-400">{{ t('common.brand_eyebrow') }}</div>
|
|
10
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('account.security.title') }}</h1>
|
|
11
|
+
@if(email)
|
|
12
|
+
<p class="mt-1 text-sm text-gray-500">{{ t('account.security.current_email', { email: email }) }}</p>
|
|
13
|
+
@end
|
|
14
|
+
</div>
|
|
15
|
+
<form method="POST" action="/account/logout">
|
|
16
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
17
|
+
<button type="submit" class="text-sm text-gray-500 hover:underline">{{ t('account.security.logout') }}</button>
|
|
18
|
+
</form>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<nav class="mb-6 flex gap-4 text-sm font-medium">
|
|
22
|
+
<a href="/account/tokens" class="text-gray-500 hover:underline">{{ t('account.tokens.title') }}</a>
|
|
23
|
+
<a href="/account/security" class="text-gray-900 underline">{{ t('account.security.title') }}</a>
|
|
24
|
+
<a href="/account/apps" class="text-gray-500 hover:underline">{{ t('account.apps.title') }}</a>
|
|
25
|
+
</nav>
|
|
26
|
+
|
|
27
|
+
@if(profileUpdated)
|
|
28
|
+
<div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
|
|
29
|
+
<p class="text-sm font-medium text-emerald-900">{{ profileUpdated }}</p>
|
|
30
|
+
</div>
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
@if(profileSupported)
|
|
34
|
+
<div class="mb-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
35
|
+
<h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.profile.section') }}</h2>
|
|
36
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.profile.intro') }}</p>
|
|
37
|
+
<form method="POST" action="/account/security/profile" enctype="multipart/form-data" class="space-y-4">
|
|
38
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
39
|
+
@if(avatarUrl)
|
|
40
|
+
<div>
|
|
41
|
+
<img src="{{ avatarUrl }}" alt="avatar" class="h-16 w-16 rounded-full object-cover ring-1 ring-black/5" />
|
|
42
|
+
</div>
|
|
43
|
+
@end
|
|
44
|
+
<div>
|
|
45
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.name_label') }}</label>
|
|
46
|
+
<input name="name" type="text" value="{{ name }}" maxlength="255"
|
|
47
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
48
|
+
</div>
|
|
49
|
+
@if(avatarUploadSupported)
|
|
50
|
+
<div>
|
|
51
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.avatar_upload_label') }}</label>
|
|
52
|
+
<input name="avatar" type="file" accept="image/jpeg,image/png,image/webp"
|
|
53
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
54
|
+
<p class="mt-1 text-xs text-gray-500">{{ t('account.profile.avatar_upload_hint') }}</p>
|
|
55
|
+
</div>
|
|
56
|
+
@end
|
|
57
|
+
<div>
|
|
58
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.avatar_label') }}</label>
|
|
59
|
+
<input name="avatarUrl" type="url" value="{{ avatarUrl }}"
|
|
60
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
61
|
+
</div>
|
|
62
|
+
<button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
|
|
63
|
+
{{ t('account.profile.submit') }}
|
|
64
|
+
</button>
|
|
65
|
+
</form>
|
|
66
|
+
</div>
|
|
67
|
+
@end
|
|
68
|
+
|
|
69
|
+
@if(!supported)
|
|
70
|
+
<div class="rounded-xl bg-white p-6 text-sm text-gray-500 shadow-sm ring-1 ring-black/5">
|
|
71
|
+
{{ t('account.security.not_supported') }}
|
|
72
|
+
</div>
|
|
73
|
+
@else
|
|
74
|
+
@if(error)
|
|
75
|
+
<div class="mb-6 rounded-lg border border-red-300 bg-red-50 p-4">
|
|
76
|
+
<p class="text-sm font-medium text-red-900">{{ error }}</p>
|
|
77
|
+
</div>
|
|
78
|
+
@end
|
|
79
|
+
@if(passwordChanged)
|
|
80
|
+
<div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
|
|
81
|
+
<p class="text-sm font-medium text-emerald-900">{{ passwordChanged }}</p>
|
|
82
|
+
</div>
|
|
83
|
+
@end
|
|
84
|
+
@if(emailChangeRequested)
|
|
85
|
+
<div class="mb-6 rounded-lg border border-blue-300 bg-blue-50 p-4">
|
|
86
|
+
<p class="text-sm font-medium text-blue-900">{{ emailChangeRequested }}</p>
|
|
87
|
+
</div>
|
|
88
|
+
@end
|
|
89
|
+
|
|
90
|
+
<div class="mb-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
91
|
+
<h2 class="mb-4 text-sm font-semibold text-gray-900">{{ t('account.security.password_section') }}</h2>
|
|
92
|
+
<form method="POST" action="/account/security/password" class="space-y-4">
|
|
93
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
94
|
+
<div>
|
|
95
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.current_password_label') }}</label>
|
|
96
|
+
<input name="currentPassword" type="password" required
|
|
97
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
98
|
+
</div>
|
|
99
|
+
<div>
|
|
100
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.new_password_label') }}</label>
|
|
101
|
+
<input name="newPassword" type="password" required minlength="8"
|
|
102
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
103
|
+
</div>
|
|
104
|
+
<button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
|
|
105
|
+
{{ t('account.security.change_password_submit') }}
|
|
106
|
+
</button>
|
|
107
|
+
</form>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
111
|
+
<h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.email_section') }}</h2>
|
|
112
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.security.email_intro') }}</p>
|
|
113
|
+
<form method="POST" action="/account/security/email" class="space-y-4">
|
|
114
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
115
|
+
<div>
|
|
116
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.new_email_label') }}</label>
|
|
117
|
+
<input name="newEmail" type="email" required
|
|
118
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
119
|
+
</div>
|
|
120
|
+
<div>
|
|
121
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.email_password_label') }}</label>
|
|
122
|
+
<input name="currentPassword" type="password" required
|
|
123
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
124
|
+
</div>
|
|
125
|
+
<button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
|
|
126
|
+
{{ t('account.security.change_email_submit') }}
|
|
127
|
+
</button>
|
|
128
|
+
</form>
|
|
129
|
+
</div>
|
|
130
|
+
@end
|
|
131
|
+
|
|
132
|
+
@if(sessionsSupported)
|
|
133
|
+
<div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
134
|
+
<h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.sessions_section') }}</h2>
|
|
135
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.security.sessions_intro') }}</p>
|
|
136
|
+
@if(sessions.length === 0)
|
|
137
|
+
<p class="text-sm text-gray-500">{{ t('account.security.sessions_empty') }}</p>
|
|
138
|
+
@else
|
|
139
|
+
<ul class="divide-y divide-gray-100">
|
|
140
|
+
@each(session in sessions)
|
|
141
|
+
<li class="py-3">
|
|
142
|
+
@if(session.browser || session.os)
|
|
143
|
+
<p class="text-sm font-medium text-gray-900">{{ t('admin.sessions.session_device', { browser: session.browser || '—', os: session.os || '—' }) }}</p>
|
|
144
|
+
@end
|
|
145
|
+
@if(session.ip)
|
|
146
|
+
<p class="text-xs text-gray-500">{{ session.location ? t('admin.sessions.session_ip_geo', { ip: session.ip, location: session.location }) : t('admin.sessions.session_ip', { ip: session.ip }) }}</p>
|
|
147
|
+
@end
|
|
148
|
+
@if(session.loginTs)
|
|
149
|
+
<p class="text-xs text-gray-400">{{ t('admin.sessions.session_login_ts', { date: session.loginTs }) }}</p>
|
|
150
|
+
@end
|
|
151
|
+
</li>
|
|
152
|
+
@end
|
|
153
|
+
</ul>
|
|
154
|
+
@end
|
|
155
|
+
</div>
|
|
156
|
+
@end
|
|
157
|
+
|
|
158
|
+
@if(trustedDevicesEnabled)
|
|
159
|
+
@if(trustedDevicesRevoked)
|
|
160
|
+
<div class="mt-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
|
|
161
|
+
<p class="text-sm font-medium text-emerald-900">{{ trustedDevicesRevoked }}</p>
|
|
162
|
+
</div>
|
|
163
|
+
@end
|
|
164
|
+
<div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
165
|
+
<h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.trusted_devices_section') }}</h2>
|
|
166
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.security.trusted_devices_intro') }}</p>
|
|
167
|
+
<form method="POST" action="/account/security/trusted-devices/revoke">
|
|
168
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
169
|
+
<button type="submit" class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50">
|
|
170
|
+
{{ t('account.security.trusted_devices_revoke') }}
|
|
171
|
+
</button>
|
|
172
|
+
</form>
|
|
173
|
+
</div>
|
|
174
|
+
@end
|
|
175
|
+
|
|
176
|
+
@if(exportSupported)
|
|
177
|
+
<div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
178
|
+
<h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.export.section') }}</h2>
|
|
179
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.export.intro') }}</p>
|
|
180
|
+
<a href="/account/security/export"
|
|
181
|
+
class="inline-block rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50">
|
|
182
|
+
{{ t('account.export.submit') }}
|
|
183
|
+
</a>
|
|
184
|
+
</div>
|
|
185
|
+
@end
|
|
186
|
+
|
|
187
|
+
@if(deletionSupported)
|
|
188
|
+
@if(deleteError)
|
|
189
|
+
<div class="mt-6 rounded-lg border border-red-300 bg-red-50 p-4">
|
|
190
|
+
<p class="text-sm font-medium text-red-900">{{ deleteError }}</p>
|
|
191
|
+
</div>
|
|
192
|
+
@end
|
|
193
|
+
<div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-red-200">
|
|
194
|
+
<h2 class="mb-1 text-sm font-semibold text-red-700">{{ t('account.delete.section') }}</h2>
|
|
195
|
+
<p class="mb-4 text-xs text-gray-500">{{ t('account.delete.intro') }}</p>
|
|
196
|
+
<form method="POST" action="/account/security/delete" class="space-y-4">
|
|
197
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
198
|
+
<div>
|
|
199
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.delete.confirm_password_label') }}</label>
|
|
200
|
+
<input name="currentPassword" type="password"
|
|
201
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-red-600" />
|
|
202
|
+
</div>
|
|
203
|
+
<div>
|
|
204
|
+
<label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.delete.confirm_email_label') }}</label>
|
|
205
|
+
<input name="confirmEmail" type="email" placeholder="{{ email }}"
|
|
206
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-red-600" />
|
|
207
|
+
</div>
|
|
208
|
+
<button type="submit" class="rounded-lg bg-red-600 px-4 py-2 text-sm font-semibold text-white hover:bg-red-700">
|
|
209
|
+
{{ t('account.delete.submit') }}
|
|
210
|
+
</button>
|
|
211
|
+
</form>
|
|
212
|
+
</div>
|
|
213
|
+
@end
|
|
214
|
+
</div>
|
|
215
|
+
</body></html>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('account.tokens.page_title') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
</head>
|
|
5
|
+
<body class="min-h-screen bg-gray-100 p-4">
|
|
6
|
+
<div class="mx-auto max-w-2xl">
|
|
7
|
+
<div class="flex items-center justify-between py-6">
|
|
8
|
+
<div>
|
|
9
|
+
<div class="text-xs font-semibold uppercase tracking-widest text-gray-400">{{ t('common.brand_eyebrow') }}</div>
|
|
10
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('account.tokens.title') }}</h1>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="flex items-center gap-4">
|
|
13
|
+
<a href="/account/security" class="text-sm text-gray-500 hover:underline">{{ t('account.tokens.security') }}</a>
|
|
14
|
+
<a href="/account/apps" class="text-sm text-gray-500 hover:underline">{{ t('account.apps.title') }}</a>
|
|
15
|
+
<form method="POST" action="/account/logout">
|
|
16
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
17
|
+
<button type="submit" class="text-sm text-gray-500 hover:underline">{{ t('account.tokens.logout') }}</button>
|
|
18
|
+
</form>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
@if(createdToken)
|
|
23
|
+
<div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
|
|
24
|
+
<p class="text-sm font-medium text-emerald-900">
|
|
25
|
+
{{ t('account.tokens.created_notice') }}
|
|
26
|
+
</p>
|
|
27
|
+
<code class="mt-2 block break-all rounded bg-white px-3 py-2 text-sm text-emerald-800 ring-1 ring-emerald-200">
|
|
28
|
+
{{ createdToken }}
|
|
29
|
+
</code>
|
|
30
|
+
</div>
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
<form method="POST" action="/account/tokens"
|
|
34
|
+
class="mb-6 flex gap-2 rounded-xl bg-white p-4 shadow-sm ring-1 ring-black/5">
|
|
35
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
36
|
+
<input name="name" placeholder="{{ t('account.tokens.name_placeholder') }}"
|
|
37
|
+
class="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
38
|
+
<button type="submit" class="rounded-lg bg-gray-900 px-4 text-sm font-semibold text-white">
|
|
39
|
+
{{ t('account.tokens.create') }}
|
|
40
|
+
</button>
|
|
41
|
+
</form>
|
|
42
|
+
|
|
43
|
+
<div class="overflow-hidden rounded-xl bg-white shadow-sm ring-1 ring-black/5">
|
|
44
|
+
@if(tokens.length === 0)
|
|
45
|
+
<p class="p-6 text-sm text-gray-500">{{ t('account.tokens.empty') }}</p>
|
|
46
|
+
@else
|
|
47
|
+
@each(token in tokens)
|
|
48
|
+
<div class="flex items-center justify-between border-b border-gray-100 p-4 last:border-0">
|
|
49
|
+
<div>
|
|
50
|
+
<p class="text-sm font-medium text-gray-900">{{ token.name }}</p>
|
|
51
|
+
<p class="text-xs text-gray-500">
|
|
52
|
+
{{ t('account.tokens.created_at', { date: token.createdAt }) }}
|
|
53
|
+
@if(token.lastUsedAt)
|
|
54
|
+
{{ t('account.tokens.last_used', { date: token.lastUsedAt }) }}
|
|
55
|
+
@else
|
|
56
|
+
{{ t('account.tokens.never_used') }}
|
|
57
|
+
@end
|
|
58
|
+
</p>
|
|
59
|
+
@if(token.scopes && token.scopes.length > 0)
|
|
60
|
+
<p class="text-xs text-gray-400">{{ t('account.tokens.scopes', { scopes: token.scopes.join(', ') }) }}</p>
|
|
61
|
+
@end
|
|
62
|
+
@if(token.audience)
|
|
63
|
+
<p class="text-xs text-gray-400">{{ t('account.tokens.audience', { audience: token.audience }) }}</p>
|
|
64
|
+
@end
|
|
65
|
+
</div>
|
|
66
|
+
<form method="POST" action="/account/tokens/{{ token.id }}/revoke">
|
|
67
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
68
|
+
<button type="submit" class="text-sm text-red-600 hover:underline">{{ t('account.tokens.revoke') }}</button>
|
|
69
|
+
</form>
|
|
70
|
+
</div>
|
|
71
|
+
@end
|
|
72
|
+
@end
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</body></html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('consent.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
</head>
|
|
5
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
6
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
7
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/consent">
|
|
8
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
9
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('consent.title') }}</h1>
|
|
10
|
+
<p class="mt-2 text-sm text-gray-600">
|
|
11
|
+
{{{ t('consent.body', { app: brand && brand.appName ? brand.appName : params.client_id }) }}}
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<button type="submit"
|
|
15
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
16
|
+
{{ t('consent.submit') }}
|
|
17
|
+
</button>
|
|
18
|
+
</form>
|
|
19
|
+
</div>
|
|
20
|
+
</body></html>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('forgot.page_title') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
@if(botProtection && botProtection.scriptUrl)
|
|
5
|
+
<script src="{{ botProtection.scriptUrl }}" async defer></script>
|
|
6
|
+
@end
|
|
7
|
+
</head>
|
|
8
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
9
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
10
|
+
@if(sent)
|
|
11
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('forgot.sent_title') }}</h1>
|
|
12
|
+
<p class="mt-2 text-sm text-gray-600">
|
|
13
|
+
{{ t('forgot.sent_body') }}
|
|
14
|
+
</p>
|
|
15
|
+
@else
|
|
16
|
+
<form method="POST" action="/auth/forgot-password">
|
|
17
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
18
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('forgot.title') }}</h1>
|
|
19
|
+
<p class="mt-1 text-sm text-gray-500">{{ t('forgot.intro') }}</p>
|
|
20
|
+
|
|
21
|
+
@if(error)
|
|
22
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
<div class="mt-6">
|
|
26
|
+
<label for="email" class="mb-1 block text-sm font-medium text-gray-700">{{ t('forgot.email_label') }}</label>
|
|
27
|
+
<input id="email" name="email" type="email" required autofocus
|
|
28
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
{{-- Bot protection: container do widget (config-trusted; HTML do host renderizado raw). --}}
|
|
32
|
+
@if(botProtection && botProtection.html)
|
|
33
|
+
<div class="mt-4">{{{ botProtection.html }}}</div>
|
|
34
|
+
@end
|
|
35
|
+
|
|
36
|
+
<button type="submit"
|
|
37
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
38
|
+
{{ t('forgot.submit') }}
|
|
39
|
+
</button>
|
|
40
|
+
</form>
|
|
41
|
+
@end
|
|
42
|
+
</div>
|
|
43
|
+
</body></html>
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('login.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
@if(botProtection && botProtection.scriptUrl)
|
|
5
|
+
<script src="{{ botProtection.scriptUrl }}" async defer></script>
|
|
6
|
+
@end
|
|
7
|
+
</head>
|
|
8
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
9
|
+
@if(step === 'identifier')
|
|
10
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
11
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/identifier">
|
|
12
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
13
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
|
|
14
|
+
<p class="mt-1 text-sm text-gray-500">{{ t('login.identifier_intro') }}</p>
|
|
15
|
+
|
|
16
|
+
@if(error)
|
|
17
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
18
|
+
@end
|
|
19
|
+
|
|
20
|
+
<div class="mt-6">
|
|
21
|
+
<label for="email" class="mb-1 block text-sm font-medium text-gray-700">{{ t('login.email_label') }}</label>
|
|
22
|
+
<input id="email" name="email" type="email" required autofocus
|
|
23
|
+
autocomplete="{{ authMethods && authMethods.passkeyAutofill ? 'username webauthn' : 'username' }}"
|
|
24
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<button type="submit"
|
|
28
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
29
|
+
{{ t('login.identifier_submit') }}
|
|
30
|
+
</button>
|
|
31
|
+
|
|
32
|
+
<div class="mt-4 flex justify-between text-sm text-gray-600">
|
|
33
|
+
@if(registrationEnabled !== false)
|
|
34
|
+
<a href="/auth/interaction/{{ uid }}/signup" class="hover:underline">{{ t('login.create_account') }}</a>
|
|
35
|
+
@end
|
|
36
|
+
@if(!authMethods || authMethods.forgotPassword !== false)
|
|
37
|
+
<a href="/auth/forgot-password" class="hover:underline">{{ t('login.forgot_password') }}</a>
|
|
38
|
+
@end
|
|
39
|
+
</div>
|
|
40
|
+
</form>
|
|
41
|
+
|
|
42
|
+
@if(!authMethods || authMethods.social === undefined || authMethods.social.length > 0)
|
|
43
|
+
<div class="my-6 flex items-center gap-3 text-xs text-gray-400">
|
|
44
|
+
<span class="h-px flex-1 bg-gray-200"></span>
|
|
45
|
+
{{ t('login.divider_or') }}
|
|
46
|
+
<span class="h-px flex-1 bg-gray-200"></span>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
@each(provider in (authMethods && authMethods.social ? authMethods.social : []))
|
|
50
|
+
<a href="/auth/{{ provider }}/redirect/{{ uid }}"
|
|
51
|
+
class="flex w-full items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white py-2.5 text-sm font-medium text-gray-700 transition hover:bg-gray-50 mb-2">
|
|
52
|
+
@if(provider === 'google')
|
|
53
|
+
<svg class="h-4 w-4" viewBox="0 0 24 24" aria-hidden="true">
|
|
54
|
+
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.27-4.74 3.27-8.1Z"/>
|
|
55
|
+
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84A11 11 0 0 0 12 23Z"/>
|
|
56
|
+
<path fill="#FBBC05" d="M5.84 14.1a6.6 6.6 0 0 1 0-4.2V7.06H2.18a11 11 0 0 0 0 9.88l3.66-2.84Z"/>
|
|
57
|
+
<path fill="#EA4335" d="M12 4.75c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 1.46 14.97.5 12 .5A11 11 0 0 0 2.18 7.06l3.66 2.84C6.71 7.3 9.14 4.75 12 4.75Z"/>
|
|
58
|
+
</svg>
|
|
59
|
+
{{ t('login.google') }}
|
|
60
|
+
@else
|
|
61
|
+
{{ t('login.social_provider', { provider: provider }) }}
|
|
62
|
+
@end
|
|
63
|
+
</a>
|
|
64
|
+
@end
|
|
65
|
+
@end
|
|
66
|
+
|
|
67
|
+
{{-- WebAuthn autofill (conditional mediation): quando passkey + passkeyAutofill estão on
|
|
68
|
+
e o browser suporta, o input de e-mail mostra sugestões de passkeys diretamente.
|
|
69
|
+
Sucesso → submete o verify e completa o login sem precisar da senha.
|
|
70
|
+
Fail-safe total: browser sem suporte, abort ou erro = silêncio, login normal segue. --}}
|
|
71
|
+
@if(authMethods && authMethods.passkeyAutofill && authMethods.passkey)
|
|
72
|
+
<form id="autofill-passkey-form" method="POST" action="/auth/interaction/{{ uid }}/passkey/verify" class="hidden">
|
|
73
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
74
|
+
<input type="hidden" name="response" id="autofill-passkey-response">
|
|
75
|
+
</form>
|
|
76
|
+
<script type="module">
|
|
77
|
+
(async () => {
|
|
78
|
+
try {
|
|
79
|
+
// SSR-safe: só roda no browser.
|
|
80
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') return
|
|
81
|
+
if (!window.PublicKeyCredential) return
|
|
82
|
+
// Detecta suporte a conditional mediation.
|
|
83
|
+
const supported = await PublicKeyCredential.isConditionalMediationAvailable?.()
|
|
84
|
+
if (!supported) return
|
|
85
|
+
|
|
86
|
+
const { startAuthentication } = await import(
|
|
87
|
+
'https://cdn.jsdelivr.net/npm/@simplewebauthn/browser@13/dist/bundle/index.js'
|
|
88
|
+
)
|
|
89
|
+
const csrf = document.querySelector('input[name="_csrf"]')?.value ?? ''
|
|
90
|
+
const optRes = await fetch('/auth/interaction/{{ uid }}/passkey/options', {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: { 'content-type': 'application/json', 'x-csrf-token': csrf },
|
|
93
|
+
body: JSON.stringify({}),
|
|
94
|
+
})
|
|
95
|
+
if (!optRes.ok) return
|
|
96
|
+
const optionsJSON = await optRes.json()
|
|
97
|
+
// Remove flag interna antes de passar ao browser.
|
|
98
|
+
delete optionsJSON._discoverable
|
|
99
|
+
|
|
100
|
+
// AbortController: cancela ao navegar/desmontar.
|
|
101
|
+
const ac = new AbortController()
|
|
102
|
+
window.addEventListener('beforeunload', () => ac.abort(), { once: true })
|
|
103
|
+
|
|
104
|
+
const assertion = await startAuthentication({
|
|
105
|
+
optionsJSON,
|
|
106
|
+
useBrowserAutofill: true,
|
|
107
|
+
verifyBrowserAutofillInput: true,
|
|
108
|
+
}, ac.signal)
|
|
109
|
+
|
|
110
|
+
document.getElementById('autofill-passkey-response').value = JSON.stringify(assertion)
|
|
111
|
+
document.getElementById('autofill-passkey-form').submit()
|
|
112
|
+
} catch {
|
|
113
|
+
// Fail-safe: abort, suporte ausente ou qualquer erro = login normal.
|
|
114
|
+
}
|
|
115
|
+
})()
|
|
116
|
+
</script>
|
|
117
|
+
@end
|
|
118
|
+
</div>
|
|
119
|
+
@else
|
|
120
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
121
|
+
@if(!authMethods || authMethods.password !== false)
|
|
122
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/login">
|
|
123
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
124
|
+
|
|
125
|
+
@if(account && account.fullName)
|
|
126
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('login.greeting', { name: account.fullName }) }}</h1>
|
|
127
|
+
@else
|
|
128
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
|
|
129
|
+
@end
|
|
130
|
+
|
|
131
|
+
<div class="mt-1 flex items-center gap-2">
|
|
132
|
+
@if(email)
|
|
133
|
+
<span class="text-sm text-gray-500">{{ email }}</span>
|
|
134
|
+
@end
|
|
135
|
+
<a href="/auth/interaction/{{ uid }}/switch" class="text-xs font-medium text-gray-900 hover:underline">
|
|
136
|
+
{{ t('login.switch_account') }}
|
|
137
|
+
</a>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
@if(error)
|
|
141
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
142
|
+
@end
|
|
143
|
+
|
|
144
|
+
<div class="mt-6">
|
|
145
|
+
<label for="password" class="mb-1 block text-sm font-medium text-gray-700">{{ t('login.password_label') }}</label>
|
|
146
|
+
<input id="password" name="password" type="password" required autofocus
|
|
147
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{{-- Bot protection: container do widget (config-trusted; HTML do host renderizado raw). --}}
|
|
151
|
+
@if(botProtection && botProtection.html)
|
|
152
|
+
<div class="mt-4">{{{ botProtection.html }}}</div>
|
|
153
|
+
@end
|
|
154
|
+
|
|
155
|
+
{{-- Remember-me checkbox: visível apenas quando rememberEnabled=true (session_policy). --}}
|
|
156
|
+
@if(rememberEnabled !== false)
|
|
157
|
+
<div class="mt-4 flex items-center gap-2">
|
|
158
|
+
<input id="remember" name="remember" type="checkbox" value="on"
|
|
159
|
+
class="h-4 w-4 rounded border-gray-300 text-gray-900 focus:ring-gray-900" />
|
|
160
|
+
<label for="remember" class="text-sm text-gray-700">{{ t('login.remember_me') }}</label>
|
|
161
|
+
</div>
|
|
162
|
+
@end
|
|
163
|
+
|
|
164
|
+
<button type="submit"
|
|
165
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
166
|
+
{{ t('login.submit') }}
|
|
167
|
+
</button>
|
|
168
|
+
|
|
169
|
+
@if(!authMethods || authMethods.forgotPassword !== false)
|
|
170
|
+
<div class="mt-4 flex justify-end text-sm text-gray-600">
|
|
171
|
+
<a href="/auth/forgot-password" class="hover:underline">{{ t('login.forgot_password') }}</a>
|
|
172
|
+
</div>
|
|
173
|
+
@end
|
|
174
|
+
</form>
|
|
175
|
+
@else
|
|
176
|
+
{{-- Sem método senha: cabeçalho sem o formulário de senha --}}
|
|
177
|
+
@if(account && account.fullName)
|
|
178
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('login.greeting', { name: account.fullName }) }}</h1>
|
|
179
|
+
@else
|
|
180
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
|
|
181
|
+
@end
|
|
182
|
+
<div class="mt-1 flex items-center gap-2">
|
|
183
|
+
@if(email)
|
|
184
|
+
<span class="text-sm text-gray-500">{{ email }}</span>
|
|
185
|
+
@end
|
|
186
|
+
<a href="/auth/interaction/{{ uid }}/switch" class="text-xs font-medium text-gray-900 hover:underline">
|
|
187
|
+
{{ t('login.switch_account') }}
|
|
188
|
+
</a>
|
|
189
|
+
</div>
|
|
190
|
+
@if(error)
|
|
191
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
192
|
+
@end
|
|
193
|
+
@end
|
|
194
|
+
|
|
195
|
+
{{-- Passwordless: confirmação de magic link enviado (anti-enumeração). --}}
|
|
196
|
+
@if(magicLinkSent)
|
|
197
|
+
<p class="mt-4 rounded-lg bg-green-50 px-3 py-2 text-sm text-green-700">{{ t('login.magic_link_sent') }}</p>
|
|
198
|
+
@end
|
|
199
|
+
|
|
200
|
+
{{-- Passwordless: "me envie um link de login" (mesma sessão/e-mail; não pede senha). --}}
|
|
201
|
+
@if(magicLinkAvailable && !magicLinkSent)
|
|
202
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/magic" class="mt-4">
|
|
203
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
204
|
+
<button type="submit"
|
|
205
|
+
class="w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
|
|
206
|
+
{{ t('login.magic_link_button') }}
|
|
207
|
+
</button>
|
|
208
|
+
</form>
|
|
209
|
+
@end
|
|
210
|
+
|
|
211
|
+
{{-- Passwordless: "entrar com passkey" ANTES da senha. Reusa as cerimônias
|
|
212
|
+
de passkey do MFA (begin/finish) liberadas no estágio de senha. --}}
|
|
213
|
+
@if(passkeyFirstAvailable)
|
|
214
|
+
<form id="passkey-form" method="POST" action="/auth/interaction/{{ uid }}/passkey/verify" class="mt-4">
|
|
215
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
216
|
+
<input type="hidden" name="response" id="passkey-response">
|
|
217
|
+
</form>
|
|
218
|
+
<button type="button" id="passkey-button"
|
|
219
|
+
class="mt-4 w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
|
|
220
|
+
{{ t('login.passkey_button') }}
|
|
221
|
+
</button>
|
|
222
|
+
<p id="passkey-error" class="mt-3 hidden text-sm text-red-600">{{ t('mfa_challenge.passkey_error') }}</p>
|
|
223
|
+
<script type="module">
|
|
224
|
+
import { startAuthentication } from 'https://cdn.jsdelivr.net/npm/@simplewebauthn/browser@13/dist/bundle/index.js'
|
|
225
|
+
const btn = document.getElementById('passkey-button')
|
|
226
|
+
const errEl = document.getElementById('passkey-error')
|
|
227
|
+
const csrf = document.querySelector('#passkey-form input[name="_csrf"]').value
|
|
228
|
+
btn?.addEventListener('click', async () => {
|
|
229
|
+
errEl.classList.add('hidden')
|
|
230
|
+
btn.disabled = true
|
|
231
|
+
try {
|
|
232
|
+
const res = await fetch('/auth/interaction/{{ uid }}/passkey/options', {
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: { 'content-type': 'application/json', 'x-csrf-token': csrf },
|
|
235
|
+
body: JSON.stringify({}),
|
|
236
|
+
})
|
|
237
|
+
if (!res.ok) throw new Error('options')
|
|
238
|
+
const optionsJSON = await res.json()
|
|
239
|
+
const assertion = await startAuthentication({ optionsJSON })
|
|
240
|
+
document.getElementById('passkey-response').value = JSON.stringify(assertion)
|
|
241
|
+
document.getElementById('passkey-form').submit()
|
|
242
|
+
} catch (e) {
|
|
243
|
+
errEl.classList.remove('hidden')
|
|
244
|
+
btn.disabled = false
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
</script>
|
|
248
|
+
@end
|
|
249
|
+
</div>
|
|
250
|
+
@end
|
|
251
|
+
</body></html>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('maintenance.title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
|
|
3
|
+
@include('authkit::partials/styles')
|
|
4
|
+
</head>
|
|
5
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
6
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5 text-center">
|
|
7
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('maintenance.title') }}</h1>
|
|
8
|
+
<p class="mt-3 text-sm text-gray-600">{{ message }}</p>
|
|
9
|
+
|
|
10
|
+
{{-- Admins can still authenticate. The form POSTs to the interaction identifier
|
|
11
|
+
endpoint; from there the normal password step runs, and the POST /login
|
|
12
|
+
guard allows admins through even during maintenance. --}}
|
|
13
|
+
@if(adminLoginAllowed && uid)
|
|
14
|
+
<details class="mt-6 text-left">
|
|
15
|
+
<summary class="cursor-pointer text-xs text-gray-400 hover:text-gray-600 select-none">
|
|
16
|
+
{{ adminLoginNote }}
|
|
17
|
+
</summary>
|
|
18
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/identifier" class="mt-3 space-y-3">
|
|
19
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
20
|
+
<input name="email" type="email" required autofocus placeholder="{{ t('login.email_label') }}"
|
|
21
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
22
|
+
<button type="submit"
|
|
23
|
+
class="w-full rounded-lg bg-gray-800 py-2 text-sm font-medium text-white transition hover:bg-gray-700">
|
|
24
|
+
{{ t('login.identifier_submit') }}
|
|
25
|
+
</button>
|
|
26
|
+
</form>
|
|
27
|
+
</details>
|
|
28
|
+
@elseif(adminLoginAllowed)
|
|
29
|
+
<p class="mt-4 text-xs text-gray-400">{{ adminLoginNote }}</p>
|
|
30
|
+
@end
|
|
31
|
+
</div>
|
|
32
|
+
</body></html>
|