@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,784 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime toggles — settings de `auth_settings` que controlam comportamento
|
|
3
|
+
* operacional em tempo de execução, no padrão do bot_protection resolver.
|
|
4
|
+
*
|
|
5
|
+
* Cada setting segue o contrato:
|
|
6
|
+
* - setting presente → manda (sobrescreve config estático)
|
|
7
|
+
* - setting ausente/inválido/erro DB → config estático (fail-safe total)
|
|
8
|
+
*
|
|
9
|
+
* Keys conhecidas em `auth_settings`:
|
|
10
|
+
* - `registration` → RegistrationSetting
|
|
11
|
+
* - `require_verified_email` → RequireVerifiedEmailSetting
|
|
12
|
+
* - `maintenance_mode` → MaintenanceModeSetting
|
|
13
|
+
*/
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Known setting keys registry
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Chaves conhecidas do catálogo de runtime settings. Centralizado aqui para
|
|
19
|
+
* que qualquer code-path possa importar a constante e não depender de strings.
|
|
20
|
+
*/
|
|
21
|
+
export const SETTING_KEYS = {
|
|
22
|
+
BOT_PROTECTION: 'bot_protection',
|
|
23
|
+
REGISTRATION: 'registration',
|
|
24
|
+
REQUIRE_VERIFIED_EMAIL: 'require_verified_email',
|
|
25
|
+
MAINTENANCE_MODE: 'maintenance_mode',
|
|
26
|
+
AUTH_METHODS: 'auth_methods',
|
|
27
|
+
EMAIL_CHANGE: 'email_change',
|
|
28
|
+
SECURITY_NOTIFICATIONS: 'security_notifications',
|
|
29
|
+
PASSWORD_HISTORY: 'password_history',
|
|
30
|
+
PASSWORD_EXPIRATION: 'password_expiration',
|
|
31
|
+
SESSION_POLICY: 'session_policy',
|
|
32
|
+
LOCKOUT: 'lockout',
|
|
33
|
+
RATE_LIMIT: 'rate_limit',
|
|
34
|
+
PASSWORD_POLICY: 'password_policy',
|
|
35
|
+
NOTIFICATIONS: 'notifications',
|
|
36
|
+
TRUSTED_DEVICES: 'trusted_devices',
|
|
37
|
+
TOKEN_TTL: 'token_ttl',
|
|
38
|
+
ADMIN_IMPERSONATION: 'admin_impersonation',
|
|
39
|
+
ORGANIZATIONS_POLICY: 'organizations_policy',
|
|
40
|
+
ROLES_CATALOG: 'roles_catalog',
|
|
41
|
+
OTP_LOCKOUT: 'otp_lockout',
|
|
42
|
+
SUDO_MODE: 'sudo_mode',
|
|
43
|
+
ACCOUNT_EXPIRATION: 'account_expiration',
|
|
44
|
+
KEY_ROTATION: 'key_rotation',
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resolve o valor efetivo de "registration enabled" combinando a setting
|
|
48
|
+
* persistida em runtime com o config estático.
|
|
49
|
+
*
|
|
50
|
+
* Regras:
|
|
51
|
+
* - `config.registration?.enabled` pode estar em `ResolvedServerConfig`
|
|
52
|
+
* (quando o host o declara). Default: `true` (aberto por padrão).
|
|
53
|
+
* - setting presente → sobrescreve o default/config.
|
|
54
|
+
* - setting ausente/inválido/erro → usa configDefault.
|
|
55
|
+
*
|
|
56
|
+
* FAIL-SAFE: `getSetting` nunca lança (contrato do RuntimeSettings). Se
|
|
57
|
+
* retornar null, usamos configDefault.
|
|
58
|
+
*/
|
|
59
|
+
export async function resolveEffectiveRegistration(configDefault = true, settings) {
|
|
60
|
+
const raw = await settings.getSetting(SETTING_KEYS.REGISTRATION);
|
|
61
|
+
if (raw === null || raw === undefined)
|
|
62
|
+
return configDefault;
|
|
63
|
+
if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
|
|
64
|
+
return configDefault; // shape inválida → fallback
|
|
65
|
+
}
|
|
66
|
+
return raw.enabled;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve o valor efetivo de `requireVerifiedEmail` combinando a setting
|
|
70
|
+
* persistida em runtime com o config estático.
|
|
71
|
+
*
|
|
72
|
+
* Regras (mesmas do `resolveEffectiveRegistration`):
|
|
73
|
+
* - configDefault vem de `cfg.login.requireVerifiedEmail` (default false).
|
|
74
|
+
* - setting presente → sobrescreve.
|
|
75
|
+
* - setting ausente/inválido/erro → usa configDefault.
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveEffectiveRequireVerifiedEmail(configDefault = false, settings) {
|
|
78
|
+
const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
|
|
79
|
+
if (raw === null || raw === undefined)
|
|
80
|
+
return configDefault;
|
|
81
|
+
if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
|
|
82
|
+
return configDefault; // shape inválida → fallback
|
|
83
|
+
}
|
|
84
|
+
return raw.enabled;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve o valor efetivo COMPLETO de `require_verified_email` incluindo
|
|
88
|
+
* `graceDays`. Usado pelo gate de login para implementar a janela de graça.
|
|
89
|
+
*
|
|
90
|
+
* FAIL-SAFE: qualquer erro → `{ enabled: configDefault, graceDays: 0 }`.
|
|
91
|
+
*/
|
|
92
|
+
export async function resolveEffectiveRequireVerifiedEmailFull(configDefault = false, settings) {
|
|
93
|
+
try {
|
|
94
|
+
const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
|
|
95
|
+
if (raw === null || raw === undefined)
|
|
96
|
+
return { enabled: configDefault, graceDays: 0 };
|
|
97
|
+
if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
|
|
98
|
+
return { enabled: configDefault, graceDays: 0 };
|
|
99
|
+
}
|
|
100
|
+
const s = raw;
|
|
101
|
+
const graceDays = typeof s.graceDays === 'number' && s.graceDays >= 0 ? Math.floor(s.graceDays) : 0;
|
|
102
|
+
return { enabled: s.enabled, graceDays };
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return { enabled: configDefault, graceDays: 0 };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resolve o estado efetivo do maintenance mode a partir da setting persistida.
|
|
110
|
+
*
|
|
111
|
+
* Regras:
|
|
112
|
+
* - setting ausente/inválido/erro DB → `{ enabled: false }` (default: sistema UP).
|
|
113
|
+
* - setting presente → usa o valor da setting.
|
|
114
|
+
*
|
|
115
|
+
* FAIL-SAFE: qualquer erro → sistema considerado UP (disponibilidade > proteção).
|
|
116
|
+
*/
|
|
117
|
+
export async function resolveEffectiveMaintenanceMode(settings) {
|
|
118
|
+
const raw = await settings.getSetting(SETTING_KEYS.MAINTENANCE_MODE);
|
|
119
|
+
if (raw === null || raw === undefined)
|
|
120
|
+
return { enabled: false };
|
|
121
|
+
if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
|
|
122
|
+
return { enabled: false }; // shape inválida → fail-safe
|
|
123
|
+
}
|
|
124
|
+
const setting = raw;
|
|
125
|
+
return {
|
|
126
|
+
enabled: setting.enabled,
|
|
127
|
+
message: typeof setting.message === 'string' ? setting.message : undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Resolve os métodos de autenticação efetivos combinando config estático + setting
|
|
132
|
+
* persistida em runtime + capabilities.
|
|
133
|
+
*
|
|
134
|
+
* Regras:
|
|
135
|
+
* 1. Defaults derivados do config/capabilities.
|
|
136
|
+
* 2. Setting presente → sobrescreve campo a campo.
|
|
137
|
+
* 3. DERIVAÇÃO: `forgotPassword` efetivo = (setting.forgotPassword ?? true) && passwordEnabled.
|
|
138
|
+
* Sem método senha ativo, "esqueci minha senha" NUNCA aparece.
|
|
139
|
+
* 4. `social` efetivo = interseção do setting.social com os providers do config.
|
|
140
|
+
* Setting não pode LIGAR provider que o código não tem.
|
|
141
|
+
* 5. FAIL-SAFE all-off: se todos os métodos ficarem desligados, volta ao derivado
|
|
142
|
+
* do config (nunca deixar a tela sem nenhum método). Loga um aviso (console.warn).
|
|
143
|
+
* 6. Qualquer erro DB → defaults derivados do config (fail-safe total).
|
|
144
|
+
*/
|
|
145
|
+
export async function resolveEffectiveAuthMethods(settings, capabilities = {}) {
|
|
146
|
+
const { configuredSocialProviders = [], magicLinkCapable = false, passkeyCapable = false, } = capabilities;
|
|
147
|
+
// Defaults derivados do config/capabilities.
|
|
148
|
+
const configDefaults = {
|
|
149
|
+
password: true,
|
|
150
|
+
magicLink: magicLinkCapable,
|
|
151
|
+
passkey: passkeyCapable,
|
|
152
|
+
social: configuredSocialProviders,
|
|
153
|
+
forgotPassword: true,
|
|
154
|
+
passkeyAutofill: passkeyCapable, // on por default quando passkey disponível
|
|
155
|
+
};
|
|
156
|
+
const raw = await settings.getSetting(SETTING_KEYS.AUTH_METHODS);
|
|
157
|
+
if (raw === null || raw === undefined)
|
|
158
|
+
return configDefaults;
|
|
159
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
160
|
+
return configDefaults; // shape inválida
|
|
161
|
+
const s = raw;
|
|
162
|
+
// Aplica campo a campo, com fallback ao default quando o campo está ausente.
|
|
163
|
+
const passwordEnabled = typeof s.password === 'boolean' ? s.password : configDefaults.password;
|
|
164
|
+
const magicLinkEnabled = typeof s.magicLink === 'boolean' ? s.magicLink : configDefaults.magicLink;
|
|
165
|
+
const passkeyEnabled = typeof s.passkey === 'boolean' ? s.passkey : configDefaults.passkey;
|
|
166
|
+
// Social: interseção com os providers do config (setting não pode ligar o que não existe).
|
|
167
|
+
let socialEnabled;
|
|
168
|
+
if (Array.isArray(s.social)) {
|
|
169
|
+
socialEnabled = s.social.filter((p) => configuredSocialProviders.includes(p));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
socialEnabled = configDefaults.social;
|
|
173
|
+
}
|
|
174
|
+
// forgotPassword: derivado automaticamente — sem senha NUNCA existe esqueci-senha.
|
|
175
|
+
const forgotPasswordEnabled = passwordEnabled && (typeof s.forgotPassword === 'boolean' ? s.forgotPassword : true);
|
|
176
|
+
// passkeyAutofill: só faz sentido quando passkey está ligado.
|
|
177
|
+
const passkeyAutofillEnabled = passkeyEnabled &&
|
|
178
|
+
(typeof s.passkeyAutofill === 'boolean' ? s.passkeyAutofill : configDefaults.passkeyAutofill);
|
|
179
|
+
const resolved = {
|
|
180
|
+
password: passwordEnabled,
|
|
181
|
+
magicLink: magicLinkEnabled,
|
|
182
|
+
passkey: passkeyEnabled,
|
|
183
|
+
social: socialEnabled,
|
|
184
|
+
forgotPassword: forgotPasswordEnabled,
|
|
185
|
+
passkeyAutofill: passkeyAutofillEnabled,
|
|
186
|
+
};
|
|
187
|
+
// FAIL-SAFE all-off: se todos ficaram false/vazio, volta ao config derivado.
|
|
188
|
+
const allOff = !resolved.password &&
|
|
189
|
+
!resolved.magicLink &&
|
|
190
|
+
!resolved.passkey &&
|
|
191
|
+
resolved.social.length === 0;
|
|
192
|
+
if (allOff) {
|
|
193
|
+
// eslint-disable-next-line no-console
|
|
194
|
+
console.warn('[authkit] auth_methods setting deixou todos os métodos desligados — ' +
|
|
195
|
+
'revertendo para os defaults do config (fail-safe). ' +
|
|
196
|
+
'Verifique a setting auth_methods no console admin.');
|
|
197
|
+
return configDefaults;
|
|
198
|
+
}
|
|
199
|
+
return resolved;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Resolve as configurações efetivas de troca de e-mail, combinando a setting
|
|
203
|
+
* persistida em runtime com defaults.
|
|
204
|
+
*
|
|
205
|
+
* FAIL-SAFE: qualquer erro → defaults (enabled true, 24h, requirePassword true).
|
|
206
|
+
*/
|
|
207
|
+
export async function resolveEffectiveEmailChange(settings) {
|
|
208
|
+
const defaults = { enabled: true, ttlHours: 24, requirePassword: true };
|
|
209
|
+
try {
|
|
210
|
+
const raw = await settings.getSetting(SETTING_KEYS.EMAIL_CHANGE);
|
|
211
|
+
if (raw === null || raw === undefined)
|
|
212
|
+
return defaults;
|
|
213
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
214
|
+
return defaults;
|
|
215
|
+
const s = raw;
|
|
216
|
+
return {
|
|
217
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
218
|
+
ttlHours: typeof s.ttlHours === 'number' && s.ttlHours > 0 ? s.ttlHours : defaults.ttlHours,
|
|
219
|
+
requirePassword: typeof s.requirePassword === 'boolean' ? s.requirePassword : defaults.requirePassword,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return defaults;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Todos os tipos de notificação de segurança suportados. */
|
|
227
|
+
export const ALL_SECURITY_NOTIFICATION_KINDS = [
|
|
228
|
+
'password_changed',
|
|
229
|
+
'mfa_enabled',
|
|
230
|
+
'mfa_disabled',
|
|
231
|
+
'passkey_added',
|
|
232
|
+
'passkey_removed',
|
|
233
|
+
'email_changed',
|
|
234
|
+
];
|
|
235
|
+
/**
|
|
236
|
+
* Resolve as notificações de segurança efetivas, combinando a setting
|
|
237
|
+
* persistida em runtime com defaults.
|
|
238
|
+
*
|
|
239
|
+
* FAIL-SAFE: qualquer erro → defaults (enabled true, todos os kinds).
|
|
240
|
+
*/
|
|
241
|
+
export async function resolveEffectiveSecurityNotifications(settings) {
|
|
242
|
+
const defaults = {
|
|
243
|
+
enabled: true,
|
|
244
|
+
kinds: [...ALL_SECURITY_NOTIFICATION_KINDS],
|
|
245
|
+
};
|
|
246
|
+
try {
|
|
247
|
+
const raw = await settings.getSetting(SETTING_KEYS.SECURITY_NOTIFICATIONS);
|
|
248
|
+
if (raw === null || raw === undefined)
|
|
249
|
+
return defaults;
|
|
250
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
251
|
+
return defaults;
|
|
252
|
+
const s = raw;
|
|
253
|
+
const enabled = typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled;
|
|
254
|
+
let kinds;
|
|
255
|
+
if (Array.isArray(s.kinds) && s.kinds.length > 0) {
|
|
256
|
+
// Apenas aceita kinds válidos (interseção com os suportados).
|
|
257
|
+
kinds = s.kinds.filter((k) => ALL_SECURITY_NOTIFICATION_KINDS.includes(k));
|
|
258
|
+
if (kinds.length === 0)
|
|
259
|
+
kinds = [...ALL_SECURITY_NOTIFICATION_KINDS];
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
kinds = [...ALL_SECURITY_NOTIFICATION_KINDS];
|
|
263
|
+
}
|
|
264
|
+
return { enabled, kinds };
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
return defaults;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Resolve as configurações efetivas de histórico de senhas.
|
|
272
|
+
*
|
|
273
|
+
* FAIL-SAFE: qualquer erro → `{ enabled: false, count: 5 }`.
|
|
274
|
+
*/
|
|
275
|
+
export async function resolveEffectivePasswordHistory(settings) {
|
|
276
|
+
const defaults = { enabled: false, count: 5 };
|
|
277
|
+
try {
|
|
278
|
+
const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_HISTORY);
|
|
279
|
+
if (raw === null || raw === undefined)
|
|
280
|
+
return defaults;
|
|
281
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
282
|
+
return defaults;
|
|
283
|
+
const s = raw;
|
|
284
|
+
return {
|
|
285
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
286
|
+
count: typeof s.count === 'number' && s.count >= 1 ? Math.floor(s.count) : defaults.count,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return defaults;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** Defaults da session_policy quando a setting não existe. */
|
|
294
|
+
export const SESSION_POLICY_DEFAULTS = {
|
|
295
|
+
rememberEnabled: true,
|
|
296
|
+
rememberDays: 30,
|
|
297
|
+
defaultSessionHours: 168, // 7 dias em horas (= 604800 s padrão do oidc-provider)
|
|
298
|
+
singleSession: false,
|
|
299
|
+
idleTimeoutMinutes: 0,
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Resolve as configurações efetivas de session policy.
|
|
303
|
+
*
|
|
304
|
+
* FAIL-SAFE: qualquer erro → defaults (comportamento original intacto).
|
|
305
|
+
*
|
|
306
|
+
* @param configDefaultSessionHours Horas derivadas de `config.ttl.session` (em segundos → horas).
|
|
307
|
+
* Quando ausente, usa 168 h (7 dias = padrão do oidc-provider).
|
|
308
|
+
*/
|
|
309
|
+
export async function resolveEffectiveSessionPolicy(settings, configDefaultSessionHours) {
|
|
310
|
+
const defaults = {
|
|
311
|
+
...SESSION_POLICY_DEFAULTS,
|
|
312
|
+
defaultSessionHours: configDefaultSessionHours ?? SESSION_POLICY_DEFAULTS.defaultSessionHours,
|
|
313
|
+
};
|
|
314
|
+
try {
|
|
315
|
+
const raw = await settings.getSetting(SETTING_KEYS.SESSION_POLICY);
|
|
316
|
+
if (raw === null || raw === undefined)
|
|
317
|
+
return defaults;
|
|
318
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
319
|
+
return defaults;
|
|
320
|
+
const s = raw;
|
|
321
|
+
return {
|
|
322
|
+
rememberEnabled: typeof s.rememberEnabled === 'boolean' ? s.rememberEnabled : defaults.rememberEnabled,
|
|
323
|
+
rememberDays: typeof s.rememberDays === 'number' && s.rememberDays >= 1 ? Math.floor(s.rememberDays) : defaults.rememberDays,
|
|
324
|
+
defaultSessionHours: typeof s.defaultSessionHours === 'number' && s.defaultSessionHours >= 1 ? Math.floor(s.defaultSessionHours) : defaults.defaultSessionHours,
|
|
325
|
+
singleSession: typeof s.singleSession === 'boolean' ? s.singleSession : defaults.singleSession,
|
|
326
|
+
idleTimeoutMinutes: typeof s.idleTimeoutMinutes === 'number' && s.idleTimeoutMinutes >= 0 ? Math.floor(s.idleTimeoutMinutes) : defaults.idleTimeoutMinutes,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
return defaults;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Resolve as configurações efetivas de expiração de senha.
|
|
335
|
+
*
|
|
336
|
+
* FAIL-SAFE: qualquer erro → `{ enabled: false, maxAgeDays: 90 }`.
|
|
337
|
+
*/
|
|
338
|
+
export async function resolveEffectivePasswordExpiration(settings) {
|
|
339
|
+
const defaults = { enabled: false, maxAgeDays: 90 };
|
|
340
|
+
try {
|
|
341
|
+
const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_EXPIRATION);
|
|
342
|
+
if (raw === null || raw === undefined)
|
|
343
|
+
return defaults;
|
|
344
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
345
|
+
return defaults;
|
|
346
|
+
const s = raw;
|
|
347
|
+
return {
|
|
348
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
349
|
+
maxAgeDays: typeof s.maxAgeDays === 'number' && s.maxAgeDays >= 1 ? Math.floor(s.maxAgeDays) : defaults.maxAgeDays,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
return defaults;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const LOCKOUT_LIB_DEFAULTS = {
|
|
357
|
+
enabled: true,
|
|
358
|
+
maxAttempts: 5,
|
|
359
|
+
windowSec: 900,
|
|
360
|
+
baseLockoutSec: 60,
|
|
361
|
+
maxLockoutSec: 3600,
|
|
362
|
+
};
|
|
363
|
+
/**
|
|
364
|
+
* Resolve as configurações efetivas de lockout.
|
|
365
|
+
*
|
|
366
|
+
* Precedência: setting BD → configDefault → lib default.
|
|
367
|
+
* FAIL-SAFE: qualquer erro → configDefault (ou lib defaults).
|
|
368
|
+
*/
|
|
369
|
+
export async function resolveEffectiveLockout(settings, configDefault = {}) {
|
|
370
|
+
const defaults = {
|
|
371
|
+
enabled: configDefault.enabled ?? LOCKOUT_LIB_DEFAULTS.enabled,
|
|
372
|
+
maxAttempts: configDefault.maxAttempts ?? LOCKOUT_LIB_DEFAULTS.maxAttempts,
|
|
373
|
+
windowSec: configDefault.windowSec ?? LOCKOUT_LIB_DEFAULTS.windowSec,
|
|
374
|
+
baseLockoutSec: configDefault.baseLockoutSec ?? LOCKOUT_LIB_DEFAULTS.baseLockoutSec,
|
|
375
|
+
maxLockoutSec: configDefault.maxLockoutSec ?? LOCKOUT_LIB_DEFAULTS.maxLockoutSec,
|
|
376
|
+
};
|
|
377
|
+
try {
|
|
378
|
+
const raw = await settings.getSetting(SETTING_KEYS.LOCKOUT);
|
|
379
|
+
if (raw === null || raw === undefined)
|
|
380
|
+
return defaults;
|
|
381
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
382
|
+
return defaults;
|
|
383
|
+
const s = raw;
|
|
384
|
+
return {
|
|
385
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
386
|
+
maxAttempts: typeof s.maxAttempts === 'number' && s.maxAttempts >= 1 ? Math.floor(s.maxAttempts) : defaults.maxAttempts,
|
|
387
|
+
windowSec: typeof s.windowSec === 'number' && s.windowSec >= 1 ? Math.floor(s.windowSec) : defaults.windowSec,
|
|
388
|
+
baseLockoutSec: typeof s.baseLockoutSec === 'number' && s.baseLockoutSec >= 1 ? Math.floor(s.baseLockoutSec) : defaults.baseLockoutSec,
|
|
389
|
+
maxLockoutSec: typeof s.maxLockoutSec === 'number' && s.maxLockoutSec >= 1 ? Math.floor(s.maxLockoutSec) : defaults.maxLockoutSec,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
return defaults;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
const RATE_LIMIT_LIB_DEFAULTS = {
|
|
397
|
+
login: { points: 10, duration: '1 min' },
|
|
398
|
+
introspection: { points: 60, duration: '1 min' },
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Resolve as configurações efetivas dos buckets de rate-limit.
|
|
402
|
+
*
|
|
403
|
+
* Precedência: setting BD → configDefault → lib default.
|
|
404
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
405
|
+
*
|
|
406
|
+
* NOTA: o middleware de throttle de rota (Adonis) usa os valores do config de
|
|
407
|
+
* boot e NÃO é afetado por esta setting em runtime. Veja JSDoc de RateLimitSetting.
|
|
408
|
+
*/
|
|
409
|
+
export async function resolveEffectiveRateLimit(settings, configDefault = {}) {
|
|
410
|
+
const defaults = {
|
|
411
|
+
login: {
|
|
412
|
+
points: configDefault.login?.points ?? RATE_LIMIT_LIB_DEFAULTS.login.points,
|
|
413
|
+
duration: configDefault.login?.duration ?? RATE_LIMIT_LIB_DEFAULTS.login.duration,
|
|
414
|
+
},
|
|
415
|
+
introspection: {
|
|
416
|
+
points: configDefault.introspection?.points ?? RATE_LIMIT_LIB_DEFAULTS.introspection.points,
|
|
417
|
+
duration: configDefault.introspection?.duration ?? RATE_LIMIT_LIB_DEFAULTS.introspection.duration,
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
try {
|
|
421
|
+
const raw = await settings.getSetting(SETTING_KEYS.RATE_LIMIT);
|
|
422
|
+
if (raw === null || raw === undefined)
|
|
423
|
+
return defaults;
|
|
424
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
425
|
+
return defaults;
|
|
426
|
+
const s = raw;
|
|
427
|
+
return {
|
|
428
|
+
login: {
|
|
429
|
+
points: typeof s.login?.points === 'number' && s.login.points >= 1 ? Math.floor(s.login.points) : defaults.login.points,
|
|
430
|
+
duration: typeof s.login?.duration === 'string' && s.login.duration.trim() ? s.login.duration.trim() : defaults.login.duration,
|
|
431
|
+
},
|
|
432
|
+
introspection: {
|
|
433
|
+
points: typeof s.introspection?.points === 'number' && s.introspection.points >= 1 ? Math.floor(s.introspection.points) : defaults.introspection.points,
|
|
434
|
+
duration: typeof s.introspection?.duration === 'string' && s.introspection.duration.trim() ? s.introspection.duration.trim() : defaults.introspection.duration,
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
return defaults;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const PASSWORD_POLICY_LIB_DEFAULTS = {
|
|
443
|
+
minLength: 8,
|
|
444
|
+
requireUppercase: false,
|
|
445
|
+
requireLowercase: false,
|
|
446
|
+
requireNumbers: false,
|
|
447
|
+
requireSymbols: false,
|
|
448
|
+
checkPwned: false,
|
|
449
|
+
blockCommon: true,
|
|
450
|
+
};
|
|
451
|
+
/**
|
|
452
|
+
* Resolve as configurações efetivas de política de senha.
|
|
453
|
+
*
|
|
454
|
+
* Precedência: setting BD → configDefault → lib default.
|
|
455
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
456
|
+
*/
|
|
457
|
+
export async function resolveEffectivePasswordPolicy(settings, configDefault = {}) {
|
|
458
|
+
const defaults = {
|
|
459
|
+
minLength: configDefault.minLength ?? PASSWORD_POLICY_LIB_DEFAULTS.minLength,
|
|
460
|
+
requireUppercase: configDefault.requireUppercase ?? PASSWORD_POLICY_LIB_DEFAULTS.requireUppercase,
|
|
461
|
+
requireLowercase: configDefault.requireLowercase ?? PASSWORD_POLICY_LIB_DEFAULTS.requireLowercase,
|
|
462
|
+
requireNumbers: configDefault.requireNumbers ?? PASSWORD_POLICY_LIB_DEFAULTS.requireNumbers,
|
|
463
|
+
requireSymbols: configDefault.requireSymbols ?? PASSWORD_POLICY_LIB_DEFAULTS.requireSymbols,
|
|
464
|
+
checkPwned: configDefault.checkPwned ?? PASSWORD_POLICY_LIB_DEFAULTS.checkPwned,
|
|
465
|
+
blockCommon: configDefault.blockCommon ?? PASSWORD_POLICY_LIB_DEFAULTS.blockCommon,
|
|
466
|
+
};
|
|
467
|
+
try {
|
|
468
|
+
const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_POLICY);
|
|
469
|
+
if (raw === null || raw === undefined)
|
|
470
|
+
return defaults;
|
|
471
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
472
|
+
return defaults;
|
|
473
|
+
const s = raw;
|
|
474
|
+
return {
|
|
475
|
+
minLength: typeof s.minLength === 'number' && s.minLength >= 1 ? Math.floor(s.minLength) : defaults.minLength,
|
|
476
|
+
requireUppercase: typeof s.requireUppercase === 'boolean' ? s.requireUppercase : defaults.requireUppercase,
|
|
477
|
+
requireLowercase: typeof s.requireLowercase === 'boolean' ? s.requireLowercase : defaults.requireLowercase,
|
|
478
|
+
requireNumbers: typeof s.requireNumbers === 'boolean' ? s.requireNumbers : defaults.requireNumbers,
|
|
479
|
+
requireSymbols: typeof s.requireSymbols === 'boolean' ? s.requireSymbols : defaults.requireSymbols,
|
|
480
|
+
checkPwned: typeof s.checkPwned === 'boolean' ? s.checkPwned : defaults.checkPwned,
|
|
481
|
+
blockCommon: typeof s.blockCommon === 'boolean' ? s.blockCommon : defaults.blockCommon,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
return defaults;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Resolve as configurações efetivas de notificações de acesso/dispositivo.
|
|
490
|
+
*
|
|
491
|
+
* Precedência: setting BD → configDefault → lib default (true/true).
|
|
492
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
493
|
+
*/
|
|
494
|
+
export async function resolveEffectiveNotifications(settings, configDefault = {}) {
|
|
495
|
+
const defaults = {
|
|
496
|
+
newLoginEmail: configDefault.newLoginEmail ?? true,
|
|
497
|
+
newDeviceEmail: configDefault.newDeviceEmail ?? true,
|
|
498
|
+
};
|
|
499
|
+
try {
|
|
500
|
+
const raw = await settings.getSetting(SETTING_KEYS.NOTIFICATIONS);
|
|
501
|
+
if (raw === null || raw === undefined)
|
|
502
|
+
return defaults;
|
|
503
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
504
|
+
return defaults;
|
|
505
|
+
const s = raw;
|
|
506
|
+
return {
|
|
507
|
+
newLoginEmail: typeof s.newLoginEmail === 'boolean' ? s.newLoginEmail : defaults.newLoginEmail,
|
|
508
|
+
newDeviceEmail: typeof s.newDeviceEmail === 'boolean' ? s.newDeviceEmail : defaults.newDeviceEmail,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
return defaults;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Resolve as configurações efetivas de trusted devices.
|
|
517
|
+
*
|
|
518
|
+
* Precedência: setting BD → configDefault → lib default (enabled=true, days=30).
|
|
519
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
520
|
+
*/
|
|
521
|
+
export async function resolveEffectiveTrustedDevices(settings, configDefault = {}) {
|
|
522
|
+
const defaults = {
|
|
523
|
+
enabled: configDefault.enabled ?? true,
|
|
524
|
+
days: configDefault.days ?? 30,
|
|
525
|
+
};
|
|
526
|
+
try {
|
|
527
|
+
const raw = await settings.getSetting(SETTING_KEYS.TRUSTED_DEVICES);
|
|
528
|
+
if (raw === null || raw === undefined)
|
|
529
|
+
return defaults;
|
|
530
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
531
|
+
return defaults;
|
|
532
|
+
const s = raw;
|
|
533
|
+
return {
|
|
534
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
535
|
+
days: typeof s.days === 'number' && s.days >= 1 ? Math.floor(s.days) : defaults.days,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
return defaults;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Resolve as configurações efetivas de TTL de tokens.
|
|
544
|
+
*
|
|
545
|
+
* Precedência: setting BD → configDefault → lib default (900s/900s/2592000s).
|
|
546
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
547
|
+
*/
|
|
548
|
+
export async function resolveEffectiveTokenTtl(settings, configDefault = {}) {
|
|
549
|
+
const defaults = {
|
|
550
|
+
accessTokenSec: configDefault.accessTokenSec ?? 900,
|
|
551
|
+
idTokenSec: configDefault.idTokenSec ?? 900,
|
|
552
|
+
refreshTokenSec: configDefault.refreshTokenSec ?? 2592000,
|
|
553
|
+
};
|
|
554
|
+
try {
|
|
555
|
+
const raw = await settings.getSetting(SETTING_KEYS.TOKEN_TTL);
|
|
556
|
+
if (raw === null || raw === undefined)
|
|
557
|
+
return defaults;
|
|
558
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
559
|
+
return defaults;
|
|
560
|
+
const s = raw;
|
|
561
|
+
return {
|
|
562
|
+
accessTokenSec: typeof s.accessTokenSec === 'number' && s.accessTokenSec >= 1 ? Math.floor(s.accessTokenSec) : defaults.accessTokenSec,
|
|
563
|
+
idTokenSec: typeof s.idTokenSec === 'number' && s.idTokenSec >= 1 ? Math.floor(s.idTokenSec) : defaults.idTokenSec,
|
|
564
|
+
refreshTokenSec: typeof s.refreshTokenSec === 'number' && s.refreshTokenSec >= 1 ? Math.floor(s.refreshTokenSec) : defaults.refreshTokenSec,
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
return defaults;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Resolve as configurações efetivas de impersonation.
|
|
573
|
+
*
|
|
574
|
+
* Precedência: setting BD → configDefault → lib default (false).
|
|
575
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
576
|
+
*/
|
|
577
|
+
export async function resolveEffectiveAdminImpersonation(settings, configDefault = false) {
|
|
578
|
+
const defaults = { enabled: configDefault };
|
|
579
|
+
try {
|
|
580
|
+
const raw = await settings.getSetting(SETTING_KEYS.ADMIN_IMPERSONATION);
|
|
581
|
+
if (raw === null || raw === undefined)
|
|
582
|
+
return defaults;
|
|
583
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
584
|
+
return defaults;
|
|
585
|
+
const s = raw;
|
|
586
|
+
return {
|
|
587
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
catch {
|
|
591
|
+
return defaults;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
const ORGS_POLICY_LIB_DEFAULTS = {
|
|
595
|
+
allowSelfCreate: false,
|
|
596
|
+
invitationTtlHours: 168,
|
|
597
|
+
roles: ['owner', 'admin', 'member'],
|
|
598
|
+
};
|
|
599
|
+
/** Default da lib: apenas ADMIN. */
|
|
600
|
+
export const ROLES_CATALOG_DEFAULT = {
|
|
601
|
+
roles: [{ name: 'ADMIN', description: 'Full access to the admin console' }],
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Resolve o catálogo efetivo de roles globais a partir da setting persistida.
|
|
605
|
+
*
|
|
606
|
+
* Regras:
|
|
607
|
+
* - ADMIN é SEMPRE garantido no resultado (merge defensivo — é o gate do console).
|
|
608
|
+
* - setting ausente/inválida/erro → default (apenas ADMIN).
|
|
609
|
+
* - O resultado é ordenado por nome (ADMIN sempre incluído).
|
|
610
|
+
* - Entradas com `name` inválido (não-string ou vazio) são descartadas silenciosamente.
|
|
611
|
+
*
|
|
612
|
+
* FAIL-SAFE: qualquer erro DB → default.
|
|
613
|
+
*/
|
|
614
|
+
/**
|
|
615
|
+
* Resolve roles catalog efetivo: org → global → default.
|
|
616
|
+
*
|
|
617
|
+
* @param settings - SettingsCapability
|
|
618
|
+
* @param orgId - opcional; quando fornecido, tenta settings da org antes do global
|
|
619
|
+
*/
|
|
620
|
+
export async function resolveEffectiveRolesCatalog(settings, orgId) {
|
|
621
|
+
async function fromRaw(raw) {
|
|
622
|
+
if (raw === null || raw === undefined)
|
|
623
|
+
return null;
|
|
624
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
625
|
+
return null;
|
|
626
|
+
const s = raw;
|
|
627
|
+
if (!Array.isArray(s.roles))
|
|
628
|
+
return null;
|
|
629
|
+
// Filtra entradas válidas (name deve ser string não-vazia).
|
|
630
|
+
const entries = s.roles
|
|
631
|
+
.filter((r) => typeof r === 'object' && r !== null && typeof r.name === 'string' && r.name.trim().length > 0)
|
|
632
|
+
.map((r) => ({
|
|
633
|
+
name: r.name.trim(),
|
|
634
|
+
...(typeof r.description === 'string' && r.description.trim().length > 0
|
|
635
|
+
? { description: r.description.trim() }
|
|
636
|
+
: {}),
|
|
637
|
+
}));
|
|
638
|
+
// Merge defensivo: ADMIN sempre presente.
|
|
639
|
+
const hasAdmin = entries.some((r) => r.name === 'ADMIN');
|
|
640
|
+
if (!hasAdmin) {
|
|
641
|
+
entries.unshift({ name: 'ADMIN', description: 'Full access to the admin console' });
|
|
642
|
+
}
|
|
643
|
+
// Ordena por nome.
|
|
644
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
645
|
+
return { roles: entries };
|
|
646
|
+
}
|
|
647
|
+
try {
|
|
648
|
+
// Resolução org → global → default
|
|
649
|
+
if (orgId) {
|
|
650
|
+
const orgRaw = await settings.getSetting(SETTING_KEYS.ROLES_CATALOG, orgId);
|
|
651
|
+
const orgResult = await fromRaw(orgRaw);
|
|
652
|
+
if (orgResult)
|
|
653
|
+
return orgResult;
|
|
654
|
+
}
|
|
655
|
+
const globalRaw = await settings.getSetting(SETTING_KEYS.ROLES_CATALOG, null);
|
|
656
|
+
const globalResult = await fromRaw(globalRaw);
|
|
657
|
+
if (globalResult)
|
|
658
|
+
return globalResult;
|
|
659
|
+
return ROLES_CATALOG_DEFAULT;
|
|
660
|
+
}
|
|
661
|
+
catch {
|
|
662
|
+
return ROLES_CATALOG_DEFAULT;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Resolve as configurações efetivas de política de organizações.
|
|
667
|
+
*
|
|
668
|
+
* Precedência: org-setting → global-setting → configDefault → lib default.
|
|
669
|
+
* FAIL-SAFE: qualquer erro → configDefault.
|
|
670
|
+
*
|
|
671
|
+
* Invariante mantida: 'owner' é sempre incluído na lista de roles (governance).
|
|
672
|
+
*
|
|
673
|
+
* @param settings - SettingsCapability
|
|
674
|
+
* @param configDefault - defaults estáticos do config do host
|
|
675
|
+
* @param orgId - opcional; quando fornecido, tenta settings da org antes do global
|
|
676
|
+
*/
|
|
677
|
+
export async function resolveEffectiveOrganizationsPolicy(settings, configDefault = {}, orgId) {
|
|
678
|
+
const defaultRoles = configDefault.roles ?? ORGS_POLICY_LIB_DEFAULTS.roles;
|
|
679
|
+
const rolesWithOwner = defaultRoles.includes('owner') ? defaultRoles : ['owner', ...defaultRoles];
|
|
680
|
+
const defaults = {
|
|
681
|
+
allowSelfCreate: configDefault.allowSelfCreate ?? ORGS_POLICY_LIB_DEFAULTS.allowSelfCreate,
|
|
682
|
+
invitationTtlHours: configDefault.invitationTtlHours ?? ORGS_POLICY_LIB_DEFAULTS.invitationTtlHours,
|
|
683
|
+
roles: rolesWithOwner,
|
|
684
|
+
};
|
|
685
|
+
function applyRaw(raw) {
|
|
686
|
+
if (raw === null || raw === undefined)
|
|
687
|
+
return null;
|
|
688
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
689
|
+
return null;
|
|
690
|
+
const s = raw;
|
|
691
|
+
// Roles: usa o valor da setting apenas se for um array não-vazio; sempre
|
|
692
|
+
// garante que 'owner' está presente (invariante de governance).
|
|
693
|
+
let roles = defaults.roles;
|
|
694
|
+
if (Array.isArray(s.roles) && s.roles.length > 0) {
|
|
695
|
+
roles = s.roles.includes('owner') ? s.roles : ['owner', ...s.roles];
|
|
696
|
+
}
|
|
697
|
+
return {
|
|
698
|
+
allowSelfCreate: typeof s.allowSelfCreate === 'boolean' ? s.allowSelfCreate : defaults.allowSelfCreate,
|
|
699
|
+
invitationTtlHours: typeof s.invitationTtlHours === 'number' && s.invitationTtlHours >= 1 ? Math.floor(s.invitationTtlHours) : defaults.invitationTtlHours,
|
|
700
|
+
roles,
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
try {
|
|
704
|
+
// Resolução org → global → defaults
|
|
705
|
+
if (orgId) {
|
|
706
|
+
const orgRaw = await settings.getSetting(SETTING_KEYS.ORGANIZATIONS_POLICY, orgId);
|
|
707
|
+
const orgResult = applyRaw(orgRaw);
|
|
708
|
+
if (orgResult)
|
|
709
|
+
return orgResult;
|
|
710
|
+
}
|
|
711
|
+
const globalRaw = await settings.getSetting(SETTING_KEYS.ORGANIZATIONS_POLICY, null);
|
|
712
|
+
const globalResult = applyRaw(globalRaw);
|
|
713
|
+
if (globalResult)
|
|
714
|
+
return globalResult;
|
|
715
|
+
return defaults;
|
|
716
|
+
}
|
|
717
|
+
catch {
|
|
718
|
+
return defaults;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Resolve o CATÁLOGO efetivo de roles de org (lista de roles permitidas),
|
|
723
|
+
* garantindo a invariante de governance: `owner` está sempre presente.
|
|
724
|
+
*
|
|
725
|
+
* Layer canônico de validação de role de org, compartilhado entre o caminho
|
|
726
|
+
* admin (`AdminOrgsService.resolveRoleCatalog`) e o member-facing
|
|
727
|
+
* (`account_orgs_controller`). Fail-safe: sem `settings` (null), usa o catálogo
|
|
728
|
+
* do config estático (mesma semântica do `resolveEffectiveOrganizationsPolicy`
|
|
729
|
+
* com `settings` indisponível — que cai nos `configDefault`).
|
|
730
|
+
*
|
|
731
|
+
* @param settings - SettingsCapability ou null (null → só config defaults)
|
|
732
|
+
* @param configDefault - defaults estáticos do config do host
|
|
733
|
+
* @param orgId - opcional; quando fornecido, tenta settings da org antes do global
|
|
734
|
+
*/
|
|
735
|
+
export async function resolveRoleCatalogList(settings, configDefault = {}, orgId) {
|
|
736
|
+
if (!settings) {
|
|
737
|
+
const roles = configDefault.roles ?? ORGS_POLICY_LIB_DEFAULTS.roles;
|
|
738
|
+
return roles.includes('owner') ? roles : ['owner', ...roles];
|
|
739
|
+
}
|
|
740
|
+
const policy = await resolveEffectiveOrganizationsPolicy(settings, configDefault, orgId);
|
|
741
|
+
return policy.roles;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Função PURA: valida se um `role` faz parte do catálogo efetivo de roles de org.
|
|
745
|
+
*
|
|
746
|
+
* É o único ponto de verdade para "esta role é válida para esta org?", reusado
|
|
747
|
+
* tanto pelo caminho admin quanto pelo member-facing — eliminando a
|
|
748
|
+
* reimplementação inline `policy.roles.includes(role)` que vivia em dois layers.
|
|
749
|
+
* H4: bloqueia roles fora do catálogo (incluindo arbitrárias e, quando não
|
|
750
|
+
* catalogadas, `owner`). Fail-safe via {@link resolveRoleCatalogList}.
|
|
751
|
+
*
|
|
752
|
+
* @param role - role candidata
|
|
753
|
+
* @param settings - SettingsCapability ou null
|
|
754
|
+
* @param configDefault - defaults estáticos do config do host
|
|
755
|
+
* @param orgId - opcional; escopo de org para a resolução do catálogo
|
|
756
|
+
*/
|
|
757
|
+
export async function isRoleInCatalog(role, settings, configDefault = {}, orgId) {
|
|
758
|
+
const catalog = await resolveRoleCatalogList(settings, configDefault, orgId);
|
|
759
|
+
return catalog.includes(role);
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Resolve as configurações efetivas de expiração de conta.
|
|
763
|
+
*
|
|
764
|
+
* FAIL-SAFE: qualquer erro → `{ enabled: false, inactiveDays: 365, warnDays: 14 }`.
|
|
765
|
+
*/
|
|
766
|
+
export async function resolveEffectiveAccountExpiration(settings) {
|
|
767
|
+
const defaults = { enabled: false, inactiveDays: 365, warnDays: 14 };
|
|
768
|
+
try {
|
|
769
|
+
const raw = await settings.getSetting(SETTING_KEYS.ACCOUNT_EXPIRATION);
|
|
770
|
+
if (raw === null || raw === undefined)
|
|
771
|
+
return defaults;
|
|
772
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
773
|
+
return defaults;
|
|
774
|
+
const s = raw;
|
|
775
|
+
return {
|
|
776
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
777
|
+
inactiveDays: typeof s.inactiveDays === 'number' && s.inactiveDays >= 1 ? Math.floor(s.inactiveDays) : defaults.inactiveDays,
|
|
778
|
+
warnDays: typeof s.warnDays === 'number' && s.warnDays >= 0 ? Math.floor(s.warnDays) : defaults.warnDays,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
catch {
|
|
782
|
+
return defaults;
|
|
783
|
+
}
|
|
784
|
+
}
|