@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,7 +1,7 @@
|
|
|
1
1
|
import { createHmac } from 'node:crypto';
|
|
2
|
-
import { checkPasswordPolicy, policyViolationParams, resolvePasswordConfig, DEFAULT_PWNED_TIMEOUT_MS, } from './policy.js';
|
|
3
|
-
import { isPasswordPwned } from './pwned.js';
|
|
4
2
|
import { isCommonPassword } from './common_passwords.js';
|
|
3
|
+
import { DEFAULT_PWNED_TIMEOUT_MS, checkPasswordPolicy, policyViolationParams, resolvePasswordConfig, } from './policy.js';
|
|
4
|
+
import { isPasswordPwned } from './pwned.js';
|
|
5
5
|
/** Erro de política/vazamento de senha — carrega a chave i18n + params. */
|
|
6
6
|
export class PasswordPolicyError extends Error {
|
|
7
7
|
key;
|
|
@@ -154,8 +154,8 @@ export class PasswordManager {
|
|
|
154
154
|
}
|
|
155
155
|
if (nativeOk) {
|
|
156
156
|
// Se este não é o pepper corrente → re-hash obrigatório com o corrente.
|
|
157
|
-
const isCurrentPepper =
|
|
158
|
-
let rehash = isCurrentPepper
|
|
157
|
+
const isCurrentPepper = p === currentPepper || (!p && !this.pepper);
|
|
158
|
+
let rehash = !isCurrentPepper;
|
|
159
159
|
if (!rehash) {
|
|
160
160
|
try {
|
|
161
161
|
rehash = hooks.needsRehash(hashedPassword);
|
|
@@ -23,16 +23,12 @@ export function lucidPatStore(Model) {
|
|
|
23
23
|
tokenHash: hashPatToken(token),
|
|
24
24
|
scopes: input.scopes ?? [],
|
|
25
25
|
audience: input.audience ?? null,
|
|
26
|
-
expiresAt: input.expiresInDays
|
|
27
|
-
? DateTime.now().plus({ days: input.expiresInDays })
|
|
28
|
-
: null,
|
|
26
|
+
expiresAt: input.expiresInDays ? DateTime.now().plus({ days: input.expiresInDays }) : null,
|
|
29
27
|
});
|
|
30
28
|
return { token, pat: toRecord(row) };
|
|
31
29
|
},
|
|
32
30
|
async listForAccount(accountId) {
|
|
33
|
-
const rows = await Model.query()
|
|
34
|
-
.where('user_id', accountId)
|
|
35
|
-
.orderBy('created_at', 'desc');
|
|
31
|
+
const rows = await Model.query().where('user_id', accountId).orderBy('created_at', 'desc');
|
|
36
32
|
return rows.map(toRecord);
|
|
37
33
|
},
|
|
38
34
|
async revoke(accountId, id) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
/** Gera um Personal Access Token opaco no formato `pat_<base64url>`. */
|
|
3
3
|
export function generatePatToken() {
|
|
4
|
-
return
|
|
4
|
+
return `pat_${randomBytes(32).toString('base64url')}`;
|
|
5
5
|
}
|
|
6
6
|
/** SHA-256 (hex) do token — é o que se persiste; o token cru nunca é guardado. */
|
|
7
7
|
export function hashPatToken(token) {
|
|
@@ -20,7 +20,7 @@ export function createInteractionActions(provider, deps) {
|
|
|
20
20
|
const login = { accountId };
|
|
21
21
|
if (extra?.acr)
|
|
22
22
|
login.acr = extra.acr;
|
|
23
|
-
if (extra?.amr
|
|
23
|
+
if (extra?.amr?.length)
|
|
24
24
|
login.amr = extra.amr;
|
|
25
25
|
// remember-me: `remember: false` → sessão transiente (transient: true no provider);
|
|
26
26
|
// `remember: true` ou ausente → sessão persistente (padrão do oidc-provider).
|
|
@@ -27,7 +27,9 @@ export class KeyRotationScheduler {
|
|
|
27
27
|
start() {
|
|
28
28
|
if (this.#timer)
|
|
29
29
|
return;
|
|
30
|
-
this.#timer = setInterval(() => {
|
|
30
|
+
this.#timer = setInterval(() => {
|
|
31
|
+
void this.tick();
|
|
32
|
+
}, this.opts.intervalMs);
|
|
31
33
|
if (typeof this.#timer.unref === 'function')
|
|
32
34
|
this.#timer.unref();
|
|
33
35
|
}
|
|
@@ -45,20 +45,14 @@ export function createLogoutSources(messages) {
|
|
|
45
45
|
async logoutSource(ctx, form) {
|
|
46
46
|
// Injeta o campo de confirmação dentro do form fornecido pela lib.
|
|
47
47
|
const confirmedForm = form.replace(/<\/form>/, '<input type="hidden" name="logout" value="yes"/></form>');
|
|
48
|
-
ctx.body = page(t('logout.title'), `<div class="spinner" aria-hidden="true"></div>`
|
|
49
|
-
`<h1>${esc(t('logout.title'))}</h1>` +
|
|
50
|
-
`<p>${esc(t('logout.body'))}</p>` +
|
|
51
|
-
confirmedForm +
|
|
52
|
-
`<noscript><button type="submit" form="op.logoutForm">${esc(t('logout.fallback'))}</button></noscript>` +
|
|
53
|
-
`<script>(function(){var f=document.forms['op.logoutForm'];if(f){f.submit();}})();</script>`);
|
|
48
|
+
ctx.body = page(t('logout.title'), `<div class="spinner" aria-hidden="true"></div><h1>${esc(t('logout.title'))}</h1><p>${esc(t('logout.body'))}</p>${confirmedForm}<noscript><button type="submit" form="op.logoutForm">${esc(t('logout.fallback'))}</button></noscript><script>(function(){var f=document.forms['op.logoutForm'];if(f){f.submit();}})();</script>`);
|
|
54
49
|
},
|
|
55
50
|
/**
|
|
56
51
|
* Mostrada apenas quando NÃO há `post_logout_redirect_uri` (senão o provider
|
|
57
52
|
* redireciona o browser direto pro RP). Tela de marca em vez do default.
|
|
58
53
|
*/
|
|
59
54
|
async postLogoutSuccessSource(ctx) {
|
|
60
|
-
ctx.body = page(t('logout.success.title'), `<h1>${esc(t('logout.success.title'))}</h1>` +
|
|
61
|
-
`<p>${esc(t('logout.success.body'))}</p>`);
|
|
55
|
+
ctx.body = page(t('logout.success.title'), `<h1>${esc(t('logout.success.title'))}</h1>` + `<p>${esc(t('logout.success.body'))}</p>`);
|
|
62
56
|
},
|
|
63
57
|
};
|
|
64
58
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type MetricsRecorder } from '@adonis-agora/authkit-core';
|
|
2
2
|
import type { ResolvedServerConfig } from '../define_config.js';
|
|
3
|
-
import { buildProvider, type SessionTtlHolder, type TokenTtlHolder } from './build_provider.js';
|
|
4
|
-
import { type InteractionActions } from './interaction_actions.js';
|
|
5
3
|
import { type ManagedKeyInfo } from '../keys/keystore.js';
|
|
6
4
|
import type { KeystoreManager } from '../keys/keystore_manager.js';
|
|
5
|
+
import { type SessionTtlHolder, type TokenTtlHolder, buildProvider } from './build_provider.js';
|
|
6
|
+
import { type InteractionActions } from './interaction_actions.js';
|
|
7
7
|
export declare class OidcService {
|
|
8
8
|
#private;
|
|
9
9
|
get provider(): ReturnType<typeof buildProvider>;
|
|
@@ -2,21 +2,27 @@ import { timingSafeEqual } from 'node:crypto';
|
|
|
2
2
|
import { NoopRecorder } from '@adonis-agora/authkit-core';
|
|
3
3
|
import Koa from 'koa';
|
|
4
4
|
import mount from 'koa-mount';
|
|
5
|
+
import { readActiveOrgFromKoaCtx } from '../host/active_org_cookie.js';
|
|
6
|
+
import { isFirstParty } from '../host/branding.js';
|
|
7
|
+
import { listKeyInfos, signingKeyAgeDays } from '../keys/keystore.js';
|
|
5
8
|
import { wireProviderEvents } from '../observability/wire_provider_events.js';
|
|
6
9
|
import { buildProvider } from './build_provider.js';
|
|
7
10
|
import { createInteractionActions } from './interaction_actions.js';
|
|
8
11
|
import { registerTokenExchange } from './token_exchange.js';
|
|
9
|
-
import { readActiveOrgFromKoaCtx } from '../host/active_org_cookie.js';
|
|
10
|
-
import { isFirstParty } from '../host/branding.js';
|
|
11
|
-
import { signingKeyAgeDays, listKeyInfos } from '../keys/keystore.js';
|
|
12
12
|
export class OidcService {
|
|
13
13
|
#provider;
|
|
14
14
|
#callback;
|
|
15
15
|
#interactions;
|
|
16
16
|
#appKey;
|
|
17
|
-
get provider() {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
get provider() {
|
|
18
|
+
return this.#provider;
|
|
19
|
+
}
|
|
20
|
+
get callback() {
|
|
21
|
+
return this.#callback;
|
|
22
|
+
}
|
|
23
|
+
get interactions() {
|
|
24
|
+
return this.#interactions;
|
|
25
|
+
}
|
|
20
26
|
/** Pathname do issuer sem barra final (ex.: `/oidc`). Vazio quando montado na raiz. */
|
|
21
27
|
mountPath;
|
|
22
28
|
recorder;
|
|
@@ -83,9 +89,7 @@ export class OidcService {
|
|
|
83
89
|
// do closure `claims()`, pois o `ctx` da request vive neste escopo). Um client
|
|
84
90
|
// third-party NUNCA recebe roles/org — mesmo solicitando `scope=roles`.
|
|
85
91
|
const clientId = ctx?.oidc?.client?.clientId;
|
|
86
|
-
const firstParty = config.branding
|
|
87
|
-
? isFirstParty(config.branding, clientId)
|
|
88
|
-
: false;
|
|
92
|
+
const firstParty = config.branding ? isFirstParty(config.branding, clientId) : false;
|
|
89
93
|
return {
|
|
90
94
|
accountId: user.id,
|
|
91
95
|
claims: async (_use, _scope) => {
|
|
@@ -103,9 +107,9 @@ export class OidcService {
|
|
|
103
107
|
: (user.globalRoles ?? []);
|
|
104
108
|
// Emite claims de org somente quando há uma org ativa na sessão.
|
|
105
109
|
if (activeOrg) {
|
|
106
|
-
base
|
|
107
|
-
base
|
|
108
|
-
base
|
|
110
|
+
base.org_id = activeOrg.orgId;
|
|
111
|
+
base.org_slug = activeOrg.orgSlug;
|
|
112
|
+
base.org_role = activeOrg.orgRole;
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
return base;
|
|
@@ -150,7 +154,9 @@ export class OidcService {
|
|
|
150
154
|
else {
|
|
151
155
|
callback = provider.callback();
|
|
152
156
|
}
|
|
153
|
-
const interactions = createInteractionActions(provider, {
|
|
157
|
+
const interactions = createInteractionActions(provider, {
|
|
158
|
+
verifyCredentials: config.verifyCredentials,
|
|
159
|
+
});
|
|
154
160
|
// Atribuição atômica no final: um throw antes deste ponto não corrompe o estado.
|
|
155
161
|
this.#provider = provider;
|
|
156
162
|
this.#callback = callback;
|
|
@@ -210,7 +216,9 @@ export class OidcService {
|
|
|
210
216
|
const { newKid, retiredKids, store } = await m.rotate(keep, retire);
|
|
211
217
|
await this.reloadKeys();
|
|
212
218
|
const keptKids = store.keys.map((k) => k.kid);
|
|
213
|
-
await this.#config.audit
|
|
219
|
+
await this.#config.audit
|
|
220
|
+
?.record({ type: 'keys.rotated', metadata: { newKid, retiredKids, keptKids, retire } })
|
|
221
|
+
.catch(() => { });
|
|
214
222
|
return { newKid, retiredKids, keptKids };
|
|
215
223
|
};
|
|
216
224
|
// serializa: encadeia após a rotação em voo; cada caller recebe o resultado da SUA rotação
|
|
@@ -8,9 +8,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
8
8
|
};
|
|
9
9
|
async function defaultLoadLock() {
|
|
10
10
|
const spec = '@adonisjs/lock/services/main';
|
|
11
|
-
return import(__rewriteRelativeImportExtension(spec))
|
|
12
|
-
.then((m) => m.default ?? null)
|
|
13
|
-
.catch(() => null);
|
|
11
|
+
return import(__rewriteRelativeImportExtension(spec)).then((m) => m.default ?? null).catch(() => null);
|
|
14
12
|
}
|
|
15
13
|
export function makeSingleFlightLock(opts) {
|
|
16
14
|
const load = opts.loadLock ?? defaultLoadLock;
|
|
@@ -255,7 +255,9 @@ export async function ensureAuthkitSchema(db, options = {}) {
|
|
|
255
255
|
if (await columnExists(conn, def.name, column))
|
|
256
256
|
continue;
|
|
257
257
|
await conn.schema.alterTable(def.name, (t) => add(t));
|
|
258
|
-
(report.altered[def.name]
|
|
258
|
+
if (!report.altered[def.name])
|
|
259
|
+
report.altered[def.name] = [];
|
|
260
|
+
report.altered[def.name].push(column);
|
|
259
261
|
}
|
|
260
262
|
}
|
|
261
263
|
return report;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/components/auth_shell.tsx') })
|
|
3
|
-
}
|
|
4
|
-
import type { ReactNode } from 'react'
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/components/auth_shell.tsx') });
|
|
3
|
+
}
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
5
|
|
|
6
6
|
export interface AuthBrand {
|
|
7
|
-
appName: string
|
|
8
|
-
accent: string
|
|
9
|
-
accentSoft?: string
|
|
10
|
-
company?: string
|
|
11
|
-
tagline?: string
|
|
12
|
-
audienceLabel?: string
|
|
7
|
+
appName: string;
|
|
8
|
+
accent: string;
|
|
9
|
+
accentSoft?: string;
|
|
10
|
+
company?: string;
|
|
11
|
+
tagline?: string;
|
|
12
|
+
audienceLabel?: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const COMPANY_FALLBACK = 'Acme'
|
|
15
|
+
const COMPANY_FALLBACK = 'Acme';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Layout de duas colunas para as telas de autenticacao do IdP.
|
|
@@ -22,14 +22,14 @@ export default function AuthShell({
|
|
|
22
22
|
brand,
|
|
23
23
|
children,
|
|
24
24
|
}: {
|
|
25
|
-
brand?: AuthBrand
|
|
26
|
-
children: ReactNode
|
|
25
|
+
brand?: AuthBrand;
|
|
26
|
+
children: ReactNode;
|
|
27
27
|
}) {
|
|
28
|
-
const accent = brand?.accent ?? '#111827'
|
|
29
|
-
const accentSoft = brand?.accentSoft ?? accent
|
|
30
|
-
const company = brand?.company ?? COMPANY_FALLBACK
|
|
31
|
-
const appName = brand?.appName ?? 'Sua conta'
|
|
32
|
-
const tagline = brand?.tagline ?? 'Acesso unificado'
|
|
28
|
+
const accent = brand?.accent ?? '#111827';
|
|
29
|
+
const accentSoft = brand?.accentSoft ?? accent;
|
|
30
|
+
const company = brand?.company ?? COMPANY_FALLBACK;
|
|
31
|
+
const appName = brand?.appName ?? 'Sua conta';
|
|
32
|
+
const tagline = brand?.tagline ?? 'Acesso unificado';
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
35
|
<div className="min-h-screen flex items-center justify-center bg-gray-100 p-4">
|
|
@@ -63,5 +63,5 @@ export default function AuthShell({
|
|
|
63
63
|
<div className="p-8 md:p-10">{children}</div>
|
|
64
64
|
</div>
|
|
65
65
|
</div>
|
|
66
|
-
)
|
|
66
|
+
);
|
|
67
67
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/account/login.tsx') })
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/account/login.tsx') });
|
|
3
|
+
}
|
|
4
4
|
interface Props {
|
|
5
|
-
csrfToken: string
|
|
6
|
-
error?: string
|
|
5
|
+
csrfToken: string;
|
|
6
|
+
error?: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export default function AccountLogin({ csrfToken, error }: Props) {
|
|
@@ -29,7 +29,6 @@ export default function AccountLogin({ csrfToken, error }: Props) {
|
|
|
29
29
|
name="email"
|
|
30
30
|
type="email"
|
|
31
31
|
required
|
|
32
|
-
autoFocus
|
|
33
32
|
className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900"
|
|
34
33
|
/>
|
|
35
34
|
|
|
@@ -52,5 +51,5 @@ export default function AccountLogin({ csrfToken, error }: Props) {
|
|
|
52
51
|
</button>
|
|
53
52
|
</form>
|
|
54
53
|
</div>
|
|
55
|
-
)
|
|
54
|
+
);
|
|
56
55
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/account/mfa.tsx') })
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/account/mfa.tsx') });
|
|
3
|
+
}
|
|
4
4
|
interface Props {
|
|
5
|
-
csrfToken: string
|
|
6
|
-
enabled: boolean
|
|
7
|
-
enrolling?: boolean
|
|
8
|
-
secret?: string | null
|
|
9
|
-
qrDataUrl?: string | null
|
|
10
|
-
error?: string
|
|
11
|
-
recoveryCodes?: string[] | null
|
|
5
|
+
csrfToken: string;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
enrolling?: boolean;
|
|
8
|
+
secret?: string | null;
|
|
9
|
+
qrDataUrl?: string | null;
|
|
10
|
+
error?: string;
|
|
11
|
+
recoveryCodes?: string[] | null;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export default function AccountMfa({
|
|
@@ -25,7 +25,9 @@ export default function AccountMfa({
|
|
|
25
25
|
<div className="mx-auto max-w-2xl">
|
|
26
26
|
<div className="flex items-center justify-between py-6">
|
|
27
27
|
<div>
|
|
28
|
-
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-gray-400">
|
|
28
|
+
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-gray-400">
|
|
29
|
+
Acme
|
|
30
|
+
</div>
|
|
29
31
|
<h1 className="text-xl font-semibold text-gray-900">Verificação em duas etapas</h1>
|
|
30
32
|
</div>
|
|
31
33
|
<form method="POST" action="/account/logout">
|
|
@@ -82,7 +84,6 @@ export default function AccountMfa({
|
|
|
82
84
|
inputMode="numeric"
|
|
83
85
|
pattern="[0-9]*"
|
|
84
86
|
maxLength={6}
|
|
85
|
-
autoFocus
|
|
86
87
|
className="w-full rounded-lg border border-gray-300 px-3 py-2 text-center text-lg tracking-[0.4em] outline-none focus:border-gray-900"
|
|
87
88
|
/>
|
|
88
89
|
<button
|
|
@@ -112,8 +113,8 @@ export default function AccountMfa({
|
|
|
112
113
|
) : (
|
|
113
114
|
<div className="rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
|
|
114
115
|
<p className="text-sm text-gray-700">
|
|
115
|
-
A verificação em duas etapas está desativada. Ative-a para proteger sua conta com um
|
|
116
|
-
autenticador.
|
|
116
|
+
A verificação em duas etapas está desativada. Ative-a para proteger sua conta com um
|
|
117
|
+
app autenticador.
|
|
117
118
|
</p>
|
|
118
119
|
<form method="POST" action="/account/mfa/enroll" className="mt-4">
|
|
119
120
|
<input type="hidden" name="_csrf" value={csrfToken} />
|
|
@@ -128,5 +129,5 @@ export default function AccountMfa({
|
|
|
128
129
|
)}
|
|
129
130
|
</div>
|
|
130
131
|
</div>
|
|
131
|
-
)
|
|
132
|
+
);
|
|
132
133
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/account/tokens.tsx') })
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/account/tokens.tsx') });
|
|
3
|
+
}
|
|
4
4
|
interface TokenRow {
|
|
5
|
-
id: string
|
|
6
|
-
name: string
|
|
7
|
-
scopes: string[]
|
|
8
|
-
audience: string | null
|
|
9
|
-
lastUsedAt: string | null
|
|
10
|
-
createdAt: string
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
scopes: string[];
|
|
8
|
+
audience: string | null;
|
|
9
|
+
lastUsedAt: string | null;
|
|
10
|
+
createdAt: string;
|
|
11
11
|
}
|
|
12
12
|
interface Props {
|
|
13
|
-
csrfToken: string
|
|
14
|
-
createdToken: string | null
|
|
15
|
-
tokens: TokenRow[]
|
|
13
|
+
csrfToken: string;
|
|
14
|
+
createdToken: string | null;
|
|
15
|
+
tokens: TokenRow[];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export default function AccountTokens({ csrfToken, createdToken, tokens }: Props) {
|
|
@@ -21,7 +21,9 @@ export default function AccountTokens({ csrfToken, createdToken, tokens }: Props
|
|
|
21
21
|
<div className="mx-auto max-w-2xl">
|
|
22
22
|
<div className="flex items-center justify-between py-6">
|
|
23
23
|
<div>
|
|
24
|
-
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-gray-400">
|
|
24
|
+
<div className="text-xs font-semibold uppercase tracking-[0.2em] text-gray-400">
|
|
25
|
+
Acme
|
|
26
|
+
</div>
|
|
25
27
|
<h1 className="text-xl font-semibold text-gray-900">Tokens de acesso</h1>
|
|
26
28
|
</div>
|
|
27
29
|
<form method="POST" action="/account/logout">
|
|
@@ -54,7 +56,10 @@ export default function AccountTokens({ csrfToken, createdToken, tokens }: Props
|
|
|
54
56
|
placeholder="Nome do token (ex.: CI deploy)"
|
|
55
57
|
className="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900"
|
|
56
58
|
/>
|
|
57
|
-
<button
|
|
59
|
+
<button
|
|
60
|
+
type="submit"
|
|
61
|
+
className="rounded-lg bg-gray-900 px-4 text-sm font-semibold text-white"
|
|
62
|
+
>
|
|
58
63
|
Criar
|
|
59
64
|
</button>
|
|
60
65
|
</form>
|
|
@@ -64,12 +69,17 @@ export default function AccountTokens({ csrfToken, createdToken, tokens }: Props
|
|
|
64
69
|
<p className="p-6 text-sm text-gray-500">Nenhum token ainda.</p>
|
|
65
70
|
) : (
|
|
66
71
|
tokens.map((t) => (
|
|
67
|
-
<div
|
|
72
|
+
<div
|
|
73
|
+
key={t.id}
|
|
74
|
+
className="flex items-center justify-between border-b border-gray-100 p-4 last:border-0"
|
|
75
|
+
>
|
|
68
76
|
<div>
|
|
69
77
|
<p className="text-sm font-medium text-gray-900">{t.name}</p>
|
|
70
78
|
<p className="text-xs text-gray-500">
|
|
71
79
|
Criado em {new Date(t.createdAt).toLocaleDateString('pt-BR')}
|
|
72
|
-
{t.lastUsedAt
|
|
80
|
+
{t.lastUsedAt
|
|
81
|
+
? ` · último uso ${new Date(t.lastUsedAt).toLocaleDateString('pt-BR')}`
|
|
82
|
+
: ' · nunca usado'}
|
|
73
83
|
</p>
|
|
74
84
|
</div>
|
|
75
85
|
<form method="POST" action={`/account/tokens/${t.id}/revoke`}>
|
|
@@ -84,5 +94,5 @@ export default function AccountTokens({ csrfToken, createdToken, tokens }: Props
|
|
|
84
94
|
</div>
|
|
85
95
|
</div>
|
|
86
96
|
</div>
|
|
87
|
-
)
|
|
97
|
+
);
|
|
88
98
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/consent.tsx') })
|
|
3
|
-
}
|
|
4
|
-
import AuthShell, { type AuthBrand } from '../../components/auth_shell'
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/consent.tsx') });
|
|
3
|
+
}
|
|
4
|
+
import AuthShell, { type AuthBrand } from '../../components/auth_shell';
|
|
5
5
|
|
|
6
6
|
export default function AuthkitConsent({
|
|
7
7
|
uid,
|
|
@@ -9,17 +9,17 @@ export default function AuthkitConsent({
|
|
|
9
9
|
csrfToken,
|
|
10
10
|
brand,
|
|
11
11
|
}: {
|
|
12
|
-
uid: string
|
|
13
|
-
params: { client_id: string }
|
|
14
|
-
csrfToken: string
|
|
15
|
-
brand?: AuthBrand
|
|
12
|
+
uid: string;
|
|
13
|
+
params: { client_id: string };
|
|
14
|
+
csrfToken: string;
|
|
15
|
+
brand?: AuthBrand;
|
|
16
16
|
}) {
|
|
17
|
-
const accent = brand?.accent ?? '#111827'
|
|
18
|
-
const appName = brand?.appName ?? params.client_id
|
|
17
|
+
const accent = brand?.accent ?? '#111827';
|
|
18
|
+
const appName = brand?.appName ?? params.client_id;
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<AuthShell brand={brand}>
|
|
22
|
-
<form method="POST" action={
|
|
22
|
+
<form method="POST" action={`/auth/interaction/${uid}/consent`}>
|
|
23
23
|
<input type="hidden" name="_csrf" value={csrfToken} />
|
|
24
24
|
<h1 className="text-xl font-semibold text-gray-900">Autorizar acesso</h1>
|
|
25
25
|
<p className="mt-2 text-sm text-gray-600">
|
|
@@ -35,5 +35,5 @@ export default function AuthkitConsent({
|
|
|
35
35
|
</button>
|
|
36
36
|
</form>
|
|
37
37
|
</AuthShell>
|
|
38
|
-
)
|
|
38
|
+
);
|
|
39
39
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/forgot.tsx') })
|
|
3
|
-
}
|
|
4
|
-
import AuthShell from '../../components/auth_shell'
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/forgot.tsx') });
|
|
3
|
+
}
|
|
4
|
+
import AuthShell from '../../components/auth_shell';
|
|
5
5
|
|
|
6
6
|
const inputClass =
|
|
7
|
-
'w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-transparent focus:ring-2 focus:ring-gray-800'
|
|
7
|
+
'w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-transparent focus:ring-2 focus:ring-gray-800';
|
|
8
8
|
|
|
9
9
|
export default function AuthkitForgot({ csrfToken, sent }: { csrfToken: string; sent?: boolean }) {
|
|
10
10
|
if (sent) {
|
|
@@ -15,7 +15,7 @@ export default function AuthkitForgot({ csrfToken, sent }: { csrfToken: string;
|
|
|
15
15
|
Se o e-mail existir, enviaremos instruções de redefinição.
|
|
16
16
|
</p>
|
|
17
17
|
</AuthShell>
|
|
18
|
-
)
|
|
18
|
+
);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
return (
|
|
@@ -40,5 +40,5 @@ export default function AuthkitForgot({ csrfToken, sent }: { csrfToken: string;
|
|
|
40
40
|
</button>
|
|
41
41
|
</form>
|
|
42
42
|
</AuthShell>
|
|
43
|
-
)
|
|
43
|
+
);
|
|
44
44
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
exports({ to: app.makePath('inertia/pages/authkit/login.tsx') })
|
|
3
|
-
}
|
|
4
|
-
import AuthShell, { type AuthBrand } from '../../components/auth_shell'
|
|
1
|
+
{
|
|
2
|
+
exports({ to: app.makePath('inertia/pages/authkit/login.tsx') });
|
|
3
|
+
}
|
|
4
|
+
import AuthShell, { type AuthBrand } from '../../components/auth_shell';
|
|
5
5
|
|
|
6
6
|
const inputClass =
|
|
7
|
-
'w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-transparent focus:ring-2'
|
|
7
|
+
'w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-transparent focus:ring-2';
|
|
8
8
|
|
|
9
9
|
export default function AuthkitLogin({
|
|
10
10
|
uid,
|
|
@@ -15,21 +15,21 @@ export default function AuthkitLogin({
|
|
|
15
15
|
error,
|
|
16
16
|
brand,
|
|
17
17
|
}: {
|
|
18
|
-
uid: string
|
|
19
|
-
csrfToken: string
|
|
20
|
-
step?: 'identifier' | 'password'
|
|
21
|
-
email?: string
|
|
22
|
-
account?: { fullName: string | null; globalRoles: string[] } | null
|
|
23
|
-
error?: string
|
|
24
|
-
brand?: AuthBrand
|
|
18
|
+
uid: string;
|
|
19
|
+
csrfToken: string;
|
|
20
|
+
step?: 'identifier' | 'password';
|
|
21
|
+
email?: string;
|
|
22
|
+
account?: { fullName: string | null; globalRoles: string[] } | null;
|
|
23
|
+
error?: string;
|
|
24
|
+
brand?: AuthBrand;
|
|
25
25
|
}) {
|
|
26
|
-
const accent = brand?.accent ?? '#111827'
|
|
27
|
-
const focusStyle = { ['--tw-ring-color' as any]: accent }
|
|
26
|
+
const accent = brand?.accent ?? '#111827';
|
|
27
|
+
const focusStyle = { ['--tw-ring-color' as any]: accent };
|
|
28
28
|
|
|
29
29
|
if (step === 'identifier') {
|
|
30
30
|
return (
|
|
31
31
|
<AuthShell brand={brand}>
|
|
32
|
-
<form method="POST" action={
|
|
32
|
+
<form method="POST" action={`/auth/interaction/${uid}/identifier`}>
|
|
33
33
|
<input type="hidden" name="_csrf" value={csrfToken} />
|
|
34
34
|
<h1 className="text-xl font-semibold text-gray-900">Entrar</h1>
|
|
35
35
|
<p className="mt-1 text-sm text-gray-500">Informe seu e-mail para continuar.</p>
|
|
@@ -45,7 +45,6 @@ export default function AuthkitLogin({
|
|
|
45
45
|
name="email"
|
|
46
46
|
type="email"
|
|
47
47
|
required
|
|
48
|
-
autoFocus
|
|
49
48
|
className={inputClass}
|
|
50
49
|
style={focusStyle}
|
|
51
50
|
/>
|
|
@@ -60,7 +59,7 @@ export default function AuthkitLogin({
|
|
|
60
59
|
</button>
|
|
61
60
|
|
|
62
61
|
<div className="mt-4 flex justify-between text-sm text-gray-600">
|
|
63
|
-
<a href={
|
|
62
|
+
<a href={`/auth/interaction/${uid}/signup`} className="hover:underline">
|
|
64
63
|
Criar conta
|
|
65
64
|
</a>
|
|
66
65
|
<a href="/auth/forgot-password" className="hover:underline">
|
|
@@ -76,7 +75,7 @@ export default function AuthkitLogin({
|
|
|
76
75
|
</div>
|
|
77
76
|
|
|
78
77
|
<a
|
|
79
|
-
href={
|
|
78
|
+
href={`/auth/google/redirect/${uid}`}
|
|
80
79
|
className="flex w-full items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white py-2.5 text-sm font-medium text-gray-700 transition hover:bg-gray-50"
|
|
81
80
|
>
|
|
82
81
|
<svg className="h-4 w-4" viewBox="0 0 24 24" aria-hidden="true">
|
|
@@ -100,15 +99,15 @@ export default function AuthkitLogin({
|
|
|
100
99
|
Entrar com Google
|
|
101
100
|
</a>
|
|
102
101
|
</AuthShell>
|
|
103
|
-
)
|
|
102
|
+
);
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
// step === 'password'
|
|
107
|
-
const isAdmin = account?.globalRoles?.includes('ADMIN') ?? false
|
|
106
|
+
const isAdmin = account?.globalRoles?.includes('ADMIN') ?? false;
|
|
108
107
|
|
|
109
108
|
return (
|
|
110
109
|
<AuthShell brand={brand}>
|
|
111
|
-
<form method="POST" action={
|
|
110
|
+
<form method="POST" action={`/auth/interaction/${uid}/login`}>
|
|
112
111
|
<input type="hidden" name="_csrf" value={csrfToken} />
|
|
113
112
|
|
|
114
113
|
{account?.fullName ? (
|
|
@@ -127,7 +126,7 @@ export default function AuthkitLogin({
|
|
|
127
126
|
<div className="mt-1 flex items-center gap-2">
|
|
128
127
|
<span className="text-sm text-gray-500">{email}</span>
|
|
129
128
|
<a
|
|
130
|
-
href={
|
|
129
|
+
href={`/auth/interaction/${uid}/switch`}
|
|
131
130
|
className="text-xs font-medium hover:underline"
|
|
132
131
|
style={{ color: accent }}
|
|
133
132
|
>
|
|
@@ -146,7 +145,6 @@ export default function AuthkitLogin({
|
|
|
146
145
|
name="password"
|
|
147
146
|
type="password"
|
|
148
147
|
required
|
|
149
|
-
autoFocus
|
|
150
148
|
className={inputClass}
|
|
151
149
|
style={focusStyle}
|
|
152
150
|
/>
|
|
@@ -167,5 +165,5 @@ export default function AuthkitLogin({
|
|
|
167
165
|
</div>
|
|
168
166
|
</form>
|
|
169
167
|
</AuthShell>
|
|
170
|
-
)
|
|
168
|
+
);
|
|
171
169
|
}
|