@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,238 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
|
|
3
|
+
import { AdminOrgsService } from '../admin_api/admin_orgs_service.js';
|
|
4
|
+
import { resolveRuntimeSettings } from '../runtime_settings.js';
|
|
5
|
+
import { orgDto, orgDetailDto, apiError } from '../admin_api/dto.js';
|
|
6
|
+
import { orgCreateValidator, orgUpdateValidator, orgAddMemberValidator, orgMemberRoleValidator, orgInvitationValidator, } from '../admin_validators.js';
|
|
7
|
+
/**
|
|
8
|
+
* Endpoints JSON de organizações do console admin React.
|
|
9
|
+
* 404 honesto quando o store não suporta organizações (`capability_unsupported`).
|
|
10
|
+
*
|
|
11
|
+
* GET {prefix}/api/orgs → lista orgs com contagem de membros
|
|
12
|
+
* POST {prefix}/api/orgs → cria uma org
|
|
13
|
+
* GET {prefix}/api/orgs/:id → detalhe da org (membros + convites)
|
|
14
|
+
* PATCH {prefix}/api/orgs/:id → edita nome/slug/logo
|
|
15
|
+
* DELETE {prefix}/api/orgs/:id → remove a org
|
|
16
|
+
* POST {prefix}/api/orgs/:id/members → adiciona membro (accountId + role)
|
|
17
|
+
* DELETE {prefix}/api/orgs/:id/members/:accountId → remove membro
|
|
18
|
+
* PATCH {prefix}/api/orgs/:id/members/:accountId → altera role do membro
|
|
19
|
+
* POST {prefix}/api/orgs/:id/invitations → cria convite (email + role)
|
|
20
|
+
* DELETE {prefix}/api/orgs/:id/invitations/:invitationId → revoga convite
|
|
21
|
+
*/
|
|
22
|
+
export default class ConsoleOrgsController {
|
|
23
|
+
async svc(ctx) {
|
|
24
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
25
|
+
return new AdminOrgsService(service.config);
|
|
26
|
+
}
|
|
27
|
+
actor(ctx) {
|
|
28
|
+
return {
|
|
29
|
+
actorId: ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null,
|
|
30
|
+
ip: ctx.request.ip?.() ?? null,
|
|
31
|
+
source: 'admin',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Resolve RuntimeSettings (fail-safe → null) para validação do catálogo de roles. */
|
|
35
|
+
async settings(ctx) {
|
|
36
|
+
return resolveRuntimeSettings(ctx);
|
|
37
|
+
}
|
|
38
|
+
/** GET {prefix}/api/orgs */
|
|
39
|
+
async index(ctx) {
|
|
40
|
+
const svc = await this.svc(ctx);
|
|
41
|
+
if (!svc.supported) {
|
|
42
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
43
|
+
}
|
|
44
|
+
const result = await svc.listOrgs();
|
|
45
|
+
if (!Array.isArray(result)) {
|
|
46
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
47
|
+
}
|
|
48
|
+
return { data: result.map((o) => orgDto(o)) };
|
|
49
|
+
}
|
|
50
|
+
/** POST {prefix}/api/orgs */
|
|
51
|
+
async store(ctx) {
|
|
52
|
+
const svc = await this.svc(ctx);
|
|
53
|
+
if (!svc.supported) {
|
|
54
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
55
|
+
}
|
|
56
|
+
const { name, slug, ownerAccountId, logoUrl } = await ctx.request.validateUsing(orgCreateValidator);
|
|
57
|
+
const result = await svc.createOrg({ name, slug, ownerAccountId, logoUrl: logoUrl ?? null }, this.actor(ctx));
|
|
58
|
+
if ('ok' in result && result.ok === false) {
|
|
59
|
+
if (result.reason === 'slug_taken') {
|
|
60
|
+
return ctx.response.unprocessableEntity(apiError('slug_taken', 'Este slug já está em uso.'));
|
|
61
|
+
}
|
|
62
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
63
|
+
}
|
|
64
|
+
return ctx.response.created(orgDto(result));
|
|
65
|
+
}
|
|
66
|
+
/** GET {prefix}/api/orgs/:id */
|
|
67
|
+
async show(ctx) {
|
|
68
|
+
const svc = await this.svc(ctx);
|
|
69
|
+
if (!svc.supported) {
|
|
70
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
71
|
+
}
|
|
72
|
+
const id = ctx.request.param('id');
|
|
73
|
+
const result = await svc.getOrg(id);
|
|
74
|
+
if ('ok' in result && result.ok === false) {
|
|
75
|
+
if (result.reason === 'not_found') {
|
|
76
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
77
|
+
}
|
|
78
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
79
|
+
}
|
|
80
|
+
return orgDetailDto(result);
|
|
81
|
+
}
|
|
82
|
+
/** PATCH {prefix}/api/orgs/:id */
|
|
83
|
+
async update(ctx) {
|
|
84
|
+
const svc = await this.svc(ctx);
|
|
85
|
+
if (!svc.supported) {
|
|
86
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
87
|
+
}
|
|
88
|
+
const id = ctx.request.param('id');
|
|
89
|
+
const { name, logoUrl } = await ctx.request.validateUsing(orgUpdateValidator);
|
|
90
|
+
const patch = {};
|
|
91
|
+
if (name !== undefined)
|
|
92
|
+
patch.name = name;
|
|
93
|
+
if (logoUrl !== undefined)
|
|
94
|
+
patch.logoUrl = logoUrl;
|
|
95
|
+
const result = await svc.updateOrg(id, patch, this.actor(ctx));
|
|
96
|
+
if ('ok' in result && result.ok === false) {
|
|
97
|
+
if (result.reason === 'not_found') {
|
|
98
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
99
|
+
}
|
|
100
|
+
if (result.reason === 'slug_taken') {
|
|
101
|
+
return ctx.response.unprocessableEntity(apiError('slug_taken', 'Este slug já está em uso.'));
|
|
102
|
+
}
|
|
103
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
104
|
+
}
|
|
105
|
+
return orgDto(result);
|
|
106
|
+
}
|
|
107
|
+
/** DELETE {prefix}/api/orgs/:id */
|
|
108
|
+
async destroy(ctx) {
|
|
109
|
+
const svc = await this.svc(ctx);
|
|
110
|
+
if (!svc.supported) {
|
|
111
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
112
|
+
}
|
|
113
|
+
const id = ctx.request.param('id');
|
|
114
|
+
const result = await svc.deleteOrg(id, this.actor(ctx));
|
|
115
|
+
if ('ok' in result && result.ok === false) {
|
|
116
|
+
if (result.reason === 'not_found') {
|
|
117
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
118
|
+
}
|
|
119
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
120
|
+
}
|
|
121
|
+
return { id, deleted: true };
|
|
122
|
+
}
|
|
123
|
+
/** POST {prefix}/api/orgs/:id/members */
|
|
124
|
+
async addMember(ctx) {
|
|
125
|
+
const svc = await this.svc(ctx);
|
|
126
|
+
if (!svc.supported) {
|
|
127
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
128
|
+
}
|
|
129
|
+
const orgId = ctx.request.param('id');
|
|
130
|
+
const { accountId, role } = await ctx.request.validateUsing(orgAddMemberValidator);
|
|
131
|
+
const result = await svc.addMember(orgId, { accountId, role: role ?? 'member' }, this.actor(ctx), await this.settings(ctx));
|
|
132
|
+
if ('ok' in result && result.ok === false) {
|
|
133
|
+
if (result.reason === 'not_found') {
|
|
134
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
135
|
+
}
|
|
136
|
+
if (result.reason === 'invalid_role') {
|
|
137
|
+
return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
|
|
138
|
+
}
|
|
139
|
+
if (result.reason === 'account_not_found') {
|
|
140
|
+
return ctx.response.notFound(apiError('account_not_found', 'Conta não encontrada.'));
|
|
141
|
+
}
|
|
142
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
143
|
+
}
|
|
144
|
+
return { ok: true };
|
|
145
|
+
}
|
|
146
|
+
/** DELETE {prefix}/api/orgs/:id/members/:accountId */
|
|
147
|
+
async removeMember(ctx) {
|
|
148
|
+
const svc = await this.svc(ctx);
|
|
149
|
+
if (!svc.supported) {
|
|
150
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
151
|
+
}
|
|
152
|
+
const orgId = ctx.request.param('id');
|
|
153
|
+
const accountId = ctx.request.param('accountId');
|
|
154
|
+
const result = await svc.removeMember(orgId, accountId, this.actor(ctx));
|
|
155
|
+
if ('ok' in result && result.ok === false) {
|
|
156
|
+
if (result.reason === 'not_found') {
|
|
157
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
158
|
+
}
|
|
159
|
+
if (result.reason === 'last_owner') {
|
|
160
|
+
return ctx.response.unprocessableEntity(apiError('last_owner', 'Não é possível remover o último owner da organização.'));
|
|
161
|
+
}
|
|
162
|
+
if (result.reason === 'member_not_found') {
|
|
163
|
+
return ctx.response.notFound(apiError('member_not_found', 'Membro não encontrado.'));
|
|
164
|
+
}
|
|
165
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
166
|
+
}
|
|
167
|
+
return { ok: true };
|
|
168
|
+
}
|
|
169
|
+
/** PATCH {prefix}/api/orgs/:id/members/:accountId */
|
|
170
|
+
async updateMemberRole(ctx) {
|
|
171
|
+
const svc = await this.svc(ctx);
|
|
172
|
+
if (!svc.supported) {
|
|
173
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
174
|
+
}
|
|
175
|
+
const orgId = ctx.request.param('id');
|
|
176
|
+
const accountId = ctx.request.param('accountId');
|
|
177
|
+
const { role } = await ctx.request.validateUsing(orgMemberRoleValidator);
|
|
178
|
+
const result = await svc.updateMemberRole(orgId, accountId, role, this.actor(ctx), await this.settings(ctx));
|
|
179
|
+
if ('ok' in result && result.ok === false) {
|
|
180
|
+
if (result.reason === 'not_found') {
|
|
181
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
182
|
+
}
|
|
183
|
+
if (result.reason === 'invalid_role') {
|
|
184
|
+
return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
|
|
185
|
+
}
|
|
186
|
+
if (result.reason === 'last_owner') {
|
|
187
|
+
return ctx.response.unprocessableEntity(apiError('last_owner', 'Não é possível alterar o role do último owner.'));
|
|
188
|
+
}
|
|
189
|
+
if (result.reason === 'member_not_found') {
|
|
190
|
+
return ctx.response.notFound(apiError('member_not_found', 'Membro não encontrado.'));
|
|
191
|
+
}
|
|
192
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
193
|
+
}
|
|
194
|
+
return { ok: true };
|
|
195
|
+
}
|
|
196
|
+
/** POST {prefix}/api/orgs/:id/invitations */
|
|
197
|
+
async createInvitation(ctx) {
|
|
198
|
+
const svc = await this.svc(ctx);
|
|
199
|
+
if (!svc.supported) {
|
|
200
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
201
|
+
}
|
|
202
|
+
const orgId = ctx.request.param('id');
|
|
203
|
+
const { email, role } = await ctx.request.validateUsing(orgInvitationValidator);
|
|
204
|
+
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
205
|
+
const result = await svc.createInvitation(orgId, { email, role: role ?? 'member' }, this.actor(ctx), origin, await this.settings(ctx));
|
|
206
|
+
if ('ok' in result && result.ok === false) {
|
|
207
|
+
if (result.reason === 'not_found') {
|
|
208
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
209
|
+
}
|
|
210
|
+
if (result.reason === 'invalid_role') {
|
|
211
|
+
return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
|
|
212
|
+
}
|
|
213
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
214
|
+
}
|
|
215
|
+
const ok = result;
|
|
216
|
+
return ctx.response.created({ ok: true, invitation: ok.invitation });
|
|
217
|
+
}
|
|
218
|
+
/** DELETE {prefix}/api/orgs/:id/invitations/:invitationId */
|
|
219
|
+
async revokeInvitation(ctx) {
|
|
220
|
+
const svc = await this.svc(ctx);
|
|
221
|
+
if (!svc.supported) {
|
|
222
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
223
|
+
}
|
|
224
|
+
const orgId = ctx.request.param('id');
|
|
225
|
+
const invitationId = ctx.request.param('invitationId');
|
|
226
|
+
const result = await svc.revokeInvitation(orgId, invitationId, this.actor(ctx));
|
|
227
|
+
if ('ok' in result && result.ok === false) {
|
|
228
|
+
if (result.reason === 'not_found') {
|
|
229
|
+
return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
|
|
230
|
+
}
|
|
231
|
+
if (result.reason === 'invitation_not_found') {
|
|
232
|
+
return ctx.response.notFound(apiError('invitation_not_found', 'Convite não encontrado.'));
|
|
233
|
+
}
|
|
234
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'O store não suporta organizações.'));
|
|
235
|
+
}
|
|
236
|
+
return { ok: true };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
+
/**
|
|
4
|
+
* GET {prefix}/api/overview
|
|
5
|
+
*
|
|
6
|
+
* Métricas-resumo do IdP para o dashboard do console React. Reutiliza
|
|
7
|
+
* `computeAdminStats` (mesma fonte do console Edge) e adiciona:
|
|
8
|
+
* - `clientsCount` — número de clients na config
|
|
9
|
+
* - `auditTotal` — total de eventos de auditoria (0 quando sink não suporta)
|
|
10
|
+
* - `recentEvents` — últimos 5 eventos de auditoria ([] quando não suporta)
|
|
11
|
+
*/
|
|
12
|
+
export default class ConsoleOverviewController {
|
|
13
|
+
handle(ctx: HttpContext): Promise<{
|
|
14
|
+
usersTotal: number;
|
|
15
|
+
activeSessions: number | null;
|
|
16
|
+
mau: number;
|
|
17
|
+
signInsTotal: number;
|
|
18
|
+
signUpsTotal: number;
|
|
19
|
+
signInsPerDay: import("../admin_stats_service.js").DailyPoint[];
|
|
20
|
+
signUpsPerDay: import("../admin_stats_service.js").DailyPoint[];
|
|
21
|
+
windowDays: number;
|
|
22
|
+
auditSupported: boolean;
|
|
23
|
+
clientsCount: any;
|
|
24
|
+
auditTotal: any;
|
|
25
|
+
recentEvents: any;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
3
|
+
import { computeAdminStats } from '../admin_stats_service.js';
|
|
4
|
+
/**
|
|
5
|
+
* GET {prefix}/api/overview
|
|
6
|
+
*
|
|
7
|
+
* Métricas-resumo do IdP para o dashboard do console React. Reutiliza
|
|
8
|
+
* `computeAdminStats` (mesma fonte do console Edge) e adiciona:
|
|
9
|
+
* - `clientsCount` — número de clients na config
|
|
10
|
+
* - `auditTotal` — total de eventos de auditoria (0 quando sink não suporta)
|
|
11
|
+
* - `recentEvents` — últimos 5 eventos de auditoria ([] quando não suporta)
|
|
12
|
+
*/
|
|
13
|
+
export default class ConsoleOverviewController {
|
|
14
|
+
async handle(ctx) {
|
|
15
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
16
|
+
const cfg = service.config;
|
|
17
|
+
const sessions = new AdminSessionsService(service);
|
|
18
|
+
const stats = await computeAdminStats(cfg, sessions);
|
|
19
|
+
const clientsCount = cfg.clients.length;
|
|
20
|
+
const recentResult = typeof cfg.audit?.list === 'function' ? await cfg.audit.list({ page: 1, limit: 5 }) : null;
|
|
21
|
+
return {
|
|
22
|
+
usersTotal: stats.totalUsers,
|
|
23
|
+
activeSessions: stats.activeSessions,
|
|
24
|
+
mau: stats.mau,
|
|
25
|
+
signInsTotal: stats.signInsTotal,
|
|
26
|
+
signUpsTotal: stats.signUpsTotal,
|
|
27
|
+
signInsPerDay: stats.signInsPerDay,
|
|
28
|
+
signUpsPerDay: stats.signUpsPerDay,
|
|
29
|
+
windowDays: stats.windowDays,
|
|
30
|
+
auditSupported: stats.auditSupported,
|
|
31
|
+
clientsCount,
|
|
32
|
+
auditTotal: recentResult?.total ?? 0,
|
|
33
|
+
recentEvents: (recentResult?.data ?? []).map((e) => ({
|
|
34
|
+
id: e.id,
|
|
35
|
+
type: e.type,
|
|
36
|
+
accountId: e.accountId ?? null,
|
|
37
|
+
email: e.email ?? null,
|
|
38
|
+
actorId: e.actorId ?? null,
|
|
39
|
+
ip: e.ip ?? null,
|
|
40
|
+
createdAt: e.createdAt instanceof Date ? e.createdAt.toISOString() : (e.createdAt ?? null),
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
+
import { type RoleCatalogEntry } from '../runtime_toggles.js';
|
|
4
|
+
/**
|
|
5
|
+
* Endpoints JSON do catálogo de roles do console admin React.
|
|
6
|
+
*
|
|
7
|
+
* GET {prefix}/api/roles → lista o catálogo
|
|
8
|
+
* POST {prefix}/api/roles → criar nova role
|
|
9
|
+
* PATCH {prefix}/api/roles/:name → editar descrição
|
|
10
|
+
* DELETE {prefix}/api/roles/:name → remover role (ADMIN protegido)
|
|
11
|
+
*
|
|
12
|
+
* 404 quando a tabela auth_settings não está disponível.
|
|
13
|
+
*/
|
|
14
|
+
export default class ConsoleRolesController {
|
|
15
|
+
/** GET {prefix}/api/roles */
|
|
16
|
+
index(ctx: HttpContext): Promise<void | {
|
|
17
|
+
data: RoleCatalogEntry[];
|
|
18
|
+
}>;
|
|
19
|
+
/** POST {prefix}/api/roles — { name, description? } */
|
|
20
|
+
store(ctx: HttpContext): Promise<void | {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
/** PATCH {prefix}/api/roles/:name — { description? } */
|
|
25
|
+
update(ctx: HttpContext): Promise<void | RoleCatalogEntry>;
|
|
26
|
+
/** DELETE {prefix}/api/roles/:name */
|
|
27
|
+
destroy(ctx: HttpContext): Promise<void | {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
deleted: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import { resolveRuntimeSettings } from '../runtime_settings.js';
|
|
3
|
+
import { resolveEffectiveRolesCatalog, SETTING_KEYS, } from '../runtime_toggles.js';
|
|
4
|
+
import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
|
|
5
|
+
import { apiError } from '../admin_api/dto.js';
|
|
6
|
+
import { roleCreateValidator, roleUpdateValidator } from '../admin_validators.js';
|
|
7
|
+
/** Regex de validação: nome de role — letras maiúsculas, dígitos e underscore. */
|
|
8
|
+
const ROLE_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
9
|
+
/** ADMIN é protegido: não pode ser removido. */
|
|
10
|
+
const PROTECTED_ROLE = 'ADMIN';
|
|
11
|
+
/**
|
|
12
|
+
* Endpoints JSON do catálogo de roles do console admin React.
|
|
13
|
+
*
|
|
14
|
+
* GET {prefix}/api/roles → lista o catálogo
|
|
15
|
+
* POST {prefix}/api/roles → criar nova role
|
|
16
|
+
* PATCH {prefix}/api/roles/:name → editar descrição
|
|
17
|
+
* DELETE {prefix}/api/roles/:name → remover role (ADMIN protegido)
|
|
18
|
+
*
|
|
19
|
+
* 404 quando a tabela auth_settings não está disponível.
|
|
20
|
+
*/
|
|
21
|
+
export default class ConsoleRolesController {
|
|
22
|
+
/** GET {prefix}/api/roles */
|
|
23
|
+
async index(ctx) {
|
|
24
|
+
const rs = await resolveRuntimeSettings(ctx);
|
|
25
|
+
if (!rs)
|
|
26
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'Tabela auth_settings não disponível.'));
|
|
27
|
+
const { roles } = await resolveEffectiveRolesCatalog(rs);
|
|
28
|
+
return { data: roles };
|
|
29
|
+
}
|
|
30
|
+
/** POST {prefix}/api/roles — { name, description? } */
|
|
31
|
+
async store(ctx) {
|
|
32
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
33
|
+
const cfg = service.config;
|
|
34
|
+
const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
|
|
35
|
+
const ip = ctx.request.ip?.() ?? null;
|
|
36
|
+
const validated = await ctx.request.validateUsing(roleCreateValidator);
|
|
37
|
+
const name = validated.name.toUpperCase();
|
|
38
|
+
const description = validated.description ?? '';
|
|
39
|
+
// Formato (uppercase + regex) e mensagem custom continuam aqui — Vine só
|
|
40
|
+
// garante presença/tipo; a regra de domínio do nome é específica do catálogo.
|
|
41
|
+
if (!ROLE_NAME_RE.test(name)) {
|
|
42
|
+
return ctx.response.badRequest(apiError('invalid_name', cfg.messages['admin.roles.name_invalid'] ?? 'Nome de role inválido.'));
|
|
43
|
+
}
|
|
44
|
+
const rs = await resolveRuntimeSettings(ctx);
|
|
45
|
+
if (!rs)
|
|
46
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'Tabela auth_settings não disponível.'));
|
|
47
|
+
const current = await resolveEffectiveRolesCatalog(rs);
|
|
48
|
+
if (current.roles.some((r) => r.name.toUpperCase() === name)) {
|
|
49
|
+
return ctx.response.conflict(apiError('name_taken', cfg.messages['admin.roles.name_taken'] ?? 'Nome de role já existe.'));
|
|
50
|
+
}
|
|
51
|
+
const newEntry = { name };
|
|
52
|
+
if (description)
|
|
53
|
+
newEntry.description = description;
|
|
54
|
+
const updated = [...current.roles, newEntry].sort((a, b) => a.name.localeCompare(b.name));
|
|
55
|
+
await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updated }, actorId);
|
|
56
|
+
await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'create', role: name } });
|
|
57
|
+
return { name, description: description || undefined };
|
|
58
|
+
}
|
|
59
|
+
/** PATCH {prefix}/api/roles/:name — { description? } */
|
|
60
|
+
async update(ctx) {
|
|
61
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
62
|
+
const cfg = service.config;
|
|
63
|
+
const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
|
|
64
|
+
const ip = ctx.request.ip?.() ?? null;
|
|
65
|
+
const roleName = decodeURIComponent(ctx.request.param('name'));
|
|
66
|
+
const { description: rawDescription } = await ctx.request.validateUsing(roleUpdateValidator);
|
|
67
|
+
const description = rawDescription ?? '';
|
|
68
|
+
const rs = await resolveRuntimeSettings(ctx);
|
|
69
|
+
if (!rs)
|
|
70
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'Tabela auth_settings não disponível.'));
|
|
71
|
+
const current = await resolveEffectiveRolesCatalog(rs);
|
|
72
|
+
if (!current.roles.some((r) => r.name === roleName)) {
|
|
73
|
+
return ctx.response.notFound(apiError('not_found', 'Role não encontrada.'));
|
|
74
|
+
}
|
|
75
|
+
const updatedRoles = current.roles.map((r) => r.name === roleName
|
|
76
|
+
? { name: r.name, ...(description ? { description } : {}) }
|
|
77
|
+
: r);
|
|
78
|
+
await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updatedRoles }, actorId);
|
|
79
|
+
await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'edit', role: roleName } });
|
|
80
|
+
const found = updatedRoles.find((r) => r.name === roleName);
|
|
81
|
+
return found;
|
|
82
|
+
}
|
|
83
|
+
/** DELETE {prefix}/api/roles/:name */
|
|
84
|
+
async destroy(ctx) {
|
|
85
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
86
|
+
const cfg = service.config;
|
|
87
|
+
const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
|
|
88
|
+
const ip = ctx.request.ip?.() ?? null;
|
|
89
|
+
const roleName = decodeURIComponent(ctx.request.param('name'));
|
|
90
|
+
if (roleName === PROTECTED_ROLE) {
|
|
91
|
+
return ctx.response.status(409).send(apiError('protected', cfg.messages['admin.roles.admin_protected'] ?? 'A role ADMIN é protegida.'));
|
|
92
|
+
}
|
|
93
|
+
const rs = await resolveRuntimeSettings(ctx);
|
|
94
|
+
if (!rs)
|
|
95
|
+
return ctx.response.notFound(apiError('capability_unsupported', 'Tabela auth_settings não disponível.'));
|
|
96
|
+
const current = await resolveEffectiveRolesCatalog(rs);
|
|
97
|
+
if (!current.roles.some((r) => r.name === roleName)) {
|
|
98
|
+
return ctx.response.notFound(apiError('not_found', 'Role não encontrada.'));
|
|
99
|
+
}
|
|
100
|
+
let updatedRoles = current.roles.filter((r) => r.name !== roleName);
|
|
101
|
+
if (!updatedRoles.some((r) => r.name === PROTECTED_ROLE)) {
|
|
102
|
+
updatedRoles.unshift({ name: PROTECTED_ROLE, description: 'Full access to the admin console' });
|
|
103
|
+
}
|
|
104
|
+
await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updatedRoles }, actorId);
|
|
105
|
+
await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'delete', role: roleName } });
|
|
106
|
+
return { ok: true, deleted: roleName };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
+
/**
|
|
4
|
+
* Endpoints JSON de sessões/grants do console admin React.
|
|
5
|
+
*
|
|
6
|
+
* GET {prefix}/api/sessions?accountId= → lista sessões + grants de uma conta (ou global)
|
|
7
|
+
* POST {prefix}/api/sessions/revoke-all → revoga todas as sessões de ?accountId=
|
|
8
|
+
* GET {prefix}/api/users/:id/sessions → lista sessões + grants de um usuário específico
|
|
9
|
+
* POST {prefix}/api/users/:id/revoke-sessions → revoga todas as sessões de um usuário específico
|
|
10
|
+
*/
|
|
11
|
+
export default class ConsoleSessionsController {
|
|
12
|
+
/**
|
|
13
|
+
* Helper privado: lista sessões + grants de uma conta específica.
|
|
14
|
+
* Retorna o shape UserSessionsResult: { supported, truncated, sessions, grants }.
|
|
15
|
+
*/
|
|
16
|
+
private listForAccount;
|
|
17
|
+
/** GET {prefix}/api/sessions?accountId= */
|
|
18
|
+
index(ctx: HttpContext): Promise<void | {
|
|
19
|
+
supported: boolean;
|
|
20
|
+
sessions: never[];
|
|
21
|
+
grants: never[];
|
|
22
|
+
truncated?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
supported: boolean;
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
sessions: {
|
|
27
|
+
id: string;
|
|
28
|
+
accountId: string;
|
|
29
|
+
email: string | null;
|
|
30
|
+
loginTs: number | null;
|
|
31
|
+
amr: string[];
|
|
32
|
+
userAgent: string | null;
|
|
33
|
+
browser: string | null;
|
|
34
|
+
os: string | null;
|
|
35
|
+
ip: string | null;
|
|
36
|
+
location: string | null;
|
|
37
|
+
}[];
|
|
38
|
+
grants: {
|
|
39
|
+
id: string;
|
|
40
|
+
accountId: string;
|
|
41
|
+
clientId: string | null;
|
|
42
|
+
accessTokens: number;
|
|
43
|
+
refreshTokens: number;
|
|
44
|
+
}[];
|
|
45
|
+
}>;
|
|
46
|
+
/** GET {prefix}/api/users/:id/sessions */
|
|
47
|
+
userSessions(ctx: HttpContext): Promise<void | {
|
|
48
|
+
supported: boolean;
|
|
49
|
+
sessions: never[];
|
|
50
|
+
grants: never[];
|
|
51
|
+
truncated?: undefined;
|
|
52
|
+
} | {
|
|
53
|
+
supported: boolean;
|
|
54
|
+
truncated: boolean;
|
|
55
|
+
sessions: {
|
|
56
|
+
id: string;
|
|
57
|
+
accountId: string;
|
|
58
|
+
email: string | null;
|
|
59
|
+
loginTs: number | null;
|
|
60
|
+
amr: string[];
|
|
61
|
+
userAgent: string | null;
|
|
62
|
+
browser: string | null;
|
|
63
|
+
os: string | null;
|
|
64
|
+
ip: string | null;
|
|
65
|
+
location: string | null;
|
|
66
|
+
}[];
|
|
67
|
+
grants: {
|
|
68
|
+
id: string;
|
|
69
|
+
accountId: string;
|
|
70
|
+
clientId: string | null;
|
|
71
|
+
accessTokens: number;
|
|
72
|
+
refreshTokens: number;
|
|
73
|
+
}[];
|
|
74
|
+
}>;
|
|
75
|
+
/** POST {prefix}/api/users/:id/revoke-sessions */
|
|
76
|
+
userRevokeSessions(ctx: HttpContext): Promise<void | {
|
|
77
|
+
sessions: number;
|
|
78
|
+
grants: number;
|
|
79
|
+
accessTokens: number;
|
|
80
|
+
refreshTokens: number;
|
|
81
|
+
ok: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
/** POST {prefix}/api/sessions/revoke-all?accountId= */
|
|
84
|
+
revokeAll(ctx: HttpContext): Promise<{
|
|
85
|
+
sessions: number;
|
|
86
|
+
grants: number;
|
|
87
|
+
accessTokens: number;
|
|
88
|
+
refreshTokens: number;
|
|
89
|
+
ok: boolean;
|
|
90
|
+
}>;
|
|
91
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
3
|
+
import { enrichSessionsWithContext } from '../session_context.js';
|
|
4
|
+
import { sessionDto, grantDto, apiError } from '../admin_api/dto.js';
|
|
5
|
+
import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
|
|
6
|
+
import { sessionAccountValidator } from '../admin_validators.js';
|
|
7
|
+
/**
|
|
8
|
+
* Endpoints JSON de sessões/grants do console admin React.
|
|
9
|
+
*
|
|
10
|
+
* GET {prefix}/api/sessions?accountId= → lista sessões + grants de uma conta (ou global)
|
|
11
|
+
* POST {prefix}/api/sessions/revoke-all → revoga todas as sessões de ?accountId=
|
|
12
|
+
* GET {prefix}/api/users/:id/sessions → lista sessões + grants de um usuário específico
|
|
13
|
+
* POST {prefix}/api/users/:id/revoke-sessions → revoga todas as sessões de um usuário específico
|
|
14
|
+
*/
|
|
15
|
+
export default class ConsoleSessionsController {
|
|
16
|
+
/**
|
|
17
|
+
* Helper privado: lista sessões + grants de uma conta específica.
|
|
18
|
+
* Retorna o shape UserSessionsResult: { supported, truncated, sessions, grants }.
|
|
19
|
+
*/
|
|
20
|
+
async listForAccount(ctx, accountId) {
|
|
21
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
22
|
+
const cfg = service.config;
|
|
23
|
+
const adminSvc = new AdminSessionsService(service);
|
|
24
|
+
if (!adminSvc.canList) {
|
|
25
|
+
return { supported: false, sessions: [], grants: [] };
|
|
26
|
+
}
|
|
27
|
+
const account = await cfg.accountStore.findById(accountId);
|
|
28
|
+
if (!account)
|
|
29
|
+
return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
|
|
30
|
+
const rawSessions = await adminSvc.listSessions(accountId);
|
|
31
|
+
const enriched = await enrichSessionsWithContext(cfg, accountId, rawSessions);
|
|
32
|
+
const grants = await adminSvc.listGrants(accountId);
|
|
33
|
+
return {
|
|
34
|
+
supported: true,
|
|
35
|
+
truncated: false,
|
|
36
|
+
sessions: enriched.map(sessionDto),
|
|
37
|
+
grants: grants.map(grantDto),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** GET {prefix}/api/sessions?accountId= */
|
|
41
|
+
async index(ctx) {
|
|
42
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
43
|
+
const accountId = ctx.request.input('accountId', '').trim();
|
|
44
|
+
const adminSvc = new AdminSessionsService(service);
|
|
45
|
+
if (!adminSvc.canList) {
|
|
46
|
+
return { supported: false, sessions: [], grants: [] };
|
|
47
|
+
}
|
|
48
|
+
// Sem accountId → listagem global de todas as sessões ativas
|
|
49
|
+
if (!accountId) {
|
|
50
|
+
const { sessions: rawSessions, truncated } = await adminSvc.listAllSessions();
|
|
51
|
+
return {
|
|
52
|
+
supported: true,
|
|
53
|
+
truncated,
|
|
54
|
+
sessions: rawSessions.map(sessionDto),
|
|
55
|
+
grants: [],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Com accountId → delega ao helper por-conta
|
|
59
|
+
return this.listForAccount(ctx, accountId);
|
|
60
|
+
}
|
|
61
|
+
/** GET {prefix}/api/users/:id/sessions */
|
|
62
|
+
async userSessions(ctx) {
|
|
63
|
+
const accountId = ctx.params.id.trim();
|
|
64
|
+
if (!accountId) {
|
|
65
|
+
return ctx.response.badRequest(apiError('invalid_request', 'O parâmetro id é obrigatório.'));
|
|
66
|
+
}
|
|
67
|
+
return this.listForAccount(ctx, accountId);
|
|
68
|
+
}
|
|
69
|
+
/** POST {prefix}/api/users/:id/revoke-sessions */
|
|
70
|
+
async userRevokeSessions(ctx) {
|
|
71
|
+
const accountId = ctx.params.id.trim();
|
|
72
|
+
if (!accountId) {
|
|
73
|
+
return ctx.response.badRequest(apiError('invalid_request', 'O parâmetro id é obrigatório.'));
|
|
74
|
+
}
|
|
75
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
76
|
+
const cfg = service.config;
|
|
77
|
+
const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
|
|
78
|
+
const ip = ctx.request.ip?.() ?? null;
|
|
79
|
+
const sessions = new AdminSessionsService(service);
|
|
80
|
+
const result = await sessions.revokeAll(accountId);
|
|
81
|
+
await cfg.audit?.record({
|
|
82
|
+
type: 'session.revoked_all',
|
|
83
|
+
accountId,
|
|
84
|
+
actorId,
|
|
85
|
+
ip,
|
|
86
|
+
metadata: {
|
|
87
|
+
sessions: result.sessions,
|
|
88
|
+
grants: result.grants,
|
|
89
|
+
accessTokens: result.accessTokens,
|
|
90
|
+
refreshTokens: result.refreshTokens,
|
|
91
|
+
source: 'admin-console',
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
return { ok: true, ...result };
|
|
95
|
+
}
|
|
96
|
+
/** POST {prefix}/api/sessions/revoke-all?accountId= */
|
|
97
|
+
async revokeAll(ctx) {
|
|
98
|
+
const service = await ctx.containerResolver.make('authkit.server');
|
|
99
|
+
const cfg = service.config;
|
|
100
|
+
const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
|
|
101
|
+
const ip = ctx.request.ip?.() ?? null;
|
|
102
|
+
// accountId pode vir por query/body OU route param — Vine valida o valor já
|
|
103
|
+
// coalescido (validate() aceita qualquer dado, não só request.all()).
|
|
104
|
+
const { accountId } = await sessionAccountValidator.validate({
|
|
105
|
+
accountId: ctx.request.input('accountId') ??
|
|
106
|
+
ctx.request.param('accountId'),
|
|
107
|
+
});
|
|
108
|
+
const sessions = new AdminSessionsService(service);
|
|
109
|
+
const result = await sessions.revokeAll(accountId);
|
|
110
|
+
await cfg.audit?.record({
|
|
111
|
+
type: 'session.revoked_all',
|
|
112
|
+
accountId,
|
|
113
|
+
actorId,
|
|
114
|
+
ip,
|
|
115
|
+
metadata: {
|
|
116
|
+
sessions: result.sessions,
|
|
117
|
+
grants: result.grants,
|
|
118
|
+
accessTokens: result.accessTokens,
|
|
119
|
+
refreshTokens: result.refreshTokens,
|
|
120
|
+
source: 'admin-console',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return { ok: true, ...result };
|
|
124
|
+
}
|
|
125
|
+
}
|