@authup/server-core 1.0.0-beta.61 → 1.0.0-beta.63
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/dist/adapters/database/domains/client-scope/entity.d.ts.map +1 -1
- package/dist/adapters/database/domains/client-scope/entity.mjs +16 -8
- package/dist/adapters/database/domains/client-scope/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-account/entity.d.ts.map +1 -1
- package/dist/adapters/database/domains/identity-provider-account/entity.mjs +1 -1
- package/dist/adapters/database/domains/identity-provider-account/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts +8 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs +14 -0
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.d.ts +50 -0
- package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.d.ts.map +1 -0
- package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.mjs +86 -0
- package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.mjs.map +1 -0
- package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.d.ts +42 -0
- package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.d.ts.map +1 -0
- package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.mjs +80 -0
- package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.mjs.map +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs +8 -2
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/guess.mjs +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/identity-provider/module.d.ts +24 -4
- package/dist/adapters/http/controllers/entities/identity-provider/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +117 -106
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts +6 -4
- package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/realm/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/session/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user/module.mjs +2 -2
- package/dist/adapters/http/controllers/entities/user-authenticator/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.d.ts +2 -0
- package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.mjs +21 -3
- package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +14 -5
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs +22 -9
- package/dist/adapters/http/controllers/workflows/token/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/utils/extract.mjs +2 -1
- package/dist/adapters/http/controllers/workflows/token/utils/extract.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/assets.mjs +1 -1
- package/dist/adapters/http/middleware/built-in/cors.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/cors.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/error.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/error.mjs +10 -1
- package/dist/adapters/http/middleware/built-in/error.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/param-id.d.ts.map +1 -1
- package/dist/adapters/http/request/helpers/param-id.mjs +2 -1
- package/dist/adapters/http/request/helpers/param-id.mjs.map +1 -1
- package/dist/adapters/http/ui/account-console/module.mjs +1 -1
- package/dist/adapters/http/ui/auth-console/http-client.mjs +1 -1
- package/dist/adapters/http/ui/auth-console/module.mjs +1 -1
- package/dist/adapters/http/ui/console-packages/module.d.ts +1 -1
- package/dist/adapters/http/ui/console-packages/module.mjs +2 -2
- package/dist/adapters/http/ui/console-packages/module.mjs.map +1 -1
- package/dist/adapters/http/ui/shared/html.d.ts.map +1 -1
- package/dist/adapters/http/ui/shared/html.mjs +1 -0
- package/dist/adapters/http/ui/shared/html.mjs.map +1 -1
- package/dist/app/modules/config/normalize.d.ts.map +1 -1
- package/dist/app/modules/config/normalize.mjs +2 -2
- package/dist/app/modules/config/normalize.mjs.map +1 -1
- package/dist/app/modules/config/read/env.mjs +1 -1
- package/dist/app/modules/config/types.d.ts +8 -0
- package/dist/app/modules/config/types.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/event/repository.d.ts +2 -2
- package/dist/app/modules/database/repositories/event/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/event/repository.mjs +23 -6
- package/dist/app/modules/database/repositories/event/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/identity-provider/repository.d.ts +3 -1
- package/dist/app/modules/database/repositories/identity-provider/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/identity-provider/repository.mjs +2 -2
- package/dist/app/modules/database/repositories/identity-provider/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/identity-provider-account/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs +9 -1
- package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs +20 -6
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/identity/module.d.ts.map +1 -1
- package/dist/app/modules/identity/module.mjs +6 -3
- package/dist/app/modules/identity/module.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/user.d.ts +1 -0
- package/dist/app/modules/identity/repositories/user.d.ts.map +1 -1
- package/dist/app/modules/identity/repositories/user.mjs +3 -0
- package/dist/app/modules/identity/repositories/user.mjs.map +1 -1
- package/dist/app/modules/oauth2/constants.d.ts +2 -1
- package/dist/app/modules/oauth2/constants.d.ts.map +1 -1
- package/dist/app/modules/oauth2/constants.mjs +1 -0
- package/dist/app/modules/oauth2/constants.mjs.map +1 -1
- package/dist/app/modules/oauth2/module.d.ts.map +1 -1
- package/dist/app/modules/oauth2/module.mjs +5 -0
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.d.ts +1 -2
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs +7 -16
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/constants.d.ts +1 -0
- package/dist/app/modules/oauth2/repositories/constants.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/constants.mjs +1 -0
- package/dist/app/modules/oauth2/repositories/constants.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/federated-login/index.d.ts +2 -0
- package/dist/app/modules/oauth2/repositories/federated-login/index.d.ts.map +1 -0
- package/dist/app/modules/oauth2/repositories/federated-login/index.mjs +5 -0
- package/dist/app/modules/oauth2/repositories/federated-login/store.d.ts +9 -0
- package/dist/app/modules/oauth2/repositories/federated-login/store.d.ts.map +1 -0
- package/dist/app/modules/oauth2/repositories/federated-login/store.mjs +33 -0
- package/dist/app/modules/oauth2/repositories/federated-login/store.mjs.map +1 -0
- package/dist/app/modules/oauth2/repositories/index.d.ts +1 -0
- package/dist/app/modules/oauth2/repositories/index.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/index.mjs +3 -1
- package/dist/app/modules/runtime/module.mjs +2 -2
- package/dist/cli/commands/migration.mjs +1 -1
- package/dist/core/entities/client-scope/schema.d.ts.map +1 -1
- package/dist/core/entities/client-scope/schema.mjs +16 -1
- package/dist/core/entities/client-scope/schema.mjs.map +1 -1
- package/dist/core/entities/event/constants.d.ts +9 -0
- package/dist/core/entities/event/constants.d.ts.map +1 -1
- package/dist/core/entities/event/constants.mjs +9 -1
- package/dist/core/entities/event/constants.mjs.map +1 -1
- package/dist/core/entities/event/entity-event-handler.d.ts.map +1 -1
- package/dist/core/entities/event/entity-event-handler.mjs +14 -1
- package/dist/core/entities/event/entity-event-handler.mjs.map +1 -1
- package/dist/core/entities/event/index.mjs +2 -2
- package/dist/core/entities/event/types.d.ts +11 -2
- package/dist/core/entities/event/types.d.ts.map +1 -1
- package/dist/core/entities/identity-provider/types.d.ts +9 -1
- package/dist/core/entities/identity-provider/types.d.ts.map +1 -1
- package/dist/core/entities/identity-provider-account/types.d.ts +6 -0
- package/dist/core/entities/identity-provider-account/types.d.ts.map +1 -1
- package/dist/core/entities/identity-provider-account/types.mjs.map +1 -1
- package/dist/core/entities/index.mjs +2 -2
- package/dist/core/identity/entities/user/types.d.ts +1 -0
- package/dist/core/identity/entities/user/types.d.ts.map +1 -1
- package/dist/core/identity/index.mjs +12 -11
- package/dist/core/identity/provider/account/module.d.ts +3 -0
- package/dist/core/identity/provider/account/module.d.ts.map +1 -1
- package/dist/core/identity/provider/account/module.mjs +54 -27
- package/dist/core/identity/provider/account/module.mjs.map +1 -1
- package/dist/core/identity/provider/account/types.d.ts +7 -0
- package/dist/core/identity/provider/account/types.d.ts.map +1 -1
- package/dist/core/identity/provider/authentication/index.mjs +3 -2
- package/dist/core/identity/provider/authentication/protocols/index.mjs +2 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.d.ts +46 -0
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.d.ts.map +1 -0
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs +89 -0
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs.map +1 -0
- package/dist/core/identity/provider/authentication/protocols/oauth2/index.d.ts +1 -0
- package/dist/core/identity/provider/authentication/protocols/oauth2/index.d.ts.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/index.mjs +2 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/module.d.ts.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/module.mjs +9 -2
- package/dist/core/identity/provider/authentication/protocols/oauth2/module.mjs.map +1 -1
- package/dist/core/identity/provider/index.mjs +12 -11
- package/dist/core/index.mjs +16 -12
- package/dist/core/oauth2/authorization/code-request/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs +7 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/helpers.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/helpers.mjs +6 -1
- package/dist/core/oauth2/authorization/helpers.mjs.map +1 -1
- package/dist/core/oauth2/authorization/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/module.mjs +5 -3
- package/dist/core/oauth2/authorization/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/state/module.mjs +1 -2
- package/dist/core/oauth2/authorization/state/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/state/types.d.ts +13 -2
- package/dist/core/oauth2/authorization/state/types.d.ts.map +1 -1
- package/dist/core/oauth2/end-session/service.d.ts.map +1 -1
- package/dist/core/oauth2/end-session/service.mjs +1 -0
- package/dist/core/oauth2/end-session/service.mjs.map +1 -1
- package/dist/core/oauth2/federated-login/constants.d.ts +22 -0
- package/dist/core/oauth2/federated-login/constants.d.ts.map +1 -0
- package/dist/core/oauth2/federated-login/constants.mjs +27 -0
- package/dist/core/oauth2/federated-login/constants.mjs.map +1 -0
- package/dist/core/oauth2/federated-login/index.d.ts +4 -0
- package/dist/core/oauth2/federated-login/index.d.ts.map +1 -0
- package/dist/core/oauth2/federated-login/index.mjs +7 -0
- package/dist/core/oauth2/federated-login/module.d.ts +29 -0
- package/dist/core/oauth2/federated-login/module.d.ts.map +1 -0
- package/dist/core/oauth2/federated-login/module.mjs +193 -0
- package/dist/core/oauth2/federated-login/module.mjs.map +1 -0
- package/dist/core/oauth2/federated-login/types.d.ts +196 -0
- package/dist/core/oauth2/federated-login/types.d.ts.map +1 -0
- package/dist/core/oauth2/federated-login/types.mjs +36 -0
- package/dist/core/oauth2/federated-login/types.mjs.map +1 -0
- package/dist/core/oauth2/grant-types/authorize.mjs +1 -1
- package/dist/core/oauth2/grant-types/client-credentials.mjs +1 -1
- package/dist/core/oauth2/grant-types/identity.mjs +1 -1
- package/dist/core/oauth2/grant-types/password.mjs +1 -1
- package/dist/core/oauth2/grant-types/refresh-token.mjs +1 -1
- package/dist/core/oauth2/index.d.ts +1 -0
- package/dist/core/oauth2/index.d.ts.map +1 -1
- package/dist/core/oauth2/index.mjs +5 -1
- package/dist/core/oauth2/token/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/token/verifier/module.mjs +3 -3
- package/dist/core/oauth2/token/verifier/module.mjs.map +1 -1
- package/dist/core/provisioning/entities/policy/validator.d.ts.map +1 -1
- package/dist/core/provisioning/entities/policy/validator.mjs +2 -1
- package/dist/core/provisioning/entities/policy/validator.mjs.map +1 -1
- package/dist/core/provisioning/entities/realm/wildcard-validator.d.ts.map +1 -1
- package/dist/core/provisioning/entities/realm/wildcard-validator.mjs +2 -1
- package/dist/core/provisioning/entities/realm/wildcard-validator.mjs.map +1 -1
- package/dist/core/security/policy/evaluator.mjs.map +1 -1
- package/dist/node_modules/@ebec/core/dist/index.mjs +130 -0
- package/dist/node_modules/@ebec/core/dist/index.mjs.map +1 -0
- package/dist/swagger.json +119 -43
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.mjs +5 -6
- package/dist/utils/error.mjs.map +1 -1
- package/package.json +29 -29
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.mjs","names":["read","path","process","USER_PASSWORD_MIN_LENGTH","AuthupError","EnvironmentName","base64ToArrayBuffer","EVENT_LOG_RETENTION_DAYS_DEFAULT","toPublicHost","expandToOrigins","parseConfig","canonicalizeTrustProxy","canonicalizeTrustProxyListEntry","normalizeConfig","input","parsed","writableDirectoryPath","join","cwd","port","host","publicUrl","regex","match","env","DEVELOPMENT","trustedOrigins","value","origin","includes","push","PRODUCTION","devOrigin","config","rootPath","themeDirectoryPath","themeFragmentsEnabled","authConsolePath","accountConsolePath","logger","redis","smtp","mtlsPublicUrl","certificateSource","trustProxy","middlewareBody","middlewareCookie","middlewareCors","middlewarePrometheus","middlewareQuery","middlewareRateLimit","middlewareSwagger","tokenRefreshMaxAge","tokenAccessMaxAge","tokenRefreshGracePeriod","promptLoginMaxAge","endSessionHintGracePeriod","registrationEnabled","emailVerificationEnabled","passwordRecoveryEnabled","passwordMinLength","accountConsoleEnabled","eventLogEnabled","eventLogRetentionDays","eventLogEntityEnabled","eventLogEntityRetentionDays","loginAttemptThrottleEnabled","loginAttemptThreshold","loginAttemptWindow","secretsEncryptionKey","mfaEnabled","mfaRequired","mfaFreshnessMaxAge","mfaTicketMaxAge","clientAuthBasic","clientSystemEnabled","clientSystemSecret","clientSystemSecretReset","userAuthBasic","userAdminEnabled","userAdminPassword","userAdminPasswordReset","permissions","permissionsDefaultPolicyAssignment","resolve","Array","isArray","map","byteLength","trim"],"sources":["../../../../src/app/modules/config/normalize.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { read } from 'envix';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { USER_PASSWORD_MIN_LENGTH } from '@authup/core-kit';\nimport { AuthupError } from '@authup/errors';\nimport { EnvironmentName, base64ToArrayBuffer } from '@authup/kit';\nimport { EVENT_LOG_RETENTION_DAYS_DEFAULT } from '../../../core/index.ts';\nimport { toPublicHost } from '../../../utils/host.ts';\nimport { expandToOrigins } from './origins.ts';\nimport { parseConfig } from './parse.ts';\nimport { canonicalizeTrustProxy, canonicalizeTrustProxyListEntry } from './trust-proxy.ts';\nimport type { Config, ConfigInput } from './types.ts';\n\nexport async function normalizeConfig(input: ConfigInput = {}): Promise<Config> {\n const parsed = await parseConfig(input);\n\n const writableDirectoryPath = parsed.writableDirectoryPath ||\n path.join(process.cwd(), 'writable');\n\n const port = parsed.port ?? 3001;\n let host = parsed.host || '0.0.0.0';\n\n let publicUrl : string;\n if (parsed.publicUrl) {\n publicUrl = parsed.publicUrl;\n } else {\n const regex = /^([^:]+)(?::(\\d+))?$/;\n const match = host.match(regex);\n if (match) {\n [, host] = match;\n publicUrl = `http://${toPublicHost(host)}:${match[2] || port}`;\n } else {\n publicUrl = `http://${toPublicHost(host)}:${port}`;\n }\n }\n\n const env = parsed.env || read('NODE_ENV', EnvironmentName.DEVELOPMENT);\n\n // Canonicalize to bare origins (scheme://host[:port]) — a scheme-less\n // entry (e.g. `hub.local`) expands to both its http and https origin.\n // Downstream consumers (redirect allowlist, getAppOrigins) can rely on\n // every entry being a full origin. Building a fresh array also keeps a\n // repeated normalizeConfig() on the same input from accumulating the\n // dev origin into a security-sensitive allowlist.\n const trustedOrigins: string[] = [];\n for (const value of parsed.trustedOrigins ?? []) {\n for (const origin of expandToOrigins(value)) {\n if (!trustedOrigins.includes(origin)) {\n trustedOrigins.push(origin);\n }\n }\n }\n\n // In non-production (development & test) client-admin-console runs on :3000 while\n // the API (publicUrl) runs on :3001. Seed :3000 into the trusted origins\n // so the redirect allowlist (<origin>/**) and CORS accept logins from the\n // dev UI out of the box; otherwise the realm-selection login is dead on\n // first run.\n if (env !== EnvironmentName.PRODUCTION) {\n const devOrigin = 'http://localhost:3000';\n if (!trustedOrigins.includes(devOrigin)) {\n trustedOrigins.push(devOrigin);\n }\n }\n\n const config : Config = {\n env,\n rootPath: process.cwd(),\n writableDirectoryPath,\n // '' = theming disabled. Deliberately NOT defaulted under\n // writableDirectoryPath: that directory is process-writable, and\n // pairing \"process-writable\" with \"content injected into the login\n // page\" would turn any write primitive landing there into\n // persistent branding control on the IdP origin.\n themeDirectoryPath: '',\n themeFragmentsEnabled: false,\n authConsolePath: '',\n accountConsolePath: '',\n\n logger: true,\n redis: false,\n smtp: false,\n\n port,\n host,\n publicUrl,\n mtlsPublicUrl: null,\n certificateSource: 'disabled',\n trustProxy: true,\n\n middlewareBody: true,\n middlewareCookie: true,\n middlewareCors: true,\n middlewarePrometheus: true,\n middlewareQuery: true,\n middlewareRateLimit: true,\n middlewareSwagger: true,\n tokenRefreshMaxAge: 259_200,\n tokenAccessMaxAge: 900,\n tokenRefreshGracePeriod: 0,\n promptLoginMaxAge: 60,\n endSessionHintGracePeriod: 0,\n registrationEnabled: false,\n emailVerificationEnabled: false,\n passwordRecoveryEnabled: false,\n passwordMinLength: USER_PASSWORD_MIN_LENGTH,\n accountConsoleEnabled: true,\n\n eventLogEnabled: true,\n eventLogRetentionDays: EVENT_LOG_RETENTION_DAYS_DEFAULT,\n eventLogEntityEnabled: true,\n eventLogEntityRetentionDays: 7,\n loginAttemptThrottleEnabled: false,\n loginAttemptThreshold: 5,\n loginAttemptWindow: 900,\n\n secretsEncryptionKey: '',\n\n mfaEnabled: false,\n mfaRequired: false,\n mfaFreshnessMaxAge: 60,\n mfaTicketMaxAge: 600,\n\n clientAuthBasic: false,\n clientSystemEnabled: false,\n clientSystemSecret: 'start123',\n clientSystemSecretReset: false,\n\n userAuthBasic: false,\n userAdminEnabled: true,\n userAdminPassword: 'start123',\n userAdminPasswordReset: false,\n\n permissions: [],\n permissionsDefaultPolicyAssignment: true,\n ...parsed,\n\n // After the spread so the canonicalized + dev-seeded list wins over\n // the raw parsed list (parsed.trustedOrigins is merged in above).\n trustedOrigins,\n };\n\n // After the spread, so a relative value supplied by any config surface\n // is resolved. Every consumer then receives an absolute path and none\n // of them has to care what the process cwd was.\n if (config.themeDirectoryPath) {\n config.themeDirectoryPath = path.resolve(config.rootPath, config.themeDirectoryPath);\n }\n\n if (config.authConsolePath) {\n config.authConsolePath = path.resolve(config.rootPath, config.authConsolePath);\n }\n\n if (config.accountConsolePath) {\n config.accountConsolePath = path.resolve(config.rootPath, config.accountConsolePath);\n }\n\n // Canonicalize the string form on EVERY config surface (env, .conf,\n // file, programmatic) — proxy-addr accepts single-integer \"long value\"\n // IPv4 notation, so an un-canonicalized `trustProxy: \"1\"` would silently\n // compile to an allowlist of `0.0.0.1` instead of one trusted hop.\n if (typeof config.trustProxy === 'string') {\n config.trustProxy = canonicalizeTrustProxy(config.trustProxy);\n } else if (Array.isArray(config.trustProxy)) {\n config.trustProxy = config.trustProxy.map(canonicalizeTrustProxyListEntry);\n }\n\n // fail loud at boot: the throttle counts loginFailed rows in\n // auth_events — with the audit log disabled it would silently no-op.\n if (config.loginAttemptThrottleEnabled && !config.eventLogEnabled) {\n throw new AuthupError('loginAttemptThrottleEnabled requires eventLogEnabled.');\n }\n\n if (config.mfaRequired && !config.mfaEnabled) {\n throw new AuthupError('mfaRequired requires mfaEnabled.');\n }\n\n if (config.mtlsPublicUrl && config.certificateSource === 'disabled') {\n throw new AuthupError('mtlsPublicUrl requires certificateSource to be enabled.');\n }\n\n // fail loud at boot rather than at first key-store access: wrapped key\n // material must never be minted under a malformed KEK. Validate the\n // DECODED length here (not just base64 shape) so a whitespace / invalid /\n // wrong-length key fails at config time, not asynchronously inside the\n // cipher at first wrap/unwrap.\n if (config.secretsEncryptionKey) {\n let byteLength = -1;\n try {\n byteLength = base64ToArrayBuffer(config.secretsEncryptionKey.trim()).byteLength;\n } catch {\n // fall through — treated as invalid below\n }\n if (byteLength !== 32) {\n throw new AuthupError('secretsEncryptionKey must decode to exactly 32 bytes (base64).');\n }\n }\n\n return config;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"normalize.mjs","names":["read","path","process","USER_PASSWORD_MIN_LENGTH","AuthupError","EnvironmentName","base64ToArrayBuffer","EVENT_LOG_RETENTION_DAYS_DEFAULT","toPublicHost","expandToOrigins","parseConfig","canonicalizeTrustProxy","canonicalizeTrustProxyListEntry","normalizeConfig","input","parsed","port","host","publicUrl","regex","match","env","DEVELOPMENT","trustedOrigins","value","origin","includes","push","PRODUCTION","devOrigin","config","rootPath","cwd","writableDirectoryPath","themeDirectoryPath","themeFragmentsEnabled","authConsolePath","accountConsolePath","logger","redis","smtp","mtlsPublicUrl","certificateSource","trustProxy","middlewareBody","middlewareCookie","middlewareCors","middlewarePrometheus","middlewareQuery","middlewareRateLimit","middlewareSwagger","tokenRefreshMaxAge","tokenAccessMaxAge","tokenRefreshGracePeriod","promptLoginMaxAge","endSessionHintGracePeriod","registrationEnabled","emailVerificationEnabled","passwordRecoveryEnabled","passwordMinLength","accountConsoleEnabled","eventLogEnabled","eventLogRetentionDays","eventLogEntityEnabled","eventLogEntityRetentionDays","loginAttemptThrottleEnabled","loginAttemptThreshold","loginAttemptWindow","secretsEncryptionKey","mfaEnabled","mfaRequired","mfaFreshnessMaxAge","mfaTicketMaxAge","clientAuthBasic","clientSystemEnabled","clientSystemSecret","clientSystemSecretReset","userAuthBasic","userAdminEnabled","userAdminPassword","userAdminPasswordReset","permissions","permissionsDefaultPolicyAssignment","resolve","Array","isArray","map","byteLength","trim"],"sources":["../../../../src/app/modules/config/normalize.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { read } from 'envix';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { USER_PASSWORD_MIN_LENGTH } from '@authup/core-kit';\nimport { AuthupError } from '@authup/errors';\nimport { EnvironmentName, base64ToArrayBuffer } from '@authup/kit';\nimport { EVENT_LOG_RETENTION_DAYS_DEFAULT } from '../../../core/index.ts';\nimport { toPublicHost } from '../../../utils/host.ts';\nimport { expandToOrigins } from './origins.ts';\nimport { parseConfig } from './parse.ts';\nimport { canonicalizeTrustProxy, canonicalizeTrustProxyListEntry } from './trust-proxy.ts';\nimport type { Config, ConfigInput } from './types.ts';\n\nexport async function normalizeConfig(input: ConfigInput = {}): Promise<Config> {\n const parsed = await parseConfig(input);\n\n const port = parsed.port ?? 3001;\n let host = parsed.host || '0.0.0.0';\n\n let publicUrl : string;\n if (parsed.publicUrl) {\n publicUrl = parsed.publicUrl;\n } else {\n const regex = /^([^:]+)(?::(\\d+))?$/;\n const match = host.match(regex);\n if (match) {\n [, host] = match;\n publicUrl = `http://${toPublicHost(host)}:${match[2] || port}`;\n } else {\n publicUrl = `http://${toPublicHost(host)}:${port}`;\n }\n }\n\n const env = parsed.env || read('NODE_ENV', EnvironmentName.DEVELOPMENT);\n\n // Canonicalize to bare origins (scheme://host[:port]) — a scheme-less\n // entry (e.g. `hub.local`) expands to both its http and https origin.\n // Downstream consumers (redirect allowlist, getAppOrigins) can rely on\n // every entry being a full origin. Building a fresh array also keeps a\n // repeated normalizeConfig() on the same input from accumulating the\n // dev origin into a security-sensitive allowlist.\n const trustedOrigins: string[] = [];\n for (const value of parsed.trustedOrigins ?? []) {\n for (const origin of expandToOrigins(value)) {\n if (!trustedOrigins.includes(origin)) {\n trustedOrigins.push(origin);\n }\n }\n }\n\n // In non-production (development & test) client-admin-console runs on :3000 while\n // the API (publicUrl) runs on :3001. Seed :3000 into the trusted origins\n // so the redirect allowlist (<origin>/**) and CORS accept logins from the\n // dev UI out of the box; otherwise the realm-selection login is dead on\n // first run.\n if (env !== EnvironmentName.PRODUCTION) {\n const devOrigin = 'http://localhost:3000';\n if (!trustedOrigins.includes(devOrigin)) {\n trustedOrigins.push(devOrigin);\n }\n }\n\n const config : Config = {\n env,\n rootPath: process.cwd(),\n writableDirectoryPath: 'writable',\n // '' = theming disabled. Deliberately NOT defaulted under\n // writableDirectoryPath: that directory is process-writable, and\n // pairing \"process-writable\" with \"content injected into the login\n // page\" would turn any write primitive landing there into\n // persistent branding control on the IdP origin.\n themeDirectoryPath: '',\n themeFragmentsEnabled: false,\n authConsolePath: '',\n accountConsolePath: '',\n\n logger: true,\n redis: false,\n smtp: false,\n\n port,\n host,\n publicUrl,\n mtlsPublicUrl: null,\n certificateSource: 'disabled',\n trustProxy: true,\n\n middlewareBody: true,\n middlewareCookie: true,\n middlewareCors: true,\n middlewarePrometheus: true,\n middlewareQuery: true,\n middlewareRateLimit: true,\n middlewareSwagger: true,\n tokenRefreshMaxAge: 259_200,\n tokenAccessMaxAge: 900,\n tokenRefreshGracePeriod: 0,\n promptLoginMaxAge: 60,\n endSessionHintGracePeriod: 0,\n registrationEnabled: false,\n emailVerificationEnabled: false,\n passwordRecoveryEnabled: false,\n passwordMinLength: USER_PASSWORD_MIN_LENGTH,\n accountConsoleEnabled: true,\n\n eventLogEnabled: true,\n eventLogRetentionDays: EVENT_LOG_RETENTION_DAYS_DEFAULT,\n eventLogEntityEnabled: true,\n eventLogEntityRetentionDays: 7,\n loginAttemptThrottleEnabled: false,\n loginAttemptThreshold: 5,\n loginAttemptWindow: 900,\n\n secretsEncryptionKey: '',\n\n mfaEnabled: false,\n mfaRequired: false,\n mfaFreshnessMaxAge: 60,\n mfaTicketMaxAge: 600,\n\n clientAuthBasic: false,\n clientSystemEnabled: false,\n clientSystemSecret: 'start123',\n clientSystemSecretReset: false,\n\n userAuthBasic: false,\n userAdminEnabled: true,\n userAdminPassword: 'start123',\n userAdminPasswordReset: false,\n\n permissions: [],\n permissionsDefaultPolicyAssignment: true,\n ...parsed,\n\n // After the spread so the canonicalized + dev-seeded list wins over\n // the raw parsed list (parsed.trustedOrigins is merged in above).\n trustedOrigins,\n };\n\n // After the spread, so a relative value supplied by any config surface\n // is resolved. Every consumer then receives an absolute path and none\n // of them has to care what the process cwd was.\n config.writableDirectoryPath = path.resolve(\n config.rootPath,\n config.writableDirectoryPath || 'writable',\n );\n\n if (config.themeDirectoryPath) {\n config.themeDirectoryPath = path.resolve(config.rootPath, config.themeDirectoryPath);\n }\n\n if (config.authConsolePath) {\n config.authConsolePath = path.resolve(config.rootPath, config.authConsolePath);\n }\n\n if (config.accountConsolePath) {\n config.accountConsolePath = path.resolve(config.rootPath, config.accountConsolePath);\n }\n\n // Canonicalize the string form on EVERY config surface (env, .conf,\n // file, programmatic) — proxy-addr accepts single-integer \"long value\"\n // IPv4 notation, so an un-canonicalized `trustProxy: \"1\"` would silently\n // compile to an allowlist of `0.0.0.1` instead of one trusted hop.\n if (typeof config.trustProxy === 'string') {\n config.trustProxy = canonicalizeTrustProxy(config.trustProxy);\n } else if (Array.isArray(config.trustProxy)) {\n config.trustProxy = config.trustProxy.map(canonicalizeTrustProxyListEntry);\n }\n\n // fail loud at boot: the throttle counts loginFailed rows in\n // auth_events — with the audit log disabled it would silently no-op.\n if (config.loginAttemptThrottleEnabled && !config.eventLogEnabled) {\n throw new AuthupError('loginAttemptThrottleEnabled requires eventLogEnabled.');\n }\n\n if (config.mfaRequired && !config.mfaEnabled) {\n throw new AuthupError('mfaRequired requires mfaEnabled.');\n }\n\n if (config.mtlsPublicUrl && config.certificateSource === 'disabled') {\n throw new AuthupError('mtlsPublicUrl requires certificateSource to be enabled.');\n }\n\n // fail loud at boot rather than at first key-store access: wrapped key\n // material must never be minted under a malformed KEK. Validate the\n // DECODED length here (not just base64 shape) so a whitespace / invalid /\n // wrong-length key fails at config time, not asynchronously inside the\n // cipher at first wrap/unwrap.\n if (config.secretsEncryptionKey) {\n let byteLength = -1;\n try {\n byteLength = base64ToArrayBuffer(config.secretsEncryptionKey.trim()).byteLength;\n } catch {\n // fall through — treated as invalid below\n }\n if (byteLength !== 32) {\n throw new AuthupError('secretsEncryptionKey must decode to exactly 32 bytes (base64).');\n }\n }\n\n return config;\n}\n"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { ConfigEnvironmentVariableName } from "../constants.mjs";
|
|
5
|
-
import { oneOf, read, readArray, readBool, readInt } from "envix";
|
|
6
5
|
import { hasEnvDataSourceOptions, readDataSourceOptionsFromEnv } from "typeorm-extension";
|
|
6
|
+
import { oneOf, read, readArray, readBool, readInt } from "envix";
|
|
7
7
|
//#region src/app/modules/config/read/env.ts
|
|
8
8
|
const BOOLEAN_TRUE_VALUES = /* @__PURE__ */ new Set([
|
|
9
9
|
"true",
|
|
@@ -20,6 +20,14 @@ export type Config = {
|
|
|
20
20
|
*/
|
|
21
21
|
rootPath: string;
|
|
22
22
|
/**
|
|
23
|
+
* Directory the application writes to at runtime (log files in
|
|
24
|
+
* production) and reads file-based provisioning from
|
|
25
|
+
* (`<writableDirectoryPath>/provisioning`).
|
|
26
|
+
*
|
|
27
|
+
* The SQLite database is NOT placed here - its path comes from the
|
|
28
|
+
* database configuration (`db.database` / `DB_DATABASE`), resolved
|
|
29
|
+
* against the process working directory by typeorm-extension.
|
|
30
|
+
*
|
|
23
31
|
* Relative or absolute path.
|
|
24
32
|
* If the path is relative, the rootPath will be appended.
|
|
25
33
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/app/modules/config/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,IAAI,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAEjF,MAAM,MAAM,MAAM,GAAG;IACjB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/app/modules/config/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import type { Event } from '@authup/core-kit';
|
|
|
2
2
|
import type { IQuery } from '@rapiq/core';
|
|
3
3
|
import type { Repository } from 'typeorm';
|
|
4
4
|
import type { EntityRepositoryFindManyResult } from '@authup/server-kit';
|
|
5
|
-
import type { EventCountRecentFilter, EventFindManyOptions, IEventRepository } from '../../../../../core/index.ts';
|
|
5
|
+
import type { EventCountRecentFilter, EventDeleteExpiredOptions, EventFindManyOptions, IEventRepository } from '../../../../../core/index.ts';
|
|
6
6
|
export declare class EventRepositoryAdapter implements IEventRepository {
|
|
7
7
|
private readonly repository;
|
|
8
8
|
constructor(repository: Repository<Event>);
|
|
@@ -11,6 +11,6 @@ export declare class EventRepositoryAdapter implements IEventRepository {
|
|
|
11
11
|
findOneById(id: string): Promise<Event | null>;
|
|
12
12
|
findMany(query: IQuery, options?: EventFindManyOptions): Promise<EntityRepositoryFindManyResult<Event>>;
|
|
13
13
|
countRecent(filter: EventCountRecentFilter): Promise<number>;
|
|
14
|
-
deleteExpired(now: string): Promise<number>;
|
|
14
|
+
deleteExpired(now: string, options?: EventDeleteExpiredOptions): Promise<number>;
|
|
15
15
|
}
|
|
16
16
|
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/event/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EACR,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EACnB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/event/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EACR,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EACnB,MAAM,8BAA8B,CAAC;AAItC,qBAAa,sBAAuB,YAAW,gBAAgB;IAC3D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;gBAEnC,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC;IAIzC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK;IAI7B,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAInC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAI9C,QAAQ,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,oBAAyB,GACnC,OAAO,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC;IAoD3C,WAAW,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAmC5D,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,MAAM,CAAC;CA+C7F"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { EVENT_RETENTION_SWEEP_BATCH_SIZE } from "../../../../../core/entities/event/constants.mjs";
|
|
5
|
+
import "../../../../../core/index.mjs";
|
|
4
6
|
import { applyQuery, redactFieldConditions } from "../query.mjs";
|
|
5
7
|
import { applyRealmScopeSelect } from "../helpers.mjs";
|
|
6
|
-
import { LessThan } from "typeorm";
|
|
8
|
+
import { In, LessThan } from "typeorm";
|
|
7
9
|
//#region src/app/modules/database/repositories/event/repository.ts
|
|
8
10
|
var EventRepositoryAdapter = class {
|
|
9
11
|
repository;
|
|
@@ -62,11 +64,26 @@ var EventRepositoryAdapter = class {
|
|
|
62
64
|
else qb.andWhere("event.realmId = :realmId", { realmId: filter.realmId });
|
|
63
65
|
return qb.getCount();
|
|
64
66
|
}
|
|
65
|
-
async deleteExpired(now) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
async deleteExpired(now, options = {}) {
|
|
68
|
+
const requested = options.batchSize;
|
|
69
|
+
const batchSize = typeof requested === "number" && Number.isSafeInteger(requested) && requested > 0 ? requested : EVENT_RETENTION_SWEEP_BATCH_SIZE;
|
|
70
|
+
let total = 0;
|
|
71
|
+
for (;;) {
|
|
72
|
+
const rows = await this.repository.find({
|
|
73
|
+
select: { id: true },
|
|
74
|
+
where: {
|
|
75
|
+
expiring: true,
|
|
76
|
+
expiresAt: LessThan(now)
|
|
77
|
+
},
|
|
78
|
+
take: batchSize
|
|
79
|
+
});
|
|
80
|
+
if (rows.length === 0) break;
|
|
81
|
+
const result = await this.repository.delete({ id: In(rows.map((row) => row.id)) });
|
|
82
|
+
total += result.affected ?? rows.length;
|
|
83
|
+
if (result.affected === 0) break;
|
|
84
|
+
if (rows.length < batchSize) break;
|
|
85
|
+
}
|
|
86
|
+
return total;
|
|
70
87
|
}
|
|
71
88
|
};
|
|
72
89
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.mjs","names":["LessThan","applyQuery","redactFieldConditions","applyRealmScopeSelect","EventRepositoryAdapter","repository","create","data","save","entity","findOneById","id","findOneBy","findMany","query","options","qb","createQueryBuilder","pagination","owner","andWhere","ownerActorId","actorId","ownerActorType","actorType","realmId","routeRealmId","visibility","constraints","parameters","realmIds","filter","length","push","visibleRealmIds","includes","visibleActorId","visibleActorType","join","entities","total","getManyAndCount","meta","countRecent","since","Date","toISOString","replace","where","name","actorName","requestIpAddress","getCount","deleteExpired","now","result","delete","expiring","expiresAt","affected"],"sources":["../../../../../../src/app/modules/database/repositories/event/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Event } from '@authup/core-kit';\nimport type { IQuery } from '@rapiq/core';\nimport type { Repository } from 'typeorm';\nimport { LessThan } from 'typeorm';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type {\n EventCountRecentFilter,\n EventFindManyOptions,\n IEventRepository,\n} from '../../../../../core/index.ts';\nimport { applyRealmScopeSelect } from '../helpers.ts';\n\nexport class EventRepositoryAdapter implements IEventRepository {\n private readonly repository: Repository<Event>;\n\n constructor(repository: Repository<Event>) {\n this.repository = repository;\n }\n\n create(data: Partial<Event>): Event {\n return this.repository.create(data);\n }\n\n async save(entity: Event): Promise<Event> {\n return this.repository.save(entity);\n }\n\n async findOneById(id: string): Promise<Event | null> {\n return this.repository.findOneBy({ id });\n }\n\n async findMany(\n query: IQuery,\n options: EventFindManyOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Event>> {\n const qb = this.repository.createQueryBuilder('event');\n\n const { pagination } = applyQuery(qb, query);\n\n applyRealmScopeSelect(qb, 'event', ['actorId', 'actorType']);\n\n if (options.owner) {\n // mandatory constraint — not overridable by a rapiq filter\n qb.andWhere('event.actorId = :ownerActorId AND event.actorType = :ownerActorType', {\n ownerActorId: options.owner.actorId,\n ownerActorType: options.owner.actorType,\n });\n }\n\n if (options.realmId) {\n qb.andWhere('event.realmId = :routeRealmId', { routeRealmId: options.realmId });\n }\n\n if (options.visibility) {\n const constraints: string[] = [];\n const parameters: Record<string, unknown> = {};\n const realmIds = options.visibility.realmIds\n .filter((realmId): realmId is string => realmId !== null);\n\n if (realmIds.length > 0) {\n constraints.push('event.realmId IN (:...visibleRealmIds)');\n parameters.visibleRealmIds = realmIds;\n }\n if (options.visibility.realmIds.includes(null)) {\n constraints.push('event.realmId IS NULL');\n }\n if (options.visibility.owner) {\n constraints.push('(event.actorId = :visibleActorId AND event.actorType = :visibleActorType)');\n parameters.visibleActorId = options.visibility.owner.actorId;\n parameters.visibleActorType = options.visibility.owner.actorType;\n }\n\n qb.andWhere(`(${constraints.length > 0 ? constraints.join(' OR ') : '1 = 0'})`, parameters);\n }\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async countRecent(filter: EventCountRecentFilter): Promise<number> {\n // created_at is stamped by the DATABASE server's clock (assumed UTC —\n // the shipped compose files and deployment posture; a non-UTC DB\n // server shifts the window regardless of what we bind), while a bound\n // Date object is serialized by the pg/mysql drivers in the HOST's\n // local timezone — on a non-UTC host that shifts the window by the\n // UTC offset (postgres: `timestamp without time zone` discards the\n // offset marker entirely). Bind a UTC wall-clock literal instead:\n // pg/mysql cast it as a wall-clock timestamp, sqlite compares it\n // lexicographically against the same format `datetime('now')` stores.\n const since = new Date(filter.since).toISOString().replace('T', ' ').replace('Z', '');\n\n const qb = this.repository.createQueryBuilder('event')\n .where('event.name = :name', { name: filter.name })\n .andWhere('event.createdAt > :since', { since });\n\n if (filter.actorName) {\n qb.andWhere('event.actorName = :actorName', { actorName: filter.actorName });\n }\n\n if (filter.requestIpAddress) {\n qb.andWhere('event.requestIpAddress = :requestIpAddress', { requestIpAddress: filter.requestIpAddress });\n }\n\n if (typeof filter.realmId !== 'undefined') {\n if (filter.realmId === null) {\n qb.andWhere('event.realmId IS NULL');\n } else {\n qb.andWhere('event.realmId = :realmId', { realmId: filter.realmId });\n }\n }\n\n return qb.getCount();\n }\n\n async deleteExpired(now: string): Promise<number> {\n const result = await this.repository.delete({\n expiring: true,\n expiresAt: LessThan(now),\n });\n\n return result.affected ?? 0;\n }\n}\n"],"mappings":";;;;;;;AAoBA,IAAaI,yBAAb,MAAaA;CACQC;CAEjB,YAAYA,YAA+B;EACvC,KAAKA,aAAaA;CACtB;CAEAC,OAAOC,MAA6B;EAChC,OAAO,KAAKF,WAAWC,OAAOC,IAAAA;CAClC;CAEA,MAAMC,KAAKC,QAA+B;EACtC,OAAO,KAAKJ,WAAWG,KAAKC,MAAAA;CAChC;CAEA,MAAMC,YAAYC,IAAmC;EACjD,OAAO,KAAKN,WAAWO,UAAU,EAAED,GAAG,CAAA;CAC1C;CAEA,MAAME,SACFC,OACAC,UAAgC,CAAC,GACa;EAC9C,MAAMC,KAAK,KAAKX,WAAWY,mBAAmB,OAAA;EAE9C,MAAM,EAAEC,eAAejB,WAAWe,IAAIF,KAAAA;EAEtCX,sBAAsBa,IAAI,SAAS,CAAC,WAAW,WAAY,CAAA;EAE3D,IAAID,QAAQI,OAERH,GAAGI,SAAS,uEAAuE;GAC/EC,cAAcN,QAAQI,MAAMG;GAC5BC,gBAAgBR,QAAQI,MAAMK;EAClC,CAAA;EAGJ,IAAIT,QAAQU,SACRT,GAAGI,SAAS,iCAAiC,EAAEM,cAAcX,QAAQU,QAAQ,CAAA;EAGjF,IAAIV,QAAQY,YAAY;GACpB,MAAMC,cAAwB,CAAA;GAC9B,MAAMC,aAAsC,CAAC;GAC7C,MAAMC,WAAWf,QAAQY,WAAWG,SAC/BC,QAAQN,YAA+BA,YAAY,IAAA;GAExD,IAAIK,SAASE,SAAS,GAAG;IACrBJ,YAAYK,KAAK,wCAAA;IACjBJ,WAAWK,kBAAkBJ;GACjC;GACA,IAAIf,QAAQY,WAAWG,SAASK,SAAS,IAAA,GACrCP,YAAYK,KAAK,uBAAA;GAErB,IAAIlB,QAAQY,WAAWR,OAAO;IAC1BS,YAAYK,KAAK,2EAAA;IACjBJ,WAAWO,iBAAiBrB,QAAQY,WAAWR,MAAMG;IACrDO,WAAWQ,mBAAmBtB,QAAQY,WAAWR,MAAMK;GAC3D;GAEAR,GAAGI,SAAS,IAAIQ,YAAYI,SAAS,IAAIJ,YAAYU,KAAK,MAAA,IAAU,QAAQ,IAAIT,UAAAA;EACpF;EAEA,MAAM,CAACU,UAAUC,SAAS,MAAMxB,GAAGyB,gBAAe;EAElD,OAAO;GACHlC,MAAML,sBAAsBY,OAAOyB,QAAAA;GACnCG,MAAM;IACFF;IACA,GAAGtB;GACP;EACJ;CACJ;CAEA,MAAMyB,YAAYZ,QAAiD;EAU/D,MAAMa,QAAQ,IAAIC,KAAKd,OAAOa,KAAK,CAAA,CAAEE,YAAW,CAAA,CAAGC,QAAQ,KAAK,GAAA,CAAA,CAAKA,QAAQ,KAAK,EAAA;EAElF,MAAM/B,KAAK,KAAKX,WAAWY,mBAAmB,OAAA,CAAA,CACzC+B,MAAM,sBAAsB,EAAEC,MAAMlB,OAAOkB,KAAK,CAAA,CAAA,CAChD7B,SAAS,4BAA4B,EAAEwB,MAAM,CAAA;EAElD,IAAIb,OAAOmB,WACPlC,GAAGI,SAAS,gCAAgC,EAAE8B,WAAWnB,OAAOmB,UAAU,CAAA;EAG9E,IAAInB,OAAOoB,kBACPnC,GAAGI,SAAS,8CAA8C,EAAE+B,kBAAkBpB,OAAOoB,iBAAiB,CAAA;EAG1G,IAAI,OAAOpB,OAAON,YAAY,aAC1B,IAAIM,OAAON,YAAY,MACnBT,GAAGI,SAAS,uBAAA;OAEZJ,GAAGI,SAAS,4BAA4B,EAAEK,SAASM,OAAON,QAAQ,CAAA;EAI1E,OAAOT,GAAGoC,SAAQ;CACtB;CAEA,MAAMC,cAAcC,KAA8B;EAM9C,QAAOC,MALc,KAAKlD,WAAWmD,OAAO;GACxCC,UAAU;GACVC,WAAW1D,SAASsD,GAAAA;EACxB,CAAA,EAAA,CAEcK,YAAY;CAC9B;AACJ"}
|
|
1
|
+
{"version":3,"file":"repository.mjs","names":["In","LessThan","applyQuery","redactFieldConditions","EVENT_RETENTION_SWEEP_BATCH_SIZE","applyRealmScopeSelect","EventRepositoryAdapter","repository","create","data","save","entity","findOneById","id","findOneBy","findMany","query","options","qb","createQueryBuilder","pagination","owner","andWhere","ownerActorId","actorId","ownerActorType","actorType","realmId","routeRealmId","visibility","constraints","parameters","realmIds","filter","length","push","visibleRealmIds","includes","visibleActorId","visibleActorType","join","entities","total","getManyAndCount","meta","countRecent","since","Date","toISOString","replace","where","name","actorName","requestIpAddress","getCount","deleteExpired","now","requested","batchSize","Number","isSafeInteger","rows","find","select","expiring","expiresAt","take","result","delete","map","row","affected"],"sources":["../../../../../../src/app/modules/database/repositories/event/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Event } from '@authup/core-kit';\nimport type { IQuery } from '@rapiq/core';\nimport type { Repository } from 'typeorm';\nimport { In, LessThan } from 'typeorm';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type {\n EventCountRecentFilter,\n EventDeleteExpiredOptions,\n EventFindManyOptions,\n IEventRepository,\n} from '../../../../../core/index.ts';\nimport { EVENT_RETENTION_SWEEP_BATCH_SIZE } from '../../../../../core/index.ts';\nimport { applyRealmScopeSelect } from '../helpers.ts';\n\nexport class EventRepositoryAdapter implements IEventRepository {\n private readonly repository: Repository<Event>;\n\n constructor(repository: Repository<Event>) {\n this.repository = repository;\n }\n\n create(data: Partial<Event>): Event {\n return this.repository.create(data);\n }\n\n async save(entity: Event): Promise<Event> {\n return this.repository.save(entity);\n }\n\n async findOneById(id: string): Promise<Event | null> {\n return this.repository.findOneBy({ id });\n }\n\n async findMany(\n query: IQuery,\n options: EventFindManyOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Event>> {\n const qb = this.repository.createQueryBuilder('event');\n\n const { pagination } = applyQuery(qb, query);\n\n applyRealmScopeSelect(qb, 'event', ['actorId', 'actorType']);\n\n if (options.owner) {\n // mandatory constraint — not overridable by a rapiq filter\n qb.andWhere('event.actorId = :ownerActorId AND event.actorType = :ownerActorType', {\n ownerActorId: options.owner.actorId,\n ownerActorType: options.owner.actorType,\n });\n }\n\n if (options.realmId) {\n qb.andWhere('event.realmId = :routeRealmId', { routeRealmId: options.realmId });\n }\n\n if (options.visibility) {\n const constraints: string[] = [];\n const parameters: Record<string, unknown> = {};\n const realmIds = options.visibility.realmIds\n .filter((realmId): realmId is string => realmId !== null);\n\n if (realmIds.length > 0) {\n constraints.push('event.realmId IN (:...visibleRealmIds)');\n parameters.visibleRealmIds = realmIds;\n }\n if (options.visibility.realmIds.includes(null)) {\n constraints.push('event.realmId IS NULL');\n }\n if (options.visibility.owner) {\n constraints.push('(event.actorId = :visibleActorId AND event.actorType = :visibleActorType)');\n parameters.visibleActorId = options.visibility.owner.actorId;\n parameters.visibleActorType = options.visibility.owner.actorType;\n }\n\n qb.andWhere(`(${constraints.length > 0 ? constraints.join(' OR ') : '1 = 0'})`, parameters);\n }\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async countRecent(filter: EventCountRecentFilter): Promise<number> {\n // created_at is stamped by the DATABASE server's clock (assumed UTC —\n // the shipped compose files and deployment posture; a non-UTC DB\n // server shifts the window regardless of what we bind), while a bound\n // Date object is serialized by the pg/mysql drivers in the HOST's\n // local timezone — on a non-UTC host that shifts the window by the\n // UTC offset (postgres: `timestamp without time zone` discards the\n // offset marker entirely). Bind a UTC wall-clock literal instead:\n // pg/mysql cast it as a wall-clock timestamp, sqlite compares it\n // lexicographically against the same format `datetime('now')` stores.\n const since = new Date(filter.since).toISOString().replace('T', ' ').replace('Z', '');\n\n const qb = this.repository.createQueryBuilder('event')\n .where('event.name = :name', { name: filter.name })\n .andWhere('event.createdAt > :since', { since });\n\n if (filter.actorName) {\n qb.andWhere('event.actorName = :actorName', { actorName: filter.actorName });\n }\n\n if (filter.requestIpAddress) {\n qb.andWhere('event.requestIpAddress = :requestIpAddress', { requestIpAddress: filter.requestIpAddress });\n }\n\n if (typeof filter.realmId !== 'undefined') {\n if (filter.realmId === null) {\n qb.andWhere('event.realmId IS NULL');\n } else {\n qb.andWhere('event.realmId = :realmId', { realmId: filter.realmId });\n }\n }\n\n return qb.getCount();\n }\n\n async deleteExpired(now: string, options: EventDeleteExpiredOptions = {}): Promise<number> {\n // A non-positive or non-integral size must never reach `take`: typeorm\n // ignores a falsy one, which would silently restore the single\n // unbounded DELETE this batching exists to prevent, and the rest reach\n // the driver as invalid SQL. Fall back to the default instead.\n const requested = options.batchSize;\n const batchSize = typeof requested === 'number' &&\n Number.isSafeInteger(requested) &&\n requested > 0 ?\n requested :\n EVENT_RETENTION_SWEEP_BATCH_SIZE;\n\n let total = 0;\n\n for (;;) {\n const rows = await this.repository.find({\n select: { id: true },\n where: {\n expiring: true,\n expiresAt: LessThan(now),\n },\n take: batchSize,\n });\n\n if (rows.length === 0) {\n break;\n }\n\n const result = await this.repository.delete({ id: In(rows.map((row) => row.id)) });\n\n // A driver that does not report affected rows still made\n // progress, so count the batch rather than returning 0.\n total += result.affected ?? rows.length;\n\n // Another replica's sweep already owns these rows. Stop rather\n // than re-selecting them; the next tick picks up whatever is left.\n if (result.affected === 0) {\n break;\n }\n\n if (rows.length < batchSize) {\n break;\n }\n }\n\n return total;\n }\n}\n"],"mappings":"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"}
|
|
@@ -21,7 +21,9 @@ export declare class IdentityProviderRepositoryAdapter implements IIdentityProvi
|
|
|
21
21
|
create(data: Partial<IdentityProvider>): IdentityProvider;
|
|
22
22
|
merge(entity: IdentityProvider, data: Partial<IdentityProvider>): IdentityProvider;
|
|
23
23
|
save(entity: IdentityProvider): Promise<IdentityProvider>;
|
|
24
|
-
saveWithEA(entity: IdentityProvider, attributes?: Record<string, any
|
|
24
|
+
saveWithEA(entity: IdentityProvider, attributes?: Record<string, any>, options?: {
|
|
25
|
+
keepAll?: boolean;
|
|
26
|
+
}): Promise<IdentityProvider>;
|
|
25
27
|
extendOneWithEA(entity: IdentityProvider): Promise<void>;
|
|
26
28
|
remove(entity: IdentityProvider): Promise<void>;
|
|
27
29
|
validateJoinColumns(data: Partial<IdentityProvider>): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/identity-provider/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,2BAA2B,EAAoB,MAAM,8BAA8B,CAAC;AAElG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mDAAmD,CAAC;AAKpG,MAAM,MAAM,wCAAwC,GAAG;IACnD,UAAU,EAAE,0BAA0B,CAAC;IACvC,eAAe,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACtC,CAAC;AAEF,qBAAa,iCAAkC,YAAW,2BAA2B;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IAExD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;gBAEvC,GAAG,EAAE,wCAAwC;IAKnD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,gBAAgB,CAAC,CAAC;IAiBlF,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAQzD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAmBhF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMrF,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAInE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAI7E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB;IAIzD,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB;IAI5E,IAAI,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIzD,UAAU,
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/identity-provider/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,2BAA2B,EAAoB,MAAM,8BAA8B,CAAC;AAElG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mDAAmD,CAAC;AAKpG,MAAM,MAAM,wCAAwC,GAAG;IACnD,UAAU,EAAE,0BAA0B,CAAC;IACvC,eAAe,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACtC,CAAC;AAEF,qBAAa,iCAAkC,YAAW,2BAA2B;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IAExD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;gBAEvC,GAAG,EAAE,wCAAwC;IAKnD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,gBAAgB,CAAC,CAAC;IAiBlF,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAQzD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAmBhF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMrF,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAInE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAI7E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB;IAIzD,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB;IAI5E,IAAI,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIzD,UAAU,CACZ,MAAM,EAAE,gBAAgB,EACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAChC,OAAO,CAAC,gBAAgB,CAAC;IAKtB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa5F,cAAc,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAgB3G"}
|
|
@@ -66,8 +66,8 @@ var IdentityProviderRepositoryAdapter = class {
|
|
|
66
66
|
async save(entity) {
|
|
67
67
|
return this.repository.save(entity);
|
|
68
68
|
}
|
|
69
|
-
async saveWithEA(entity, attributes) {
|
|
70
|
-
await this.repository.saveOneWithEA(entity, attributes);
|
|
69
|
+
async saveWithEA(entity, attributes, options) {
|
|
70
|
+
await this.repository.saveOneWithEA(entity, attributes, options);
|
|
71
71
|
return entity;
|
|
72
72
|
}
|
|
73
73
|
async extendOneWithEA(entity) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.mjs","names":["isUUID","validateEntityJoinColumns","applyQuery","redactFieldConditions","DatabaseConflictError","IdentityProviderEntity","isEntityUnique","translateWhereConditions","RealmRepositoryAdapter","IdentityProviderRepositoryAdapter","repository","realmRepository","ctx","findMany","query","qb","createQueryBuilder","groupBy","pagination","entities","total","getManyAndCount","data","meta","findOneById","id","entity","findOneBy","extendOneWithEA","findOneByName","name","realmKey","where","realmId","resolveId","andWhere","getOne","findOneByIdOrName","idOrName","realm","findManyBy","findBy","create","merge","save","saveWithEA","attributes","saveOneWithEA","remove","validateJoinColumns","dataSource","manager","connection","entityTarget","checkUniqueness","existing","isUnique","entityExisting","findByProtocol","protocol","getMany","extendManyWithEA"],"sources":["../../../../../../src/app/modules/database/repositories/identity-provider/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IdentityProvider, IdentityProviderProtocol, Realm } from '@authup/core-kit';\nimport type { IQuery } from '@rapiq/core';\nimport { isUUID } from '@authup/kit';\nimport type { Repository } from 'typeorm';\nimport { validateEntityJoinColumns } from 'typeorm-extension';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { IIdentityProviderRepository, IRealmRepository } from '../../../../../core/index.ts';\nimport { DatabaseConflictError } from '../../../../../adapters/database/index.ts';\nimport type { IdentityProviderRepository } from '../../../../../adapters/database/domains/index.ts';\nimport { IdentityProviderEntity } from '../../../../../adapters/database/domains/index.ts';\nimport { isEntityUnique, translateWhereConditions } from '../helpers.ts';\nimport { RealmRepositoryAdapter } from '../realm/repository.ts';\n\nexport type IdentityProviderRepositoryAdapterContext = {\n repository: IdentityProviderRepository,\n realmRepository: Repository<Realm>,\n};\n\nexport class IdentityProviderRepositoryAdapter implements IIdentityProviderRepository {\n private readonly repository: IdentityProviderRepository;\n\n private readonly realmRepository: IRealmRepository;\n\n constructor(ctx: IdentityProviderRepositoryAdapterContext) {\n this.repository = ctx.repository;\n this.realmRepository = new RealmRepositoryAdapter(ctx.realmRepository);\n }\n\n async findMany(query: IQuery): Promise<EntityRepositoryFindManyResult<IdentityProvider>> {\n const qb = this.repository.createQueryBuilder('provider');\n qb.groupBy('provider.id');\n\n const { pagination } = applyQuery(qb, query);\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async findOneById(id: string): Promise<IdentityProvider | null> {\n const entity = await this.findOneBy({ id });\n if (entity) {\n await this.repository.extendOneWithEA(entity);\n }\n return entity;\n }\n\n async findOneByName(name: string, realmKey?: string): Promise<IdentityProvider | null> {\n const qb = this.repository.createQueryBuilder('provider');\n qb.where('provider.name = :name', { name });\n\n if (realmKey) {\n const realmId = await this.realmRepository.resolveId(realmKey);\n if (!realmId) {\n return null;\n }\n qb.andWhere('provider.realmId = :realmId', { realmId });\n }\n\n const entity = await qb.getOne();\n if (entity) {\n await this.repository.extendOneWithEA(entity);\n }\n return entity;\n }\n\n async findOneByIdOrName(idOrName: string, realm?: string): Promise<IdentityProvider | null> {\n return isUUID(idOrName) ?\n this.findOneById(idOrName) :\n this.findOneByName(idOrName, realm);\n }\n\n async findManyBy(where: Record<string, any>): Promise<IdentityProvider[]> {\n return this.repository.findBy(translateWhereConditions(where));\n }\n\n async findOneBy(where: Record<string, any>): Promise<IdentityProvider | null> {\n return this.repository.findOneBy(translateWhereConditions(where));\n }\n\n create(data: Partial<IdentityProvider>): IdentityProvider {\n return this.repository.create(data);\n }\n\n merge(entity: IdentityProvider, data: Partial<IdentityProvider>): IdentityProvider {\n return this.repository.merge(entity, data);\n }\n\n async save(entity: IdentityProvider): Promise<IdentityProvider> {\n return this.repository.save(entity);\n }\n\n async saveWithEA(entity: IdentityProvider
|
|
1
|
+
{"version":3,"file":"repository.mjs","names":["isUUID","validateEntityJoinColumns","applyQuery","redactFieldConditions","DatabaseConflictError","IdentityProviderEntity","isEntityUnique","translateWhereConditions","RealmRepositoryAdapter","IdentityProviderRepositoryAdapter","repository","realmRepository","ctx","findMany","query","qb","createQueryBuilder","groupBy","pagination","entities","total","getManyAndCount","data","meta","findOneById","id","entity","findOneBy","extendOneWithEA","findOneByName","name","realmKey","where","realmId","resolveId","andWhere","getOne","findOneByIdOrName","idOrName","realm","findManyBy","findBy","create","merge","save","saveWithEA","attributes","options","saveOneWithEA","remove","validateJoinColumns","dataSource","manager","connection","entityTarget","checkUniqueness","existing","isUnique","entityExisting","findByProtocol","protocol","getMany","extendManyWithEA"],"sources":["../../../../../../src/app/modules/database/repositories/identity-provider/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IdentityProvider, IdentityProviderProtocol, Realm } from '@authup/core-kit';\nimport type { IQuery } from '@rapiq/core';\nimport { isUUID } from '@authup/kit';\nimport type { Repository } from 'typeorm';\nimport { validateEntityJoinColumns } from 'typeorm-extension';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { IIdentityProviderRepository, IRealmRepository } from '../../../../../core/index.ts';\nimport { DatabaseConflictError } from '../../../../../adapters/database/index.ts';\nimport type { IdentityProviderRepository } from '../../../../../adapters/database/domains/index.ts';\nimport { IdentityProviderEntity } from '../../../../../adapters/database/domains/index.ts';\nimport { isEntityUnique, translateWhereConditions } from '../helpers.ts';\nimport { RealmRepositoryAdapter } from '../realm/repository.ts';\n\nexport type IdentityProviderRepositoryAdapterContext = {\n repository: IdentityProviderRepository,\n realmRepository: Repository<Realm>,\n};\n\nexport class IdentityProviderRepositoryAdapter implements IIdentityProviderRepository {\n private readonly repository: IdentityProviderRepository;\n\n private readonly realmRepository: IRealmRepository;\n\n constructor(ctx: IdentityProviderRepositoryAdapterContext) {\n this.repository = ctx.repository;\n this.realmRepository = new RealmRepositoryAdapter(ctx.realmRepository);\n }\n\n async findMany(query: IQuery): Promise<EntityRepositoryFindManyResult<IdentityProvider>> {\n const qb = this.repository.createQueryBuilder('provider');\n qb.groupBy('provider.id');\n\n const { pagination } = applyQuery(qb, query);\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async findOneById(id: string): Promise<IdentityProvider | null> {\n const entity = await this.findOneBy({ id });\n if (entity) {\n await this.repository.extendOneWithEA(entity);\n }\n return entity;\n }\n\n async findOneByName(name: string, realmKey?: string): Promise<IdentityProvider | null> {\n const qb = this.repository.createQueryBuilder('provider');\n qb.where('provider.name = :name', { name });\n\n if (realmKey) {\n const realmId = await this.realmRepository.resolveId(realmKey);\n if (!realmId) {\n return null;\n }\n qb.andWhere('provider.realmId = :realmId', { realmId });\n }\n\n const entity = await qb.getOne();\n if (entity) {\n await this.repository.extendOneWithEA(entity);\n }\n return entity;\n }\n\n async findOneByIdOrName(idOrName: string, realm?: string): Promise<IdentityProvider | null> {\n return isUUID(idOrName) ?\n this.findOneById(idOrName) :\n this.findOneByName(idOrName, realm);\n }\n\n async findManyBy(where: Record<string, any>): Promise<IdentityProvider[]> {\n return this.repository.findBy(translateWhereConditions(where));\n }\n\n async findOneBy(where: Record<string, any>): Promise<IdentityProvider | null> {\n return this.repository.findOneBy(translateWhereConditions(where));\n }\n\n create(data: Partial<IdentityProvider>): IdentityProvider {\n return this.repository.create(data);\n }\n\n merge(entity: IdentityProvider, data: Partial<IdentityProvider>): IdentityProvider {\n return this.repository.merge(entity, data);\n }\n\n async save(entity: IdentityProvider): Promise<IdentityProvider> {\n return this.repository.save(entity);\n }\n\n async saveWithEA(\n entity: IdentityProvider,\n attributes?: Record<string, any>,\n options?: { keepAll?: boolean },\n ): Promise<IdentityProvider> {\n await this.repository.saveOneWithEA(entity, attributes, options);\n return entity;\n }\n\n async extendOneWithEA(entity: IdentityProvider): Promise<void> {\n await this.repository.extendOneWithEA(entity);\n }\n\n async remove(entity: IdentityProvider): Promise<void> {\n await this.repository.remove(entity);\n }\n\n async validateJoinColumns(data: Partial<IdentityProvider>): Promise<void> {\n await validateEntityJoinColumns(data, {\n dataSource: this.repository.manager.connection,\n entityTarget: IdentityProviderEntity,\n });\n }\n\n async checkUniqueness(data: Partial<IdentityProvider>, existing?: IdentityProvider): Promise<void> {\n const isUnique = await isEntityUnique({\n dataSource: this.repository.manager.connection,\n entityTarget: IdentityProviderEntity,\n entity: data,\n entityExisting: existing,\n });\n\n if (!isUnique) {\n throw new DatabaseConflictError();\n }\n }\n\n async findByProtocol(protocol: IdentityProviderProtocol, realmKey?: string): Promise<IdentityProvider[]> {\n const qb = this.repository.createQueryBuilder('provider');\n qb.where('provider.protocol = :protocol', { protocol });\n\n if (realmKey) {\n const realmId = await this.realmRepository.resolveId(realmKey);\n if (!realmId) {\n return [];\n }\n qb.andWhere('provider.realmId = :realmId', { realmId });\n }\n\n const entities = await qb.getMany();\n await this.repository.extendManyWithEA(entities);\n return entities;\n }\n}\n"],"mappings":"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"}
|
package/dist/app/modules/database/repositories/identity-provider-account/repository.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/identity-provider-account/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/app/modules/database/repositories/identity-provider-account/repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EACR,UAAU,EACV,WAAW,EACX,UAAU,EACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAC;AAGlG,OAAO,KAAK,EACR,kCAAkC,EAClC,sCAAsC,EACtC,wBAAwB,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,qBAAa,wCAAyC,YAAW,kCAAkC;IAC/F,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;IAEjC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,6BAA6B,CAAC,CAAC;gBAEpD,UAAU,EAAE,UAAU;IAK5B,QAAQ,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,sCAA2C,GACrD,OAAO,CAAC,8BAA8B,CAAC,uBAAuB,CAAC,CAAC;IAuC7D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAIhE,aAAa,CAAC,MAAM,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAsC5F,yBAAyB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAUtG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,uBAAuB,CAAC,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAiBpF,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/D"}
|
|
@@ -6,6 +6,9 @@ import "../../../../../adapters/database/helpers/index.mjs";
|
|
|
6
6
|
import { IdentityProviderAccountEntity } from "../../../../../adapters/database/domains/identity-provider-account/entity.mjs";
|
|
7
7
|
import "../../../../../adapters/database/domains/index.mjs";
|
|
8
8
|
import { applyQuery, redactFieldConditions } from "../query.mjs";
|
|
9
|
+
import { isUniqueConstraintDatabaseError } from "../../../../../adapters/database/errors/driver.mjs";
|
|
10
|
+
import "../../../../../adapters/database/errors/index.mjs";
|
|
11
|
+
import { EntityConflictError } from "@authup/errors";
|
|
9
12
|
//#region src/app/modules/database/repositories/identity-provider-account/repository.ts
|
|
10
13
|
var IdentityProviderAccountRepositoryAdapter = class {
|
|
11
14
|
dataSource;
|
|
@@ -57,7 +60,12 @@ var IdentityProviderAccountRepositoryAdapter = class {
|
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
62
|
async save(entity) {
|
|
60
|
-
|
|
63
|
+
try {
|
|
64
|
+
return await this.repository.save(entity);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
if (isUniqueConstraintDatabaseError(e)) throw new EntityConflictError({ entity: "identity provider account" });
|
|
67
|
+
throw e;
|
|
68
|
+
}
|
|
61
69
|
}
|
|
62
70
|
async remove(entity) {
|
|
63
71
|
await this.repository.remove(entity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.mjs","names":["applyQuery","redactFieldConditions","IdentityProviderAccountEntity","isDatabaseTypeRowLockable","IdentityProviderAccountRepositoryAdapter","dataSource","repository","getRepository","findMany","query","options","qb","createQueryBuilder","pagination","existing","Set","expressionMap","selects","map","select","selection","selections","column","filter","has","length","addSelect","userId","andWhere","ownerUserId","realmId","ownerRealmId","entities","total","getManyAndCount","data","meta","findOneById","id","findOneBy","removeGuarded","entity","userHasOtherLogin","type","count","countBy","remove","transaction","manager","rows","where","setLock","getMany","findOneByProviderIdentity","identity","findOne","providerUserId","providerId","provider","relations","user","save"],"sources":["../../../../../../src/app/modules/database/repositories/identity-provider-account/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IdentityProviderAccount } from '@authup/core-kit';\nimport type { IQuery } from '@rapiq/core';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type {\n DataSource, \n DeepPartial, \n Repository,\n} from 'typeorm';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport { IdentityProviderAccountEntity } from '../../../../../adapters/database/domains/index.ts';\nimport { isDatabaseTypeRowLockable } from '../../../../../adapters/database/helpers/index.ts';\nimport type {\n IIdentityProviderAccountRepository,\n IdentityProviderAccountFindManyOptions,\n IdentityProviderIdentity,\n} from '../../../../../core/index.ts';\n\nexport class IdentityProviderAccountRepositoryAdapter implements IIdentityProviderAccountRepository {\n protected dataSource: DataSource;\n\n protected repository: Repository<IdentityProviderAccountEntity>;\n\n constructor(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.repository = dataSource.getRepository(IdentityProviderAccountEntity);\n }\n\n async findMany(\n query: IQuery,\n options: IdentityProviderAccountFindManyOptions = {},\n ): Promise<EntityRepositoryFindManyResult<IdentityProviderAccount>> {\n const qb = this.repository.createQueryBuilder('identityProviderAccount');\n\n const { pagination } = applyQuery(qb, query);\n\n // plan-039 force-select: the per-row gate reads userId (ownership)\n // and userRealmId (realm reach). The shared applyRealmScopeSelect\n // pins a `realmId` column this entity does not have, so dedupe and\n // add the two columns the same way it would.\n const existing = new Set(qb.expressionMap.selects.map((select) => select.selection));\n const selections = ['userId', 'userRealmId']\n .map((column) => `identityProviderAccount.${column}`)\n .filter((selection) => !existing.has(selection));\n if (selections.length > 0) {\n qb.addSelect(selections);\n }\n\n if (options.userId) {\n // mandatory constraint — not overridable by a rapiq filter\n qb.andWhere('identityProviderAccount.userId = :ownerUserId', { ownerUserId: options.userId });\n }\n\n if (options.realmId) {\n // nested `/realms/:realmId/identity-provider-accounts` mount —\n // mandatory constraint, not overridable by a rapiq filter\n qb.andWhere('identityProviderAccount.userRealmId = :ownerRealmId', { ownerRealmId: options.realmId });\n }\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async findOneById(id: string): Promise<IdentityProviderAccount | null> {\n return this.repository.findOneBy({ id });\n }\n\n async removeGuarded(entity: IdentityProviderAccount, userHasOtherLogin: boolean): Promise<boolean> {\n if (!isDatabaseTypeRowLockable(this.dataSource.options.type)) {\n // better-sqlite3: a single synchronous writer, so the\n // count/delete race cannot manifest and no transaction is\n // needed. Deliberately NOT wrapped in one — a held write\n // transaction would contend the database lock (single-file\n // driver) without buying any atomicity here. Plain\n // count-then-remove, exactly as the un-guarded path did.\n const count = await this.repository.countBy({ userId: entity.userId });\n if (count <= 1 && !userHasOtherLogin) {\n return false;\n }\n\n await this.repository.remove(entity as IdentityProviderAccountEntity);\n return true;\n }\n\n // mysql / postgres: real concurrency. Lock the user's account rows,\n // count, and delete in one transaction so two concurrent unlinks for\n // the same user cannot both read > 1 and both delete.\n return this.dataSource.transaction(async (manager) => {\n const repository = manager.getRepository(IdentityProviderAccountEntity);\n\n const rows = await repository.createQueryBuilder('identityProviderAccount')\n .select(['identityProviderAccount.id'])\n .where('identityProviderAccount.userId = :userId', { userId: entity.userId })\n .setLock('pessimistic_write')\n .getMany();\n\n if (rows.length <= 1 && !userHasOtherLogin) {\n return false;\n }\n\n await repository.remove(entity as IdentityProviderAccountEntity);\n return true;\n });\n }\n\n async findOneByProviderIdentity(identity: IdentityProviderIdentity): Promise<IdentityProviderAccount | null> {\n return this.repository.findOne({\n where: {\n providerUserId: identity.id,\n providerId: identity.provider.id,\n },\n relations: { user: true },\n });\n }\n\n async save(entity: DeepPartial<IdentityProviderAccount>): Promise<IdentityProviderAccount> {\n return this.repository.save(entity);\n }\n\n async remove(entity: IdentityProviderAccount): Promise<void> {\n await this.repository.remove(entity as IdentityProviderAccountEntity);\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository.mjs","names":["EntityConflictError","applyQuery","redactFieldConditions","IdentityProviderAccountEntity","isUniqueConstraintDatabaseError","isDatabaseTypeRowLockable","IdentityProviderAccountRepositoryAdapter","dataSource","repository","getRepository","findMany","query","options","qb","createQueryBuilder","pagination","existing","Set","expressionMap","selects","map","select","selection","selections","column","filter","has","length","addSelect","userId","andWhere","ownerUserId","realmId","ownerRealmId","entities","total","getManyAndCount","data","meta","findOneById","id","findOneBy","removeGuarded","entity","userHasOtherLogin","type","count","countBy","remove","transaction","manager","rows","where","setLock","getMany","findOneByProviderIdentity","identity","findOne","providerUserId","providerId","provider","relations","user","save","e"],"sources":["../../../../../../src/app/modules/database/repositories/identity-provider-account/repository.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IdentityProviderAccount } from '@authup/core-kit';\nimport { EntityConflictError } from '@authup/errors';\nimport type { IQuery } from '@rapiq/core';\nimport type { EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type {\n DataSource, \n DeepPartial, \n Repository,\n} from 'typeorm';\nimport { applyQuery, redactFieldConditions } from '../query.ts';\nimport { IdentityProviderAccountEntity } from '../../../../../adapters/database/domains/index.ts';\nimport { isUniqueConstraintDatabaseError } from '../../../../../adapters/database/errors/index.ts';\nimport { isDatabaseTypeRowLockable } from '../../../../../adapters/database/helpers/index.ts';\nimport type {\n IIdentityProviderAccountRepository,\n IdentityProviderAccountFindManyOptions,\n IdentityProviderIdentity,\n} from '../../../../../core/index.ts';\n\nexport class IdentityProviderAccountRepositoryAdapter implements IIdentityProviderAccountRepository {\n protected dataSource: DataSource;\n\n protected repository: Repository<IdentityProviderAccountEntity>;\n\n constructor(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.repository = dataSource.getRepository(IdentityProviderAccountEntity);\n }\n\n async findMany(\n query: IQuery,\n options: IdentityProviderAccountFindManyOptions = {},\n ): Promise<EntityRepositoryFindManyResult<IdentityProviderAccount>> {\n const qb = this.repository.createQueryBuilder('identityProviderAccount');\n\n const { pagination } = applyQuery(qb, query);\n\n // plan-039 force-select: the per-row gate reads userId (ownership)\n // and userRealmId (realm reach). The shared applyRealmScopeSelect\n // pins a `realmId` column this entity does not have, so dedupe and\n // add the two columns the same way it would.\n const existing = new Set(qb.expressionMap.selects.map((select) => select.selection));\n const selections = ['userId', 'userRealmId']\n .map((column) => `identityProviderAccount.${column}`)\n .filter((selection) => !existing.has(selection));\n if (selections.length > 0) {\n qb.addSelect(selections);\n }\n\n if (options.userId) {\n // mandatory constraint — not overridable by a rapiq filter\n qb.andWhere('identityProviderAccount.userId = :ownerUserId', { ownerUserId: options.userId });\n }\n\n if (options.realmId) {\n // nested `/realms/:realmId/identity-provider-accounts` mount —\n // mandatory constraint, not overridable by a rapiq filter\n qb.andWhere('identityProviderAccount.userRealmId = :ownerRealmId', { ownerRealmId: options.realmId });\n }\n\n const [entities, total] = await qb.getManyAndCount();\n\n return {\n data: redactFieldConditions(query, entities),\n meta: {\n total,\n ...pagination,\n },\n };\n }\n\n async findOneById(id: string): Promise<IdentityProviderAccount | null> {\n return this.repository.findOneBy({ id });\n }\n\n async removeGuarded(entity: IdentityProviderAccount, userHasOtherLogin: boolean): Promise<boolean> {\n if (!isDatabaseTypeRowLockable(this.dataSource.options.type)) {\n // better-sqlite3: a single synchronous writer, so the\n // count/delete race cannot manifest and no transaction is\n // needed. Deliberately NOT wrapped in one — a held write\n // transaction would contend the database lock (single-file\n // driver) without buying any atomicity here. Plain\n // count-then-remove, exactly as the un-guarded path did.\n const count = await this.repository.countBy({ userId: entity.userId });\n if (count <= 1 && !userHasOtherLogin) {\n return false;\n }\n\n await this.repository.remove(entity as IdentityProviderAccountEntity);\n return true;\n }\n\n // mysql / postgres: real concurrency. Lock the user's account rows,\n // count, and delete in one transaction so two concurrent unlinks for\n // the same user cannot both read > 1 and both delete.\n return this.dataSource.transaction(async (manager) => {\n const repository = manager.getRepository(IdentityProviderAccountEntity);\n\n const rows = await repository.createQueryBuilder('identityProviderAccount')\n .select(['identityProviderAccount.id'])\n .where('identityProviderAccount.userId = :userId', { userId: entity.userId })\n .setLock('pessimistic_write')\n .getMany();\n\n if (rows.length <= 1 && !userHasOtherLogin) {\n return false;\n }\n\n await repository.remove(entity as IdentityProviderAccountEntity);\n return true;\n });\n }\n\n async findOneByProviderIdentity(identity: IdentityProviderIdentity): Promise<IdentityProviderAccount | null> {\n return this.repository.findOne({\n where: {\n providerUserId: identity.id,\n providerId: identity.provider.id,\n },\n relations: { user: true },\n });\n }\n\n async save(entity: DeepPartial<IdentityProviderAccount>): Promise<IdentityProviderAccount> {\n try {\n return await this.repository.save(entity);\n } catch (e) {\n // one of the two unique indexes rejected the row: the identity\n // is already linked (issue #3442) or the user already holds a link\n // at this provider. The driver does not say which, so the manager\n // classifies after a re-read; here only the driver error is kept\n // from escaping as a 500.\n if (isUniqueConstraintDatabaseError(e)) {\n throw new EntityConflictError({ entity: 'identity provider account' });\n }\n\n throw e;\n }\n }\n\n async remove(entity: IdentityProviderAccount): Promise<void> {\n await this.repository.remove(entity as IdentityProviderAccountEntity);\n }\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,IAAaM,2CAAb,MAAaA;CACCC;CAEAC;CAEV,YAAYD,YAAwB;EAChC,KAAKA,aAAaA;EAClB,KAAKC,aAAaD,WAAWE,cAAcN,6BAAAA;CAC/C;CAEA,MAAMO,SACFC,OACAC,UAAkD,CAAC,GACa;EAChE,MAAMC,KAAK,KAAKL,WAAWM,mBAAmB,yBAAA;EAE9C,MAAM,EAAEC,eAAed,WAAWY,IAAIF,KAAAA;EAMtC,MAAMK,WAAW,IAAIC,IAAIJ,GAAGK,cAAcC,QAAQC,KAAKC,WAAWA,OAAOC,SAAS,CAAA;EAClF,MAAMC,aAAa,CAAC,UAAU,aAAc,CAAA,CACvCH,KAAKI,WAAW,2BAA2BA,QAAQ,CAAA,CACnDC,QAAQH,cAAc,CAACN,SAASU,IAAIJ,SAAAA,CAAAA;EACzC,IAAIC,WAAWI,SAAS,GACpBd,GAAGe,UAAUL,UAAAA;EAGjB,IAAIX,QAAQiB,QAERhB,GAAGiB,SAAS,iDAAiD,EAAEC,aAAanB,QAAQiB,OAAO,CAAA;EAG/F,IAAIjB,QAAQoB,SAGRnB,GAAGiB,SAAS,uDAAuD,EAAEG,cAAcrB,QAAQoB,QAAQ,CAAA;EAGvG,MAAM,CAACE,UAAUC,SAAS,MAAMtB,GAAGuB,gBAAe;EAElD,OAAO;GACHC,MAAMnC,sBAAsBS,OAAOuB,QAAAA;GACnCI,MAAM;IACFH;IACA,GAAGpB;GACP;EACJ;CACJ;CAEA,MAAMwB,YAAYC,IAAqD;EACnE,OAAO,KAAKhC,WAAWiC,UAAU,EAAED,GAAG,CAAA;CAC1C;CAEA,MAAME,cAAcC,QAAiCC,mBAA8C;EAC/F,IAAI,CAACvC,0BAA0B,KAAKE,WAAWK,QAAQiC,IAAI,GAAG;GAQ1D,IAAIC,MADgB,KAAKtC,WAAWuC,QAAQ,EAAElB,QAAQc,OAAOd,OAAO,CAAA,KACvD,KAAK,CAACe,mBACf,OAAO;GAGX,MAAM,KAAKpC,WAAWwC,OAAOL,MAAAA;GAC7B,OAAO;EACX;EAKA,OAAO,KAAKpC,WAAW0C,YAAY,OAAOC,YAAAA;GACtC,MAAM1C,aAAa0C,QAAQzC,cAAcN,6BAAAA;GAQzC,KAAIgD,MANe3C,WAAWM,mBAAmB,yBAAA,CAAA,CAC5CO,OAAO,CAAC,4BAA6B,CAAA,CAAA,CACrC+B,MAAM,4CAA4C,EAAEvB,QAAQc,OAAOd,OAAO,CAAA,CAAA,CAC1EwB,QAAQ,mBAAA,CAAA,CACRC,QAAO,EAAA,CAEH3B,UAAU,KAAK,CAACiB,mBACrB,OAAO;GAGX,MAAMpC,WAAWwC,OAAOL,MAAAA;GACxB,OAAO;EACX,CAAA;CACJ;CAEA,MAAMY,0BAA0BC,UAA6E;EACzG,OAAO,KAAKhD,WAAWiD,QAAQ;GAC3BL,OAAO;IACHM,gBAAgBF,SAAShB;IACzBmB,YAAYH,SAASI,SAASpB;GAClC;GACAqB,WAAW,EAAEC,MAAM,KAAK;EAC5B,CAAA;CACJ;CAEA,MAAMC,KAAKpB,QAAgF;EACvF,IAAI;GACA,OAAO,MAAM,KAAKnC,WAAWuD,KAAKpB,MAAAA;EACtC,SAASqB,GAAG;GAMR,IAAI5D,gCAAgC4D,CAAAA,GAChC,MAAM,IAAIhE,oBAAoB,EAAE2C,QAAQ,4BAA4B,CAAA;GAGxE,MAAMqB;EACV;CACJ;CAEA,MAAMhB,OAAOL,QAAgD;EACzD,MAAM,KAAKnC,WAAWwC,OAAOL,MAAAA;CACjC;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../../src/app/modules/http/modules/controller.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAoElC,OAAO,EACH,gBAAgB,EAChB,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,iCAAiC,EACjC,0BAA0B,EAC1B,qCAAqC,EACrC,aAAa,EACb,oBAAoB,EACpB,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,uBAAuB,EACvB,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,2BAA2B,EAC3B,cAAc,EACd,wBAAwB,EACxB,kBAAkB,EAErB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACH,iBAAiB,EACjB,kBAAkB,EAClB,gCAAgC,EAChC,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EACrB,MAAM,gDAAgD,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAMH,cAAc,EAOd,2BAA2B,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../../src/app/modules/http/modules/controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -58,6 +58,7 @@ import { IdentityProviderRoleMappingService } from "../../../../core/entities/id
|
|
|
58
58
|
import { OAuth2AccessPolicyEvaluator } from "../../../../core/oauth2/access-policy/module.mjs";
|
|
59
59
|
import { OAuth2ClientAuthenticator } from "../../../../core/oauth2/client/authenticator.mjs";
|
|
60
60
|
import { OAuth2EndSessionService } from "../../../../core/oauth2/end-session/service.mjs";
|
|
61
|
+
import { OAuth2FederatedLoginService } from "../../../../core/oauth2/federated-login/module.mjs";
|
|
61
62
|
import { OAuth2MfaLoginService } from "../../../../core/oauth2/mfa-login/module.mjs";
|
|
62
63
|
import { PasswordRecoveryService } from "../../../../core/identity/password-recovery/service.mjs";
|
|
63
64
|
import { PermissionCheckerService } from "../../../../core/identity/permission/checker/service.mjs";
|
|
@@ -439,7 +440,6 @@ var HTTPControllerModule = class {
|
|
|
439
440
|
const dataSource = container.resolve(DatabaseInjectionKey.DataSource);
|
|
440
441
|
const accountManager = container.resolve(IdentityInjectionKey.ProviderAccountManager);
|
|
441
442
|
const linkStore = container.resolve(IdentityInjectionKey.ProviderAccountLinkStore);
|
|
442
|
-
const codeIssuer = container.resolve(OAuth2InjectionToken.AuthorizationCodeIssuer);
|
|
443
443
|
const codeRequestVerifier = container.resolve(OAuth2InjectionToken.AuthorizationCodeRequestVerifier);
|
|
444
444
|
const stateManager = container.resolve(OAuth2InjectionToken.AuthorizationStateManager);
|
|
445
445
|
const realmRepository = container.resolve(RealmEntity);
|
|
@@ -447,18 +447,32 @@ var HTTPControllerModule = class {
|
|
|
447
447
|
repository: new IdentityProviderRepository(dataSource),
|
|
448
448
|
realmRepository
|
|
449
449
|
});
|
|
450
|
+
const logger = container.resolve(LoggerInjectionKey);
|
|
451
|
+
const eventService = container.resolve(DatabaseInjectionKey.EventService);
|
|
452
|
+
const loginService = new OAuth2FederatedLoginService({
|
|
453
|
+
options: { baseURL: config.publicUrl },
|
|
454
|
+
accountManager,
|
|
455
|
+
realmRepository: new RealmRepositoryAdapter(realmRepository),
|
|
456
|
+
codeRequestVerifier,
|
|
457
|
+
sessionManager: container.resolve(AuthenticationInjectionKey.SessionManager),
|
|
458
|
+
pendingLoginStore: container.resolve(OAuth2InjectionToken.FederatedLoginStore),
|
|
459
|
+
accessTokenIssuer: container.resolve(OAuth2InjectionToken.AccessTokenIssuer),
|
|
460
|
+
refreshTokenIssuer: container.resolve(OAuth2InjectionToken.RefreshTokenIssuer),
|
|
461
|
+
accessPolicyEvaluator: this.resolveAccessPolicyEvaluator(container),
|
|
462
|
+
eventService,
|
|
463
|
+
metrics: container.resolve(MetricsInjectionKey),
|
|
464
|
+
logger
|
|
465
|
+
});
|
|
450
466
|
return new IdentityProviderController({
|
|
451
467
|
options: { baseURL: config.publicUrl },
|
|
452
468
|
repository,
|
|
453
|
-
realmRepository: new RealmRepositoryAdapter(realmRepository),
|
|
454
469
|
accountManager,
|
|
455
470
|
linkStore,
|
|
456
|
-
codeIssuer,
|
|
457
471
|
codeRequestVerifier,
|
|
458
472
|
stateManager,
|
|
459
|
-
|
|
460
|
-
eventService
|
|
461
|
-
logger
|
|
473
|
+
loginService,
|
|
474
|
+
eventService,
|
|
475
|
+
logger
|
|
462
476
|
});
|
|
463
477
|
}
|
|
464
478
|
createClientController(container) {
|