@portaidentity/server 1.7.3 → 1.9.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/CHANGELOG.md +28 -0
- package/dist/applications/index.d.ts +2 -2
- package/dist/applications/index.d.ts.map +1 -1
- package/dist/applications/index.js +2 -2
- package/dist/applications/index.js.map +1 -1
- package/dist/applications/repository.d.ts +49 -4
- package/dist/applications/repository.d.ts.map +1 -1
- package/dist/applications/repository.js +148 -10
- package/dist/applications/repository.js.map +1 -1
- package/dist/applications/service.d.ts +35 -17
- package/dist/applications/service.d.ts.map +1 -1
- package/dist/applications/service.js +144 -35
- package/dist/applications/service.js.map +1 -1
- package/dist/applications/types.d.ts +1 -1
- package/dist/applications/types.d.ts.map +1 -1
- package/dist/applications/validators.d.ts +14 -0
- package/dist/applications/validators.d.ts.map +1 -0
- package/dist/applications/validators.js +14 -0
- package/dist/applications/validators.js.map +1 -0
- package/dist/auth/effective-branding.d.ts +35 -0
- package/dist/auth/effective-branding.d.ts.map +1 -0
- package/dist/auth/effective-branding.js +81 -0
- package/dist/auth/effective-branding.js.map +1 -0
- package/dist/auth/email-service.d.ts +3 -8
- package/dist/auth/email-service.d.ts.map +1 -1
- package/dist/auth/email-service.js +22 -30
- package/dist/auth/email-service.js.map +1 -1
- package/dist/auth/i18n.d.ts +5 -0
- package/dist/auth/i18n.d.ts.map +1 -1
- package/dist/auth/i18n.js +6 -5
- package/dist/auth/i18n.js.map +1 -1
- package/dist/auth/rate-limiter.d.ts +6 -10
- package/dist/auth/rate-limiter.d.ts.map +1 -1
- package/dist/auth/rate-limiter.js +12 -16
- package/dist/auth/rate-limiter.js.map +1 -1
- package/dist/auth/recovery-job-processor.d.ts.map +1 -1
- package/dist/auth/recovery-job-processor.js +1 -1
- package/dist/auth/recovery-job-processor.js.map +1 -1
- package/dist/auth/template-engine.d.ts +3 -1
- package/dist/auth/template-engine.d.ts.map +1 -1
- package/dist/auth/template-engine.js +1 -1
- package/dist/auth/template-engine.js.map +1 -1
- package/dist/auth/token-repository.d.ts +9 -3
- package/dist/auth/token-repository.d.ts.map +1 -1
- package/dist/auth/token-repository.js +17 -8
- package/dist/auth/token-repository.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -12
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/error-handler.d.ts +3 -2
- package/dist/cli/error-handler.d.ts.map +1 -1
- package/dist/cli/error-handler.js +9 -2
- package/dist/cli/error-handler.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/clients/index.d.ts +1 -1
- package/dist/clients/index.js +1 -1
- package/dist/clients/repository.d.ts +24 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +39 -0
- package/dist/clients/repository.js.map +1 -1
- package/dist/clients/secret-repository.d.ts +35 -8
- package/dist/clients/secret-repository.d.ts.map +1 -1
- package/dist/clients/secret-repository.js +69 -16
- package/dist/clients/secret-repository.js.map +1 -1
- package/dist/clients/secret-service.d.ts +5 -9
- package/dist/clients/secret-service.d.ts.map +1 -1
- package/dist/clients/secret-service.js +13 -22
- package/dist/clients/secret-service.js.map +1 -1
- package/dist/clients/service.d.ts +10 -13
- package/dist/clients/service.d.ts.map +1 -1
- package/dist/clients/service.js +121 -42
- package/dist/clients/service.js.map +1 -1
- package/dist/clients/types.d.ts +14 -1
- package/dist/clients/types.d.ts.map +1 -1
- package/dist/clients/types.js +1 -0
- package/dist/clients/types.js.map +1 -1
- package/dist/clients/validators.d.ts +83 -1
- package/dist/clients/validators.d.ts.map +1 -1
- package/dist/clients/validators.js +110 -0
- package/dist/clients/validators.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +23 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/custom-claims/repository.d.ts +14 -9
- package/dist/custom-claims/repository.d.ts.map +1 -1
- package/dist/custom-claims/repository.js +38 -11
- package/dist/custom-claims/repository.js.map +1 -1
- package/dist/custom-claims/service.d.ts +11 -6
- package/dist/custom-claims/service.d.ts.map +1 -1
- package/dist/custom-claims/service.js +43 -20
- package/dist/custom-claims/service.js.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/admin-permissions.d.ts +12 -7
- package/dist/lib/admin-permissions.d.ts.map +1 -1
- package/dist/lib/admin-permissions.js +26 -16
- package/dist/lib/admin-permissions.js.map +1 -1
- package/dist/lib/audit-log.d.ts +2 -2
- package/dist/lib/audit-log.d.ts.map +1 -1
- package/dist/lib/audit-log.js +1 -1
- package/dist/lib/audit-log.js.map +1 -1
- package/dist/lib/authority-revocation.d.ts +18 -0
- package/dist/lib/authority-revocation.d.ts.map +1 -0
- package/dist/lib/authority-revocation.js +37 -0
- package/dist/lib/authority-revocation.js.map +1 -0
- package/dist/lib/branding-assets.d.ts +35 -5
- package/dist/lib/branding-assets.d.ts.map +1 -1
- package/dist/lib/branding-assets.js +33 -26
- package/dist/lib/branding-assets.js.map +1 -1
- package/dist/lib/bulk-operations.d.ts +1 -1
- package/dist/lib/bulk-operations.d.ts.map +1 -1
- package/dist/lib/bulk-operations.js +1 -13
- package/dist/lib/bulk-operations.js.map +1 -1
- package/dist/lib/cursor.d.ts +2 -0
- package/dist/lib/cursor.d.ts.map +1 -1
- package/dist/lib/cursor.js +2 -7
- package/dist/lib/cursor.js.map +1 -1
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +5 -0
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/deletion-cleanup.d.ts +43 -0
- package/dist/lib/deletion-cleanup.d.ts.map +1 -0
- package/dist/lib/deletion-cleanup.js +207 -0
- package/dist/lib/deletion-cleanup.js.map +1 -0
- package/dist/lib/image-validator.d.ts +3 -1
- package/dist/lib/image-validator.d.ts.map +1 -1
- package/dist/lib/image-validator.js +32 -19
- package/dist/lib/image-validator.js.map +1 -1
- package/dist/lib/log-format.d.ts +20 -0
- package/dist/lib/log-format.d.ts.map +1 -0
- package/dist/lib/log-format.js +22 -0
- package/dist/lib/log-format.js.map +1 -0
- package/dist/lib/logger.d.ts +3 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +21 -4
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/redis.d.ts.map +1 -1
- package/dist/lib/redis.js +3 -0
- package/dist/lib/redis.js.map +1 -1
- package/dist/lib/session-tracking.d.ts +73 -11
- package/dist/lib/session-tracking.d.ts.map +1 -1
- package/dist/lib/session-tracking.js +76 -32
- package/dist/lib/session-tracking.js.map +1 -1
- package/dist/lib/signing-key-crypto.d.ts.map +1 -1
- package/dist/lib/signing-key-crypto.js +4 -5
- package/dist/lib/signing-key-crypto.js.map +1 -1
- package/dist/lib/signing-keys.d.ts +3 -4
- package/dist/lib/signing-keys.d.ts.map +1 -1
- package/dist/lib/signing-keys.js +66 -41
- package/dist/lib/signing-keys.js.map +1 -1
- package/dist/lib/super-admin-protection.d.ts +5 -5
- package/dist/lib/super-admin-protection.d.ts.map +1 -1
- package/dist/lib/super-admin-protection.js +6 -9
- package/dist/lib/super-admin-protection.js.map +1 -1
- package/dist/lib/system-config-catalog.d.ts +268 -0
- package/dist/lib/system-config-catalog.d.ts.map +1 -0
- package/dist/lib/system-config-catalog.js +90 -0
- package/dist/lib/system-config-catalog.js.map +1 -0
- package/dist/lib/system-config.d.ts +30 -33
- package/dist/lib/system-config.d.ts.map +1 -1
- package/dist/lib/system-config.js +78 -93
- package/dist/lib/system-config.js.map +1 -1
- package/dist/lib/with-timeout.d.ts +32 -0
- package/dist/lib/with-timeout.d.ts.map +1 -0
- package/dist/lib/with-timeout.js +45 -0
- package/dist/lib/with-timeout.js.map +1 -0
- package/dist/middleware/admin-auth.d.ts +6 -5
- package/dist/middleware/admin-auth.d.ts.map +1 -1
- package/dist/middleware/admin-auth.js +30 -20
- package/dist/middleware/admin-auth.js.map +1 -1
- package/dist/middleware/admin-cors.d.ts +3 -3
- package/dist/middleware/admin-cors.js +3 -3
- package/dist/middleware/admin-mutation-audit.d.ts +3 -2
- package/dist/middleware/admin-mutation-audit.d.ts.map +1 -1
- package/dist/middleware/admin-mutation-audit.js +12 -5
- package/dist/middleware/admin-mutation-audit.js.map +1 -1
- package/dist/middleware/admin-rate-limiter.d.ts +7 -8
- package/dist/middleware/admin-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/admin-rate-limiter.js +7 -8
- package/dist/middleware/admin-rate-limiter.js.map +1 -1
- package/dist/middleware/client-secret-hash.d.ts +10 -29
- package/dist/middleware/client-secret-hash.d.ts.map +1 -1
- package/dist/middleware/client-secret-hash.js +161 -59
- package/dist/middleware/client-secret-hash.js.map +1 -1
- package/dist/middleware/health.d.ts +17 -0
- package/dist/middleware/health.d.ts.map +1 -1
- package/dist/middleware/health.js +25 -21
- package/dist/middleware/health.js.map +1 -1
- package/dist/middleware/ready.d.ts.map +1 -1
- package/dist/middleware/ready.js +1 -12
- package/dist/middleware/ready.js.map +1 -1
- package/dist/middleware/require-existing-organization.d.ts +18 -0
- package/dist/middleware/require-existing-organization.d.ts.map +1 -0
- package/dist/middleware/require-existing-organization.js +38 -0
- package/dist/middleware/require-existing-organization.js.map +1 -0
- package/dist/middleware/require-permission.d.ts.map +1 -1
- package/dist/middleware/require-permission.js +35 -1
- package/dist/middleware/require-permission.js.map +1 -1
- package/dist/middleware/require-user-organization.d.ts.map +1 -1
- package/dist/middleware/require-user-organization.js +4 -2
- package/dist/middleware/require-user-organization.js.map +1 -1
- package/dist/middleware/security-headers.d.ts +18 -0
- package/dist/middleware/security-headers.d.ts.map +1 -1
- package/dist/middleware/security-headers.js +32 -1
- package/dist/middleware/security-headers.js.map +1 -1
- package/dist/middleware/tenant-resolver.d.ts +1 -2
- package/dist/middleware/tenant-resolver.d.ts.map +1 -1
- package/dist/middleware/tenant-resolver.js +1 -5
- package/dist/middleware/tenant-resolver.js.map +1 -1
- package/dist/middleware/token-rate-limiter.d.ts +37 -16
- package/dist/middleware/token-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/token-rate-limiter.js +126 -54
- package/dist/middleware/token-rate-limiter.js.map +1 -1
- package/dist/oidc/account-finder.d.ts +5 -5
- package/dist/oidc/account-finder.d.ts.map +1 -1
- package/dist/oidc/account-finder.js +31 -23
- package/dist/oidc/account-finder.js.map +1 -1
- package/dist/oidc/adapter-factory.d.ts.map +1 -1
- package/dist/oidc/adapter-factory.js +83 -3
- package/dist/oidc/adapter-factory.js.map +1 -1
- package/dist/oidc/configuration.d.ts +3 -8
- package/dist/oidc/configuration.d.ts.map +1 -1
- package/dist/oidc/configuration.js +67 -50
- package/dist/oidc/configuration.js.map +1 -1
- package/dist/oidc/provider.d.ts.map +1 -1
- package/dist/oidc/provider.js +7 -0
- package/dist/oidc/provider.js.map +1 -1
- package/dist/oidc/redis-adapter.d.ts +2 -3
- package/dist/oidc/redis-adapter.d.ts.map +1 -1
- package/dist/oidc/redis-adapter.js +54 -46
- package/dist/oidc/redis-adapter.js.map +1 -1
- package/dist/organizations/branding-url.d.ts +17 -0
- package/dist/organizations/branding-url.d.ts.map +1 -0
- package/dist/organizations/branding-url.js +38 -0
- package/dist/organizations/branding-url.js.map +1 -0
- package/dist/organizations/index.d.ts +2 -2
- package/dist/organizations/index.d.ts.map +1 -1
- package/dist/organizations/index.js +1 -1
- package/dist/organizations/index.js.map +1 -1
- package/dist/organizations/repository.d.ts +22 -32
- package/dist/organizations/repository.d.ts.map +1 -1
- package/dist/organizations/repository.js +64 -45
- package/dist/organizations/repository.js.map +1 -1
- package/dist/organizations/service.d.ts +14 -46
- package/dist/organizations/service.d.ts.map +1 -1
- package/dist/organizations/service.js +60 -112
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/types.d.ts +1 -15
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/organizations/validators.d.ts +41 -0
- package/dist/organizations/validators.d.ts.map +1 -0
- package/dist/organizations/validators.js +48 -0
- package/dist/organizations/validators.js.map +1 -0
- package/dist/portability/apply.d.ts +15 -0
- package/dist/portability/apply.d.ts.map +1 -0
- package/dist/portability/apply.js +274 -0
- package/dist/portability/apply.js.map +1 -0
- package/dist/portability/authorization.d.ts +30 -0
- package/dist/portability/authorization.d.ts.map +1 -0
- package/dist/portability/authorization.js +130 -0
- package/dist/portability/authorization.js.map +1 -0
- package/dist/portability/cleanup.d.ts +29 -0
- package/dist/portability/cleanup.d.ts.map +1 -0
- package/dist/portability/cleanup.js +167 -0
- package/dist/portability/cleanup.js.map +1 -0
- package/dist/portability/export.d.ts +18 -0
- package/dist/portability/export.d.ts.map +1 -0
- package/dist/portability/export.js +125 -0
- package/dist/portability/export.js.map +1 -0
- package/dist/portability/import-repository.d.ts +204 -0
- package/dist/portability/import-repository.d.ts.map +1 -0
- package/dist/portability/import-repository.js +348 -0
- package/dist/portability/import-repository.js.map +1 -0
- package/dist/portability/import-user-client-writers.d.ts +40 -0
- package/dist/portability/import-user-client-writers.d.ts.map +1 -0
- package/dist/portability/import-user-client-writers.js +171 -0
- package/dist/portability/import-user-client-writers.js.map +1 -0
- package/dist/portability/index.d.ts +8 -0
- package/dist/portability/index.d.ts.map +1 -0
- package/dist/portability/index.js +8 -0
- package/dist/portability/index.js.map +1 -0
- package/dist/portability/plan-support.d.ts +137 -0
- package/dist/portability/plan-support.d.ts.map +1 -0
- package/dist/portability/plan-support.js +337 -0
- package/dist/portability/plan-support.js.map +1 -0
- package/dist/portability/plan.d.ts +34 -0
- package/dist/portability/plan.d.ts.map +1 -0
- package/dist/portability/plan.js +450 -0
- package/dist/portability/plan.js.map +1 -0
- package/dist/portability/repository.d.ts +95 -0
- package/dist/portability/repository.d.ts.map +1 -0
- package/dist/portability/repository.js +390 -0
- package/dist/portability/repository.js.map +1 -0
- package/dist/portability/schema.d.ts +591 -0
- package/dist/portability/schema.d.ts.map +1 -0
- package/dist/portability/schema.js +459 -0
- package/dist/portability/schema.js.map +1 -0
- package/dist/portability/types.d.ts +382 -0
- package/dist/portability/types.d.ts.map +1 -0
- package/dist/portability/types.js +19 -0
- package/dist/portability/types.js.map +1 -0
- package/dist/rbac/errors.d.ts +4 -0
- package/dist/rbac/errors.d.ts.map +1 -1
- package/dist/rbac/errors.js +7 -0
- package/dist/rbac/errors.js.map +1 -1
- package/dist/rbac/index.d.ts +3 -3
- package/dist/rbac/index.d.ts.map +1 -1
- package/dist/rbac/index.js +3 -3
- package/dist/rbac/index.js.map +1 -1
- package/dist/rbac/mapping-repository.d.ts +84 -9
- package/dist/rbac/mapping-repository.d.ts.map +1 -1
- package/dist/rbac/mapping-repository.js +222 -55
- package/dist/rbac/mapping-repository.js.map +1 -1
- package/dist/rbac/permission-repository.d.ts +36 -19
- package/dist/rbac/permission-repository.d.ts.map +1 -1
- package/dist/rbac/permission-repository.js +93 -35
- package/dist/rbac/permission-repository.js.map +1 -1
- package/dist/rbac/permission-service.d.ts +18 -19
- package/dist/rbac/permission-service.d.ts.map +1 -1
- package/dist/rbac/permission-service.js +100 -57
- package/dist/rbac/permission-service.js.map +1 -1
- package/dist/rbac/role-repository.d.ts +29 -24
- package/dist/rbac/role-repository.d.ts.map +1 -1
- package/dist/rbac/role-repository.js +66 -43
- package/dist/rbac/role-repository.js.map +1 -1
- package/dist/rbac/role-service.d.ts +35 -32
- package/dist/rbac/role-service.d.ts.map +1 -1
- package/dist/rbac/role-service.js +210 -96
- package/dist/rbac/role-service.js.map +1 -1
- package/dist/rbac/slugs.d.ts +16 -27
- package/dist/rbac/slugs.d.ts.map +1 -1
- package/dist/rbac/slugs.js +36 -59
- package/dist/rbac/slugs.js.map +1 -1
- package/dist/rbac/types.d.ts +2 -4
- package/dist/rbac/types.d.ts.map +1 -1
- package/dist/rbac/types.js.map +1 -1
- package/dist/rbac/user-role-service.d.ts +23 -24
- package/dist/rbac/user-role-service.d.ts.map +1 -1
- package/dist/rbac/user-role-service.js +117 -61
- package/dist/rbac/user-role-service.js.map +1 -1
- package/dist/routes/applications.d.ts +4 -2
- package/dist/routes/applications.d.ts.map +1 -1
- package/dist/routes/applications.js +57 -19
- package/dist/routes/applications.js.map +1 -1
- package/dist/routes/audit.js +1 -1
- package/dist/routes/audit.js.map +1 -1
- package/dist/routes/branding.d.ts +3 -3
- package/dist/routes/branding.d.ts.map +1 -1
- package/dist/routes/branding.js +44 -16
- package/dist/routes/branding.js.map +1 -1
- package/dist/routes/bulk.d.ts +0 -5
- package/dist/routes/bulk.d.ts.map +1 -1
- package/dist/routes/bulk.js +3 -5
- package/dist/routes/bulk.js.map +1 -1
- package/dist/routes/clients.d.ts +4 -4
- package/dist/routes/clients.d.ts.map +1 -1
- package/dist/routes/clients.js +113 -52
- package/dist/routes/clients.js.map +1 -1
- package/dist/routes/config.d.ts +17 -12
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +165 -64
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/custom-claims.d.ts.map +1 -1
- package/dist/routes/custom-claims.js +8 -2
- package/dist/routes/custom-claims.js.map +1 -1
- package/dist/routes/exports.d.ts +2 -1
- package/dist/routes/exports.d.ts.map +1 -1
- package/dist/routes/exports.js +57 -1
- package/dist/routes/exports.js.map +1 -1
- package/dist/routes/imports.d.ts +2 -2
- package/dist/routes/imports.d.ts.map +1 -1
- package/dist/routes/imports.js +95 -40
- package/dist/routes/imports.js.map +1 -1
- package/dist/routes/interactions.d.ts.map +1 -1
- package/dist/routes/interactions.js +113 -87
- package/dist/routes/interactions.js.map +1 -1
- package/dist/routes/invitation.d.ts.map +1 -1
- package/dist/routes/invitation.js +28 -27
- package/dist/routes/invitation.js.map +1 -1
- package/dist/routes/keys.d.ts.map +1 -1
- package/dist/routes/keys.js +26 -13
- package/dist/routes/keys.js.map +1 -1
- package/dist/routes/magic-link.d.ts.map +1 -1
- package/dist/routes/magic-link.js +5 -17
- package/dist/routes/magic-link.js.map +1 -1
- package/dist/routes/organizations.d.ts +1 -2
- package/dist/routes/organizations.d.ts.map +1 -1
- package/dist/routes/organizations.js +43 -104
- package/dist/routes/organizations.js.map +1 -1
- package/dist/routes/password-reset.d.ts.map +1 -1
- package/dist/routes/password-reset.js +13 -35
- package/dist/routes/password-reset.js.map +1 -1
- package/dist/routes/permissions.d.ts +1 -1
- package/dist/routes/permissions.d.ts.map +1 -1
- package/dist/routes/permissions.js +58 -17
- package/dist/routes/permissions.js.map +1 -1
- package/dist/routes/public-branding.d.ts +16 -0
- package/dist/routes/public-branding.d.ts.map +1 -0
- package/dist/routes/public-branding.js +52 -0
- package/dist/routes/public-branding.js.map +1 -0
- package/dist/routes/roles.d.ts +1 -1
- package/dist/routes/roles.d.ts.map +1 -1
- package/dist/routes/roles.js +63 -21
- package/dist/routes/roles.js.map +1 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +23 -12
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/two-factor.d.ts.map +1 -1
- package/dist/routes/two-factor.js +91 -38
- package/dist/routes/two-factor.js.map +1 -1
- package/dist/routes/user-roles.d.ts.map +1 -1
- package/dist/routes/user-roles.js +56 -9
- package/dist/routes/user-roles.js.map +1 -1
- package/dist/routes/users.d.ts +4 -8
- package/dist/routes/users.d.ts.map +1 -1
- package/dist/routes/users.js +108 -265
- package/dist/routes/users.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53 -37
- package/dist/server.js.map +1 -1
- package/dist/two-factor/errors.d.ts +9 -0
- package/dist/two-factor/errors.d.ts.map +1 -1
- package/dist/two-factor/errors.js +12 -0
- package/dist/two-factor/errors.js.map +1 -1
- package/dist/two-factor/index.d.ts +5 -4
- package/dist/two-factor/index.d.ts.map +1 -1
- package/dist/two-factor/index.js +4 -4
- package/dist/two-factor/index.js.map +1 -1
- package/dist/two-factor/repository.d.ts +17 -6
- package/dist/two-factor/repository.d.ts.map +1 -1
- package/dist/two-factor/repository.js +37 -9
- package/dist/two-factor/repository.js.map +1 -1
- package/dist/two-factor/service.d.ts.map +1 -1
- package/dist/two-factor/service.js +26 -19
- package/dist/two-factor/service.js.map +1 -1
- package/dist/two-factor/totp.d.ts +13 -2
- package/dist/two-factor/totp.d.ts.map +1 -1
- package/dist/two-factor/totp.js +20 -7
- package/dist/two-factor/totp.js.map +1 -1
- package/dist/two-factor/types.d.ts +3 -0
- package/dist/two-factor/types.d.ts.map +1 -1
- package/dist/two-factor/types.js +5 -0
- package/dist/two-factor/types.js.map +1 -1
- package/dist/users/gdpr.d.ts +2 -40
- package/dist/users/gdpr.d.ts.map +1 -1
- package/dist/users/gdpr.js +3 -110
- package/dist/users/gdpr.js.map +1 -1
- package/dist/users/index.d.ts +5 -4
- package/dist/users/index.d.ts.map +1 -1
- package/dist/users/index.js +5 -4
- package/dist/users/index.js.map +1 -1
- package/dist/users/repository.d.ts +49 -3
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +169 -18
- package/dist/users/repository.js.map +1 -1
- package/dist/users/service.d.ts +19 -51
- package/dist/users/service.d.ts.map +1 -1
- package/dist/users/service.js +72 -122
- package/dist/users/service.js.map +1 -1
- package/dist/users/types.d.ts +4 -5
- package/dist/users/types.d.ts.map +1 -1
- package/dist/users/types.js.map +1 -1
- package/dist/users/validators.d.ts +28 -0
- package/dist/users/validators.d.ts.map +1 -0
- package/dist/users/validators.js +25 -0
- package/dist/users/validators.js.map +1 -0
- package/locales/default/en/errors.json +2 -1
- package/migrations/024_application_client_correction.sql +39 -0
- package/migrations/025_record_deletion_lifecycle.sql +26 -0
- package/migrations/026_simplify_user_lifecycle.sql +33 -0
- package/migrations/027_branding_asset_size_limits.sql +19 -0
- package/migrations/028_totp_replay_protection.sql +17 -0
- package/migrations/029_public_session_identifiers.sql +16 -0
- package/migrations/030_global_configuration_catalog.sql +39 -0
- package/migrations/031_monotonic_updated_at.sql +28 -0
- package/migrations/032_client_require_consent.sql +15 -0
- package/package.json +2 -2
- package/dist/lib/data-import-plan.d.ts +0 -50
- package/dist/lib/data-import-plan.d.ts.map +0 -1
- package/dist/lib/data-import-plan.js +0 -235
- package/dist/lib/data-import-plan.js.map +0 -1
- package/dist/lib/data-import.d.ts +0 -276
- package/dist/lib/data-import.d.ts.map +0 -1
- package/dist/lib/data-import.js +0 -1694
- package/dist/lib/data-import.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-repository.d.ts","sourceRoot":"","sources":["../../src/clients/secret-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"secret-repository.d.ts","sourceRoot":"","sources":["../../src/clients/secret-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAC;AAOhE,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uEAAuE;IACvE,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CA6BhF;AAMD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CASnF;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU/F;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAa9C;AAMD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAY7F;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhE;AAMD;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAWvF;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBpF;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAY9C;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1E"}
|
|
@@ -10,26 +10,45 @@
|
|
|
10
10
|
* - Insert hashed secret
|
|
11
11
|
* - List secrets (metadata only, no hashes)
|
|
12
12
|
* - Find active secrets with hashes (for verification only)
|
|
13
|
-
* -
|
|
13
|
+
* - Permanently delete secrets
|
|
14
14
|
* - Update last_used_at timestamp
|
|
15
15
|
* - Cleanup expired secrets
|
|
16
16
|
*/
|
|
17
|
-
import { getPool } from '../lib/database.js';
|
|
17
|
+
import { getPool, runDatabaseTransaction } from '../lib/database.js';
|
|
18
|
+
import { ClientNotFoundError, ClientValidationError } from './errors.js';
|
|
18
19
|
import { mapRowToClientSecret } from './types.js';
|
|
19
20
|
/**
|
|
20
21
|
* Insert a new client secret.
|
|
21
22
|
*
|
|
22
|
-
* Stores the Argon2id hash — never the plaintext.
|
|
23
|
+
* Stores the Argon2id hash — never the plaintext. The client row is locked while
|
|
24
|
+
* counting and inserting so concurrent callers cannot exceed ten active,
|
|
25
|
+
* unexpired secrets.
|
|
23
26
|
*
|
|
24
27
|
* @param data - Secret data including the hash
|
|
25
28
|
* @returns The created secret metadata (without hash)
|
|
29
|
+
* @throws ClientNotFoundError when the client is absent or public
|
|
30
|
+
* @throws ClientValidationError when the client already has ten active secrets
|
|
26
31
|
*/
|
|
27
32
|
export async function insertSecret(data) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
return runDatabaseTransaction(async () => {
|
|
34
|
+
const db = getPool();
|
|
35
|
+
const parent = await db.query('SELECT id, client_type, status FROM clients WHERE id = $1 FOR UPDATE', [data.clientId]);
|
|
36
|
+
const eligible = parent.rows[0];
|
|
37
|
+
if (eligible === undefined || eligible.client_type !== 'confidential') {
|
|
38
|
+
throw new ClientNotFoundError(data.clientId);
|
|
39
|
+
}
|
|
40
|
+
const active = await db.query(`SELECT COUNT(*)::text AS count FROM client_secrets
|
|
41
|
+
WHERE client_id = $1
|
|
42
|
+
AND status = 'active'
|
|
43
|
+
AND (expires_at IS NULL OR expires_at > NOW())`, [data.clientId]);
|
|
44
|
+
if (Number(active.rows[0]?.count ?? '0') >= 10) {
|
|
45
|
+
throw new ClientValidationError('Client secret active limit reached');
|
|
46
|
+
}
|
|
47
|
+
const result = await db.query(`INSERT INTO client_secrets (client_id, secret_hash, secret_sha256, label, expires_at)
|
|
48
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
49
|
+
RETURNING *`, [data.clientId, data.secretHash, data.secretSha256, data.label, data.expiresAt]);
|
|
50
|
+
return mapRowToClientSecret(result.rows[0]);
|
|
51
|
+
});
|
|
33
52
|
}
|
|
34
53
|
// ===========================================================================
|
|
35
54
|
// Find / List
|
|
@@ -48,12 +67,13 @@ export async function listSecretsByClient(clientId) {
|
|
|
48
67
|
/**
|
|
49
68
|
* Find a specific secret by ID.
|
|
50
69
|
*
|
|
70
|
+
* @param clientId - Authoritative parent client UUID
|
|
51
71
|
* @param id - Secret UUID
|
|
52
72
|
* @returns Secret metadata or null
|
|
53
73
|
*/
|
|
54
|
-
export async function findSecretById(id) {
|
|
74
|
+
export async function findSecretById(clientId, id) {
|
|
55
75
|
const pool = getPool();
|
|
56
|
-
const result = await pool.query('SELECT * FROM client_secrets WHERE id = $
|
|
76
|
+
const result = await pool.query('SELECT * FROM client_secrets WHERE client_id = $1 AND id = $2', [clientId, id]);
|
|
57
77
|
if (result.rows.length === 0)
|
|
58
78
|
return null;
|
|
59
79
|
return mapRowToClientSecret(result.rows[0]);
|
|
@@ -81,16 +101,17 @@ export async function getActiveSecretHashes(clientId) {
|
|
|
81
101
|
// Update
|
|
82
102
|
// ===========================================================================
|
|
83
103
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* This is a permanent operation — revoked secrets cannot be reactivated.
|
|
104
|
+
* Permanently delete a secret.
|
|
87
105
|
*
|
|
106
|
+
* @param clientId - Authoritative parent client UUID
|
|
88
107
|
* @param id - Secret UUID
|
|
89
|
-
* @returns
|
|
108
|
+
* @returns Deleted secret metadata, or null if absent or owned by another client
|
|
90
109
|
*/
|
|
91
|
-
export async function revokeSecret(id) {
|
|
110
|
+
export async function revokeSecret(clientId, id) {
|
|
92
111
|
const pool = getPool();
|
|
93
|
-
const result = await pool.query(`
|
|
112
|
+
const result = await pool.query(`DELETE FROM client_secrets
|
|
113
|
+
WHERE client_id = $1 AND id = $2
|
|
114
|
+
RETURNING *`, [clientId, id]);
|
|
94
115
|
if (result.rows.length === 0)
|
|
95
116
|
return null;
|
|
96
117
|
return mapRowToClientSecret(result.rows[0]);
|
|
@@ -149,6 +170,38 @@ export async function getLatestActiveSha256(clientId) {
|
|
|
149
170
|
return null;
|
|
150
171
|
return result.rows[0].secret_sha256;
|
|
151
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Find an active modern secret by its indexed SHA-256 value.
|
|
175
|
+
*
|
|
176
|
+
* @param clientId - Parent client UUID
|
|
177
|
+
* @param secretSha256 - SHA-256 digest of the presented credential
|
|
178
|
+
* @returns Matching secret ID, or null when no active credential matches
|
|
179
|
+
*/
|
|
180
|
+
export async function findActiveSecretIdBySha256(clientId, secretSha256) {
|
|
181
|
+
const result = await getPool().query(`SELECT id FROM client_secrets
|
|
182
|
+
WHERE client_id = $1
|
|
183
|
+
AND secret_sha256 = $2
|
|
184
|
+
AND status = 'active'
|
|
185
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
186
|
+
LIMIT 1`, [clientId, secretSha256]);
|
|
187
|
+
return result.rows[0]?.id ?? null;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Load at most eleven active Argon2-only credentials so callers can reject over-limit data.
|
|
191
|
+
*
|
|
192
|
+
* @param clientId - Parent client UUID
|
|
193
|
+
* @returns Active legacy secret identifiers and hashes, newest first
|
|
194
|
+
*/
|
|
195
|
+
export async function getActiveLegacySecretHashes(clientId) {
|
|
196
|
+
const result = await getPool().query(`SELECT id, secret_hash FROM client_secrets
|
|
197
|
+
WHERE client_id = $1
|
|
198
|
+
AND secret_sha256 IS NULL
|
|
199
|
+
AND status = 'active'
|
|
200
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
201
|
+
ORDER BY created_at DESC
|
|
202
|
+
LIMIT 11`, [clientId]);
|
|
203
|
+
return result.rows.map((row) => ({ id: row.id, hash: row.secret_hash }));
|
|
204
|
+
}
|
|
152
205
|
/**
|
|
153
206
|
* Count active secrets for a client.
|
|
154
207
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-repository.js","sourceRoot":"","sources":["../../src/clients/secret-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-repository.js","sourceRoot":"","sources":["../../src/clients/secret-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles the full lifecycle of OIDC client secrets:
|
|
5
5
|
* - Generate and store new secrets (Argon2id hashed)
|
|
6
6
|
* - Verify secrets during token endpoint authentication
|
|
7
|
-
* -
|
|
7
|
+
* - Delete secrets permanently
|
|
8
8
|
* - List secrets (metadata only, never hashes)
|
|
9
9
|
* - Cleanup expired secrets
|
|
10
10
|
*
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* This service is consumed by:
|
|
19
19
|
* - The client service (initial secret on confidential client creation)
|
|
20
|
-
* - The API routes (secret
|
|
20
|
+
* - The API routes (secret creation and deletion)
|
|
21
21
|
* - The OIDC token endpoint (secret verification via admin API)
|
|
22
22
|
*/
|
|
23
23
|
import type { ClientSecret, SecretWithPlaintext, CreateSecretInput } from './types.js';
|
|
@@ -55,18 +55,14 @@ export declare function generateAndStore(clientDbId: string, input?: CreateSecre
|
|
|
55
55
|
*/
|
|
56
56
|
export declare function verify(clientDbId: string, plaintext: string): Promise<boolean>;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Revocation is irreversible — once revoked, a secret cannot be
|
|
61
|
-
* reactivated. The revoked secret remains in the database for
|
|
62
|
-
* audit trail purposes until cleanup removes it.
|
|
58
|
+
* Permanently delete a client secret.
|
|
63
59
|
*
|
|
60
|
+
* @param clientDbId - Authoritative parent client UUID
|
|
64
61
|
* @param secretId - Secret UUID
|
|
65
62
|
* @param actorId - UUID of the user performing the action
|
|
66
63
|
* @throws ClientNotFoundError if secret not found
|
|
67
|
-
* @throws ClientValidationError if secret already revoked
|
|
68
64
|
*/
|
|
69
|
-
export declare function revoke(secretId: string, actorId?: string): Promise<void>;
|
|
65
|
+
export declare function revoke(clientDbId: string, secretId: string, actorId?: string): Promise<void>;
|
|
70
66
|
/**
|
|
71
67
|
* List all secrets for a client (metadata only, never hashes).
|
|
72
68
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-service.d.ts","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAmBvF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,iBAAsB,EAC7B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,CAAC,CAyC9B;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,MAAM,
|
|
1
|
+
{"version":3,"file":"secret-service.d.ts","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAmBvF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,iBAAsB,EAC7B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,CAAC,CAyC9B;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAyCpF;AAMD;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAC1B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiBf;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAE9E;AAMD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5E"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles the full lifecycle of OIDC client secrets:
|
|
5
5
|
* - Generate and store new secrets (Argon2id hashed)
|
|
6
6
|
* - Verify secrets during token endpoint authentication
|
|
7
|
-
* -
|
|
7
|
+
* - Delete secrets permanently
|
|
8
8
|
* - List secrets (metadata only, never hashes)
|
|
9
9
|
* - Cleanup expired secrets
|
|
10
10
|
*
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
*
|
|
18
18
|
* This service is consumed by:
|
|
19
19
|
* - The client service (initial secret on confidential client creation)
|
|
20
|
-
* - The API routes (secret
|
|
20
|
+
* - The API routes (secret creation and deletion)
|
|
21
21
|
* - The OIDC token endpoint (secret verification via admin API)
|
|
22
22
|
*/
|
|
23
23
|
import { insertSecret, listSecretsByClient, findSecretById, getActiveSecretHashes, revokeSecret as repoRevokeSecret, updateLastUsedAt, cleanupExpiredSecrets, } from './secret-repository.js';
|
|
24
24
|
import { generateSecret, hashSecret, sha256Secret, verifySecretHash } from './crypto.js';
|
|
25
25
|
import { writeAuditLog } from '../lib/audit-log.js';
|
|
26
26
|
import { logger } from '../lib/logger.js';
|
|
27
|
-
import { ClientNotFoundError
|
|
27
|
+
import { ClientNotFoundError } from './errors.js';
|
|
28
28
|
// ===========================================================================
|
|
29
29
|
// Secret generation
|
|
30
30
|
// ===========================================================================
|
|
@@ -136,35 +136,26 @@ export async function verify(clientDbId, plaintext) {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
// ===========================================================================
|
|
139
|
-
// Secret
|
|
139
|
+
// Secret deletion
|
|
140
140
|
// ===========================================================================
|
|
141
141
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* Revocation is irreversible — once revoked, a secret cannot be
|
|
145
|
-
* reactivated. The revoked secret remains in the database for
|
|
146
|
-
* audit trail purposes until cleanup removes it.
|
|
142
|
+
* Permanently delete a client secret.
|
|
147
143
|
*
|
|
144
|
+
* @param clientDbId - Authoritative parent client UUID
|
|
148
145
|
* @param secretId - Secret UUID
|
|
149
146
|
* @param actorId - UUID of the user performing the action
|
|
150
147
|
* @throws ClientNotFoundError if secret not found
|
|
151
|
-
* @throws ClientValidationError if secret already revoked
|
|
152
148
|
*/
|
|
153
|
-
export async function revoke(secretId, actorId) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
149
|
+
export async function revoke(clientDbId, secretId, actorId) {
|
|
150
|
+
const existing = await findSecretById(clientDbId, secretId);
|
|
151
|
+
if (!existing || existing.clientId !== clientDbId)
|
|
152
|
+
throw new ClientNotFoundError(secretId);
|
|
153
|
+
const secret = await repoRevokeSecret(clientDbId, secretId);
|
|
154
|
+
if (!secret)
|
|
157
155
|
throw new ClientNotFoundError(secretId);
|
|
158
|
-
}
|
|
159
|
-
// Validate secret is not already revoked
|
|
160
|
-
if (secret.status === 'revoked') {
|
|
161
|
-
throw new ClientValidationError('Secret is already revoked');
|
|
162
|
-
}
|
|
163
|
-
// Revoke in database
|
|
164
|
-
await repoRevokeSecret(secretId);
|
|
165
156
|
// Audit log (fire-and-forget)
|
|
166
157
|
await writeAuditLog({
|
|
167
|
-
eventType: 'client.secret.
|
|
158
|
+
eventType: 'client.secret.deleted',
|
|
168
159
|
eventCategory: 'admin',
|
|
169
160
|
actorId,
|
|
170
161
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-service.js","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,YAAY,IAAI,gBAAgB,EAChC,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"secret-service.js","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* metadata format, used by the adapter factory during OIDC operations.
|
|
20
20
|
*/
|
|
21
21
|
import type { Client, ClientWithSecret, CreateClientInput, UpdateClientInput, ListClientsOptions, PaginatedResult } from './types.js';
|
|
22
|
-
import type { ListClientsCursorOptions } from './repository.js';
|
|
22
|
+
import type { ClientDeletionCapture, ListClientsCursorOptions } from './repository.js';
|
|
23
23
|
import type { CursorPaginatedResult } from '../lib/cursor.js';
|
|
24
24
|
/**
|
|
25
25
|
* Create a new OIDC client.
|
|
@@ -114,18 +114,6 @@ export declare function deactivateClient(id: string, actorId?: string): Promise<
|
|
|
114
114
|
* @throws ClientValidationError if not currently inactive
|
|
115
115
|
*/
|
|
116
116
|
export declare function activateClient(id: string, actorId?: string): Promise<void>;
|
|
117
|
-
/**
|
|
118
|
-
* Revoke a client (active or inactive → revoked).
|
|
119
|
-
*
|
|
120
|
-
* Revocation is permanent — revoked clients cannot be reactivated.
|
|
121
|
-
* This effectively disables the client for all OIDC operations.
|
|
122
|
-
*
|
|
123
|
-
* @param id - Client internal UUID
|
|
124
|
-
* @param actorId - UUID of the user performing the action
|
|
125
|
-
* @throws ClientNotFoundError if not found
|
|
126
|
-
* @throws ClientValidationError if already revoked
|
|
127
|
-
*/
|
|
128
|
-
export declare function revokeClient(id: string, actorId?: string): Promise<void>;
|
|
129
117
|
/**
|
|
130
118
|
* Find a client by OIDC client_id and return oidc-provider metadata format.
|
|
131
119
|
*
|
|
@@ -155,4 +143,13 @@ export declare function findForOidc(clientId: string): Promise<Record<string, un
|
|
|
155
143
|
* @returns true if secret matches any active hash, false otherwise
|
|
156
144
|
*/
|
|
157
145
|
export declare function verifyClientSecret(clientId: string, plaintext: string): Promise<boolean>;
|
|
146
|
+
/**
|
|
147
|
+
* Physically delete an OIDC client after capturing its protocol authority.
|
|
148
|
+
*
|
|
149
|
+
* @param id - Internal client UUID.
|
|
150
|
+
* @param actorId - Actor identifier available for audit attribution.
|
|
151
|
+
* @returns The graph captured before PostgreSQL applied its cascade.
|
|
152
|
+
* @throws ClientNotFoundError when the client does not exist.
|
|
153
|
+
*/
|
|
154
|
+
export declare function deleteClient(id: string, actorId?: string): Promise<ClientDeletionCapture>;
|
|
158
155
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/clients/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/clients/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,MAAM,YAAY,CAAC;AAYpB,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAsG9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAsG3B;AAMD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWtE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWlF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAsGjB;AAMD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,GAClD,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAElC;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAElC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAExC;AAgBD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlF;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhF;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CA6DhG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW9F;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAsC/F"}
|
package/dist/clients/service.js
CHANGED
|
@@ -19,17 +19,20 @@
|
|
|
19
19
|
* metadata format, used by the adapter factory during OIDC operations.
|
|
20
20
|
*/
|
|
21
21
|
import { LOGIN_METHODS } from './types.js';
|
|
22
|
-
import { insertClient, findClientById, findClientByClientId, updateClient as repoUpdateClient, listClients as repoListClients, listClientsCursor as repoListClientsCursor, } from './repository.js';
|
|
22
|
+
import { insertClient, findClientById, findClientByClientId, updateClient as repoUpdateClient, listClients as repoListClients, listClientsCursor as repoListClientsCursor, captureClientForDeletion, deleteCapturedClient, } from './repository.js';
|
|
23
23
|
import { getLatestActiveSha256 } from './secret-repository.js';
|
|
24
24
|
import { getCachedClientByClientId, getCachedClientById, cacheClient, invalidateClientCache, } from './cache.js';
|
|
25
25
|
import { generateClientId } from './crypto.js';
|
|
26
|
-
import { validateRedirectUris, getDefaultGrantTypes, getDefaultTokenEndpointAuthMethod, getDefaultResponseTypes, getDefaultScope, } from './validators.js';
|
|
26
|
+
import { validateRedirectUris, getDefaultGrantTypes, getDefaultTokenEndpointAuthMethod, getDefaultResponseTypes, getDefaultScope, validateClientProtocolCompatibility, } from './validators.js';
|
|
27
27
|
import { normalizeLoginMethods } from './resolve-login-methods.js';
|
|
28
28
|
import { verify } from './secret-service.js';
|
|
29
29
|
import { writeAuditLog } from '../lib/audit-log.js';
|
|
30
30
|
import { ClientNotFoundError, ClientValidationError } from './errors.js';
|
|
31
31
|
import { getApplicationById } from '../applications/service.js';
|
|
32
32
|
import { getOrganizationById } from '../organizations/service.js';
|
|
33
|
+
import { getDatabaseTransactionClient } from '../lib/database.js';
|
|
34
|
+
import { writeAuditLogInTransaction } from '../lib/audit-log.js';
|
|
35
|
+
import { registerDeletionCleanup } from '../lib/deletion-cleanup.js';
|
|
33
36
|
// ===========================================================================
|
|
34
37
|
// Validation helpers (private)
|
|
35
38
|
// ===========================================================================
|
|
@@ -67,6 +70,21 @@ function validateClientLoginMethods(methods) {
|
|
|
67
70
|
}
|
|
68
71
|
return normalizeLoginMethods(methods);
|
|
69
72
|
}
|
|
73
|
+
/** Validate a complete protocol configuration and map failures to the client domain error. */
|
|
74
|
+
function requireCompatibleProtocol(configuration) {
|
|
75
|
+
if (configuration.tokenEndpointAuthMethod !== 'client_secret_basic' &&
|
|
76
|
+
configuration.tokenEndpointAuthMethod !== 'client_secret_post' &&
|
|
77
|
+
configuration.tokenEndpointAuthMethod !== 'none') {
|
|
78
|
+
throw new ClientValidationError('Unsupported token endpoint authentication method');
|
|
79
|
+
}
|
|
80
|
+
const result = validateClientProtocolCompatibility({
|
|
81
|
+
...configuration,
|
|
82
|
+
tokenEndpointAuthMethod: configuration.tokenEndpointAuthMethod,
|
|
83
|
+
});
|
|
84
|
+
if (!result.isValid) {
|
|
85
|
+
throw new ClientValidationError(result.errors.join('; '));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
70
88
|
// ===========================================================================
|
|
71
89
|
// Client CRUD
|
|
72
90
|
// ===========================================================================
|
|
@@ -119,13 +137,22 @@ export async function createClient(input, actorId) {
|
|
|
119
137
|
throw new ClientValidationError(`Invalid redirect URIs: ${uriValidation.errors.join('; ')}`);
|
|
120
138
|
}
|
|
121
139
|
// Apply defaults for optional fields
|
|
122
|
-
const grantTypes = input.grantTypes ??
|
|
123
|
-
getDefaultGrantTypes(input.clientType, input.applicationType);
|
|
140
|
+
const grantTypes = input.grantTypes ?? getDefaultGrantTypes(input.clientType, input.applicationType);
|
|
124
141
|
const responseTypes = input.responseTypes ?? getDefaultResponseTypes();
|
|
125
142
|
const scope = input.scope ?? getDefaultScope();
|
|
126
|
-
const tokenEndpointAuthMethod = input.tokenEndpointAuthMethod ??
|
|
127
|
-
getDefaultTokenEndpointAuthMethod(input.clientType);
|
|
143
|
+
const tokenEndpointAuthMethod = input.tokenEndpointAuthMethod ?? getDefaultTokenEndpointAuthMethod(input.clientType);
|
|
128
144
|
const requirePkce = input.requirePkce ?? true;
|
|
145
|
+
const requireConsent = input.requireConsent ?? false;
|
|
146
|
+
requireCompatibleProtocol({
|
|
147
|
+
clientType: input.clientType,
|
|
148
|
+
redirectUris: input.redirectUris,
|
|
149
|
+
postLogoutRedirectUris: input.postLogoutRedirectUris ?? [],
|
|
150
|
+
grantTypes,
|
|
151
|
+
responseTypes,
|
|
152
|
+
tokenEndpointAuthMethod,
|
|
153
|
+
requirePkce,
|
|
154
|
+
allowedOrigins: input.allowedOrigins ?? [],
|
|
155
|
+
});
|
|
129
156
|
// Validate + normalize the login-method override (may throw). Three-state
|
|
130
157
|
// input: undefined → column omitted → DB DEFAULT NULL → inherit.
|
|
131
158
|
// null → inherit explicitly. Array → override with validated methods.
|
|
@@ -148,6 +175,7 @@ export async function createClient(input, actorId) {
|
|
|
148
175
|
tokenEndpointAuthMethod,
|
|
149
176
|
allowedOrigins: input.allowedOrigins ?? [],
|
|
150
177
|
requirePkce,
|
|
178
|
+
requireConsent,
|
|
151
179
|
// Pass through validated value as-is: `undefined` triggers column
|
|
152
180
|
// omission (DB default), `null` inserts NULL explicitly, array inserts
|
|
153
181
|
// the validated methods. The repo honors all three states.
|
|
@@ -239,6 +267,30 @@ export async function updateClient(id, input, actorId) {
|
|
|
239
267
|
throw new ClientValidationError(`Invalid redirect URIs: ${uriValidation.errors.join('; ')}`);
|
|
240
268
|
}
|
|
241
269
|
}
|
|
270
|
+
const changesProtocol = [
|
|
271
|
+
input.redirectUris,
|
|
272
|
+
input.postLogoutRedirectUris,
|
|
273
|
+
input.grantTypes,
|
|
274
|
+
input.responseTypes,
|
|
275
|
+
input.tokenEndpointAuthMethod,
|
|
276
|
+
input.allowedOrigins,
|
|
277
|
+
input.requirePkce,
|
|
278
|
+
].some((value) => value !== undefined);
|
|
279
|
+
if (changesProtocol) {
|
|
280
|
+
const existing = await getClientById(id);
|
|
281
|
+
if (!existing)
|
|
282
|
+
throw new ClientNotFoundError(id);
|
|
283
|
+
requireCompatibleProtocol({
|
|
284
|
+
clientType: existing.clientType,
|
|
285
|
+
redirectUris: input.redirectUris ?? existing.redirectUris,
|
|
286
|
+
postLogoutRedirectUris: input.postLogoutRedirectUris ?? existing.postLogoutRedirectUris,
|
|
287
|
+
grantTypes: input.grantTypes ?? existing.grantTypes,
|
|
288
|
+
responseTypes: input.responseTypes ?? existing.responseTypes,
|
|
289
|
+
tokenEndpointAuthMethod: input.tokenEndpointAuthMethod ?? existing.tokenEndpointAuthMethod,
|
|
290
|
+
requirePkce: input.requirePkce ?? existing.requirePkce,
|
|
291
|
+
allowedOrigins: input.allowedOrigins ?? existing.allowedOrigins,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
242
294
|
// Build update data from input
|
|
243
295
|
const updateData = {};
|
|
244
296
|
if (input.clientName !== undefined)
|
|
@@ -259,6 +311,8 @@ export async function updateClient(id, input, actorId) {
|
|
|
259
311
|
updateData.allowedOrigins = input.allowedOrigins;
|
|
260
312
|
if (input.requirePkce !== undefined)
|
|
261
313
|
updateData.requirePkce = input.requirePkce;
|
|
314
|
+
if (input.requireConsent !== undefined)
|
|
315
|
+
updateData.requireConsent = input.requireConsent;
|
|
262
316
|
// Validate + normalize the login-method override if the caller passed the
|
|
263
317
|
// key (including `null` = clear). Capture the previous value first for the
|
|
264
318
|
// audit log diff — we use the cache-aware accessor so stale reads don't
|
|
@@ -401,36 +455,6 @@ export async function activateClient(id, actorId) {
|
|
|
401
455
|
metadata: { clientDbId: client.id, clientId: client.clientId },
|
|
402
456
|
});
|
|
403
457
|
}
|
|
404
|
-
/**
|
|
405
|
-
* Revoke a client (active or inactive → revoked).
|
|
406
|
-
*
|
|
407
|
-
* Revocation is permanent — revoked clients cannot be reactivated.
|
|
408
|
-
* This effectively disables the client for all OIDC operations.
|
|
409
|
-
*
|
|
410
|
-
* @param id - Client internal UUID
|
|
411
|
-
* @param actorId - UUID of the user performing the action
|
|
412
|
-
* @throws ClientNotFoundError if not found
|
|
413
|
-
* @throws ClientValidationError if already revoked
|
|
414
|
-
*/
|
|
415
|
-
export async function revokeClient(id, actorId) {
|
|
416
|
-
const client = await loadClientForStatusChange(id);
|
|
417
|
-
if (client.status === 'revoked') {
|
|
418
|
-
throw new ClientValidationError('Client is already revoked');
|
|
419
|
-
}
|
|
420
|
-
await repoUpdateClient(id, { status: 'revoked' });
|
|
421
|
-
await invalidateClientCache(client.clientId, client.id);
|
|
422
|
-
await writeAuditLog({
|
|
423
|
-
organizationId: client.organizationId,
|
|
424
|
-
eventType: 'client.revoked',
|
|
425
|
-
eventCategory: 'admin',
|
|
426
|
-
actorId,
|
|
427
|
-
metadata: {
|
|
428
|
-
clientDbId: client.id,
|
|
429
|
-
clientId: client.clientId,
|
|
430
|
-
previousStatus: client.status,
|
|
431
|
-
},
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
458
|
// ===========================================================================
|
|
435
459
|
// OIDC integration
|
|
436
460
|
// ===========================================================================
|
|
@@ -448,7 +472,9 @@ export async function revokeClient(id, actorId) {
|
|
|
448
472
|
* @returns OIDC client metadata object, or undefined if not found/inactive
|
|
449
473
|
*/
|
|
450
474
|
export async function findForOidc(clientId) {
|
|
451
|
-
|
|
475
|
+
// Protocol authority must come from PostgreSQL. Administrative cache reads
|
|
476
|
+
// remain useful elsewhere, but stale metadata cannot authorize an OIDC flow.
|
|
477
|
+
const client = await findClientByClientId(clientId);
|
|
452
478
|
// Client must exist and be active for OIDC operations
|
|
453
479
|
if (!client || client.status !== 'active') {
|
|
454
480
|
return undefined;
|
|
@@ -463,9 +489,7 @@ export async function findForOidc(clientId) {
|
|
|
463
489
|
grant_types: client.grantTypes,
|
|
464
490
|
response_types: client.responseTypes,
|
|
465
491
|
scope: client.scope,
|
|
466
|
-
token_endpoint_auth_method: client.clientType === 'public'
|
|
467
|
-
? 'none'
|
|
468
|
-
: client.tokenEndpointAuthMethod,
|
|
492
|
+
token_endpoint_auth_method: client.clientType === 'public' ? 'none' : client.tokenEndpointAuthMethod,
|
|
469
493
|
// Porta uses ES256 signing keys — must declare this explicitly
|
|
470
494
|
// or oidc-provider defaults to RS256 and rejects the client.
|
|
471
495
|
id_token_signed_response_alg: 'ES256',
|
|
@@ -473,6 +497,9 @@ export async function findForOidc(clientId) {
|
|
|
473
497
|
'urn:porta:allowed_origins': client.allowedOrigins,
|
|
474
498
|
// Client type for internal use
|
|
475
499
|
'urn:porta:client_type': client.clientType,
|
|
500
|
+
// Public authorization-code clients always require PKCE. Confidential clients preserve the
|
|
501
|
+
// administrator's persisted choice and the provider reads it through registered metadata.
|
|
502
|
+
'urn:porta:require_pkce': client.requirePkce,
|
|
476
503
|
// Per-client login-methods override. Null means "inherit org default";
|
|
477
504
|
// a non-null array is the validated override. The OIDC configuration
|
|
478
505
|
// layer registers this URN under `extraClientMetadata.properties` so
|
|
@@ -480,9 +507,15 @@ export async function findForOidc(clientId) {
|
|
|
480
507
|
// the interaction handlers — where `resolveLoginMethodsFromOidcClient()`
|
|
481
508
|
// combines it with the org default to compute the effective methods.
|
|
482
509
|
'urn:porta:login_methods': client.loginMethods,
|
|
483
|
-
//
|
|
484
|
-
//
|
|
510
|
+
// Internal authority boundary consumed only while building this client's claims.
|
|
511
|
+
// Keeping the value in provider metadata avoids a database lookup on every claim request.
|
|
512
|
+
'urn:porta:internal_application_id': client.applicationId,
|
|
513
|
+
// Organization ID — the tenant that owns the client.
|
|
485
514
|
organizationId: client.organizationId,
|
|
515
|
+
// Whether the client must ask the end user for consent. The consent gate
|
|
516
|
+
// in showConsent() renders the consent page when this is true and a
|
|
517
|
+
// requested scope has not already been granted.
|
|
518
|
+
requireConsent: client.requireConsent,
|
|
486
519
|
};
|
|
487
520
|
// For confidential clients, include the SHA-256 hash as client_secret.
|
|
488
521
|
// oidc-provider will compare this against the SHA-256 of the presented
|
|
@@ -520,4 +553,50 @@ export async function verifyClientSecret(clientId, plaintext) {
|
|
|
520
553
|
// Delegate to secret-service which checks all active, non-expired hashes
|
|
521
554
|
return verify(client.id, plaintext);
|
|
522
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Physically delete an OIDC client after capturing its protocol authority.
|
|
558
|
+
*
|
|
559
|
+
* @param id - Internal client UUID.
|
|
560
|
+
* @param actorId - Actor identifier available for audit attribution.
|
|
561
|
+
* @returns The graph captured before PostgreSQL applied its cascade.
|
|
562
|
+
* @throws ClientNotFoundError when the client does not exist.
|
|
563
|
+
*/
|
|
564
|
+
export async function deleteClient(id, actorId) {
|
|
565
|
+
const transaction = getDatabaseTransactionClient();
|
|
566
|
+
if (!transaction)
|
|
567
|
+
throw new Error('Client deletion requires an active database transaction');
|
|
568
|
+
const capture = await captureClientForDeletion(id);
|
|
569
|
+
if (!capture)
|
|
570
|
+
throw new ClientNotFoundError(id);
|
|
571
|
+
await transaction.query(`DELETE FROM oidc_payloads
|
|
572
|
+
WHERE id = ANY($1::varchar[]) OR grant_id = ANY($1::varchar[])
|
|
573
|
+
OR payload->>'clientId' = ANY($2::text[])`, [capture.grantIds, capture.publicClientIds]);
|
|
574
|
+
await writeAuditLogInTransaction(transaction, {
|
|
575
|
+
organizationId: capture.client.organizationId,
|
|
576
|
+
actorId,
|
|
577
|
+
eventType: 'client.deleted',
|
|
578
|
+
eventCategory: 'admin',
|
|
579
|
+
metadata: {
|
|
580
|
+
clientDbId: capture.client.id,
|
|
581
|
+
clientId: capture.client.clientId,
|
|
582
|
+
applicationId: capture.client.applicationId,
|
|
583
|
+
status: capture.client.status,
|
|
584
|
+
},
|
|
585
|
+
});
|
|
586
|
+
await deleteCapturedClient(id);
|
|
587
|
+
await registerDeletionCleanup({
|
|
588
|
+
resource: 'client',
|
|
589
|
+
targetId: id,
|
|
590
|
+
parentId: capture.client.applicationId,
|
|
591
|
+
userIds: [],
|
|
592
|
+
clientIds: capture.clientIds,
|
|
593
|
+
publicClientIds: capture.publicClientIds,
|
|
594
|
+
grantIds: capture.grantIds,
|
|
595
|
+
roleIds: [],
|
|
596
|
+
permissionIds: [],
|
|
597
|
+
claimIds: [],
|
|
598
|
+
applicationIds: [capture.client.applicationId],
|
|
599
|
+
});
|
|
600
|
+
return capture;
|
|
601
|
+
}
|
|
523
602
|
//# sourceMappingURL=service.js.map
|