@adonis-agora/authkit-server 0.47.0 → 0.49.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/build/commands/clients_create.js +4 -4
- package/build/commands/configure.js +3 -2
- package/build/commands/doctor.js +8 -5
- package/build/commands/eject.js +1 -1
- package/build/commands/expire_scan.js +7 -5
- package/build/commands/import_users.js +1 -1
- package/build/commands/keys_rotate.js +7 -4
- package/build/host/views/account/apps.edge +5 -5
- package/build/host/views/account/login.edge +1 -1
- package/build/host/views/account/mfa.edge +7 -7
- package/build/host/views/account/orgs.edge +5 -5
- package/build/host/views/account/security.edge +10 -10
- package/build/host/views/account/tokens.edge +5 -5
- package/build/index.d.ts +22 -7
- package/build/index.js +18 -5
- package/build/providers/authkit_server_provider.d.ts +2 -2
- package/build/providers/authkit_server_provider.js +20 -11
- package/build/services/main.d.ts +1 -1
- package/build/services/main.js +2 -2
- package/build/src/accounts/lucid_account_store.d.ts +3 -3
- package/build/src/accounts/lucid_account_store.js +6 -8
- package/build/src/accounts/lucid_store/core.js +1 -1
- package/build/src/accounts/lucid_store/mfa.js +1 -1
- package/build/src/accounts/lucid_store/organizations.js +2 -4
- package/build/src/accounts/lucid_store/password_hygiene.js +1 -4
- package/build/src/accounts/lucid_store/shared.d.ts +1 -1
- package/build/src/accounts/lucid_stores.d.ts +3 -3
- package/build/src/accounts/lucid_stores.js +2 -2
- package/build/src/adapters/database_adapter.js +3 -1
- package/build/src/adapters/factory.js +1 -1
- package/build/src/adapters/redis_adapter.js +2 -1
- package/build/src/commands/expire_scan_command.js +19 -5
- package/build/src/commands/settings_commands.js +22 -5
- package/build/src/define_config.d.ts +20 -20
- package/build/src/define_config.js +62 -67
- package/build/src/doctor/checks.js +45 -20
- package/build/src/events/dispatcher.d.ts +1 -1
- package/build/src/events/dispatcher.js +10 -10
- package/build/src/host/account_api/account_api_controller.js +95 -39
- package/build/src/host/account_deletion_ops.d.ts +4 -4
- package/build/src/host/account_deletion_ops.js +5 -5
- package/build/src/host/account_deletion_service.d.ts +2 -2
- package/build/src/host/account_deletion_service.js +2 -2
- package/build/src/host/account_export_service.d.ts +1 -1
- package/build/src/host/account_export_service.js +4 -6
- package/build/src/host/account_home.d.ts +0 -8
- package/build/src/host/account_home.js +6 -4
- package/build/src/host/account_login_url.d.ts +6 -3
- package/build/src/host/account_login_url.js +16 -8
- package/build/src/host/account_paths.d.ts +120 -0
- package/build/src/host/account_paths.js +161 -0
- package/build/src/host/account_screen_props.d.ts +163 -0
- package/build/src/host/account_screen_props.js +23 -0
- package/build/src/host/admin_api/admin_orgs_service.d.ts +2 -2
- package/build/src/host/admin_api/admin_orgs_service.js +3 -2
- package/build/src/host/admin_api/admin_users_service.d.ts +12 -12
- package/build/src/host/admin_api/admin_users_service.js +20 -20
- package/build/src/host/admin_api/api_clients_controller.js +2 -2
- package/build/src/host/admin_api/api_misc_controller.js +2 -2
- package/build/src/host/admin_api/api_orgs_controller.js +3 -3
- package/build/src/host/admin_api/api_settings_controller.js +11 -5
- package/build/src/host/admin_api/api_users_controller.d.ts +2 -2
- package/build/src/host/admin_api/api_users_controller.js +37 -38
- package/build/src/host/admin_api/dto.d.ts +4 -4
- package/build/src/host/admin_clients_service.js +5 -4
- package/build/src/host/admin_console/admin_shell_controller.js +4 -2
- package/build/src/host/admin_console/console_audit_controller.js +1 -1
- package/build/src/host/admin_console/console_clients_controller.js +5 -3
- package/build/src/host/admin_console/console_impersonation_controller.js +1 -1
- package/build/src/host/admin_console/console_keys_controller.js +2 -4
- package/build/src/host/admin_console/console_orgs_controller.js +3 -3
- package/build/src/host/admin_console/console_roles_controller.js +30 -12
- package/build/src/host/admin_console/console_sessions_controller.js +3 -3
- package/build/src/host/admin_console/console_settings_controller.js +11 -5
- package/build/src/host/admin_console/console_users_controller.d.ts +2 -2
- package/build/src/host/admin_console/console_users_controller.js +46 -47
- package/build/src/host/admin_prefix.js +2 -2
- package/build/src/host/admin_sessions_service.js +1 -3
- package/build/src/host/adonis_auth_sync.d.ts +1 -1
- package/build/src/host/adonis_auth_user_provider.d.ts +1 -1
- package/build/src/host/app_key.js +1 -1
- package/build/src/host/avatar_storage.js +1 -3
- package/build/src/host/config_locks.js +1 -3
- package/build/src/host/console_session.js +1 -1
- package/build/src/host/controllers/account_apps_controller.js +3 -2
- package/build/src/host/controllers/account_confirm_controller.js +5 -8
- package/build/src/host/controllers/account_mfa_controller.js +72 -18
- package/build/src/host/controllers/account_orgs_controller.js +47 -27
- package/build/src/host/controllers/account_security_controller.d.ts +2 -2
- package/build/src/host/controllers/account_security_controller.js +116 -116
- package/build/src/host/controllers/account_session_controller.js +13 -8
- package/build/src/host/controllers/account_tokens_controller.js +3 -2
- package/build/src/host/controllers/interaction_controller.js +59 -22
- package/build/src/host/controllers/registration_controller.js +28 -13
- package/build/src/host/default_mailer.js +11 -7
- package/build/src/host/durable/account_deletion_workflow.d.ts +2 -2
- package/build/src/host/durable/account_deletion_workflow.js +14 -14
- package/build/src/host/durable/account_export_workflow.d.ts +2 -2
- package/build/src/host/durable/account_export_workflow.js +12 -12
- package/build/src/host/durable/index.d.ts +5 -5
- package/build/src/host/durable/index.js +6 -6
- package/build/src/host/i18n.d.ts +1376 -1376
- package/build/src/host/i18n.js +1380 -1380
- package/build/src/host/impersonation.js +1 -7
- package/build/src/host/key_rotation_actions.d.ts +1 -1
- package/build/src/host/login_attempt.js +35 -6
- package/build/src/host/login_notify.js +1 -1
- package/build/src/host/otp_lockout.js +1 -3
- package/build/src/host/rate_limit.js +1 -1
- package/build/src/host/register_auth_host.d.ts +30 -0
- package/build/src/host/register_auth_host.js +120 -74
- package/build/src/host/renderers/edge_renderer.js +15 -2
- package/build/src/host/renderers/inertia_renderer.d.ts +23 -58
- package/build/src/host/renderers/inertia_renderer.js +23 -58
- package/build/src/host/runtime_settings.js +1 -1
- package/build/src/host/runtime_toggles.d.ts +3 -3
- package/build/src/host/runtime_toggles.js +69 -24
- package/build/src/host/security_notice_service.d.ts +1 -1
- package/build/src/host/security_notice_service.js +1 -1
- package/build/src/host/session_context.js +1 -1
- package/build/src/host/sudo/index.d.ts +3 -3
- package/build/src/host/sudo/index.js +3 -3
- package/build/src/host/sudo/methods/magic_link.js +6 -5
- package/build/src/host/sudo/methods/passkey.js +7 -4
- package/build/src/host/sudo/methods/password.js +8 -3
- package/build/src/host/sudo/runtime.js +6 -13
- package/build/src/host/sudo_mode.js +3 -2
- package/build/src/host/ui-dist/assets/index-BQoTDiLV.js +137 -0
- package/build/src/host/ui-dist/index.html +1 -1
- package/build/src/keys/jwks_manager.js +1 -1
- package/build/src/keys/keystore.js +1 -1
- package/build/src/keys/keystore_manager.d.ts +2 -2
- package/build/src/keys/keystore_manager.js +2 -2
- package/build/src/keys/keystore_vault.js +8 -4
- package/build/src/mixins/with_audit_log.d.ts +1 -1
- package/build/src/mixins/with_auth_user.d.ts +1 -1
- package/build/src/mixins/with_auth_user.js +1 -1
- package/build/src/mixins/with_credentials.d.ts +1 -1
- package/build/src/mixins/with_mfa.d.ts +1 -1
- package/build/src/mixins/with_personal_access_token.d.ts +1 -1
- package/build/src/mixins/with_provider_identity.d.ts +1 -1
- package/build/src/mixins/with_webauthn_credential.d.ts +1 -1
- package/build/src/observability/diagnostics_bridge.js +2 -2
- package/build/src/observability/metrics_service.js +1 -1
- package/build/src/observability/telescope/data_providers.d.ts +1 -1
- package/build/src/observability/telescope/data_providers.js +29 -43
- package/build/src/observability/telescope/extension.d.ts +1 -1
- package/build/src/observability/telescope/extension.js +58 -58
- package/build/src/observability/telescope/index.d.ts +2 -2
- package/build/src/observability/telescope/index.js +2 -2
- package/build/src/observability/wire_provider_events.d.ts +1 -1
- package/build/src/observability/wire_provider_events.js +11 -11
- package/build/src/password/common_passwords.js +1 -1
- package/build/src/password/password_manager.d.ts +1 -1
- package/build/src/password/password_manager.js +4 -4
- package/build/src/pat/lucid_pat_store.js +2 -6
- package/build/src/pat/pat_tokens.js +1 -1
- package/build/src/provider/interaction_actions.js +1 -1
- package/build/src/provider/key_rotation_scheduler.js +3 -1
- package/build/src/provider/logout_sources.js +2 -8
- package/build/src/provider/oidc_service.d.ts +2 -2
- package/build/src/provider/oidc_service.js +22 -14
- package/build/src/provider/single_flight_lock.js +1 -3
- package/build/src/provider/token_exchange.d.ts +1 -1
- package/build/src/schema/ensure.js +3 -1
- package/build/stubs/ui/react/components/auth_shell.tsx +19 -19
- package/build/stubs/ui/react/pages/account/login.tsx +6 -7
- package/build/stubs/ui/react/pages/account/mfa.tsx +16 -15
- package/build/stubs/ui/react/pages/account/tokens.tsx +27 -17
- package/build/stubs/ui/react/pages/consent.tsx +12 -12
- package/build/stubs/ui/react/pages/forgot.tsx +7 -7
- package/build/stubs/ui/react/pages/login.tsx +22 -24
- package/build/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
- package/build/stubs/ui/react/pages/reset.tsx +10 -10
- package/build/stubs/ui/react/pages/signup.tsx +30 -16
- package/build/stubs/ui/react/pages/verify-email.tsx +6 -6
- package/package.json +2 -2
- package/stubs/main.ts +2 -2
- package/stubs/ui/react/components/auth_shell.tsx +19 -19
- package/stubs/ui/react/pages/account/login.tsx +6 -7
- package/stubs/ui/react/pages/account/mfa.tsx +16 -15
- package/stubs/ui/react/pages/account/tokens.tsx +27 -17
- package/stubs/ui/react/pages/consent.tsx +12 -12
- package/stubs/ui/react/pages/forgot.tsx +7 -7
- package/stubs/ui/react/pages/login.tsx +22 -24
- package/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
- package/stubs/ui/react/pages/reset.tsx +10 -10
- package/stubs/ui/react/pages/signup.tsx +30 -16
- package/stubs/ui/react/pages/verify-email.tsx +6 -6
- package/build/src/host/ui-dist/assets/index-BmI_J87g.js +0 -137
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prefixo e segmentos de tela do console de conta (`/account/*`) — singleton de
|
|
3
|
+
* processo, configurável/localizável.
|
|
4
|
+
*
|
|
5
|
+
* Definidos em tempo de registro das rotas (`registerAuthHost`, via a opção
|
|
6
|
+
* `accountRoutes`) e lidos em runtime por TODOS os pontos que constroem uma URL
|
|
7
|
+
* do console de conta: o registro de rotas, os redirects dos controllers, as
|
|
8
|
+
* URLs absolutas dos e-mails transacionais, os guards de sudo e as views Edge
|
|
9
|
+
* (injetados como prop global `accountPaths` pelo renderer).
|
|
10
|
+
*
|
|
11
|
+
* Por que módulo singleton e não binding do container? Mesma razão do
|
|
12
|
+
* `admin_prefix` e do `account_login_url`: os guards e o registro de rotas são
|
|
13
|
+
* closures construídas em tempo de registro, ANTES da primeira request, quando
|
|
14
|
+
* o container do AdonisJS ainda não existe. Um módulo ESM é inicializado uma vez
|
|
15
|
+
* por processo — ideal para configuração imutável de boot.
|
|
16
|
+
*
|
|
17
|
+
* ── O que é configurável e o que NÃO é ──────────────────────────────────────
|
|
18
|
+
* Configuráveis: o PREFIXO (`/account` → `/conta`) e o SEGMENTO de cada TELA
|
|
19
|
+
* navegável (`security` → `seguranca`, `confirm` → `confirmar`, ...). São paths
|
|
20
|
+
* que o usuário vê na barra de endereço e que um host pode querer no idioma dele.
|
|
21
|
+
*
|
|
22
|
+
* NÃO configuráveis (de propósito): os action-subpaths dos POSTs de dentro de
|
|
23
|
+
* cada tela — `/password`, `/email`, `/enroll`, `/confirm`, `/disable`,
|
|
24
|
+
* `/passkeys/options`, `/passkeys/verify`, `/delete`, `/export`, o `/magic-link`
|
|
25
|
+
* e o `/passkey` das rotas de sudo, etc. São endpoints de formulário invisíveis
|
|
26
|
+
* ao usuário (ele nunca digita `/account/security/password`), servem apenas de
|
|
27
|
+
* alvo de `<form action>`/`fetch`, e mantê-los fixos evita multiplicar a
|
|
28
|
+
* superfície de configuração (e a de bugs) sem nenhum ganho de UX. Renomear a
|
|
29
|
+
* tela já cobre o caso real "quero /conta/seguranca". Idem para o segmento fixo
|
|
30
|
+
* `api` da JSON API (`{prefix}/api/*`): ele segue o prefixo mas nunca é
|
|
31
|
+
* traduzido — é contrato de máquina (authkit-react), não de humano.
|
|
32
|
+
*/
|
|
33
|
+
/** Prefixo default do console de conta. */
|
|
34
|
+
const DEFAULT_ACCOUNT_PREFIX = '/account';
|
|
35
|
+
/**
|
|
36
|
+
* Segmentos default de cada TELA navegável do console de conta. A chave é o
|
|
37
|
+
* identificador estável usado no código (`accountPath('security')`); o valor é
|
|
38
|
+
* o segmento de URL, sobrescrevível por `setAccountPaths`.
|
|
39
|
+
*/
|
|
40
|
+
const DEFAULT_ACCOUNT_SEGMENTS = {
|
|
41
|
+
login: 'login',
|
|
42
|
+
logout: 'logout',
|
|
43
|
+
security: 'security',
|
|
44
|
+
mfa: 'mfa',
|
|
45
|
+
confirm: 'confirm',
|
|
46
|
+
tokens: 'tokens',
|
|
47
|
+
apps: 'apps',
|
|
48
|
+
orgs: 'orgs',
|
|
49
|
+
emailConfirm: 'email/confirm',
|
|
50
|
+
};
|
|
51
|
+
let _prefix = DEFAULT_ACCOUNT_PREFIX;
|
|
52
|
+
let _segments = { ...DEFAULT_ACCOUNT_SEGMENTS };
|
|
53
|
+
/**
|
|
54
|
+
* Normaliza o prefixo: começa com '/', sem trailing slash. Mesma semântica de
|
|
55
|
+
* `normalizeAdminPrefix`. `'/'` → `'/'` (raiz) é improvável mas seguro.
|
|
56
|
+
*/
|
|
57
|
+
export function normalizeAccountPrefix(raw) {
|
|
58
|
+
let p = raw.trim();
|
|
59
|
+
if (!p.startsWith('/'))
|
|
60
|
+
p = `/${p}`;
|
|
61
|
+
p = p.replace(/\/+$/, '');
|
|
62
|
+
return p || '/';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Normaliza um segmento de tela: sem barras nas pontas (mas preserva barras
|
|
66
|
+
* internas, ex.: `'email/confirm'`). Valor vazio é ignorado pelo caller.
|
|
67
|
+
*/
|
|
68
|
+
function normalizeSegment(raw) {
|
|
69
|
+
return raw.trim().replace(/^\/+/, '').replace(/\/+$/, '');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Define o prefixo e/ou os segmentos de tela do console de conta para este
|
|
73
|
+
* processo. Chamado UMA VEZ por `registerAuthHost` no boot da aplicação.
|
|
74
|
+
*
|
|
75
|
+
* Só sobrescreve o que foi passado — chamada sem `prefix` mantém o prefixo
|
|
76
|
+
* atual, e segmentos ausentes de `paths` mantêm o default. Valores
|
|
77
|
+
* vazios/whitespace são ignorados (caem no default), nunca produzem um path
|
|
78
|
+
* quebrado.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* setAccountPaths({ prefix: '/conta', paths: { security: 'seguranca', confirm: 'confirmar' } })
|
|
82
|
+
* accountPath('security') // → '/conta/seguranca'
|
|
83
|
+
* accountPath('confirm') // → '/conta/confirmar'
|
|
84
|
+
*/
|
|
85
|
+
export function setAccountPaths(opts) {
|
|
86
|
+
if (!opts)
|
|
87
|
+
return;
|
|
88
|
+
if (opts.prefix !== undefined) {
|
|
89
|
+
const trimmed = opts.prefix.trim();
|
|
90
|
+
if (trimmed)
|
|
91
|
+
_prefix = normalizeAccountPrefix(trimmed);
|
|
92
|
+
}
|
|
93
|
+
if (opts.paths) {
|
|
94
|
+
for (const key of Object.keys(opts.paths)) {
|
|
95
|
+
const value = opts.paths[key];
|
|
96
|
+
if (value === undefined)
|
|
97
|
+
continue;
|
|
98
|
+
const seg = normalizeSegment(value);
|
|
99
|
+
if (seg)
|
|
100
|
+
_segments[key] = seg;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Junta o prefixo do console de conta com um subpath arbitrário, tratando o
|
|
106
|
+
* prefixo raiz (`'/'`) como `''` na composição: sem isso o resultado seria
|
|
107
|
+
* `'//<sub>'`, que num `<form action>`/`fetch()` é URL protocol-relative (o
|
|
108
|
+
* browser lê `<sub>` como HOST, não como path).
|
|
109
|
+
*
|
|
110
|
+
* Base canônica de `accountPath()` e de QUALQUER outra composição
|
|
111
|
+
* prefixo+subpath fora das TELAS fixas (ex.: o `{prefix}/api` da JSON API em
|
|
112
|
+
* `register_auth_host`). Novas composições devem passar por aqui em vez de
|
|
113
|
+
* reimplementar `${accountPrefix()}/algo` — é exatamente essa duplicação que
|
|
114
|
+
* reproduz o bug do `//` quando o prefixo normaliza pra raiz.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* joinAccountPath('api') // default → '/account/api'
|
|
118
|
+
*/
|
|
119
|
+
export function joinAccountPath(sub) {
|
|
120
|
+
const base = _prefix === '/' ? '' : _prefix;
|
|
121
|
+
return `${base}/${sub}`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Retorna o path completo de uma TELA do console de conta (prefixo + segmento).
|
|
125
|
+
* Para os action-subpaths (POSTs de dentro da tela) concatene o subpath fixo:
|
|
126
|
+
* `accountPath('security') + '/password'`.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* accountPath('security') // default → '/account/security'
|
|
130
|
+
* accountPath('confirm') // default → '/account/confirm'
|
|
131
|
+
*/
|
|
132
|
+
export function accountPath(key) {
|
|
133
|
+
return joinAccountPath(_segments[key]);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Retorna o prefixo BRUTO do console de conta (default `'/account'`; pode ser
|
|
137
|
+
* `'/'` na raiz). Para compor `{prefix}/algo` (ex.: a JSON API, cujo segmento
|
|
138
|
+
* `api` é fixo — contrato de máquina), use `joinAccountPath('algo')`: ela
|
|
139
|
+
* colapsa a raiz e evita o `//`. Este getter existe para os casos (ex.: os
|
|
140
|
+
* asserts de teste) que precisam do valor cru do prefixo.
|
|
141
|
+
*/
|
|
142
|
+
export function accountPrefix() {
|
|
143
|
+
return _prefix;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Mapa `{ chave → path completo }` de TODAS as telas. Injetado como prop global
|
|
147
|
+
* `accountPaths` nas views Edge, para que os `<form action>`/`fetch()` respeitem
|
|
148
|
+
* os overrides sem cada view conhecer o prefixo.
|
|
149
|
+
*/
|
|
150
|
+
export function accountPathsMap() {
|
|
151
|
+
const out = {};
|
|
152
|
+
for (const key of Object.keys(_segments)) {
|
|
153
|
+
out[key] = accountPath(key);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
/** Restaura os defaults — uso em testes (isola o singleton entre casos). */
|
|
158
|
+
export function resetAccountPaths() {
|
|
159
|
+
_prefix = DEFAULT_ACCOUNT_PREFIX;
|
|
160
|
+
_segments = { ...DEFAULT_ACCOUNT_SEGMENTS };
|
|
161
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos de props das telas do console de conta (`/account/*`) — a FONTE ÚNICA da
|
|
3
|
+
* verdade sobre o shape que cada página React recebe.
|
|
4
|
+
*
|
|
5
|
+
* ── Por que esses tipos existem ──────────────────────────────────────────────
|
|
6
|
+
* Um host que cria as telas do console em React próprio (via `inertiaRenderer`,
|
|
7
|
+
* em vez das views Edge built-in) precisa tipar o componente da página. Antes
|
|
8
|
+
* disso, o único "contrato" era o DOCBLOCK do `inertiaRenderer`, copiado à mão —
|
|
9
|
+
* frágil: um docblock desatualizado já enganou um host. Agora o shape vem daqui,
|
|
10
|
+
* e os CONTROLLERS REAIS (`account_session_controller`, `account_security_-
|
|
11
|
+
* controller`, `account_mfa_controller`, `account_confirm_controller`) satisfazem
|
|
12
|
+
* (`satisfies Omit<…, 'messages'>`) exatamente estes tipos ao chamar `render()`.
|
|
13
|
+
* Se o payload de um controller divergir do tipo — campo a mais, a menos, tipo
|
|
14
|
+
* trocado — o `tsc` do pacote quebra. Esse é o objetivo: um único ponto muda, e
|
|
15
|
+
* o compilador força o outro a acompanhar.
|
|
16
|
+
*
|
|
17
|
+
* ── Sobre a prop `messages` ──────────────────────────────────────────────────
|
|
18
|
+
* `messages` (catálogo i18n) é injetada pelo `inertiaRenderer` como shared prop,
|
|
19
|
+
* NÃO pelos controllers. Por isso ela faz parte destes tipos (é o que a página
|
|
20
|
+
* React recebe), mas os controllers satisfazem `Omit<…, 'messages'>` — eles nunca
|
|
21
|
+
* passam `messages` no literal do `render()`.
|
|
22
|
+
*/
|
|
23
|
+
import type { PasskeySummary } from '../accounts/account_store.js';
|
|
24
|
+
import type { AuthMessages } from './i18n.js';
|
|
25
|
+
import type { SudoMethodDescriptor } from './sudo/types.js';
|
|
26
|
+
/**
|
|
27
|
+
* Props da tela `account/login` (tela de login do console de conta).
|
|
28
|
+
*
|
|
29
|
+
* - `csrfToken`: token para o campo `_csrf` do formulário.
|
|
30
|
+
* - `returnTo`: caminho interno de destino pós-login (já validado pelo servidor —
|
|
31
|
+
* só caminhos internos) ou `null`. Quando presente, o formulário deve incluir
|
|
32
|
+
* `<input type="hidden" name="return_to" value={returnTo} />`; o servidor
|
|
33
|
+
* revalida no POST.
|
|
34
|
+
* - `error`: mensagem de erro de autenticação localizada (credenciais inválidas,
|
|
35
|
+
* conta bloqueada/desabilitada). Ausente quando não há erro.
|
|
36
|
+
* - `messages`: catálogo i18n (injetado pelo renderer).
|
|
37
|
+
*/
|
|
38
|
+
export interface AccountLoginProps {
|
|
39
|
+
csrfToken: string;
|
|
40
|
+
returnTo: string | null;
|
|
41
|
+
error?: string;
|
|
42
|
+
messages: AuthMessages;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Props da tela `account/security` (perfil, senha, e-mail, sessões, export,
|
|
46
|
+
* danger-zone). Todas as flags de `*Supported` degradam a UI quando o store não
|
|
47
|
+
* suporta a capacidade correspondente.
|
|
48
|
+
*
|
|
49
|
+
* - `supported`: `false` quando o store não suporta o self-service de segurança.
|
|
50
|
+
* - `profileSupported`: `true` quando dá para editar nome/avatar (`updateProfile`).
|
|
51
|
+
* - `avatarUploadSupported`: `true` quando algum backend (drive OU media) armazena o upload.
|
|
52
|
+
* - `email` / `name` / `avatarUrl`: valores atuais da conta (`''` se ausentes).
|
|
53
|
+
* - `passwordChanged` / `emailChangeRequested` / `emailChanged` / `profileUpdated`
|
|
54
|
+
* / `error` / `trustedDevicesRevoked` / `deleteError`: flashes localizados ou `null`.
|
|
55
|
+
* - `trustedDevicesEnabled`: recurso de dispositivos confiáveis ligado.
|
|
56
|
+
* - `sessionsSupported`: `true` quando o adapter OIDC enumera as sessões ativas.
|
|
57
|
+
* - `sessions`: sessões ativas da própria conta (vazio quando não suportado).
|
|
58
|
+
* `loginTs` é ISO ou `''`.
|
|
59
|
+
* - `exportSupported`: sempre `true` (portabilidade/LGPD para a conta logada).
|
|
60
|
+
* - `deletionSupported`: `true` quando o store suporta hard delete.
|
|
61
|
+
* - `messages`: catálogo i18n (injetado pelo renderer).
|
|
62
|
+
*/
|
|
63
|
+
export interface AccountSecurityProps {
|
|
64
|
+
csrfToken: string;
|
|
65
|
+
supported: boolean;
|
|
66
|
+
profileSupported: boolean;
|
|
67
|
+
avatarUploadSupported: boolean;
|
|
68
|
+
email: string;
|
|
69
|
+
name: string;
|
|
70
|
+
avatarUrl: string;
|
|
71
|
+
passwordChanged: string | null;
|
|
72
|
+
emailChangeRequested: string | null;
|
|
73
|
+
emailChanged: string | null;
|
|
74
|
+
profileUpdated: string | null;
|
|
75
|
+
error: string | null;
|
|
76
|
+
trustedDevicesEnabled: boolean;
|
|
77
|
+
trustedDevicesRevoked: string | null;
|
|
78
|
+
sessionsSupported: boolean;
|
|
79
|
+
sessions: Array<{
|
|
80
|
+
loginTs: string;
|
|
81
|
+
browser: string;
|
|
82
|
+
os: string;
|
|
83
|
+
ip: string;
|
|
84
|
+
location: string;
|
|
85
|
+
}>;
|
|
86
|
+
exportSupported: boolean;
|
|
87
|
+
deletionSupported: boolean;
|
|
88
|
+
deleteError: string | null;
|
|
89
|
+
messages: AuthMessages;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Props da tela `account/mfa` (TOTP + passkeys). As props VARIAM por action, e é
|
|
93
|
+
* por isso que as específicas de passo são opcionais:
|
|
94
|
+
*
|
|
95
|
+
* - `index` manda o estado base + a lista de passkeys (`passkeysSupported` /
|
|
96
|
+
* `passkeys`).
|
|
97
|
+
* - `enroll` (após `POST /mfa/enroll`) acrescenta o passo do QR: `enrolling: true`,
|
|
98
|
+
* `secret` (base32 para entrada manual) e `qrDataUrl` (data-URL do `otpauth://`).
|
|
99
|
+
* - `confirm` com código inválido reexibe `enrolling: true` + `error`, com
|
|
100
|
+
* `secret`/`qrDataUrl` `null` (o segredo pendente NÃO é regenerado).
|
|
101
|
+
*
|
|
102
|
+
* - `enabled`: `true` quando o TOTP já está confirmado.
|
|
103
|
+
* - `recoveryCodes`: códigos recém-gerados (exibidos UMA vez) ou `null`.
|
|
104
|
+
* - `messages`: catálogo i18n (injetado pelo renderer).
|
|
105
|
+
*/
|
|
106
|
+
export interface AccountMfaProps {
|
|
107
|
+
csrfToken: string;
|
|
108
|
+
enabled: boolean;
|
|
109
|
+
recoveryCodes: string[] | null;
|
|
110
|
+
/** Presente em `index`: `true` quando o store persiste credenciais WebAuthn. */
|
|
111
|
+
passkeysSupported?: boolean;
|
|
112
|
+
/** Presente em `index`: passkeys cadastradas (vazio quando não suportado). */
|
|
113
|
+
passkeys?: PasskeySummary[];
|
|
114
|
+
/** Passo de enroll/confirm: `true` mostra QR/segredo + campo de código. */
|
|
115
|
+
enrolling?: boolean;
|
|
116
|
+
/** Segredo TOTP (base32) no passo de enroll; `null` na reexibição do confirm. */
|
|
117
|
+
secret?: string | null;
|
|
118
|
+
/** QR do `otpauth://` como data-URL no passo de enroll; `null` na reexibição. */
|
|
119
|
+
qrDataUrl?: string | null;
|
|
120
|
+
/** Erro localizado (ex.: código TOTP inválido no confirm). */
|
|
121
|
+
error?: string;
|
|
122
|
+
messages: AuthMessages;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Um método de sudo, como a tela `account/confirm` o recebe: o descritor do SPI
|
|
126
|
+
* (`SudoMethodDescriptor`) acrescido do `id` estável do método. A tela renderiza
|
|
127
|
+
* por `kind` (`form`/`action`/`redirect`/`webauthn`); `endpoint` é o POST de
|
|
128
|
+
* verificação (para `webauthn`, as options ficam em `${endpoint}/options`).
|
|
129
|
+
*/
|
|
130
|
+
export type AccountConfirmMethod = {
|
|
131
|
+
id: string;
|
|
132
|
+
} & SudoMethodDescriptor;
|
|
133
|
+
/**
|
|
134
|
+
* Props da tela `account/confirm` (sudo — confirmar identidade).
|
|
135
|
+
*
|
|
136
|
+
* - `csrfToken`: token para o POST de cada método.
|
|
137
|
+
* - `returnTo`: caminho interno de destino após confirmar (validado) ou `null`.
|
|
138
|
+
* - `error`: flash de erro da última tentativa ou `null`.
|
|
139
|
+
* - `notice`: flash informativo (ex.: "link de confirmação enviado") ou `null`.
|
|
140
|
+
* - `methods`: métodos de sudo disponíveis para a conta (ver {@link AccountConfirmMethod}).
|
|
141
|
+
* - `preferredId`: `id` do último método usado (destaque na UI) ou `null`.
|
|
142
|
+
* - `messages`: catálogo i18n (injetado pelo renderer).
|
|
143
|
+
*/
|
|
144
|
+
export interface AccountConfirmProps {
|
|
145
|
+
csrfToken: string;
|
|
146
|
+
returnTo: string | null;
|
|
147
|
+
error: string | null;
|
|
148
|
+
notice: string | null;
|
|
149
|
+
methods: AccountConfirmMethod[];
|
|
150
|
+
preferredId: string | null;
|
|
151
|
+
messages: AuthMessages;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Props da tela `account/email-confirmed` (terminal do link de troca de e-mail).
|
|
155
|
+
*
|
|
156
|
+
* - `ok`: `true` quando o token era válido e o novo e-mail foi aplicado; `false`
|
|
157
|
+
* para token inválido/expirado ou store sem suporte.
|
|
158
|
+
* - `messages`: catálogo i18n (injetado pelo renderer).
|
|
159
|
+
*/
|
|
160
|
+
export interface AccountEmailConfirmedProps {
|
|
161
|
+
ok: boolean;
|
|
162
|
+
messages: AuthMessages;
|
|
163
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos de props das telas do console de conta (`/account/*`) — a FONTE ÚNICA da
|
|
3
|
+
* verdade sobre o shape que cada página React recebe.
|
|
4
|
+
*
|
|
5
|
+
* ── Por que esses tipos existem ──────────────────────────────────────────────
|
|
6
|
+
* Um host que cria as telas do console em React próprio (via `inertiaRenderer`,
|
|
7
|
+
* em vez das views Edge built-in) precisa tipar o componente da página. Antes
|
|
8
|
+
* disso, o único "contrato" era o DOCBLOCK do `inertiaRenderer`, copiado à mão —
|
|
9
|
+
* frágil: um docblock desatualizado já enganou um host. Agora o shape vem daqui,
|
|
10
|
+
* e os CONTROLLERS REAIS (`account_session_controller`, `account_security_-
|
|
11
|
+
* controller`, `account_mfa_controller`, `account_confirm_controller`) satisfazem
|
|
12
|
+
* (`satisfies Omit<…, 'messages'>`) exatamente estes tipos ao chamar `render()`.
|
|
13
|
+
* Se o payload de um controller divergir do tipo — campo a mais, a menos, tipo
|
|
14
|
+
* trocado — o `tsc` do pacote quebra. Esse é o objetivo: um único ponto muda, e
|
|
15
|
+
* o compilador força o outro a acompanhar.
|
|
16
|
+
*
|
|
17
|
+
* ── Sobre a prop `messages` ──────────────────────────────────────────────────
|
|
18
|
+
* `messages` (catálogo i18n) é injetada pelo `inertiaRenderer` como shared prop,
|
|
19
|
+
* NÃO pelos controllers. Por isso ela faz parte destes tipos (é o que a página
|
|
20
|
+
* React recebe), mas os controllers satisfazem `Omit<…, 'messages'>` — eles nunca
|
|
21
|
+
* passam `messages` no literal do `render()`.
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { OrgInvitation, OrgMember, OrgSummary } from '../../accounts/account_store.js';
|
|
1
2
|
import type { ResolvedServerConfig } from '../../define_config.js';
|
|
2
|
-
import type { OrgSummary, OrgMember, OrgInvitation } from '../../accounts/account_store.js';
|
|
3
|
-
import type { AdminActor } from './admin_users_service.js';
|
|
4
3
|
import type { SettingsCapability } from '../runtime_settings.js';
|
|
4
|
+
import type { AdminActor } from './admin_users_service.js';
|
|
5
5
|
export interface OrgWithMemberCount extends OrgSummary {
|
|
6
6
|
memberCount: number;
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { supportsOrganizations } from '../../accounts/account_store.js';
|
|
2
|
-
import {
|
|
2
|
+
import { accountPath } from '../account_paths.js';
|
|
3
|
+
import { isRoleInCatalog, resolveRoleCatalogList } from '../runtime_toggles.js';
|
|
3
4
|
/**
|
|
4
5
|
* Lógica de gestão de organizações compartilhada entre o console admin (HTML)
|
|
5
6
|
* e a Admin REST API (JSON). Usada pelos `AdminOrgsController` e `ApiOrgsController`.
|
|
@@ -267,7 +268,7 @@ export class AdminOrgsService {
|
|
|
267
268
|
});
|
|
268
269
|
// Dispara mail hook (best-effort)
|
|
269
270
|
if (this.cfg.mail?.onOrgInvitation) {
|
|
270
|
-
const acceptUrl = `${origin}
|
|
271
|
+
const acceptUrl = `${origin}${accountPath('orgs')}/invitations/${token}/accept`;
|
|
271
272
|
try {
|
|
272
273
|
await this.cfg.mail.onOrgInvitation({
|
|
273
274
|
email: input.email,
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import type { HttpContext } from
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import { type DeletionResult } from
|
|
6
|
-
import type { SettingsCapability } from
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { AuthAccount } from '../../accounts/account_store.js';
|
|
3
|
+
import type { ResolvedServerConfig } from '../../define_config.js';
|
|
4
|
+
import type { OidcService } from '../../provider/oidc_service.js';
|
|
5
|
+
import { type DeletionResult } from '../account_deletion_service.js';
|
|
6
|
+
import type { SettingsCapability } from '../runtime_settings.js';
|
|
7
7
|
/** Quem disparou a operação (para auditoria). `admin-api` quando via REST API. */
|
|
8
8
|
export interface AdminActor {
|
|
9
9
|
actorId: string | null;
|
|
10
10
|
ip: string | null;
|
|
11
11
|
/** Marca metadata da auditoria — 'admin-api' nas escritas via REST, 'admin' no console HTML. */
|
|
12
|
-
source?:
|
|
12
|
+
source?: 'admin-api' | 'admin';
|
|
13
13
|
}
|
|
14
14
|
/** Resultado da deleção via admin: false quando o store não suporta hard delete. */
|
|
15
15
|
export type DeleteUserResult = {
|
|
16
16
|
ok: false;
|
|
17
|
-
reason:
|
|
17
|
+
reason: 'not_found' | 'unsupported';
|
|
18
18
|
} | {
|
|
19
19
|
ok: true;
|
|
20
20
|
result: DeletionResult;
|
|
@@ -34,7 +34,7 @@ export type EnqueueDeletion = (input: {
|
|
|
34
34
|
actor: {
|
|
35
35
|
actorId: string | null;
|
|
36
36
|
ip: string | null;
|
|
37
|
-
source:
|
|
37
|
+
source: 'admin' | 'admin-api';
|
|
38
38
|
};
|
|
39
39
|
}) => Promise<string>;
|
|
40
40
|
export interface CreateUserInput {
|
|
@@ -50,10 +50,10 @@ export type CreateUserResult = {
|
|
|
50
50
|
invited: boolean;
|
|
51
51
|
} | {
|
|
52
52
|
ok: false;
|
|
53
|
-
reason:
|
|
53
|
+
reason: 'email_taken';
|
|
54
54
|
} | {
|
|
55
55
|
ok: false;
|
|
56
|
-
reason:
|
|
56
|
+
reason: 'password_policy';
|
|
57
57
|
/** Chave i18n da regra violada + params para interpolar. */
|
|
58
58
|
messageKey: string;
|
|
59
59
|
messageParams?: Record<string, string | number>;
|
|
@@ -141,7 +141,7 @@ export declare class AdminUsersService {
|
|
|
141
141
|
*
|
|
142
142
|
* @returns código i18n/erro quando a operação deve ser bloqueada; `null` quando OK.
|
|
143
143
|
*/
|
|
144
|
-
guardGlobalRolesChange(targetId: string, newRoles: string[], actorId: string | null): Promise<
|
|
144
|
+
guardGlobalRolesChange(targetId: string, newRoles: string[], actorId: string | null): Promise<'last_admin' | 'cannot_self_demote' | null>;
|
|
145
145
|
/** Atualiza nome/avatar (capacidade opcional). Retorna a conta ou null. */
|
|
146
146
|
updateProfile(accountId: string, patch: {
|
|
147
147
|
name?: string | null;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { randomBytes } from
|
|
2
|
-
import { supportsAccountDeletion, supportsAccountStatus,
|
|
3
|
-
import {
|
|
4
|
-
import { AccountDeletionService
|
|
5
|
-
import {
|
|
6
|
-
import { resolveEffectiveRolesCatalog } from
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { supportsAccountDeletion, supportsAccountStatus, supportsCountByGlobalRole, supportsProfile, } from '../../accounts/account_store.js';
|
|
3
|
+
import { PasswordPolicyError } from '../../password/password_manager.js';
|
|
4
|
+
import { AccountDeletionService } from '../account_deletion_service.js';
|
|
5
|
+
import { sendPasswordResetEmail } from '../default_mailer.js';
|
|
6
|
+
import { resolveEffectiveRolesCatalog } from '../runtime_toggles.js';
|
|
7
7
|
/**
|
|
8
8
|
* Lógica de gestão de usuários compartilhada entre o console admin (B6, HTML) e a
|
|
9
9
|
* Admin REST API (R6, JSON). Encapsula o fluxo "create + invite", reset de senha,
|
|
@@ -24,9 +24,9 @@ export class AdminUsersService {
|
|
|
24
24
|
const store = this.cfg.accountStore;
|
|
25
25
|
const existing = await store.findByEmail(input.email);
|
|
26
26
|
if (existing)
|
|
27
|
-
return { ok: false, reason:
|
|
27
|
+
return { ok: false, reason: 'email_taken' };
|
|
28
28
|
const hasPassword = !!input.password;
|
|
29
|
-
const initialPassword = input.password ?? randomBytes(24).toString(
|
|
29
|
+
const initialPassword = input.password ?? randomBytes(24).toString('hex');
|
|
30
30
|
let account;
|
|
31
31
|
try {
|
|
32
32
|
account = await store.create({
|
|
@@ -40,7 +40,7 @@ export class AdminUsersService {
|
|
|
40
40
|
if (error instanceof PasswordPolicyError) {
|
|
41
41
|
return {
|
|
42
42
|
ok: false,
|
|
43
|
-
reason:
|
|
43
|
+
reason: 'password_policy',
|
|
44
44
|
messageKey: error.key,
|
|
45
45
|
messageParams: error.params,
|
|
46
46
|
};
|
|
@@ -48,7 +48,7 @@ export class AdminUsersService {
|
|
|
48
48
|
throw error;
|
|
49
49
|
}
|
|
50
50
|
await this.cfg.audit?.record({
|
|
51
|
-
type:
|
|
51
|
+
type: 'user.created',
|
|
52
52
|
accountId: account.id,
|
|
53
53
|
email: input.email,
|
|
54
54
|
actorId: actor.actorId,
|
|
@@ -70,7 +70,7 @@ export class AdminUsersService {
|
|
|
70
70
|
return null;
|
|
71
71
|
await this.sendResetEmail(ctx, account.email);
|
|
72
72
|
await this.cfg.audit?.record({
|
|
73
|
-
type:
|
|
73
|
+
type: 'user.password_reset_sent',
|
|
74
74
|
accountId,
|
|
75
75
|
email: account.email,
|
|
76
76
|
actorId: actor.actorId,
|
|
@@ -92,7 +92,7 @@ export class AdminUsersService {
|
|
|
92
92
|
else
|
|
93
93
|
await store.enableAccount(accountId);
|
|
94
94
|
await this.cfg.audit?.record({
|
|
95
|
-
type: disable ?
|
|
95
|
+
type: disable ? 'user.disabled' : 'user.enabled',
|
|
96
96
|
accountId,
|
|
97
97
|
actorId: actor.actorId,
|
|
98
98
|
ip: actor.ip,
|
|
@@ -123,7 +123,7 @@ export class AdminUsersService {
|
|
|
123
123
|
// Roles que o usuário não tinha E que não estão no catálogo = inválidas.
|
|
124
124
|
for (const role of roles) {
|
|
125
125
|
if (!catalogNames.has(role) && !currentRoles.has(role)) {
|
|
126
|
-
return
|
|
126
|
+
return 'admin.roles.unknown_role';
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
@@ -137,7 +137,7 @@ export class AdminUsersService {
|
|
|
137
137
|
/** Roles globais que conferem acesso de admin (default ['ADMIN']). */
|
|
138
138
|
adminRoles() {
|
|
139
139
|
const roles = this.cfg.admin?.roles;
|
|
140
|
-
return roles && roles.length > 0 ? roles : [
|
|
140
|
+
return roles && roles.length > 0 ? roles : ['ADMIN'];
|
|
141
141
|
}
|
|
142
142
|
/** Um conjunto de roles contém ao menos uma role de admin? */
|
|
143
143
|
hasAdminRole(roles) {
|
|
@@ -226,11 +226,11 @@ export class AdminUsersService {
|
|
|
226
226
|
return null;
|
|
227
227
|
// Auto-rebaixamento: o ator removendo a própria role de admin.
|
|
228
228
|
if (actorId && actorId === targetId)
|
|
229
|
-
return
|
|
229
|
+
return 'cannot_self_demote';
|
|
230
230
|
// Último admin: se o target é o único admin, a remoção causaria lockout.
|
|
231
231
|
const admins = await this.countAdmins();
|
|
232
232
|
if (admins <= 1)
|
|
233
|
-
return
|
|
233
|
+
return 'last_admin';
|
|
234
234
|
return null;
|
|
235
235
|
}
|
|
236
236
|
/** Atualiza nome/avatar (capacidade opcional). Retorna a conta ou null. */
|
|
@@ -251,15 +251,15 @@ export class AdminUsersService {
|
|
|
251
251
|
async delete(oidc, accountId, actor, enqueue) {
|
|
252
252
|
const store = this.cfg.accountStore;
|
|
253
253
|
if (!supportsAccountDeletion(store))
|
|
254
|
-
return { ok: false, reason:
|
|
254
|
+
return { ok: false, reason: 'unsupported' };
|
|
255
255
|
const account = await store.findById(accountId);
|
|
256
256
|
if (!account)
|
|
257
|
-
return { ok: false, reason:
|
|
258
|
-
const source = actor.source ===
|
|
257
|
+
return { ok: false, reason: 'not_found' };
|
|
258
|
+
const source = actor.source === 'admin' ? 'admin' : 'admin-api';
|
|
259
259
|
// Trilha administrativa ANTES do cascade — assim esta linha também é
|
|
260
260
|
// anonimizada na etapa de anonimização do audit (não reintroduz PII).
|
|
261
261
|
await this.cfg.audit?.record({
|
|
262
|
-
type:
|
|
262
|
+
type: 'user.deleted',
|
|
263
263
|
accountId,
|
|
264
264
|
email: account.email,
|
|
265
265
|
actorId: actor.actorId,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
2
|
import { AdminClientsService } from '../admin_clients_service.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { clientCreateInput, clientInputValidator, clientPartialInput, } from '../admin_validators.js';
|
|
4
|
+
import { apiError, clientDto, createdClientDto } from './dto.js';
|
|
5
5
|
/** Resolve o serviço (== OidcService) + o AdminClientsService. */
|
|
6
6
|
async function clientsService(ctx) {
|
|
7
7
|
const service = await ctx.containerResolver.make('authkit.server');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
-
import { TokenVerifyService } from './token_verify_service.js';
|
|
3
2
|
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
4
3
|
import { computeAdminStats } from '../admin_stats_service.js';
|
|
5
|
-
import { auditDto, apiError } from './dto.js';
|
|
6
4
|
import { tokenVerifyValidator } from '../admin_validators.js';
|
|
5
|
+
import { apiError, auditDto } from './dto.js';
|
|
6
|
+
import { TokenVerifyService } from './token_verify_service.js';
|
|
7
7
|
/**
|
|
8
8
|
* Endpoints utilitários da Admin REST API: log de auditoria (`GET /audit`) e
|
|
9
9
|
* introspecção genérica de token (`POST /tokens/verify`).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
-
import {
|
|
3
|
-
import { orgDto, orgDetailDto, orgInvitationDto, apiError } from './dto.js';
|
|
2
|
+
import { orgAddMemberValidator, orgCreateValidator, orgInvitationValidator, orgMemberRoleValidator, orgUpdateValidator, } from '../admin_validators.js';
|
|
4
3
|
import { resolveRuntimeSettings } from '../runtime_settings.js';
|
|
5
|
-
import {
|
|
4
|
+
import { AdminOrgsService } from './admin_orgs_service.js';
|
|
5
|
+
import { apiError, orgDetailDto, orgDto, orgInvitationDto } from './dto.js';
|
|
6
6
|
/** Lê a config + monta o actor `admin-api` para auditoria. */
|
|
7
7
|
async function ctxBits(ctx) {
|
|
8
8
|
const service = await ctx.containerResolver.make('authkit.server');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
+
import { SettingLockedError, isSettingLocked, lockedSettingKeys } from '../config_locks.js';
|
|
2
3
|
import { resolveRuntimeSettings } from '../runtime_settings.js';
|
|
3
|
-
import {
|
|
4
|
-
import { isSettingLocked, lockedSettingKeys, SettingLockedError } from '../config_locks.js';
|
|
4
|
+
import { apiError, settingDto } from './dto.js';
|
|
5
5
|
/** 423 Locked: a setting foi travada via defineConfig (não editável em runtime). */
|
|
6
6
|
function lockedResponse(ctx, err) {
|
|
7
7
|
return ctx.response
|
|
@@ -16,8 +16,8 @@ function notSupported(ctx) {
|
|
|
16
16
|
function resolveOrgId(ctx) {
|
|
17
17
|
const qs = ctx.request.qs();
|
|
18
18
|
if ('organizationId' in qs) {
|
|
19
|
-
const v = qs
|
|
20
|
-
return v
|
|
19
|
+
const v = qs.organizationId;
|
|
20
|
+
return v?.trim() ? v.trim() : null;
|
|
21
21
|
}
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
@@ -99,7 +99,13 @@ export default class ApiSettingsController {
|
|
|
99
99
|
metadata: { key, value: body.value, organizationId: orgId },
|
|
100
100
|
});
|
|
101
101
|
const saved = await svc.getSetting(key, orgId);
|
|
102
|
-
return settingDto({
|
|
102
|
+
return settingDto({
|
|
103
|
+
key,
|
|
104
|
+
organizationId: orgId,
|
|
105
|
+
value: saved,
|
|
106
|
+
updatedAt: new Date(),
|
|
107
|
+
updatedBy: null,
|
|
108
|
+
});
|
|
103
109
|
}
|
|
104
110
|
/** DELETE /settings/:key */
|
|
105
111
|
async destroy(ctx) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { HttpContext } from
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
3
|
/**
|
|
4
4
|
* Recurso de usuários da Admin REST API (R6). JSON puro (camelCase), erros no
|
|
5
5
|
* envelope `{ error: { code, message } }`. Toda escrita audita com `actor: 'admin-api'`.
|