@portaidentity/server 1.7.3 → 1.8.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 +5 -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/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 +18 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +36 -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 +112 -40
- package/dist/clients/service.js.map +1 -1
- package/dist/clients/types.d.ts +1 -1
- package/dist/clients/types.d.ts.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 +64 -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 +347 -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 +168 -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 +336 -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 +388 -0
- package/dist/portability/repository.js.map +1 -0
- package/dist/portability/schema.d.ts +589 -0
- package/dist/portability/schema.d.ts.map +1 -0
- package/dist/portability/schema.js +458 -0
- package/dist/portability/schema.js.map +1 -0
- package/dist/portability/types.d.ts +381 -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 +111 -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 +16 -34
- package/dist/routes/interactions.js.map +1 -1
- package/dist/routes/invitation.d.ts.map +1 -1
- package/dist/routes/invitation.js +10 -23
- 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/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
package/dist/rbac/slugs.js
CHANGED
|
@@ -3,38 +3,38 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two types of slugs are used in the RBAC module:
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* 2. **Permission slugs** — colon-separated namespaced identifiers
|
|
11
|
-
* following the `module:resource:action` format (e.g., "crm:contacts:read").
|
|
12
|
-
* Each segment must be lowercase alphanumeric with hyphens.
|
|
13
|
-
* Minimum 3 segments required.
|
|
6
|
+
* Role and permission slugs are exact external claim values. Explicit values keep their case and
|
|
7
|
+
* printable characters after surrounding whitespace is removed. Generated role slugs retain the
|
|
8
|
+
* familiar kebab-case default.
|
|
14
9
|
*
|
|
15
10
|
* This module provides:
|
|
16
11
|
* - `generateRoleSlug(name)` — Derive a role slug from a role name
|
|
17
|
-
* - `
|
|
18
|
-
* - `
|
|
12
|
+
* - `normalizeRbacSlug(slug)` — Remove surrounding whitespace before storage and comparison
|
|
13
|
+
* - `validateRoleSlug(slug)` — Check the role claim value safety bounds
|
|
14
|
+
* - `validatePermissionSlug(slug)` — Check the permission claim value safety bounds
|
|
19
15
|
* - `parsePermissionSlug(slug)` — Decompose a permission slug into its parts
|
|
20
16
|
*/
|
|
21
17
|
// ---------------------------------------------------------------------------
|
|
22
18
|
// Role slug format
|
|
23
19
|
// ---------------------------------------------------------------------------
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
20
|
+
/** Removes surrounding whitespace while preserving the exact internal claim value. */
|
|
21
|
+
export function normalizeRbacSlug(slug) {
|
|
22
|
+
return slug.trim();
|
|
23
|
+
}
|
|
24
|
+
/** Returns whether text contains an ASCII or C1 control character. */
|
|
25
|
+
function containsControlCharacter(value) {
|
|
26
|
+
return [...value].some((character) => {
|
|
27
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
28
|
+
return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Validates one normalized, bounded, control-free external claim value. */
|
|
32
|
+
function validateRbacSlug(slug, maximumLength) {
|
|
33
|
+
const normalized = normalizeRbacSlug(slug);
|
|
34
|
+
return (normalized.length > 0 &&
|
|
35
|
+
normalized.length <= maximumLength &&
|
|
36
|
+
!containsControlCharacter(normalized));
|
|
37
|
+
}
|
|
38
38
|
// ---------------------------------------------------------------------------
|
|
39
39
|
// Role slug generation
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
@@ -80,11 +80,8 @@ export function generateRoleSlug(name) {
|
|
|
80
80
|
/**
|
|
81
81
|
* Validate a role slug format.
|
|
82
82
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* - Lowercase alphanumeric characters and hyphens only
|
|
86
|
-
* - Cannot start or end with a hyphen
|
|
87
|
-
* - Empty strings are invalid
|
|
83
|
+
* The trimmed value must contain 1–100 printable characters. Case and internal characters are
|
|
84
|
+
* preserved because this value is emitted directly to external applications.
|
|
88
85
|
*
|
|
89
86
|
* Does NOT check uniqueness — that's the repository/service layer's job.
|
|
90
87
|
*
|
|
@@ -94,28 +91,18 @@ export function generateRoleSlug(name) {
|
|
|
94
91
|
* @example
|
|
95
92
|
* validateRoleSlug('crm-editor') // true
|
|
96
93
|
* validateRoleSlug('admin') // true
|
|
97
|
-
* validateRoleSlug('CRM Editor') //
|
|
94
|
+
* validateRoleSlug('CRM Editor') // true
|
|
98
95
|
* validateRoleSlug('') // false (empty)
|
|
99
96
|
*/
|
|
100
97
|
export function validateRoleSlug(slug) {
|
|
101
|
-
|
|
102
|
-
if (!slug || slug.length > 100) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
return ROLE_SLUG_REGEX.test(slug);
|
|
98
|
+
return validateRbacSlug(slug, 100);
|
|
106
99
|
}
|
|
107
100
|
// ---------------------------------------------------------------------------
|
|
108
101
|
// Permission slug validation
|
|
109
102
|
// ---------------------------------------------------------------------------
|
|
110
103
|
/**
|
|
111
|
-
* Validate a permission
|
|
112
|
-
*
|
|
113
|
-
* Rules:
|
|
114
|
-
* - Must have at least 3 segments separated by colons
|
|
115
|
-
* - Each segment must be lowercase alphanumeric with hyphens
|
|
116
|
-
* - Each segment must start and end with an alphanumeric character
|
|
117
|
-
* - Empty segments are not allowed
|
|
118
|
-
* - Total length must not exceed 150 characters (matches DB column)
|
|
104
|
+
* Validate a permission claim value. `module:resource:action` remains a useful convention, but is
|
|
105
|
+
* not mandatory for external applications that already use another identifier scheme.
|
|
119
106
|
*
|
|
120
107
|
* @param slug - Permission slug to validate
|
|
121
108
|
* @returns true if the slug format is valid, false otherwise
|
|
@@ -124,22 +111,12 @@ export function validateRoleSlug(slug) {
|
|
|
124
111
|
* validatePermissionSlug('crm:contacts:read') // true
|
|
125
112
|
* validatePermissionSlug('admin:system:manage') // true
|
|
126
113
|
* validatePermissionSlug('crm:sub-module:items:write') // true (4+ segments OK)
|
|
127
|
-
* validatePermissionSlug('
|
|
128
|
-
* validatePermissionSlug('
|
|
114
|
+
* validatePermissionSlug('CAN_ADD_ORDER') // true
|
|
115
|
+
* validatePermissionSlug('access-that-resource') // true
|
|
129
116
|
* validatePermissionSlug('') // false (empty)
|
|
130
117
|
*/
|
|
131
118
|
export function validatePermissionSlug(slug) {
|
|
132
|
-
|
|
133
|
-
if (!slug || slug.length > 150) {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
// Split on colons — need at least 3 segments
|
|
137
|
-
const segments = slug.split(':');
|
|
138
|
-
if (segments.length < 3) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
// Each segment must match the segment format
|
|
142
|
-
return segments.every((segment) => segment.length > 0 && PERMISSION_SEGMENT_REGEX.test(segment));
|
|
119
|
+
return validateRbacSlug(slug, 150);
|
|
143
120
|
}
|
|
144
121
|
/**
|
|
145
122
|
* Parse a permission slug into its module, resource, and action components.
|
|
@@ -149,7 +126,7 @@ export function validatePermissionSlug(slug) {
|
|
|
149
126
|
* both 3-segment slugs (crm:contacts:read) and 4+ segment slugs
|
|
150
127
|
* (crm:sub-module:items:write → module="crm", resource="sub-module:items", action="write").
|
|
151
128
|
*
|
|
152
|
-
* Returns null
|
|
129
|
+
* Returns null when the claim value does not use the conventional three-or-more-part colon form.
|
|
153
130
|
*
|
|
154
131
|
* @param slug - Permission slug to parse
|
|
155
132
|
* @returns Parsed components or null if invalid
|
|
@@ -165,10 +142,10 @@ export function validatePermissionSlug(slug) {
|
|
|
165
142
|
* // null
|
|
166
143
|
*/
|
|
167
144
|
export function parsePermissionSlug(slug) {
|
|
168
|
-
|
|
145
|
+
const segments = normalizeRbacSlug(slug).split(':');
|
|
146
|
+
if (!validatePermissionSlug(slug) || segments.length < 3 || segments.some((part) => !part)) {
|
|
169
147
|
return null;
|
|
170
148
|
}
|
|
171
|
-
const segments = slug.split(':');
|
|
172
149
|
// First segment = module, last = action, middle = resource
|
|
173
150
|
const module = segments[0];
|
|
174
151
|
const action = segments[segments.length - 1];
|
package/dist/rbac/slugs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slugs.js","sourceRoot":"","sources":["../../src/rbac/slugs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"slugs.js","sourceRoot":"","sources":["../../src/rbac/slugs.ts"],"names":[],"mappings":"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"}
|
package/dist/rbac/types.d.ts
CHANGED
|
@@ -62,8 +62,7 @@ export interface UpdateRoleInput {
|
|
|
62
62
|
* Full permission record as stored in the database.
|
|
63
63
|
* Maps to the `permissions` table columns (see migration 006).
|
|
64
64
|
* Permissions are defined globally per application, optionally scoped
|
|
65
|
-
* to a module. The slug
|
|
66
|
-
* (e.g., "crm:contacts:read").
|
|
65
|
+
* to a module. The slug is the exact permission value emitted to the application.
|
|
67
66
|
*/
|
|
68
67
|
export interface Permission {
|
|
69
68
|
id: string;
|
|
@@ -89,8 +88,7 @@ export interface PermissionRow {
|
|
|
89
88
|
}
|
|
90
89
|
/**
|
|
91
90
|
* Input for creating a new permission.
|
|
92
|
-
* The slug
|
|
93
|
-
* validated by the service layer before insert.
|
|
91
|
+
* The slug is an application-defined claim value validated by the service layer before insert.
|
|
94
92
|
*/
|
|
95
93
|
export interface CreatePermissionInput {
|
|
96
94
|
applicationId: string;
|
package/dist/rbac/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rbac/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAMD
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rbac/types.ts"],"names":[],"mappings":"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"}
|
package/dist/rbac/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rbac/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rbac/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA+KH,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,aAAa,EAAE,GAAG,CAAC,cAAc;QACjC,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,aAAa,EAAE,GAAG,CAAC,cAAc;QACjC,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAgB;IAC/C,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -5,14 +5,8 @@
|
|
|
5
5
|
* roles and permissions, and building the claims arrays that get
|
|
6
6
|
* injected into OIDC tokens.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* database queries during token issuance.
|
|
11
|
-
*
|
|
12
|
-
* Cache strategy for claims:
|
|
13
|
-
* 1. Check Redis for cached slug arrays
|
|
14
|
-
* 2. On cache hit → return immediately (fast path)
|
|
15
|
-
* 3. On cache miss → query DB, cache result, return
|
|
8
|
+
* Token claim construction reads PostgreSQL directly. This makes role and
|
|
9
|
+
* permission deletion authoritative even when an older Redis entry remains.
|
|
16
10
|
*
|
|
17
11
|
* @see mapping-repository.ts — Database operations for user-role join table
|
|
18
12
|
* @see cache.ts — Redis cache for role/permission slug arrays
|
|
@@ -24,47 +18,57 @@ import type { Role, Permission, UserRole } from './types.js';
|
|
|
24
18
|
* Uses ON CONFLICT DO NOTHING for idempotent assignment. Invalidates
|
|
25
19
|
* the user's RBAC cache since their effective permissions may change.
|
|
26
20
|
*
|
|
21
|
+
* @param organizationId - Authoritative organization UUID
|
|
27
22
|
* @param userId - User UUID
|
|
28
23
|
* @param roleIds - Array of role UUIDs to assign
|
|
29
|
-
* @param assignedBy -
|
|
24
|
+
* @param assignedBy - UUID of the admin performing the assignment
|
|
30
25
|
*/
|
|
31
|
-
export declare function assignRolesToUser(userId: string, roleIds: string[], assignedBy
|
|
26
|
+
export declare function assignRolesToUser(organizationId: string, userId: string, roleIds: string[], assignedBy: string): Promise<void>;
|
|
32
27
|
/**
|
|
33
28
|
* Remove roles from a user (bulk).
|
|
34
29
|
*
|
|
35
30
|
* Invalidates the user's RBAC cache since their effective permissions
|
|
36
31
|
* may change.
|
|
37
32
|
*
|
|
33
|
+
* @param organizationId - Authoritative organization UUID
|
|
38
34
|
* @param userId - User UUID
|
|
39
35
|
* @param roleIds - Array of role UUIDs to remove
|
|
40
|
-
* @param actorId -
|
|
36
|
+
* @param actorId - UUID of the admin performing the action
|
|
37
|
+
* @returns Whether the actor must authenticate again
|
|
41
38
|
*/
|
|
42
|
-
export declare function removeRolesFromUser(userId: string, roleIds: string[], actorId
|
|
39
|
+
export declare function removeRolesFromUser(organizationId: string, userId: string, roleIds: string[], actorId: string): Promise<{
|
|
40
|
+
reauthenticationRequired: boolean;
|
|
41
|
+
}>;
|
|
43
42
|
/**
|
|
44
43
|
* Get all roles assigned to a user.
|
|
45
44
|
*
|
|
45
|
+
* @param organizationId - Authoritative organization UUID
|
|
46
46
|
* @param userId - User UUID
|
|
47
47
|
* @returns Array of Role objects
|
|
48
48
|
*/
|
|
49
|
-
export declare function getUserRoles(userId: string): Promise<Role[]>;
|
|
49
|
+
export declare function getUserRoles(organizationId: string, userId: string): Promise<Role[]>;
|
|
50
|
+
/** Read all roles for internal authority resolution without a route parent. */
|
|
51
|
+
export declare function getUserRolesForAuthority(userId: string): Promise<Role[]>;
|
|
50
52
|
/**
|
|
51
53
|
* Get all permissions for a user (resolved through roles).
|
|
52
54
|
*
|
|
55
|
+
* @param organizationId - Authoritative organization UUID
|
|
53
56
|
* @param userId - User UUID
|
|
54
57
|
* @returns Deduplicated array of Permission objects
|
|
55
58
|
*/
|
|
56
|
-
export declare function getUserPermissions(userId: string): Promise<Permission[]>;
|
|
59
|
+
export declare function getUserPermissions(organizationId: string, userId: string): Promise<Permission[]>;
|
|
57
60
|
/**
|
|
58
61
|
* List users with a specific role within an organization.
|
|
59
62
|
*
|
|
60
63
|
* Supports pagination for admin UI views.
|
|
61
64
|
*
|
|
65
|
+
* @param applicationId - Authoritative application UUID
|
|
62
66
|
* @param roleId - Role UUID
|
|
63
67
|
* @param orgId - Organization UUID
|
|
64
68
|
* @param options - Pagination options
|
|
65
69
|
* @returns Paginated user-role assignments and total count
|
|
66
70
|
*/
|
|
67
|
-
export declare function getUsersWithRole(roleId: string, orgId: string, options?: {
|
|
71
|
+
export declare function getUsersWithRole(applicationId: string, roleId: string, orgId: string, options?: {
|
|
68
72
|
page?: number;
|
|
69
73
|
pageSize?: number;
|
|
70
74
|
}): Promise<{
|
|
@@ -77,25 +81,20 @@ export declare function getUsersWithRole(roleId: string, orgId: string, options?
|
|
|
77
81
|
* Returns an array of role slugs (e.g., ["crm-editor", "invoice-approver"])
|
|
78
82
|
* for inclusion in the token's custom claims.
|
|
79
83
|
*
|
|
80
|
-
* Cache-first: checks Redis for cached role slugs. On cache miss,
|
|
81
|
-
* resolves from DB and caches the result for future token issuances.
|
|
82
|
-
*
|
|
83
84
|
* @param userId - User UUID
|
|
85
|
+
* @param applicationId - Application UUID that owns the requested token authority
|
|
84
86
|
* @returns Array of role slug strings
|
|
85
87
|
*/
|
|
86
|
-
export declare function buildRoleClaims(userId: string): Promise<string[]>;
|
|
88
|
+
export declare function buildRoleClaims(userId: string, applicationId: string): Promise<string[]>;
|
|
87
89
|
/**
|
|
88
90
|
* Build permission claims for a user's token.
|
|
89
91
|
*
|
|
90
92
|
* Returns an array of permission slugs (e.g., ["crm:contacts:read",
|
|
91
93
|
* "crm:deals:write"]) for inclusion in the token's custom claims.
|
|
92
94
|
*
|
|
93
|
-
* Cache-first: checks Redis for cached permission slugs. On cache miss,
|
|
94
|
-
* resolves through the full user → roles → permissions chain from DB
|
|
95
|
-
* and caches the result.
|
|
96
|
-
*
|
|
97
95
|
* @param userId - User UUID
|
|
96
|
+
* @param applicationId - Application UUID that owns the requested token authority
|
|
98
97
|
* @returns Array of permission slug strings
|
|
99
98
|
*/
|
|
100
|
-
export declare function buildPermissionClaims(userId: string): Promise<string[]>;
|
|
99
|
+
export declare function buildPermissionClaims(userId: string, applicationId: string): Promise<string[]>;
|
|
101
100
|
//# sourceMappingURL=user-role-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-role-service.d.ts","sourceRoot":"","sources":["../../src/rbac/user-role-service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"user-role-service.d.ts","sourceRoot":"","sources":["../../src/rbac/user-role-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAaH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAwB7D;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,wBAAwB,EAAE,OAAO,CAAA;CAAE,CAAC,CAsChD;AAMD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAE1F;AAED,+EAA+E;AAC/E,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAE9E;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,CAEvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC;IAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAK9C;AA0DD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG9F;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB"}
|
|
@@ -5,21 +5,24 @@
|
|
|
5
5
|
* roles and permissions, and building the claims arrays that get
|
|
6
6
|
* injected into OIDC tokens.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* database queries during token issuance.
|
|
11
|
-
*
|
|
12
|
-
* Cache strategy for claims:
|
|
13
|
-
* 1. Check Redis for cached slug arrays
|
|
14
|
-
* 2. On cache hit → return immediately (fast path)
|
|
15
|
-
* 3. On cache miss → query DB, cache result, return
|
|
8
|
+
* Token claim construction reads PostgreSQL directly. This makes role and
|
|
9
|
+
* permission deletion authoritative even when an older Redis entry remains.
|
|
16
10
|
*
|
|
17
11
|
* @see mapping-repository.ts — Database operations for user-role join table
|
|
18
12
|
* @see cache.ts — Redis cache for role/permission slug arrays
|
|
19
13
|
*/
|
|
20
|
-
import { assignRolesToUser as repoAssignRoles, removeRolesFromUser as repoRemoveRoles, getRolesForUser as repoGetRolesForUser, getPermissionsForUser as repoGetPermissionsForUser, getUsersWithRole as repoGetUsersWithRole, } from './mapping-repository.js';
|
|
21
|
-
import { getCachedUserRoles, setCachedUserRoles, getCachedUserPermissions, setCachedUserPermissions, invalidateUserRbacCache, } from './cache.js';
|
|
14
|
+
import { assignRolesToUser as repoAssignRoles, removeRolesFromUser as repoRemoveRoles, getRolesForUser as repoGetRolesForUser, getPermissionsForUser as repoGetPermissionsForUser, getUsersWithRole as repoGetUsersWithRole, getRolesForOrganizationUser, getPermissionsForOrganizationUser, lockUserRoleTargets, } from './mapping-repository.js';
|
|
22
15
|
import { writeAuditLog } from '../lib/audit-log.js';
|
|
16
|
+
import { getDatabaseTransactionClient } from '../lib/database.js';
|
|
17
|
+
import { writeAuditLogInTransaction } from '../lib/audit-log.js';
|
|
18
|
+
import { registerAuthorityCleanup } from '../lib/deletion-cleanup.js';
|
|
19
|
+
import { revokeAffectedAuthorityInTransaction } from '../lib/authority-revocation.js';
|
|
20
|
+
import { getApplicationBySlug } from '../applications/service.js';
|
|
21
|
+
import { ADMIN_ROLE_DEFINITIONS, getPermissionsForAdminRole, resolvePermissionsFromRoles, } from '../lib/admin-permissions.js';
|
|
22
|
+
import { RoleDelegationError, RoleNotFoundError } from './errors.js';
|
|
23
|
+
import { UserNotFoundError } from '../users/errors.js';
|
|
24
|
+
import { lockControlPlaneOrganization, requireActiveSuperAdminSurvivor, } from '../users/repository.js';
|
|
25
|
+
const ADMIN_APPLICATION_SLUG = 'porta-admin';
|
|
23
26
|
// ---------------------------------------------------------------------------
|
|
24
27
|
// Assignment management
|
|
25
28
|
// ---------------------------------------------------------------------------
|
|
@@ -29,23 +32,35 @@ import { writeAuditLog } from '../lib/audit-log.js';
|
|
|
29
32
|
* Uses ON CONFLICT DO NOTHING for idempotent assignment. Invalidates
|
|
30
33
|
* the user's RBAC cache since their effective permissions may change.
|
|
31
34
|
*
|
|
35
|
+
* @param organizationId - Authoritative organization UUID
|
|
32
36
|
* @param userId - User UUID
|
|
33
37
|
* @param roleIds - Array of role UUIDs to assign
|
|
34
|
-
* @param assignedBy -
|
|
38
|
+
* @param assignedBy - UUID of the admin performing the assignment
|
|
35
39
|
*/
|
|
36
|
-
export async function assignRolesToUser(userId, roleIds, assignedBy) {
|
|
40
|
+
export async function assignRolesToUser(organizationId, userId, roleIds, assignedBy) {
|
|
37
41
|
if (roleIds.length === 0)
|
|
38
42
|
return;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
if (!getDatabaseTransactionClient()) {
|
|
44
|
+
throw new Error('User role assignment requires an active database transaction');
|
|
45
|
+
}
|
|
46
|
+
const targets = await requireUserRoleTargets(organizationId, userId, roleIds);
|
|
47
|
+
await requireDelegableRoles(targets.roles, assignedBy, targets.adminApplicationId);
|
|
48
|
+
const insertedRoleIds = await repoAssignRoles(organizationId, userId, roleIds, assignedBy);
|
|
49
|
+
if (insertedRoleIds.length === 0)
|
|
50
|
+
return;
|
|
51
|
+
await registerAuthorityCleanup({
|
|
52
|
+
userIds: [userId],
|
|
53
|
+
grantIds: [],
|
|
54
|
+
roleIds: [],
|
|
55
|
+
revokeOidcState: false,
|
|
56
|
+
});
|
|
42
57
|
// Audit log (fire-and-forget)
|
|
43
58
|
void writeAuditLog({
|
|
44
59
|
eventType: 'user.roles.assigned',
|
|
45
60
|
eventCategory: 'admin',
|
|
46
61
|
userId,
|
|
47
62
|
actorId: assignedBy,
|
|
48
|
-
metadata: { roleIds },
|
|
63
|
+
metadata: { organizationId, roleIds: insertedRoleIds },
|
|
49
64
|
});
|
|
50
65
|
}
|
|
51
66
|
/**
|
|
@@ -54,24 +69,47 @@ export async function assignRolesToUser(userId, roleIds, assignedBy) {
|
|
|
54
69
|
* Invalidates the user's RBAC cache since their effective permissions
|
|
55
70
|
* may change.
|
|
56
71
|
*
|
|
72
|
+
* @param organizationId - Authoritative organization UUID
|
|
57
73
|
* @param userId - User UUID
|
|
58
74
|
* @param roleIds - Array of role UUIDs to remove
|
|
59
|
-
* @param actorId -
|
|
75
|
+
* @param actorId - UUID of the admin performing the action
|
|
76
|
+
* @returns Whether the actor must authenticate again
|
|
60
77
|
*/
|
|
61
|
-
export async function removeRolesFromUser(userId, roleIds, actorId) {
|
|
78
|
+
export async function removeRolesFromUser(organizationId, userId, roleIds, actorId) {
|
|
62
79
|
if (roleIds.length === 0)
|
|
63
|
-
return;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
return { reauthenticationRequired: false };
|
|
81
|
+
const transaction = getDatabaseTransactionClient();
|
|
82
|
+
if (!transaction) {
|
|
83
|
+
throw new Error('User role removal requires an active database transaction');
|
|
84
|
+
}
|
|
85
|
+
await lockControlPlaneOrganization(organizationId);
|
|
86
|
+
const targets = await requireUserRoleTargets(organizationId, userId, roleIds);
|
|
87
|
+
if (targets.assignedRoleIds.length === 0)
|
|
88
|
+
return { reauthenticationRequired: false };
|
|
89
|
+
const removesExactSuperAdmin = targets.roles.some((role) => targets.assignedRoleIds.includes(role.id) &&
|
|
90
|
+
role.applicationId === targets.adminApplicationId &&
|
|
91
|
+
role.slug === ADMIN_ROLE_DEFINITIONS.SUPER_ADMIN.slug);
|
|
92
|
+
if (targets.user.status === 'active' && removesExactSuperAdmin) {
|
|
93
|
+
await requireActiveSuperAdminSurvivor(organizationId, userId);
|
|
94
|
+
}
|
|
95
|
+
const revoked = await revokeAffectedAuthorityInTransaction([userId]);
|
|
96
|
+
const removedRoleIds = await repoRemoveRoles(organizationId, userId, [
|
|
97
|
+
...targets.assignedRoleIds,
|
|
98
|
+
]);
|
|
99
|
+
await writeAuditLogInTransaction(transaction, {
|
|
69
100
|
eventType: 'user.roles.removed',
|
|
70
101
|
eventCategory: 'admin',
|
|
71
102
|
userId,
|
|
72
103
|
actorId,
|
|
73
|
-
metadata: { roleIds },
|
|
104
|
+
metadata: { organizationId, roleIds: removedRoleIds },
|
|
74
105
|
});
|
|
106
|
+
await registerAuthorityCleanup({
|
|
107
|
+
userIds: [userId],
|
|
108
|
+
grantIds: revoked.grantIds,
|
|
109
|
+
roleIds: [],
|
|
110
|
+
revokeOidcState: true,
|
|
111
|
+
});
|
|
112
|
+
return { reauthenticationRequired: actorId === userId };
|
|
75
113
|
}
|
|
76
114
|
// ---------------------------------------------------------------------------
|
|
77
115
|
// Query operations
|
|
@@ -79,35 +117,76 @@ export async function removeRolesFromUser(userId, roleIds, actorId) {
|
|
|
79
117
|
/**
|
|
80
118
|
* Get all roles assigned to a user.
|
|
81
119
|
*
|
|
120
|
+
* @param organizationId - Authoritative organization UUID
|
|
82
121
|
* @param userId - User UUID
|
|
83
122
|
* @returns Array of Role objects
|
|
84
123
|
*/
|
|
85
|
-
export async function getUserRoles(userId) {
|
|
124
|
+
export async function getUserRoles(organizationId, userId) {
|
|
125
|
+
return getRolesForOrganizationUser(organizationId, userId);
|
|
126
|
+
}
|
|
127
|
+
/** Read all roles for internal authority resolution without a route parent. */
|
|
128
|
+
export async function getUserRolesForAuthority(userId) {
|
|
86
129
|
return repoGetRolesForUser(userId);
|
|
87
130
|
}
|
|
88
131
|
/**
|
|
89
132
|
* Get all permissions for a user (resolved through roles).
|
|
90
133
|
*
|
|
134
|
+
* @param organizationId - Authoritative organization UUID
|
|
91
135
|
* @param userId - User UUID
|
|
92
136
|
* @returns Deduplicated array of Permission objects
|
|
93
137
|
*/
|
|
94
|
-
export async function getUserPermissions(userId) {
|
|
95
|
-
return
|
|
138
|
+
export async function getUserPermissions(organizationId, userId) {
|
|
139
|
+
return getPermissionsForOrganizationUser(organizationId, userId);
|
|
96
140
|
}
|
|
97
141
|
/**
|
|
98
142
|
* List users with a specific role within an organization.
|
|
99
143
|
*
|
|
100
144
|
* Supports pagination for admin UI views.
|
|
101
145
|
*
|
|
146
|
+
* @param applicationId - Authoritative application UUID
|
|
102
147
|
* @param roleId - Role UUID
|
|
103
148
|
* @param orgId - Organization UUID
|
|
104
149
|
* @param options - Pagination options
|
|
105
150
|
* @returns Paginated user-role assignments and total count
|
|
106
151
|
*/
|
|
107
|
-
export async function getUsersWithRole(roleId, orgId, options) {
|
|
152
|
+
export async function getUsersWithRole(applicationId, roleId, orgId, options) {
|
|
108
153
|
const page = options?.page ?? 1;
|
|
109
154
|
const pageSize = options?.pageSize ?? 20;
|
|
110
|
-
return repoGetUsersWithRole(roleId, orgId, page, pageSize);
|
|
155
|
+
return repoGetUsersWithRole(applicationId, roleId, orgId, page, pageSize);
|
|
156
|
+
}
|
|
157
|
+
/** Lock the target user and every requested role, then reject missing records. */
|
|
158
|
+
async function requireUserRoleTargets(organizationId, userId, roleIds) {
|
|
159
|
+
const requestedRoleIds = [...new Set(roleIds)].sort();
|
|
160
|
+
const targets = await lockUserRoleTargets(organizationId, userId, requestedRoleIds);
|
|
161
|
+
if (!targets.user)
|
|
162
|
+
throw new UserNotFoundError(userId);
|
|
163
|
+
if (targets.roles.length !== requestedRoleIds.length) {
|
|
164
|
+
const found = new Set(targets.roles.map((role) => role.id));
|
|
165
|
+
const missing = requestedRoleIds.find((roleId) => !found.has(roleId));
|
|
166
|
+
throw new RoleNotFoundError(missing ?? 'requested role');
|
|
167
|
+
}
|
|
168
|
+
const adminApplication = await getApplicationBySlug(ADMIN_APPLICATION_SLUG);
|
|
169
|
+
return {
|
|
170
|
+
user: targets.user,
|
|
171
|
+
roles: targets.roles,
|
|
172
|
+
assignedRoleIds: targets.assignedRoleIds,
|
|
173
|
+
adminApplicationId: adminApplication?.id ?? null,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/** Enforce the static capability ceiling for canonical Admin role assignments. */
|
|
177
|
+
async function requireDelegableRoles(roles, actorId, adminApplicationId) {
|
|
178
|
+
if (adminApplicationId === null)
|
|
179
|
+
return;
|
|
180
|
+
const requestedCapabilities = roles
|
|
181
|
+
.filter((role) => role.applicationId === adminApplicationId)
|
|
182
|
+
.flatMap((role) => getPermissionsForAdminRole(role.slug));
|
|
183
|
+
if (requestedCapabilities.length === 0)
|
|
184
|
+
return;
|
|
185
|
+
const actorRoles = await repoGetRolesForUser(actorId, adminApplicationId);
|
|
186
|
+
const actorCapabilities = new Set(resolvePermissionsFromRoles(actorRoles.map((role) => role.slug)));
|
|
187
|
+
if (requestedCapabilities.some((capability) => !actorCapabilities.has(capability))) {
|
|
188
|
+
throw new RoleDelegationError();
|
|
189
|
+
}
|
|
111
190
|
}
|
|
112
191
|
// ---------------------------------------------------------------------------
|
|
113
192
|
// Token claims building (hot path)
|
|
@@ -118,24 +197,13 @@ export async function getUsersWithRole(roleId, orgId, options) {
|
|
|
118
197
|
* Returns an array of role slugs (e.g., ["crm-editor", "invoice-approver"])
|
|
119
198
|
* for inclusion in the token's custom claims.
|
|
120
199
|
*
|
|
121
|
-
* Cache-first: checks Redis for cached role slugs. On cache miss,
|
|
122
|
-
* resolves from DB and caches the result for future token issuances.
|
|
123
|
-
*
|
|
124
200
|
* @param userId - User UUID
|
|
201
|
+
* @param applicationId - Application UUID that owns the requested token authority
|
|
125
202
|
* @returns Array of role slug strings
|
|
126
203
|
*/
|
|
127
|
-
export async function buildRoleClaims(userId) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (cached !== null) {
|
|
131
|
-
return cached;
|
|
132
|
-
}
|
|
133
|
-
// 2. Cache miss — resolve from DB
|
|
134
|
-
const roles = await repoGetRolesForUser(userId);
|
|
135
|
-
const slugs = roles.map((role) => role.slug);
|
|
136
|
-
// 3. Cache the slugs for future requests
|
|
137
|
-
await setCachedUserRoles(userId, slugs);
|
|
138
|
-
return slugs;
|
|
204
|
+
export async function buildRoleClaims(userId, applicationId) {
|
|
205
|
+
const roles = await repoGetRolesForUser(userId, applicationId);
|
|
206
|
+
return [...new Set(roles.map((role) => role.slug))];
|
|
139
207
|
}
|
|
140
208
|
/**
|
|
141
209
|
* Build permission claims for a user's token.
|
|
@@ -143,24 +211,12 @@ export async function buildRoleClaims(userId) {
|
|
|
143
211
|
* Returns an array of permission slugs (e.g., ["crm:contacts:read",
|
|
144
212
|
* "crm:deals:write"]) for inclusion in the token's custom claims.
|
|
145
213
|
*
|
|
146
|
-
* Cache-first: checks Redis for cached permission slugs. On cache miss,
|
|
147
|
-
* resolves through the full user → roles → permissions chain from DB
|
|
148
|
-
* and caches the result.
|
|
149
|
-
*
|
|
150
214
|
* @param userId - User UUID
|
|
215
|
+
* @param applicationId - Application UUID that owns the requested token authority
|
|
151
216
|
* @returns Array of permission slug strings
|
|
152
217
|
*/
|
|
153
|
-
export async function buildPermissionClaims(userId) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (cached !== null) {
|
|
157
|
-
return cached;
|
|
158
|
-
}
|
|
159
|
-
// 2. Cache miss — resolve from DB (through roles)
|
|
160
|
-
const permissions = await repoGetPermissionsForUser(userId);
|
|
161
|
-
const slugs = permissions.map((perm) => perm.slug);
|
|
162
|
-
// 3. Cache the slugs for future requests
|
|
163
|
-
await setCachedUserPermissions(userId, slugs);
|
|
164
|
-
return slugs;
|
|
218
|
+
export async function buildPermissionClaims(userId, applicationId) {
|
|
219
|
+
const permissions = await repoGetPermissionsForUser(userId, applicationId);
|
|
220
|
+
return [...new Set(permissions.map((permission) => permission.slug))];
|
|
165
221
|
}
|
|
166
222
|
//# sourceMappingURL=user-role-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-role-service.js","sourceRoot":"","sources":["../../src/rbac/user-role-service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"user-role-service.js","sourceRoot":"","sources":["../../src/rbac/user-role-service.ts"],"names":[],"mappings":"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"}
|