@adonis-agora/authkit-server 0.47.0 → 0.48.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 +7 -7
- package/build/index.js +5 -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/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 +2 -6
- package/build/src/host/controllers/account_mfa_controller.js +63 -12
- 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 +114 -115
- package/build/src/host/controllers/account_session_controller.js +5 -5
- 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 +9 -1
- package/build/src/host/renderers/inertia_renderer.js +9 -1
- 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 +1 -1
- 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
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
+
import { supportsMagicLink, supportsPasskeys } from '../../accounts/account_store.js';
|
|
3
|
+
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
4
|
+
import { guardBotProtection, resolveEffectiveBotProtection } from '../bot_protection.js';
|
|
2
5
|
import { brandFor, isFirstParty } from '../branding.js';
|
|
6
|
+
import { sendMagicLinkEmail } from '../default_mailer.js';
|
|
7
|
+
import { sendOtpUnlockEmail } from '../default_mailer.js';
|
|
3
8
|
import { translate } from '../i18n.js';
|
|
4
9
|
import { attemptPasswordLogin, isEmailUnverifiedBlock } from '../login_attempt.js';
|
|
5
10
|
import { notifyLoginSuccess } from '../login_notify.js';
|
|
6
|
-
import {
|
|
11
|
+
import { createOtpLockout, generateOtpUnlockToken, rawToDbOtpUnlockToken, resolveEffectiveOtpLockout, } from '../otp_lockout.js';
|
|
7
12
|
import { RuntimeSettings, resolveRuntimeSettings } from '../runtime_settings.js';
|
|
8
|
-
import { resolveEffectiveMaintenanceMode, resolveEffectiveRegistration,
|
|
9
|
-
import { supportsPasskeys, supportsMagicLink } from '../../accounts/account_store.js';
|
|
10
|
-
import { sendMagicLinkEmail } from '../default_mailer.js';
|
|
13
|
+
import { resolveEffectiveAuthMethods, resolveEffectiveMaintenanceMode, resolveEffectiveRegistration, resolveEffectiveSessionPolicy, } from '../runtime_toggles.js';
|
|
11
14
|
import { TRUSTED_DEVICE_COOKIE, buildTrustedDevicePayload, isTrustedDeviceValid, } from '../trusted_device.js';
|
|
12
|
-
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
13
|
-
import { createOtpLockout, resolveEffectiveOtpLockout, generateOtpUnlockToken, rawToDbOtpUnlockToken, } from '../otp_lockout.js';
|
|
14
|
-
import { sendOtpUnlockEmail } from '../default_mailer.js';
|
|
15
15
|
/**
|
|
16
16
|
* Best-effort: returns a RuntimeSettings backed by the container DB, or a no-op
|
|
17
17
|
* fallback. Contrato NON-NULL preservado — é chamado 6× passando direto p/
|
|
@@ -21,7 +21,12 @@ import { sendOtpUnlockEmail } from '../default_mailer.js';
|
|
|
21
21
|
*/
|
|
22
22
|
async function getRuntimeSettings(ctx) {
|
|
23
23
|
const rs = await resolveRuntimeSettings(ctx);
|
|
24
|
-
return rs ??
|
|
24
|
+
return (rs ??
|
|
25
|
+
new RuntimeSettings({
|
|
26
|
+
table: () => {
|
|
27
|
+
throw new Error('no-op');
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
25
30
|
}
|
|
26
31
|
const SESSION_KEY = 'authkit_login_email';
|
|
27
32
|
/** accountId aguardando o 2º fator depois da senha verificada. */
|
|
@@ -78,7 +83,8 @@ export default class AuthInteractionController {
|
|
|
78
83
|
});
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
|
-
if (details.prompt.name === 'consent' &&
|
|
86
|
+
if (details.prompt.name === 'consent' &&
|
|
87
|
+
isFirstParty(cfg.branding, details.params.client_id)) {
|
|
82
88
|
// Clients first-party: auto-concede o consent (pula a tela de consent).
|
|
83
89
|
// interactions.consent monta o Grant + interactionFinished e escreve o
|
|
84
90
|
// redirect de volta para o client — opera via provider.interactionDetails,
|
|
@@ -185,9 +191,7 @@ export default class AuthInteractionController {
|
|
|
185
191
|
// Bot protection (plugável): valida o token do widget ANTES de tocar nas
|
|
186
192
|
// credenciais. Fail-safe: erro/timeout no verify do host PERMITE o fluxo.
|
|
187
193
|
// We use a cfg-compatible object: pass effectiveBotLogin merged into cfg.
|
|
188
|
-
const cfgWithEffectiveBot = effectiveBotLogin !== cfg.botProtection
|
|
189
|
-
? { ...cfg, botProtection: effectiveBotLogin }
|
|
190
|
-
: cfg;
|
|
194
|
+
const cfgWithEffectiveBot = effectiveBotLogin !== cfg.botProtection ? { ...cfg, botProtection: effectiveBotLogin } : cfg;
|
|
191
195
|
if (!(await guardBotProtection(ctx, cfgWithEffectiveBot, 'login', { email, clientId }))) {
|
|
192
196
|
const found = await cfg.accountStore.findByEmail(email);
|
|
193
197
|
const account = found
|
|
@@ -209,7 +213,14 @@ export default class AuthInteractionController {
|
|
|
209
213
|
// ligado precisamos exigir o 2º fator e NÃO podemos chamar interactionFinished
|
|
210
214
|
// ainda. A sequência verificação + lockout + auditoria de falha é centralizada
|
|
211
215
|
// em attemptPasswordLogin; a renderização (lookup p/ personalização) fica aqui.
|
|
212
|
-
const result = await attemptPasswordLogin(cfg, {
|
|
216
|
+
const result = await attemptPasswordLogin(cfg, {
|
|
217
|
+
email,
|
|
218
|
+
password,
|
|
219
|
+
ip,
|
|
220
|
+
clientId,
|
|
221
|
+
settings: runtimeSettings,
|
|
222
|
+
logger: ctx.logger,
|
|
223
|
+
});
|
|
213
224
|
if (!result.ok) {
|
|
214
225
|
// Senha expirada: redireciona para o step de troca obrigatória.
|
|
215
226
|
if (result.passwordExpired && result.account) {
|
|
@@ -250,7 +261,9 @@ export default class AuthInteractionController {
|
|
|
250
261
|
? translate(cfg.messages, 'errors.account_expired')
|
|
251
262
|
: translate(cfg.messages, 'errors.invalid_credentials'),
|
|
252
263
|
brand,
|
|
253
|
-
botProtection: effectiveBotLogin?.on.includes('login')
|
|
264
|
+
botProtection: effectiveBotLogin?.on.includes('login')
|
|
265
|
+
? effectiveBotLogin.widget
|
|
266
|
+
: undefined,
|
|
254
267
|
});
|
|
255
268
|
}
|
|
256
269
|
const acc = result.account;
|
|
@@ -329,7 +342,10 @@ export default class AuthInteractionController {
|
|
|
329
342
|
// remember-me: lê o checkbox do form. Checkbox HTML ausente/desmarcado = sem valor.
|
|
330
343
|
// Quando rememberEnabled=false, ignora o checkbox (sessão sempre transiente).
|
|
331
344
|
const rememberChecked = ctx.request.input('remember');
|
|
332
|
-
const rememberOn = rememberChecked === 'on' ||
|
|
345
|
+
const rememberOn = rememberChecked === 'on' ||
|
|
346
|
+
rememberChecked === '1' ||
|
|
347
|
+
rememberChecked === 'true' ||
|
|
348
|
+
rememberChecked === true;
|
|
333
349
|
const remember = sessionPolicy.rememberEnabled ? rememberOn : false;
|
|
334
350
|
// single-session: lista sessões ANTES do login para saber quais existem.
|
|
335
351
|
// Após o completeLogin, a sessão NOVA é criada; revogamos as ANTERIORES.
|
|
@@ -389,7 +405,7 @@ export default class AuthInteractionController {
|
|
|
389
405
|
const otpLockoutCfg = await resolveEffectiveOtpLockout(runtimeForOtp);
|
|
390
406
|
const otpLockout = createOtpLockout(otpLockoutCfg, ctx.logger);
|
|
391
407
|
// Verifica se o fator OTP está travado ANTES de tentar verificar.
|
|
392
|
-
if (otpLockoutCfg.enabled && await otpLockout.isLocked(accountId)) {
|
|
408
|
+
if (otpLockoutCfg.enabled && (await otpLockout.isLocked(accountId))) {
|
|
393
409
|
return render(ctx, 'mfa-challenge', {
|
|
394
410
|
uid: ctx.request.param('uid'),
|
|
395
411
|
csrfToken: ctx.request.csrfToken,
|
|
@@ -642,7 +658,12 @@ export default class AuthInteractionController {
|
|
|
642
658
|
}
|
|
643
659
|
const acc = await cfg.accountStore.consumeMagicLinkToken(token);
|
|
644
660
|
if (!acc) {
|
|
645
|
-
await cfg.audit?.record({
|
|
661
|
+
await cfg.audit?.record({
|
|
662
|
+
type: 'login.failure',
|
|
663
|
+
ip,
|
|
664
|
+
clientId,
|
|
665
|
+
metadata: { stage: 'magic_link' },
|
|
666
|
+
});
|
|
646
667
|
return ctx.response.redirect(`/auth/interaction/${uid}`);
|
|
647
668
|
}
|
|
648
669
|
// E-mail não verificado (LGPD/compliance): mesmo com o link válido, não
|
|
@@ -707,14 +728,20 @@ export default class AuthInteractionController {
|
|
|
707
728
|
// Modo discoverable: sem accountId na sessão, gera options sem restrição
|
|
708
729
|
// de credenciais (allowCredentials vazio = o browser apresenta todas).
|
|
709
730
|
if (!supportsPasskeys(cfg.accountStore)) {
|
|
710
|
-
return ctx.response.badRequest({
|
|
731
|
+
return ctx.response.badRequest({
|
|
732
|
+
message: translate(cfg.messages, 'errors.passkeys_unavailable'),
|
|
733
|
+
discoverable: false,
|
|
734
|
+
});
|
|
711
735
|
}
|
|
712
736
|
// Passa '__discoverable__' como sentinel — o store (LucidStore) detecta e
|
|
713
737
|
// retorna options com allowCredentials:[] se suportar; caso contrário null.
|
|
714
738
|
const generated = await cfg.accountStore.generatePasskeyAuthenticationOptions?.('__discoverable__');
|
|
715
739
|
if (!generated) {
|
|
716
740
|
// Store não suporta discoverable credentials — autofill não disponível.
|
|
717
|
-
return ctx.response.badRequest({
|
|
741
|
+
return ctx.response.badRequest({
|
|
742
|
+
message: translate(cfg.messages, 'errors.passkeys_unavailable'),
|
|
743
|
+
discoverable: false,
|
|
744
|
+
});
|
|
718
745
|
}
|
|
719
746
|
ctx.session.put(PASSKEY_AUTH_CHALLENGE_KEY, generated.challenge);
|
|
720
747
|
return { ...generated.options, _discoverable: true };
|
|
@@ -782,7 +809,8 @@ export default class AuthInteractionController {
|
|
|
782
809
|
parsed = null;
|
|
783
810
|
}
|
|
784
811
|
const ok = parsed
|
|
785
|
-
? ((await cfg.accountStore.verifyPasskeyAuthentication?.(accountId, parsed, challenge)) ??
|
|
812
|
+
? ((await cfg.accountStore.verifyPasskeyAuthentication?.(accountId, parsed, challenge)) ??
|
|
813
|
+
false)
|
|
786
814
|
: false;
|
|
787
815
|
ctx.session.forget(PASSKEY_AUTH_CHALLENGE_KEY);
|
|
788
816
|
if (!ok) {
|
|
@@ -975,14 +1003,23 @@ export default class AuthInteractionController {
|
|
|
975
1003
|
}
|
|
976
1004
|
}
|
|
977
1005
|
if (!row) {
|
|
978
|
-
await cfg.audit?.record({
|
|
1006
|
+
await cfg.audit?.record({
|
|
1007
|
+
type: 'otp.unlock_failed',
|
|
1008
|
+
ip,
|
|
1009
|
+
metadata: { reason: 'token_not_found' },
|
|
1010
|
+
});
|
|
979
1011
|
return render(ctx, 'otp-unlock', { ok: false });
|
|
980
1012
|
}
|
|
981
1013
|
// Verifica TTL.
|
|
982
1014
|
const { DateTime } = await import('luxon');
|
|
983
1015
|
const expiresAt = row.passwordResetExpiresAt;
|
|
984
1016
|
if (!expiresAt || expiresAt < DateTime.now()) {
|
|
985
|
-
await cfg.audit?.record({
|
|
1017
|
+
await cfg.audit?.record({
|
|
1018
|
+
type: 'otp.unlock_failed',
|
|
1019
|
+
accountId: row.id,
|
|
1020
|
+
ip,
|
|
1021
|
+
metadata: { reason: 'token_expired' },
|
|
1022
|
+
});
|
|
986
1023
|
return render(ctx, 'otp-unlock', { ok: false, expired: true });
|
|
987
1024
|
}
|
|
988
1025
|
// Token válido: zera o lock OTP + limpa o token do DB.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
-
import { brandFor } from '../branding.js';
|
|
3
2
|
import { randomBytes } from 'node:crypto';
|
|
4
|
-
import { signupValidator, passwordlessSignupValidator, forgotPasswordValidator, resetPasswordValidator, } from '../validators.js';
|
|
5
|
-
import { sendPasswordResetEmail, sendEmailVerificationEmail, sendMagicLinkEmail, } from '../default_mailer.js';
|
|
6
|
-
import { translate } from '../i18n.js';
|
|
7
3
|
import { PasswordPolicyError } from '../../password/password_manager.js';
|
|
4
|
+
import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
8
5
|
import { guardBotProtection, resolveEffectiveBotProtection } from '../bot_protection.js';
|
|
6
|
+
import { brandFor } from '../branding.js';
|
|
7
|
+
import { sendEmailVerificationEmail, sendMagicLinkEmail, sendPasswordResetEmail, } from '../default_mailer.js';
|
|
8
|
+
import { translate } from '../i18n.js';
|
|
9
9
|
import { RuntimeSettings, resolveRuntimeSettings } from '../runtime_settings.js';
|
|
10
|
-
import {
|
|
10
|
+
import { resolveEffectiveAuthMethods, resolveEffectiveMaintenanceMode, resolveEffectiveRegistration, } from '../runtime_toggles.js';
|
|
11
11
|
import { dispatchSecurityNotice } from '../security_notice_service.js';
|
|
12
|
-
import {
|
|
12
|
+
import { forgotPasswordValidator, passwordlessSignupValidator, resetPasswordValidator, signupValidator, } from '../validators.js';
|
|
13
13
|
/**
|
|
14
14
|
* Best-effort: returns a RuntimeSettings backed by the container DB, or a no-op
|
|
15
15
|
* fallback. Contrato NON-NULL preservado (callers passam direto p/ resolvers que
|
|
@@ -19,7 +19,12 @@ import { AdminSessionsService } from '../admin_sessions_service.js';
|
|
|
19
19
|
*/
|
|
20
20
|
async function getRuntimeSettings(ctx) {
|
|
21
21
|
const rs = await resolveRuntimeSettings(ctx);
|
|
22
|
-
return rs ??
|
|
22
|
+
return (rs ??
|
|
23
|
+
new RuntimeSettings({
|
|
24
|
+
table: () => {
|
|
25
|
+
throw new Error('no-op');
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
23
28
|
}
|
|
24
29
|
export default class AuthRegistrationController {
|
|
25
30
|
/** GET /auth/interaction/:uid/signup — tela de cadastro (dentro do fluxo OIDC). */
|
|
@@ -119,7 +124,9 @@ export default class AuthRegistrationController {
|
|
|
119
124
|
csrfToken: ctx.request.csrfToken,
|
|
120
125
|
error: translate(cfg.messages, 'errors.email_taken'),
|
|
121
126
|
brand,
|
|
122
|
-
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
127
|
+
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
128
|
+
? effectiveBotSignup.widget
|
|
129
|
+
: undefined,
|
|
123
130
|
});
|
|
124
131
|
}
|
|
125
132
|
let created;
|
|
@@ -139,7 +146,9 @@ export default class AuthRegistrationController {
|
|
|
139
146
|
csrfToken: ctx.request.csrfToken,
|
|
140
147
|
error: translate(cfg.messages, error.key, error.params),
|
|
141
148
|
brand,
|
|
142
|
-
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
149
|
+
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
150
|
+
? effectiveBotSignup.widget
|
|
151
|
+
: undefined,
|
|
143
152
|
});
|
|
144
153
|
}
|
|
145
154
|
throw error;
|
|
@@ -163,7 +172,9 @@ export default class AuthRegistrationController {
|
|
|
163
172
|
csrfToken: ctx.request.csrfToken,
|
|
164
173
|
error: translate(cfg.messages, 'errors.signup_failed'),
|
|
165
174
|
brand,
|
|
166
|
-
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
175
|
+
botProtection: effectiveBotSignup?.on.includes('signup')
|
|
176
|
+
? effectiveBotSignup.widget
|
|
177
|
+
: undefined,
|
|
167
178
|
});
|
|
168
179
|
}
|
|
169
180
|
// Verificação de e-mail (best-effort — não bloqueia nem reverte o login).
|
|
@@ -257,7 +268,8 @@ export default class AuthRegistrationController {
|
|
|
257
268
|
// auth_methods: se forgotPassword efetivo for false → 404 (endpoint desligado).
|
|
258
269
|
const authMethods = await resolveEffectiveAuthMethods(runtimeSettings, {
|
|
259
270
|
configuredSocialProviders: cfg.social?.providers ?? [],
|
|
260
|
-
magicLinkCapable: cfg.passwordless?.magicLink &&
|
|
271
|
+
magicLinkCapable: cfg.passwordless?.magicLink &&
|
|
272
|
+
typeof cfg.accountStore.issueMagicLinkToken === 'function',
|
|
261
273
|
configOverrides: cfg.authMethods,
|
|
262
274
|
});
|
|
263
275
|
if (!authMethods.forgotPassword) {
|
|
@@ -286,7 +298,8 @@ export default class AuthRegistrationController {
|
|
|
286
298
|
// auth_methods: se forgotPassword efetivo for false → 404 (endpoint desligado).
|
|
287
299
|
const authMethods = await resolveEffectiveAuthMethods(runtimeSettings, {
|
|
288
300
|
configuredSocialProviders: cfg.social?.providers ?? [],
|
|
289
|
-
magicLinkCapable: cfg.passwordless?.magicLink &&
|
|
301
|
+
magicLinkCapable: cfg.passwordless?.magicLink &&
|
|
302
|
+
typeof cfg.accountStore.issueMagicLinkToken === 'function',
|
|
290
303
|
configOverrides: cfg.authMethods,
|
|
291
304
|
});
|
|
292
305
|
if (!authMethods.forgotPassword) {
|
|
@@ -377,7 +390,9 @@ export default class AuthRegistrationController {
|
|
|
377
390
|
throw error;
|
|
378
391
|
}
|
|
379
392
|
if (!ok) {
|
|
380
|
-
return ctx.response.badRequest({
|
|
393
|
+
return ctx.response.badRequest({
|
|
394
|
+
error: translate(cfg.messages, 'errors.invalid_or_expired_token'),
|
|
395
|
+
});
|
|
381
396
|
}
|
|
382
397
|
await cfg.audit?.record({
|
|
383
398
|
type: 'password_reset.consumed',
|
|
@@ -6,8 +6,9 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
+
import { accountPath } from './account_paths.js';
|
|
9
10
|
import { renderTransactionalEmail } from './email_templates.js';
|
|
10
|
-
import { resolveMessages, translate
|
|
11
|
+
import { resolveMessages, translate } from './i18n.js';
|
|
11
12
|
let mailServicePromise;
|
|
12
13
|
/**
|
|
13
14
|
* Importa o service de mail do HOST de forma preguiçosa e fail-safe.
|
|
@@ -191,7 +192,7 @@ export async function sendNewLoginEmail(ctx, data) {
|
|
|
191
192
|
heading: translate(t, 'mail.new_login.heading'),
|
|
192
193
|
intro,
|
|
193
194
|
ctaLabel: translate(t, 'account.security.title'),
|
|
194
|
-
ctaUrl: `${origin}
|
|
195
|
+
ctaUrl: `${origin}${accountPath('security')}`,
|
|
195
196
|
footnote: translate(t, 'mail.new_login.fallback'),
|
|
196
197
|
});
|
|
197
198
|
const sent = await sendEmail(ctx, data.email, content);
|
|
@@ -212,7 +213,10 @@ export async function sendNewDeviceLoginEmail(ctx, data) {
|
|
|
212
213
|
const brand = resolveBrand(ctx);
|
|
213
214
|
const { messages: t, locale } = resolveMailMessages(ctx);
|
|
214
215
|
const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
|
|
215
|
-
const lines = [
|
|
216
|
+
const lines = [
|
|
217
|
+
translate(t, 'mail.new_login.intro'),
|
|
218
|
+
translate(t, 'mail.new_login.when', { date: data.when }),
|
|
219
|
+
];
|
|
216
220
|
if (data.userAgent)
|
|
217
221
|
lines.push(translate(t, 'mail.new_login.device', { device: data.userAgent }));
|
|
218
222
|
if (data.ip)
|
|
@@ -225,7 +229,7 @@ export async function sendNewDeviceLoginEmail(ctx, data) {
|
|
|
225
229
|
heading: translate(t, 'mail.new_login.heading'),
|
|
226
230
|
intro: lines.join(' '),
|
|
227
231
|
ctaLabel: translate(t, 'account.security.title'),
|
|
228
|
-
ctaUrl: `${origin}
|
|
232
|
+
ctaUrl: `${origin}${accountPath('security')}`,
|
|
229
233
|
footnote: translate(t, 'mail.new_login.fallback'),
|
|
230
234
|
});
|
|
231
235
|
const sent = await sendEmail(ctx, data.email, content);
|
|
@@ -283,7 +287,7 @@ export async function sendEmailChangeNoticeEmail(ctx, data) {
|
|
|
283
287
|
heading: translate(t, 'mail.email_change_notice.heading'),
|
|
284
288
|
intro: translate(t, 'mail.email_change_notice.intro', { newEmail: data.newEmail }),
|
|
285
289
|
ctaLabel: translate(t, 'mail.email_change_notice.cta'),
|
|
286
|
-
ctaUrl: `${origin}
|
|
290
|
+
ctaUrl: `${origin}${accountPath('security')}`,
|
|
287
291
|
footnote: translate(t, 'mail.email_change_notice.fallback'),
|
|
288
292
|
});
|
|
289
293
|
const sent = await sendEmail(ctx, data.email, content);
|
|
@@ -316,7 +320,7 @@ export async function sendEmailChangedCompletedEmail(ctx, data) {
|
|
|
316
320
|
newEmail: data.newEmail,
|
|
317
321
|
}),
|
|
318
322
|
ctaLabel: translate(t, 'mail.email_changed_completed.cta'),
|
|
319
|
-
ctaUrl: `${origin}
|
|
323
|
+
ctaUrl: `${origin}${accountPath('security')}`,
|
|
320
324
|
footnote: translate(t, 'mail.email_changed_completed.fallback'),
|
|
321
325
|
});
|
|
322
326
|
const sent = await sendEmail(ctx, data.oldEmail, content);
|
|
@@ -354,7 +358,7 @@ export async function sendSecurityNoticeEmail(ctx, data) {
|
|
|
354
358
|
heading: translate(t, 'mail.security_notice.heading'),
|
|
355
359
|
intro: intro.join(' '),
|
|
356
360
|
ctaLabel: translate(t, 'account.security.title'),
|
|
357
|
-
ctaUrl: `${origin}
|
|
361
|
+
ctaUrl: `${origin}${accountPath('security')}`,
|
|
358
362
|
footnote: translate(t, 'mail.security_notice.fallback'),
|
|
359
363
|
});
|
|
360
364
|
const sent = await sendEmail(ctx, data.email, content);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { OidcService } from
|
|
2
|
-
import type { DeletionActor } from
|
|
1
|
+
import type { OidcService } from '../../provider/oidc_service.js';
|
|
2
|
+
import type { DeletionActor } from '../account_deletion_service.js';
|
|
3
3
|
/** Nome canônico do workflow durável de deleção de conta. */
|
|
4
4
|
export declare const ACCOUNT_DELETE_WORKFLOW = "authkit.account.delete";
|
|
5
5
|
/** Input do workflow `authkit.account.delete`. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { anonymizeAudit, auditDeleted, deleteAccountAvatar, deleteAccountRow, disableMfa, removeFromOrgs, removePasskeys, revokePats, revokeSessions, snapshotAccount, unlinkProviders, } from
|
|
1
|
+
import { anonymizeAudit, auditDeleted, deleteAccountAvatar, deleteAccountRow, disableMfa, removeFromOrgs, removePasskeys, revokePats, revokeSessions, snapshotAccount, unlinkProviders, } from '../account_deletion_ops.js';
|
|
2
2
|
/** Nome canônico do workflow durável de deleção de conta. */
|
|
3
|
-
export const ACCOUNT_DELETE_WORKFLOW =
|
|
3
|
+
export const ACCOUNT_DELETE_WORKFLOW = 'authkit.account.delete';
|
|
4
4
|
/** Estado inicial vazio do {@link DeletionResult} (acumulado etapa a etapa). */
|
|
5
5
|
function emptyResult() {
|
|
6
6
|
return {
|
|
@@ -42,7 +42,7 @@ export function defineAccountDeletionWorkflow(deps) {
|
|
|
42
42
|
// Snapshot da conta ANTES de destruir (e-mail + avatar) — capturado num step
|
|
43
43
|
// para ser determinístico no replay. Se a conta não existe (ou já foi
|
|
44
44
|
// deletada num run anterior), encerra como no-op.
|
|
45
|
-
const snapshot = await ctx.step(
|
|
45
|
+
const snapshot = await ctx.step('snapshot', async () => {
|
|
46
46
|
const cfg = (await deps.oidc()).config;
|
|
47
47
|
return snapshotAccount(cfg, accountId);
|
|
48
48
|
});
|
|
@@ -50,37 +50,37 @@ export function defineAccountDeletionWorkflow(deps) {
|
|
|
50
50
|
return emptyResult();
|
|
51
51
|
const result = emptyResult();
|
|
52
52
|
// 1) Audit `account.deleted` ANTES de qualquer destruição.
|
|
53
|
-
await ctx.step(
|
|
53
|
+
await ctx.step('audit.deleted', async () => {
|
|
54
54
|
const cfg = (await deps.oidc()).config;
|
|
55
55
|
await auditDeleted(cfg, snapshot, actor);
|
|
56
56
|
});
|
|
57
57
|
// 2) Sessões + grants (cascateia os tokens do oidc-provider).
|
|
58
|
-
const revoke = await ctx.step(
|
|
58
|
+
const revoke = await ctx.step('revoke.sessions', async () => revokeSessions(await deps.oidc(), accountId));
|
|
59
59
|
result.sessions = revoke.sessions;
|
|
60
60
|
result.grants = revoke.grants;
|
|
61
61
|
result.accessTokens = revoke.accessTokens;
|
|
62
62
|
result.refreshTokens = revoke.refreshTokens;
|
|
63
63
|
// 3) Personal Access Tokens.
|
|
64
|
-
result.pats = (await ctx.step(
|
|
64
|
+
result.pats = (await ctx.step('revoke.pats', async () => revokePats((await deps.oidc()).config, accountId))).pats;
|
|
65
65
|
// 4) Passkeys / credenciais WebAuthn.
|
|
66
|
-
result.passkeys = (await ctx.step(
|
|
66
|
+
result.passkeys = (await ctx.step('remove.passkeys', async () => removePasskeys((await deps.oidc()).config, accountId))).passkeys;
|
|
67
67
|
// 5) MFA / TOTP.
|
|
68
|
-
await ctx.step(
|
|
68
|
+
await ctx.step('disable.mfa', async () => {
|
|
69
69
|
await disableMfa((await deps.oidc()).config, accountId);
|
|
70
70
|
});
|
|
71
71
|
// 6) Identidades de provider linkadas.
|
|
72
|
-
result.providerIdentities = (await ctx.step(
|
|
72
|
+
result.providerIdentities = (await ctx.step('unlink.providers', async () => unlinkProviders((await deps.oidc()).config, accountId))).providerIdentities;
|
|
73
73
|
// 6b) Organizations.
|
|
74
|
-
const orgResult = await ctx.step(
|
|
74
|
+
const orgResult = await ctx.step('remove.orgs', async () => removeFromOrgs((await deps.oidc()).config, accountId));
|
|
75
75
|
result.orgMemberships = orgResult.orgMemberships;
|
|
76
76
|
result.orgInvitations = orgResult.orgInvitations;
|
|
77
77
|
// 7) Avatar no drive.
|
|
78
|
-
result.avatarDeleted = (await ctx.step(
|
|
78
|
+
result.avatarDeleted = (await ctx.step('delete.avatar', async () => deleteAccountAvatar((await deps.oidc()).config, accountId, snapshot.avatarUrl))).avatarDeleted;
|
|
79
79
|
// 8) Anonimiza o histórico de audit.
|
|
80
|
-
result.auditAnonymized = (await ctx.step(
|
|
80
|
+
result.auditAnonymized = (await ctx.step('anonymize.audit', async () => anonymizeAudit((await deps.oidc()).config, accountId))).auditAnonymized;
|
|
81
81
|
// 9) Deleta a linha da conta (ÚLTIMA etapa, forward-only).
|
|
82
|
-
result.ok = (await ctx.step(
|
|
82
|
+
result.ok = (await ctx.step('delete.account', async () => deleteAccountRow((await deps.oidc()).config, accountId))).ok;
|
|
83
83
|
return result;
|
|
84
84
|
};
|
|
85
|
-
return { name: ACCOUNT_DELETE_WORKFLOW, version:
|
|
85
|
+
return { name: ACCOUNT_DELETE_WORKFLOW, version: '1', body };
|
|
86
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { OidcService } from
|
|
2
|
-
import type { DurableStepCtx } from
|
|
1
|
+
import type { OidcService } from '../../provider/oidc_service.js';
|
|
2
|
+
import type { DurableStepCtx } from './account_deletion_workflow.js';
|
|
3
3
|
/** Nome canônico do workflow durável de export de dados de conta. */
|
|
4
4
|
export declare const ACCOUNT_EXPORT_WORKFLOW = "authkit.account.export";
|
|
5
5
|
/** Input do workflow `authkit.account.export`. */
|
|
@@ -6,14 +6,14 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
-
import { AccountExportService
|
|
9
|
+
import { AccountExportService } from '../account_export_service.js';
|
|
10
10
|
/** Nome canônico do workflow durável de export de dados de conta. */
|
|
11
|
-
export const ACCOUNT_EXPORT_WORKFLOW =
|
|
11
|
+
export const ACCOUNT_EXPORT_WORKFLOW = 'authkit.account.export';
|
|
12
12
|
/** Persistência default: grava o JSON no disk do drive do app (best-effort). */
|
|
13
|
-
const defaultPersist = async ({ accountId, runId, json, oidc
|
|
13
|
+
const defaultPersist = async ({ accountId, runId, json, oidc }) => {
|
|
14
14
|
// Indireção via variável: `@adonisjs/drive` é peer/opcional — pode não estar
|
|
15
15
|
// instalado, então o specifier não é resolvido em build-time.
|
|
16
|
-
const specifier =
|
|
16
|
+
const specifier = '@adonisjs/drive/services/main';
|
|
17
17
|
let drive = null;
|
|
18
18
|
try {
|
|
19
19
|
const mod = await import(__rewriteRelativeImportExtension(specifier));
|
|
@@ -26,13 +26,13 @@ const defaultPersist = async ({ accountId, runId, json, oidc, }) => {
|
|
|
26
26
|
return null;
|
|
27
27
|
const cfg = oidc.config;
|
|
28
28
|
const exportsCfg = cfg.uploads.exports;
|
|
29
|
-
const directory = (exportsCfg?.directory ??
|
|
29
|
+
const directory = (exportsCfg?.directory ?? 'authkit/exports').replace(/\/+$/, '');
|
|
30
30
|
const diskName = exportsCfg?.disk ?? cfg.uploads.avatars?.disk;
|
|
31
31
|
const key = `${directory}/authkit-data-export-${accountId}-${runId}.json`;
|
|
32
32
|
try {
|
|
33
33
|
const disk = diskName ? drive.use(diskName) : drive.use();
|
|
34
34
|
await disk.put(key, json, {
|
|
35
|
-
contentType:
|
|
35
|
+
contentType: 'application/json; charset=utf-8',
|
|
36
36
|
});
|
|
37
37
|
return key;
|
|
38
38
|
}
|
|
@@ -61,33 +61,33 @@ export function defineAccountExportWorkflow(deps) {
|
|
|
61
61
|
const { accountId } = input;
|
|
62
62
|
const runId = ctx.runId ?? accountId;
|
|
63
63
|
// 1) Coleta o payload (reusa a coleta inline do AccountExportService).
|
|
64
|
-
const payload = await ctx.step(
|
|
64
|
+
const payload = await ctx.step('collect', async () => {
|
|
65
65
|
const oidc = await deps.oidc();
|
|
66
66
|
return new AccountExportService(oidc).collect(accountId);
|
|
67
67
|
});
|
|
68
68
|
if (!payload)
|
|
69
69
|
return { ok: false, artifactKey: null, bytes: 0 };
|
|
70
70
|
// 2) Audita o export (account.exported).
|
|
71
|
-
await ctx.step(
|
|
71
|
+
await ctx.step('audit', async () => {
|
|
72
72
|
const cfg = (await deps.oidc()).config;
|
|
73
73
|
await cfg.audit?.record({
|
|
74
|
-
type:
|
|
74
|
+
type: 'account.exported',
|
|
75
75
|
accountId,
|
|
76
76
|
ip: input.ip ?? null,
|
|
77
77
|
});
|
|
78
78
|
});
|
|
79
79
|
// 3) Serializa + persiste o artefato.
|
|
80
80
|
const json = JSON.stringify(payload, null, 2);
|
|
81
|
-
const artifactKey = await ctx.step(
|
|
81
|
+
const artifactKey = await ctx.step('persist', async () => {
|
|
82
82
|
const oidc = await deps.oidc();
|
|
83
83
|
return persist({ accountId, runId, json, oidc });
|
|
84
84
|
});
|
|
85
85
|
// 4) Entrega ao titular (signal + e-mail, pluggable).
|
|
86
|
-
await ctx.step(
|
|
86
|
+
await ctx.step('deliver', async () => {
|
|
87
87
|
const oidc = await deps.oidc();
|
|
88
88
|
await deliver({ accountId, runId, artifactKey, oidc });
|
|
89
89
|
});
|
|
90
90
|
return { ok: true, artifactKey, bytes: json.length };
|
|
91
91
|
};
|
|
92
|
-
return { name: ACCOUNT_EXPORT_WORKFLOW, version:
|
|
92
|
+
return { name: ACCOUNT_EXPORT_WORKFLOW, version: '1', body };
|
|
93
93
|
}
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
* // ...e rode um worker (engine.runPending / runOne) p/ o grupo do authkit.
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
import type { DeletionActor } from
|
|
30
|
-
import { type AccountDeleteWorkflowInput } from
|
|
31
|
-
import { type AccountExportWorkflowInput } from
|
|
32
|
-
export { defineAccountDeletionWorkflow, ACCOUNT_DELETE_WORKFLOW, type AccountDeleteWorkflowInput, type AccountDeletionWorkflowDeps, type DurableStepCtx, type WorkflowBody, } from
|
|
33
|
-
export { defineAccountExportWorkflow, ACCOUNT_EXPORT_WORKFLOW, type AccountExportWorkflowInput, type AccountExportWorkflowResult, type AccountExportWorkflowDeps, type PersistArtifact, type DeliverArtifact, } from
|
|
29
|
+
import type { DeletionActor } from '../account_deletion_service.js';
|
|
30
|
+
import { type AccountDeleteWorkflowInput } from './account_deletion_workflow.js';
|
|
31
|
+
import { type AccountExportWorkflowInput } from './account_export_workflow.js';
|
|
32
|
+
export { defineAccountDeletionWorkflow, ACCOUNT_DELETE_WORKFLOW, type AccountDeleteWorkflowInput, type AccountDeletionWorkflowDeps, type DurableStepCtx, type WorkflowBody, } from './account_deletion_workflow.js';
|
|
33
|
+
export { defineAccountExportWorkflow, ACCOUNT_EXPORT_WORKFLOW, type AccountExportWorkflowInput, type AccountExportWorkflowResult, type AccountExportWorkflowDeps, type PersistArtifact, type DeliverArtifact, } from './account_export_workflow.js';
|
|
34
34
|
/**
|
|
35
35
|
* Superfície mínima do `WorkflowEngine` que o enqueue usa (`start` idempotente por
|
|
36
36
|
* run-id). Tipada estruturalmente p/ NÃO acoplar o build ao peer opcional.
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
* // ...e rode um worker (engine.runPending / runOne) p/ o grupo do authkit.
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
import { ACCOUNT_DELETE_WORKFLOW, } from
|
|
30
|
-
import { ACCOUNT_EXPORT_WORKFLOW, } from
|
|
31
|
-
export { defineAccountDeletionWorkflow, ACCOUNT_DELETE_WORKFLOW, } from
|
|
32
|
-
export { defineAccountExportWorkflow, ACCOUNT_EXPORT_WORKFLOW, } from
|
|
29
|
+
import { ACCOUNT_DELETE_WORKFLOW, } from './account_deletion_workflow.js';
|
|
30
|
+
import { ACCOUNT_EXPORT_WORKFLOW, } from './account_export_workflow.js';
|
|
31
|
+
export { defineAccountDeletionWorkflow, ACCOUNT_DELETE_WORKFLOW, } from './account_deletion_workflow.js';
|
|
32
|
+
export { defineAccountExportWorkflow, ACCOUNT_EXPORT_WORKFLOW, } from './account_export_workflow.js';
|
|
33
33
|
/**
|
|
34
34
|
* Resolve o `WorkflowEngine` do container — SÓ no caminho durável. Importa
|
|
35
35
|
* `@adonis-agora/durable` dinamicamente (peer opcional), então o barrel principal
|
|
@@ -38,11 +38,11 @@ export { defineAccountExportWorkflow, ACCOUNT_EXPORT_WORKFLOW, } from "./account
|
|
|
38
38
|
export async function resolveWorkflowEngine(resolver) {
|
|
39
39
|
let mod;
|
|
40
40
|
try {
|
|
41
|
-
mod = (await import(
|
|
41
|
+
mod = (await import('@adonis-agora/durable'));
|
|
42
42
|
}
|
|
43
43
|
catch {
|
|
44
44
|
throw new Error('[authkit] durable account-lifecycle is enabled but "@adonis-agora/durable" is not installed. ' +
|
|
45
|
-
|
|
45
|
+
'Add it as a dependency and register the workflows on your WorkflowEngine.');
|
|
46
46
|
}
|
|
47
47
|
return resolver.make(mod.WorkflowEngine);
|
|
48
48
|
}
|