@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,324 @@
|
|
|
1
|
+
import { supportsOrganizations } from '../../accounts/account_store.js';
|
|
2
|
+
import { resolveRoleCatalogList, isRoleInCatalog } from '../runtime_toggles.js';
|
|
3
|
+
/**
|
|
4
|
+
* Lógica de gestão de organizações compartilhada entre o console admin (HTML)
|
|
5
|
+
* e a Admin REST API (JSON). Usada pelos `AdminOrgsController` e `ApiOrgsController`.
|
|
6
|
+
* Todos os métodos de escrita auditam com o `actor` informado.
|
|
7
|
+
*/
|
|
8
|
+
export class AdminOrgsService {
|
|
9
|
+
cfg;
|
|
10
|
+
constructor(cfg) {
|
|
11
|
+
this.cfg = cfg;
|
|
12
|
+
}
|
|
13
|
+
get supported() {
|
|
14
|
+
return supportsOrganizations(this.cfg.accountStore);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve o catálogo efetivo de roles de org (runtime settings → config →
|
|
18
|
+
* defaults da lib), garantindo sempre a presença de `owner`. Fail-safe: sem
|
|
19
|
+
* `settings`, usa o catálogo do config estático (`cfg.organizations`).
|
|
20
|
+
*/
|
|
21
|
+
async resolveRoleCatalog(settings, orgId) {
|
|
22
|
+
return resolveRoleCatalogList(settings, this.orgPolicyConfigDefaults(), orgId);
|
|
23
|
+
}
|
|
24
|
+
/** Defaults estáticos de policy de org derivados do config do host. */
|
|
25
|
+
orgPolicyConfigDefaults() {
|
|
26
|
+
return {
|
|
27
|
+
roles: this.cfg.organizations.roles,
|
|
28
|
+
allowSelfCreate: this.cfg.organizations.allowSelfCreate,
|
|
29
|
+
invitationTtlHours: this.cfg.organizations.invitationTtlHours,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Valida um `role` de org contra o catálogo efetivo. Retorna `true` quando o
|
|
34
|
+
* role faz parte do catálogo. H4: bloqueia roles fora do catálogo (incluindo
|
|
35
|
+
* roles arbitrárias e, quando não catalogadas, `owner`).
|
|
36
|
+
*
|
|
37
|
+
* Delega ao helper PURO `isRoleInCatalog` de `runtime_toggles` — mesmo ponto de
|
|
38
|
+
* verdade usado pelo caminho member-facing (`account_orgs_controller`).
|
|
39
|
+
*/
|
|
40
|
+
async isRoleInCatalog(role, settings, orgId) {
|
|
41
|
+
return isRoleInCatalog(role, settings, this.orgPolicyConfigDefaults(), orgId);
|
|
42
|
+
}
|
|
43
|
+
/** Lista todas as orgs com contagem de membros. */
|
|
44
|
+
async listOrgs() {
|
|
45
|
+
const store = this.cfg.accountStore;
|
|
46
|
+
if (!supportsOrganizations(store))
|
|
47
|
+
return { ok: false, reason: 'not_supported' };
|
|
48
|
+
// O store não tem listAllOrgs — acumulamos via memberships de todas as contas.
|
|
49
|
+
// Para admin, fazemos um listAccounts full e coletamos todas as orgs únicas.
|
|
50
|
+
// Mais eficiente: usa a tabela de organizations diretamente pelo listOrgMembers
|
|
51
|
+
// mas o store não expõe listAllOrgs. Usamos hack: listAccounts com limit alto,
|
|
52
|
+
// coletamos orgs via listOrgsForAccount por conta.
|
|
53
|
+
// Para evitar N+1 excessivo, usamos uma abordagem "seen" de IDs.
|
|
54
|
+
const seen = new Map();
|
|
55
|
+
let page = 1;
|
|
56
|
+
const limit = 100;
|
|
57
|
+
while (true) {
|
|
58
|
+
const result = await store.listAccounts({ page, limit });
|
|
59
|
+
for (const account of result.data) {
|
|
60
|
+
const orgs = await store.listOrgsForAccount(account.id);
|
|
61
|
+
for (const org of orgs) {
|
|
62
|
+
if (!seen.has(org.id)) {
|
|
63
|
+
// Conta membros
|
|
64
|
+
const members = await store.listOrgMembers(org.id);
|
|
65
|
+
seen.set(org.id, { ...org, memberCount: members.length });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (result.data.length < limit)
|
|
70
|
+
break;
|
|
71
|
+
page++;
|
|
72
|
+
}
|
|
73
|
+
return Array.from(seen.values());
|
|
74
|
+
}
|
|
75
|
+
/** Obtém uma org pelo id, com membros e convites pendentes. */
|
|
76
|
+
async getOrg(orgId) {
|
|
77
|
+
const store = this.cfg.accountStore;
|
|
78
|
+
if (!supportsOrganizations(store))
|
|
79
|
+
return { ok: false, reason: 'not_supported' };
|
|
80
|
+
const org = await store.findOrgById(orgId);
|
|
81
|
+
if (!org)
|
|
82
|
+
return { ok: false, reason: 'not_found' };
|
|
83
|
+
const [members, pendingInvitations] = await Promise.all([
|
|
84
|
+
store.listOrgMembers(orgId),
|
|
85
|
+
store.listPendingInvitationsForOrg(orgId),
|
|
86
|
+
]);
|
|
87
|
+
// Enriquece membros com e-mail da conta
|
|
88
|
+
const enrichedMembers = await Promise.all(members.map(async (m) => {
|
|
89
|
+
const account = await store.findById(m.accountId);
|
|
90
|
+
return { ...m, email: account?.email ?? null };
|
|
91
|
+
}));
|
|
92
|
+
return { ...org, members: enrichedMembers, pendingInvitations };
|
|
93
|
+
}
|
|
94
|
+
/** Cria uma org. */
|
|
95
|
+
async createOrg(input, actor) {
|
|
96
|
+
const store = this.cfg.accountStore;
|
|
97
|
+
if (!supportsOrganizations(store))
|
|
98
|
+
return { ok: false, reason: 'not_supported' };
|
|
99
|
+
try {
|
|
100
|
+
const org = await store.createOrg({
|
|
101
|
+
name: input.name,
|
|
102
|
+
slug: input.slug,
|
|
103
|
+
logoUrl: input.logoUrl ?? null,
|
|
104
|
+
ownerAccountId: input.ownerAccountId,
|
|
105
|
+
});
|
|
106
|
+
await this.cfg.audit?.record({
|
|
107
|
+
type: 'organization.created',
|
|
108
|
+
accountId: input.ownerAccountId,
|
|
109
|
+
actorId: actor.actorId,
|
|
110
|
+
ip: actor.ip,
|
|
111
|
+
metadata: { slug: org.slug, ...(actor.source ? { actor: actor.source } : {}) },
|
|
112
|
+
});
|
|
113
|
+
return org;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return { ok: false, reason: 'slug_taken' };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Atualiza nome/logo de uma org. */
|
|
120
|
+
async updateOrg(orgId, patch, actor) {
|
|
121
|
+
const store = this.cfg.accountStore;
|
|
122
|
+
if (!supportsOrganizations(store))
|
|
123
|
+
return { ok: false, reason: 'not_supported' };
|
|
124
|
+
const existing = await store.findOrgById(orgId);
|
|
125
|
+
if (!existing)
|
|
126
|
+
return { ok: false, reason: 'not_found' };
|
|
127
|
+
try {
|
|
128
|
+
const updated = await store.updateOrg(orgId, {
|
|
129
|
+
name: patch.name,
|
|
130
|
+
logoUrl: patch.logoUrl,
|
|
131
|
+
});
|
|
132
|
+
if (!updated)
|
|
133
|
+
return { ok: false, reason: 'not_found' };
|
|
134
|
+
await this.cfg.audit?.record({
|
|
135
|
+
type: 'organization.updated',
|
|
136
|
+
actorId: actor.actorId,
|
|
137
|
+
ip: actor.ip,
|
|
138
|
+
metadata: { orgId, ...(actor.source ? { actor: actor.source } : {}) },
|
|
139
|
+
});
|
|
140
|
+
return updated;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return { ok: false, reason: 'slug_taken' };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/** Deleta uma org e todos os seus dados (membros + convites). */
|
|
147
|
+
async deleteOrg(orgId, actor) {
|
|
148
|
+
const store = this.cfg.accountStore;
|
|
149
|
+
if (!supportsOrganizations(store))
|
|
150
|
+
return { ok: false, reason: 'not_supported' };
|
|
151
|
+
const existing = await store.findOrgById(orgId);
|
|
152
|
+
if (!existing)
|
|
153
|
+
return { ok: false, reason: 'not_found' };
|
|
154
|
+
await store.deleteOrg(orgId);
|
|
155
|
+
await this.cfg.audit?.record({
|
|
156
|
+
type: 'organization.deleted',
|
|
157
|
+
actorId: actor.actorId,
|
|
158
|
+
ip: actor.ip,
|
|
159
|
+
metadata: { orgId, slug: existing.slug, ...(actor.source ? { actor: actor.source } : {}) },
|
|
160
|
+
});
|
|
161
|
+
return { ok: true };
|
|
162
|
+
}
|
|
163
|
+
/** Adiciona um membro a uma org. */
|
|
164
|
+
async addMember(orgId, input, actor, settings = null) {
|
|
165
|
+
const store = this.cfg.accountStore;
|
|
166
|
+
if (!supportsOrganizations(store))
|
|
167
|
+
return { ok: false, reason: 'not_supported' };
|
|
168
|
+
const org = await store.findOrgById(orgId);
|
|
169
|
+
if (!org)
|
|
170
|
+
return { ok: false, reason: 'not_found' };
|
|
171
|
+
// H4: valida o role contra o catálogo efetivo (runtime → config → defaults).
|
|
172
|
+
if (!(await this.isRoleInCatalog(input.role, settings, orgId))) {
|
|
173
|
+
return { ok: false, reason: 'invalid_role' };
|
|
174
|
+
}
|
|
175
|
+
const account = await store.findById(input.accountId);
|
|
176
|
+
if (!account)
|
|
177
|
+
return { ok: false, reason: 'account_not_found' };
|
|
178
|
+
await store.addOrgMember(orgId, input.accountId, input.role);
|
|
179
|
+
await this.cfg.audit?.record({
|
|
180
|
+
type: 'organization.member_added',
|
|
181
|
+
actorId: actor.actorId,
|
|
182
|
+
ip: actor.ip,
|
|
183
|
+
metadata: {
|
|
184
|
+
orgId,
|
|
185
|
+
accountId: input.accountId,
|
|
186
|
+
role: input.role,
|
|
187
|
+
...(actor.source ? { actor: actor.source } : {}),
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
return { ok: true };
|
|
191
|
+
}
|
|
192
|
+
/** Remove um membro de uma org. Respeita invariante last_owner. */
|
|
193
|
+
async removeMember(orgId, accountId, actor) {
|
|
194
|
+
const store = this.cfg.accountStore;
|
|
195
|
+
if (!supportsOrganizations(store))
|
|
196
|
+
return { ok: false, reason: 'not_supported' };
|
|
197
|
+
const org = await store.findOrgById(orgId);
|
|
198
|
+
if (!org)
|
|
199
|
+
return { ok: false, reason: 'not_found' };
|
|
200
|
+
const result = await store.removeOrgMember(orgId, accountId);
|
|
201
|
+
if (!result.ok) {
|
|
202
|
+
if (result.reason === 'last_owner')
|
|
203
|
+
return { ok: false, reason: 'last_owner' };
|
|
204
|
+
return { ok: false, reason: 'member_not_found' };
|
|
205
|
+
}
|
|
206
|
+
await this.cfg.audit?.record({
|
|
207
|
+
type: 'organization.member_removed',
|
|
208
|
+
actorId: actor.actorId,
|
|
209
|
+
ip: actor.ip,
|
|
210
|
+
metadata: {
|
|
211
|
+
orgId,
|
|
212
|
+
targetAccountId: accountId,
|
|
213
|
+
...(actor.source ? { actor: actor.source } : {}),
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
return { ok: true };
|
|
217
|
+
}
|
|
218
|
+
/** Troca o papel de um membro. Respeita invariante last_owner. */
|
|
219
|
+
async updateMemberRole(orgId, accountId, newRole, actor, settings = null) {
|
|
220
|
+
const store = this.cfg.accountStore;
|
|
221
|
+
if (!supportsOrganizations(store))
|
|
222
|
+
return { ok: false, reason: 'not_supported' };
|
|
223
|
+
const org = await store.findOrgById(orgId);
|
|
224
|
+
if (!org)
|
|
225
|
+
return { ok: false, reason: 'not_found' };
|
|
226
|
+
// H4: valida o role-alvo contra o catálogo efetivo antes de promover/rebaixar.
|
|
227
|
+
if (!(await this.isRoleInCatalog(newRole, settings, orgId))) {
|
|
228
|
+
return { ok: false, reason: 'invalid_role' };
|
|
229
|
+
}
|
|
230
|
+
const result = await store.updateOrgMemberRole(orgId, accountId, newRole);
|
|
231
|
+
if (!result.ok) {
|
|
232
|
+
if (result.reason === 'last_owner')
|
|
233
|
+
return { ok: false, reason: 'last_owner' };
|
|
234
|
+
return { ok: false, reason: 'member_not_found' };
|
|
235
|
+
}
|
|
236
|
+
await this.cfg.audit?.record({
|
|
237
|
+
type: 'organization.member_role_changed',
|
|
238
|
+
actorId: actor.actorId,
|
|
239
|
+
ip: actor.ip,
|
|
240
|
+
metadata: {
|
|
241
|
+
orgId,
|
|
242
|
+
targetAccountId: accountId,
|
|
243
|
+
newRole,
|
|
244
|
+
...(actor.source ? { actor: actor.source } : {}),
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
return { ok: true };
|
|
248
|
+
}
|
|
249
|
+
/** Cria um convite por e-mail. Dispara o mail hook quando configurado. */
|
|
250
|
+
async createInvitation(orgId, input, actor, origin, settings = null) {
|
|
251
|
+
const store = this.cfg.accountStore;
|
|
252
|
+
if (!supportsOrganizations(store))
|
|
253
|
+
return { ok: false, reason: 'not_supported' };
|
|
254
|
+
const org = await store.findOrgById(orgId);
|
|
255
|
+
if (!org)
|
|
256
|
+
return { ok: false, reason: 'not_found' };
|
|
257
|
+
// H4: valida o role do convite contra o catálogo efetivo.
|
|
258
|
+
if (!(await this.isRoleInCatalog(input.role, settings, orgId))) {
|
|
259
|
+
return { ok: false, reason: 'invalid_role' };
|
|
260
|
+
}
|
|
261
|
+
const { invitation, token } = await store.createOrgInvitation({
|
|
262
|
+
organizationId: orgId,
|
|
263
|
+
email: input.email,
|
|
264
|
+
role: input.role,
|
|
265
|
+
invitedBy: actor.actorId ?? 'admin',
|
|
266
|
+
ttlHours: this.cfg.organizations.invitationTtlHours,
|
|
267
|
+
});
|
|
268
|
+
// Dispara mail hook (best-effort)
|
|
269
|
+
if (this.cfg.mail?.onOrgInvitation) {
|
|
270
|
+
const acceptUrl = `${origin}/account/orgs/invitations/${token}/accept`;
|
|
271
|
+
try {
|
|
272
|
+
await this.cfg.mail.onOrgInvitation({
|
|
273
|
+
email: input.email,
|
|
274
|
+
invitationId: invitation.id,
|
|
275
|
+
orgName: org.name,
|
|
276
|
+
orgSlug: org.slug,
|
|
277
|
+
role: input.role,
|
|
278
|
+
acceptUrl,
|
|
279
|
+
token,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// best-effort
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
await this.cfg.audit?.record({
|
|
287
|
+
type: 'organization.invitation_sent',
|
|
288
|
+
actorId: actor.actorId,
|
|
289
|
+
ip: actor.ip,
|
|
290
|
+
metadata: {
|
|
291
|
+
orgId,
|
|
292
|
+
email: input.email,
|
|
293
|
+
role: input.role,
|
|
294
|
+
...(actor.source ? { actor: actor.source } : {}),
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
return { ok: true, invitation, token };
|
|
298
|
+
}
|
|
299
|
+
/** Revoga um convite. */
|
|
300
|
+
async revokeInvitation(orgId, invitationId, actor) {
|
|
301
|
+
const store = this.cfg.accountStore;
|
|
302
|
+
if (!supportsOrganizations(store))
|
|
303
|
+
return { ok: false, reason: 'not_supported' };
|
|
304
|
+
const org = await store.findOrgById(orgId);
|
|
305
|
+
if (!org)
|
|
306
|
+
return { ok: false, reason: 'not_found' };
|
|
307
|
+
// Escopado por org: o convite só é revogado se pertencer a esta org —
|
|
308
|
+
// mesmo no Admin API global, evita revogar convite de outra org por id.
|
|
309
|
+
const revoked = await store.revokeInvitation(orgId, invitationId);
|
|
310
|
+
if (!revoked)
|
|
311
|
+
return { ok: false, reason: 'invitation_not_found' };
|
|
312
|
+
await this.cfg.audit?.record({
|
|
313
|
+
type: 'organization.invitation_revoked',
|
|
314
|
+
actorId: actor.actorId,
|
|
315
|
+
ip: actor.ip,
|
|
316
|
+
metadata: {
|
|
317
|
+
orgId,
|
|
318
|
+
invitationId,
|
|
319
|
+
...(actor.source ? { actor: actor.source } : {}),
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
return { ok: true };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type { HttpContext } from "@adonisjs/core/http";
|
|
2
|
+
import type { ResolvedServerConfig } from "../../define_config.js";
|
|
3
|
+
import type { OidcService } from "../../provider/oidc_service.js";
|
|
4
|
+
import type { AuthAccount } from "../../accounts/account_store.js";
|
|
5
|
+
import { type DeletionResult } from "../account_deletion_service.js";
|
|
6
|
+
import type { SettingsCapability } from "../runtime_settings.js";
|
|
7
|
+
/** Quem disparou a operação (para auditoria). `admin-api` quando via REST API. */
|
|
8
|
+
export interface AdminActor {
|
|
9
|
+
actorId: string | null;
|
|
10
|
+
ip: string | null;
|
|
11
|
+
/** Marca metadata da auditoria — 'admin-api' nas escritas via REST, 'admin' no console HTML. */
|
|
12
|
+
source?: "admin-api" | "admin";
|
|
13
|
+
}
|
|
14
|
+
/** Resultado da deleção via admin: false quando o store não suporta hard delete. */
|
|
15
|
+
export type DeleteUserResult = {
|
|
16
|
+
ok: false;
|
|
17
|
+
reason: "not_found" | "unsupported";
|
|
18
|
+
} | {
|
|
19
|
+
ok: true;
|
|
20
|
+
result: DeletionResult;
|
|
21
|
+
}
|
|
22
|
+
/** Deleção ENFILEIRADA (modo durável): o cascade roda async no WorkflowEngine. */
|
|
23
|
+
| {
|
|
24
|
+
ok: true;
|
|
25
|
+
enqueued: true;
|
|
26
|
+
runId: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Enfileira o cascade durável (modo opt-in). Injetado pelos controllers admin —
|
|
30
|
+
* mantém o `AdminUsersService` desacoplado do peer `@adonis-agora/durable`.
|
|
31
|
+
*/
|
|
32
|
+
export type EnqueueDeletion = (input: {
|
|
33
|
+
accountId: string;
|
|
34
|
+
actor: {
|
|
35
|
+
actorId: string | null;
|
|
36
|
+
ip: string | null;
|
|
37
|
+
source: "admin" | "admin-api";
|
|
38
|
+
};
|
|
39
|
+
}) => Promise<string>;
|
|
40
|
+
export interface CreateUserInput {
|
|
41
|
+
email: string;
|
|
42
|
+
name?: string | null;
|
|
43
|
+
password?: string | null;
|
|
44
|
+
/** Quando true (e sem password), cria com senha aleatória e envia convite/reset. */
|
|
45
|
+
invite?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export type CreateUserResult = {
|
|
48
|
+
ok: true;
|
|
49
|
+
account: AuthAccount;
|
|
50
|
+
invited: boolean;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
reason: "email_taken";
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
reason: "password_policy";
|
|
57
|
+
/** Chave i18n da regra violada + params para interpolar. */
|
|
58
|
+
messageKey: string;
|
|
59
|
+
messageParams?: Record<string, string | number>;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Lógica de gestão de usuários compartilhada entre o console admin (B6, HTML) e a
|
|
63
|
+
* Admin REST API (R6, JSON). Encapsula o fluxo "create + invite", reset de senha,
|
|
64
|
+
* troca de status e atualização de perfil/roles — todos auditando com o `actor`
|
|
65
|
+
* informado (`admin-api` nas chamadas REST).
|
|
66
|
+
*/
|
|
67
|
+
export declare class AdminUsersService {
|
|
68
|
+
private cfg;
|
|
69
|
+
constructor(cfg: ResolvedServerConfig);
|
|
70
|
+
/**
|
|
71
|
+
* Cria uma conta. Com `password`: já nasce com a senha. Sem `password` (ou
|
|
72
|
+
* `invite: true`): cria com senha aleatória forte e dispara o e-mail de reset
|
|
73
|
+
* (o usuário define a própria). Audita `user.created`.
|
|
74
|
+
*/
|
|
75
|
+
create(ctx: HttpContext, input: CreateUserInput, actor: AdminActor): Promise<CreateUserResult>;
|
|
76
|
+
/** Emite token de reset + envia e-mail. Retorna a conta (ou null se inexistente). */
|
|
77
|
+
resetPassword(ctx: HttpContext, accountId: string, actor: AdminActor): Promise<AuthAccount | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Habilita/desabilita uma conta. Retorna false quando o store não suporta a
|
|
80
|
+
* capacidade (o caller responde 409). Audita `user.disabled`/`user.enabled`.
|
|
81
|
+
*/
|
|
82
|
+
setStatus(accountId: string, disable: boolean, actor: AdminActor): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Substitui as roles globais de uma conta validando contra o catálogo runtime.
|
|
85
|
+
*
|
|
86
|
+
* Regras:
|
|
87
|
+
* - Roles presentes no catálogo são aceitas.
|
|
88
|
+
* - Roles que o usuário JÁ TEM mas que não estão no catálogo ("fora do catálogo")
|
|
89
|
+
* podem ser REMOVIDAS (não incluir no array roles = remoção normal).
|
|
90
|
+
* - Roles desconhecidas que não estão no catálogo E que o usuário não tinha
|
|
91
|
+
* são REJEITADAS (retorna erro i18n).
|
|
92
|
+
* - Quando settings não disponível, aceita tudo (fail-safe).
|
|
93
|
+
*
|
|
94
|
+
* @returns `null` quando OK; string i18n key quando há role inválida nova.
|
|
95
|
+
*/
|
|
96
|
+
setGlobalRolesValidated(accountId: string, roles: string[], settings: SettingsCapability | null): Promise<string | null>;
|
|
97
|
+
/** Substitui as roles globais de uma conta (normaliza nada — recebe array pronto). */
|
|
98
|
+
setGlobalRoles(accountId: string, roles: string[]): Promise<void>;
|
|
99
|
+
/** Roles globais que conferem acesso de admin (default ['ADMIN']). */
|
|
100
|
+
private adminRoles;
|
|
101
|
+
/** Um conjunto de roles contém ao menos uma role de admin? */
|
|
102
|
+
private hasAdminRole;
|
|
103
|
+
/**
|
|
104
|
+
* Conta quantas contas possuem ao menos uma role de admin. Usado para a
|
|
105
|
+
* invariante de "último admin" — chamado apenas em mudanças de role.
|
|
106
|
+
*
|
|
107
|
+
* CAMINHO EFICIENTE: quando o store expõe `countByGlobalRole` E há exatamente
|
|
108
|
+
* UMA role de admin, conta direto no DB sem paginar a base. Com MÚLTIPLAS roles
|
|
109
|
+
* de admin NÃO usamos a capability: somar `countByGlobalRole` por role
|
|
110
|
+
* sobrecontaria contas que possuem 2+ roles de admin, e overcount aqui é uma
|
|
111
|
+
* regressão de SEGURANÇA (relaxaria o guard de last-admin). Nesse caso caímos
|
|
112
|
+
* no scan paginado, que deduplica naturalmente (conta cada conta uma vez).
|
|
113
|
+
*
|
|
114
|
+
* FALLBACK (sem capability ou múltiplas roles): pagina via `listAccounts`
|
|
115
|
+
* (store-agnóstico, não exige query SQL específica de dialeto sobre a coluna
|
|
116
|
+
* JSON `globalRoles`) e conta in-memory deduplicado.
|
|
117
|
+
*/
|
|
118
|
+
countAdmins(): Promise<number>;
|
|
119
|
+
/**
|
|
120
|
+
* Fallback de contagem por paginação de `listAccounts` (deduplicado: cada
|
|
121
|
+
* conta é contada no máximo uma vez via {@link hasAdminRole}).
|
|
122
|
+
*
|
|
123
|
+
* Terminadores honestos (sem número mágico): a paginação para quando
|
|
124
|
+
* - a página veio incompleta (`data.length < pageSize`) → última página, OU
|
|
125
|
+
* - a página veio vazia (`data.length === 0`) → sem mais dados, OU
|
|
126
|
+
* - já cobrimos o total reportado (`page * pageSize >= total`).
|
|
127
|
+
* Uma página COMPLETA com `total` ainda maior continua paginando. Isto encerra
|
|
128
|
+
* de forma garantida para qualquer store que devolva páginas finitas (a última
|
|
129
|
+
* página é, por definição, menor que `pageSize` ou vazia).
|
|
130
|
+
*/
|
|
131
|
+
private countAdminsByScan;
|
|
132
|
+
/**
|
|
133
|
+
* Aplica proteções de segurança a uma troca de roles globais ANTES de gravar:
|
|
134
|
+
*
|
|
135
|
+
* - `last_admin`: bloqueia remover a role de admin da ÚLTIMA conta que a possui
|
|
136
|
+
* (evita lockout permanente do console). Só dispara quando o target ATUALMENTE
|
|
137
|
+
* é admin, o novo conjunto NÃO é admin, e ele é o único admin.
|
|
138
|
+
* - `cannot_self_demote`: bloqueia o ator remover a própria role de admin
|
|
139
|
+
* (`actorId === targetId` e o novo conjunto não tem admin). Só aplica quando
|
|
140
|
+
* há um `actorId` identificável.
|
|
141
|
+
*
|
|
142
|
+
* @returns código i18n/erro quando a operação deve ser bloqueada; `null` quando OK.
|
|
143
|
+
*/
|
|
144
|
+
guardGlobalRolesChange(targetId: string, newRoles: string[], actorId: string | null): Promise<"last_admin" | "cannot_self_demote" | null>;
|
|
145
|
+
/** Atualiza nome/avatar (capacidade opcional). Retorna a conta ou null. */
|
|
146
|
+
updateProfile(accountId: string, patch: {
|
|
147
|
+
name?: string | null;
|
|
148
|
+
avatarUrl?: string | null;
|
|
149
|
+
}): Promise<AuthAccount | null>;
|
|
150
|
+
/**
|
|
151
|
+
* Deleta uma conta pelo admin, usando o MESMO cascade do self-service
|
|
152
|
+
* ({@link AccountDeletionService}). Precisa do {@link OidcService} (para revogar
|
|
153
|
+
* sessões/grants). Retorna `{ ok: false, reason }` se a conta não existe ou o
|
|
154
|
+
* store não suporta hard delete (o caller responde 404/409). Audita
|
|
155
|
+
* `account.deleted` (ator admin) dentro do cascade + `user.deleted` aqui (trilha
|
|
156
|
+
* administrativa).
|
|
157
|
+
*/
|
|
158
|
+
delete(oidc: OidcService, accountId: string, actor: AdminActor, enqueue?: EnqueueDeletion): Promise<DeleteUserResult>;
|
|
159
|
+
/** Indica se a conta está desabilitada (false quando a capacidade não existe). */
|
|
160
|
+
isDisabled(accountId: string): Promise<boolean>;
|
|
161
|
+
/** Emite o token de reset e dispara o e-mail (hook do config tem prioridade). */
|
|
162
|
+
private sendResetEmail;
|
|
163
|
+
}
|