@portaidentity/server 1.7.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 +11 -0
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/applications/cache.d.ts +64 -0
- package/dist/applications/cache.d.ts.map +1 -0
- package/dist/applications/cache.js +161 -0
- package/dist/applications/cache.js.map +1 -0
- package/dist/applications/errors.d.ts +25 -0
- package/dist/applications/errors.d.ts.map +1 -0
- package/dist/applications/errors.js +31 -0
- package/dist/applications/errors.js.map +1 -0
- package/dist/applications/index.d.ts +17 -0
- package/dist/applications/index.d.ts.map +1 -0
- package/dist/applications/index.js +19 -0
- package/dist/applications/index.js.map +1 -0
- package/dist/applications/repository.d.ts +184 -0
- package/dist/applications/repository.d.ts.map +1 -0
- package/dist/applications/repository.js +367 -0
- package/dist/applications/repository.js.map +1 -0
- package/dist/applications/service.d.ts +160 -0
- package/dist/applications/service.d.ts.map +1 -0
- package/dist/applications/service.js +388 -0
- package/dist/applications/service.js.map +1 -0
- package/dist/applications/slugs.d.ts +61 -0
- package/dist/applications/slugs.d.ts.map +1 -0
- package/dist/applications/slugs.js +115 -0
- package/dist/applications/slugs.js.map +1 -0
- package/dist/applications/types.d.ts +129 -0
- package/dist/applications/types.d.ts.map +1 -0
- package/dist/applications/types.js +62 -0
- package/dist/applications/types.js.map +1 -0
- package/dist/auth/csrf.d.ts +71 -0
- package/dist/auth/csrf.d.ts.map +1 -0
- package/dist/auth/csrf.js +112 -0
- package/dist/auth/csrf.js.map +1 -0
- package/dist/auth/email-renderer.d.ts +37 -0
- package/dist/auth/email-renderer.d.ts.map +1 -0
- package/dist/auth/email-renderer.js +116 -0
- package/dist/auth/email-renderer.js.map +1 -0
- package/dist/auth/email-service.d.ts +154 -0
- package/dist/auth/email-service.d.ts.map +1 -0
- package/dist/auth/email-service.js +415 -0
- package/dist/auth/email-service.js.map +1 -0
- package/dist/auth/email-transport.d.ts +65 -0
- package/dist/auth/email-transport.d.ts.map +1 -0
- package/dist/auth/email-transport.js +82 -0
- package/dist/auth/email-transport.js.map +1 -0
- package/dist/auth/i18n.d.ts +81 -0
- package/dist/auth/i18n.d.ts.map +1 -0
- package/dist/auth/i18n.js +395 -0
- package/dist/auth/i18n.js.map +1 -0
- package/dist/auth/index.d.ts +28 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +31 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/interaction-authority.d.ts +39 -0
- package/dist/auth/interaction-authority.d.ts.map +1 -0
- package/dist/auth/interaction-authority.js +30 -0
- package/dist/auth/interaction-authority.js.map +1 -0
- package/dist/auth/magic-link-session.d.ts +81 -0
- package/dist/auth/magic-link-session.d.ts.map +1 -0
- package/dist/auth/magic-link-session.js +183 -0
- package/dist/auth/magic-link-session.js.map +1 -0
- package/dist/auth/rate-limiter.d.ts +143 -0
- package/dist/auth/rate-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limiter.js +220 -0
- package/dist/auth/rate-limiter.js.map +1 -0
- package/dist/auth/recovery-crypto.d.ts +34 -0
- package/dist/auth/recovery-crypto.d.ts.map +1 -0
- package/dist/auth/recovery-crypto.js +103 -0
- package/dist/auth/recovery-crypto.js.map +1 -0
- package/dist/auth/recovery-job-processor.d.ts +24 -0
- package/dist/auth/recovery-job-processor.d.ts.map +1 -0
- package/dist/auth/recovery-job-processor.js +123 -0
- package/dist/auth/recovery-job-processor.js.map +1 -0
- package/dist/auth/recovery-job-repository.d.ts +219 -0
- package/dist/auth/recovery-job-repository.d.ts.map +1 -0
- package/dist/auth/recovery-job-repository.js +340 -0
- package/dist/auth/recovery-job-repository.js.map +1 -0
- package/dist/auth/recovery-service.d.ts +27 -0
- package/dist/auth/recovery-service.d.ts.map +1 -0
- package/dist/auth/recovery-service.js +53 -0
- package/dist/auth/recovery-service.js.map +1 -0
- package/dist/auth/recovery-worker.d.ts +158 -0
- package/dist/auth/recovery-worker.d.ts.map +1 -0
- package/dist/auth/recovery-worker.js +306 -0
- package/dist/auth/recovery-worker.js.map +1 -0
- package/dist/auth/template-engine.d.ts +134 -0
- package/dist/auth/template-engine.d.ts.map +1 -0
- package/dist/auth/template-engine.js +225 -0
- package/dist/auth/template-engine.js.map +1 -0
- package/dist/auth/token-repository.d.ts +238 -0
- package/dist/auth/token-repository.d.ts.map +1 -0
- package/dist/auth/token-repository.js +475 -0
- package/dist/auth/token-repository.js.map +1 -0
- package/dist/auth/tokens.d.ts +45 -0
- package/dist/auth/tokens.d.ts.map +1 -0
- package/dist/auth/tokens.js +51 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +55 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +90 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/health.d.ts +20 -0
- package/dist/cli/commands/health.d.ts.map +1 -0
- package/dist/cli/commands/health.js +80 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/init.d.ts +48 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +349 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +19 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +88 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/seed.d.ts +19 -0
- package/dist/cli/commands/seed.d.ts.map +1 -0
- package/dist/cli/commands/seed.js +71 -0
- package/dist/cli/commands/seed.js.map +1 -0
- package/dist/cli/commands/user-2fa.d.ts +29 -0
- package/dist/cli/commands/user-2fa.d.ts.map +1 -0
- package/dist/cli/commands/user-2fa.js +113 -0
- package/dist/cli/commands/user-2fa.js.map +1 -0
- package/dist/cli/error-handler.d.ts +31 -0
- package/dist/cli/error-handler.d.ts.map +1 -0
- package/dist/cli/error-handler.js +65 -0
- package/dist/cli/error-handler.js.map +1 -0
- package/dist/cli/index.d.ts +48 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output.d.ts +94 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +124 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/prompt.d.ts +48 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +96 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/clients/cache.d.ts +63 -0
- package/dist/clients/cache.d.ts.map +1 -0
- package/dist/clients/cache.js +160 -0
- package/dist/clients/cache.js.map +1 -0
- package/dist/clients/crypto.d.ts +69 -0
- package/dist/clients/crypto.d.ts.map +1 -0
- package/dist/clients/crypto.js +83 -0
- package/dist/clients/crypto.js.map +1 -0
- package/dist/clients/errors.d.ts +27 -0
- package/dist/clients/errors.d.ts.map +1 -0
- package/dist/clients/errors.js +33 -0
- package/dist/clients/errors.js.map +1 -0
- package/dist/clients/index.d.ts +19 -0
- package/dist/clients/index.d.ts.map +1 -0
- package/dist/clients/index.js +23 -0
- package/dist/clients/index.js.map +1 -0
- package/dist/clients/repository.d.ts +161 -0
- package/dist/clients/repository.d.ts.map +1 -0
- package/dist/clients/repository.js +318 -0
- package/dist/clients/repository.js.map +1 -0
- package/dist/clients/resolve-login-methods.d.ts +74 -0
- package/dist/clients/resolve-login-methods.d.ts.map +1 -0
- package/dist/clients/resolve-login-methods.js +68 -0
- package/dist/clients/resolve-login-methods.js.map +1 -0
- package/dist/clients/secret-repository.d.ts +109 -0
- package/dist/clients/secret-repository.d.ts.map +1 -0
- package/dist/clients/secret-repository.js +166 -0
- package/dist/clients/secret-repository.js.map +1 -0
- package/dist/clients/secret-service.d.ts +87 -0
- package/dist/clients/secret-service.d.ts.map +1 -0
- package/dist/clients/secret-service.js +204 -0
- package/dist/clients/secret-service.js.map +1 -0
- package/dist/clients/service.d.ts +158 -0
- package/dist/clients/service.d.ts.map +1 -0
- package/dist/clients/service.js +523 -0
- package/dist/clients/service.js.map +1 -0
- package/dist/clients/types.d.ts +214 -0
- package/dist/clients/types.d.ts.map +1 -0
- package/dist/clients/types.js +77 -0
- package/dist/clients/types.js.map +1 -0
- package/dist/clients/validators.d.ts +87 -0
- package/dist/clients/validators.d.ts.map +1 -0
- package/dist/clients/validators.js +164 -0
- package/dist/clients/validators.js.map +1 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +52 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +35 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +167 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/custom-claims/cache.d.ts +48 -0
- package/dist/custom-claims/cache.d.ts.map +1 -0
- package/dist/custom-claims/cache.js +122 -0
- package/dist/custom-claims/cache.js.map +1 -0
- package/dist/custom-claims/errors.d.ts +25 -0
- package/dist/custom-claims/errors.d.ts.map +1 -0
- package/dist/custom-claims/errors.js +31 -0
- package/dist/custom-claims/errors.js.map +1 -0
- package/dist/custom-claims/index.d.ts +14 -0
- package/dist/custom-claims/index.d.ts.map +1 -0
- package/dist/custom-claims/index.js +17 -0
- package/dist/custom-claims/index.js.map +1 -0
- package/dist/custom-claims/repository.d.ts +147 -0
- package/dist/custom-claims/repository.d.ts.map +1 -0
- package/dist/custom-claims/repository.js +338 -0
- package/dist/custom-claims/repository.js.map +1 -0
- package/dist/custom-claims/service.d.ts +129 -0
- package/dist/custom-claims/service.d.ts.map +1 -0
- package/dist/custom-claims/service.js +296 -0
- package/dist/custom-claims/service.js.map +1 -0
- package/dist/custom-claims/types.d.ts +132 -0
- package/dist/custom-claims/types.d.ts.map +1 -0
- package/dist/custom-claims/types.js +61 -0
- package/dist/custom-claims/types.js.map +1 -0
- package/dist/custom-claims/validators.d.ts +61 -0
- package/dist/custom-claims/validators.d.ts.map +1 -0
- package/dist/custom-claims/validators.js +136 -0
- package/dist/custom-claims/validators.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/admin-permissions.d.ts +147 -0
- package/dist/lib/admin-permissions.d.ts.map +1 -0
- package/dist/lib/admin-permissions.js +261 -0
- package/dist/lib/admin-permissions.js.map +1 -0
- package/dist/lib/audit-log.d.ts +45 -0
- package/dist/lib/audit-log.d.ts.map +1 -0
- package/dist/lib/audit-log.js +79 -0
- package/dist/lib/audit-log.js.map +1 -0
- package/dist/lib/branding-assets.d.ts +47 -0
- package/dist/lib/branding-assets.d.ts.map +1 -0
- package/dist/lib/branding-assets.js +93 -0
- package/dist/lib/branding-assets.js.map +1 -0
- package/dist/lib/bulk-operations.d.ts +54 -0
- package/dist/lib/bulk-operations.d.ts.map +1 -0
- package/dist/lib/bulk-operations.js +201 -0
- package/dist/lib/bulk-operations.js.map +1 -0
- package/dist/lib/cursor.d.ts +110 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +115 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/data-export.d.ts +67 -0
- package/dist/lib/data-export.d.ts.map +1 -0
- package/dist/lib/data-export.js +272 -0
- package/dist/lib/data-export.js.map +1 -0
- package/dist/lib/data-import-plan.d.ts +50 -0
- package/dist/lib/data-import-plan.d.ts.map +1 -0
- package/dist/lib/data-import-plan.js +235 -0
- package/dist/lib/data-import-plan.js.map +1 -0
- package/dist/lib/data-import.d.ts +276 -0
- package/dist/lib/data-import.d.ts.map +1 -0
- package/dist/lib/data-import.js +1694 -0
- package/dist/lib/data-import.js.map +1 -0
- package/dist/lib/database.d.ts +22 -0
- package/dist/lib/database.d.ts.map +1 -0
- package/dist/lib/database.js +103 -0
- package/dist/lib/database.js.map +1 -0
- package/dist/lib/entity-history.d.ts +52 -0
- package/dist/lib/entity-history.d.ts.map +1 -0
- package/dist/lib/entity-history.js +121 -0
- package/dist/lib/entity-history.js.map +1 -0
- package/dist/lib/etag.d.ts +92 -0
- package/dist/lib/etag.d.ts.map +1 -0
- package/dist/lib/etag.js +155 -0
- package/dist/lib/etag.js.map +1 -0
- package/dist/lib/image-validator.d.ts +44 -0
- package/dist/lib/image-validator.d.ts.map +1 -0
- package/dist/lib/image-validator.js +204 -0
- package/dist/lib/image-validator.js.map +1 -0
- package/dist/lib/logger.d.ts +15 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +84 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/migrator.d.ts +14 -0
- package/dist/lib/migrator.d.ts.map +1 -0
- package/dist/lib/migrator.js +34 -0
- package/dist/lib/migrator.js.map +1 -0
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +29 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/runtime-paths.d.ts +38 -0
- package/dist/lib/runtime-paths.d.ts.map +1 -0
- package/dist/lib/runtime-paths.js +50 -0
- package/dist/lib/runtime-paths.js.map +1 -0
- package/dist/lib/session-tracking.d.ts +81 -0
- package/dist/lib/session-tracking.d.ts.map +1 -0
- package/dist/lib/session-tracking.js +145 -0
- package/dist/lib/session-tracking.js.map +1 -0
- package/dist/lib/signing-key-crypto.d.ts +53 -0
- package/dist/lib/signing-key-crypto.d.ts.map +1 -0
- package/dist/lib/signing-key-crypto.js +108 -0
- package/dist/lib/signing-key-crypto.js.map +1 -0
- package/dist/lib/signing-keys.d.ts +141 -0
- package/dist/lib/signing-keys.d.ts.map +1 -0
- package/dist/lib/signing-keys.js +206 -0
- package/dist/lib/signing-keys.js.map +1 -0
- package/dist/lib/stats.d.ts +83 -0
- package/dist/lib/stats.d.ts.map +1 -0
- package/dist/lib/stats.js +187 -0
- package/dist/lib/stats.js.map +1 -0
- package/dist/lib/super-admin-protection.d.ts +69 -0
- package/dist/lib/super-admin-protection.d.ts.map +1 -0
- package/dist/lib/super-admin-protection.js +102 -0
- package/dist/lib/super-admin-protection.js.map +1 -0
- package/dist/lib/system-config.d.ts +79 -0
- package/dist/lib/system-config.d.ts.map +1 -0
- package/dist/lib/system-config.js +159 -0
- package/dist/lib/system-config.js.map +1 -0
- package/dist/middleware/admin-auth.d.ts +100 -0
- package/dist/middleware/admin-auth.d.ts.map +1 -0
- package/dist/middleware/admin-auth.js +241 -0
- package/dist/middleware/admin-auth.js.map +1 -0
- package/dist/middleware/admin-cors.d.ts +41 -0
- package/dist/middleware/admin-cors.d.ts.map +1 -0
- package/dist/middleware/admin-cors.js +83 -0
- package/dist/middleware/admin-cors.js.map +1 -0
- package/dist/middleware/admin-mutation-audit.d.ts +9 -0
- package/dist/middleware/admin-mutation-audit.d.ts.map +1 -0
- package/dist/middleware/admin-mutation-audit.js +76 -0
- package/dist/middleware/admin-mutation-audit.js.map +1 -0
- package/dist/middleware/admin-rate-limiter.d.ts +56 -0
- package/dist/middleware/admin-rate-limiter.d.ts.map +1 -0
- package/dist/middleware/admin-rate-limiter.js +97 -0
- package/dist/middleware/admin-rate-limiter.js.map +1 -0
- package/dist/middleware/client-secret-hash.d.ts +34 -0
- package/dist/middleware/client-secret-hash.d.ts.map +1 -0
- package/dist/middleware/client-secret-hash.js +74 -0
- package/dist/middleware/client-secret-hash.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +3 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +93 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/health.d.ts +3 -0
- package/dist/middleware/health.d.ts.map +1 -0
- package/dist/middleware/health.js +35 -0
- package/dist/middleware/health.js.map +1 -0
- package/dist/middleware/metrics.d.ts +40 -0
- package/dist/middleware/metrics.d.ts.map +1 -0
- package/dist/middleware/metrics.js +75 -0
- package/dist/middleware/metrics.js.map +1 -0
- package/dist/middleware/oidc-client-tenant.d.ts +37 -0
- package/dist/middleware/oidc-client-tenant.d.ts.map +1 -0
- package/dist/middleware/oidc-client-tenant.js +156 -0
- package/dist/middleware/oidc-client-tenant.js.map +1 -0
- package/dist/middleware/oidc-cors.d.ts +33 -0
- package/dist/middleware/oidc-cors.d.ts.map +1 -0
- package/dist/middleware/oidc-cors.js +68 -0
- package/dist/middleware/oidc-cors.js.map +1 -0
- package/dist/middleware/oidc-preflight-cors.d.ts +54 -0
- package/dist/middleware/oidc-preflight-cors.d.ts.map +1 -0
- package/dist/middleware/oidc-preflight-cors.js +267 -0
- package/dist/middleware/oidc-preflight-cors.js.map +1 -0
- package/dist/middleware/prompt-login-reset.d.ts +103 -0
- package/dist/middleware/prompt-login-reset.d.ts.map +1 -0
- package/dist/middleware/prompt-login-reset.js +204 -0
- package/dist/middleware/prompt-login-reset.js.map +1 -0
- package/dist/middleware/ready.d.ts +23 -0
- package/dist/middleware/ready.d.ts.map +1 -0
- package/dist/middleware/ready.js +60 -0
- package/dist/middleware/ready.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +27 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +46 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/middleware/require-permission.d.ts +28 -0
- package/dist/middleware/require-permission.d.ts.map +1 -0
- package/dist/middleware/require-permission.js +63 -0
- package/dist/middleware/require-permission.js.map +1 -0
- package/dist/middleware/require-user-organization.d.ts +18 -0
- package/dist/middleware/require-user-organization.d.ts.map +1 -0
- package/dist/middleware/require-user-organization.js +53 -0
- package/dist/middleware/require-user-organization.js.map +1 -0
- package/dist/middleware/root-page.d.ts +62 -0
- package/dist/middleware/root-page.d.ts.map +1 -0
- package/dist/middleware/root-page.js +134 -0
- package/dist/middleware/root-page.js.map +1 -0
- package/dist/middleware/security-headers.d.ts +98 -0
- package/dist/middleware/security-headers.d.ts.map +1 -0
- package/dist/middleware/security-headers.js +159 -0
- package/dist/middleware/security-headers.js.map +1 -0
- package/dist/middleware/tenant-resolver.d.ts +37 -0
- package/dist/middleware/tenant-resolver.d.ts.map +1 -0
- package/dist/middleware/tenant-resolver.js +71 -0
- package/dist/middleware/tenant-resolver.js.map +1 -0
- package/dist/middleware/token-rate-limiter.d.ts +89 -0
- package/dist/middleware/token-rate-limiter.d.ts.map +1 -0
- package/dist/middleware/token-rate-limiter.js +189 -0
- package/dist/middleware/token-rate-limiter.js.map +1 -0
- package/dist/oidc/account-finder.d.ts +52 -0
- package/dist/oidc/account-finder.d.ts.map +1 -0
- package/dist/oidc/account-finder.js +134 -0
- package/dist/oidc/account-finder.js.map +1 -0
- package/dist/oidc/adapter-factory.d.ts +90 -0
- package/dist/oidc/adapter-factory.d.ts.map +1 -0
- package/dist/oidc/adapter-factory.js +165 -0
- package/dist/oidc/adapter-factory.js.map +1 -0
- package/dist/oidc/configuration.d.ts +155 -0
- package/dist/oidc/configuration.d.ts.map +1 -0
- package/dist/oidc/configuration.js +531 -0
- package/dist/oidc/configuration.js.map +1 -0
- package/dist/oidc/postgres-adapter.d.ts +159 -0
- package/dist/oidc/postgres-adapter.d.ts.map +1 -0
- package/dist/oidc/postgres-adapter.js +222 -0
- package/dist/oidc/postgres-adapter.js.map +1 -0
- package/dist/oidc/protocol-security-observer.d.ts +38 -0
- package/dist/oidc/protocol-security-observer.d.ts.map +1 -0
- package/dist/oidc/protocol-security-observer.js +93 -0
- package/dist/oidc/protocol-security-observer.js.map +1 -0
- package/dist/oidc/provider.d.ts +37 -0
- package/dist/oidc/provider.d.ts.map +1 -0
- package/dist/oidc/provider.js +71 -0
- package/dist/oidc/provider.js.map +1 -0
- package/dist/oidc/redis-adapter.d.ts +140 -0
- package/dist/oidc/redis-adapter.d.ts.map +1 -0
- package/dist/oidc/redis-adapter.js +344 -0
- package/dist/oidc/redis-adapter.js.map +1 -0
- package/dist/organizations/cache.d.ts +60 -0
- package/dist/organizations/cache.d.ts.map +1 -0
- package/dist/organizations/cache.js +157 -0
- package/dist/organizations/cache.js.map +1 -0
- package/dist/organizations/errors.d.ts +25 -0
- package/dist/organizations/errors.d.ts.map +1 -0
- package/dist/organizations/errors.js +31 -0
- package/dist/organizations/errors.js.map +1 -0
- package/dist/organizations/index.d.ts +15 -0
- package/dist/organizations/index.d.ts.map +1 -0
- package/dist/organizations/index.js +15 -0
- package/dist/organizations/index.js.map +1 -0
- package/dist/organizations/repository.d.ts +183 -0
- package/dist/organizations/repository.d.ts.map +1 -0
- package/dist/organizations/repository.js +354 -0
- package/dist/organizations/repository.js.map +1 -0
- package/dist/organizations/service.d.ts +168 -0
- package/dist/organizations/service.d.ts.map +1 -0
- package/dist/organizations/service.js +511 -0
- package/dist/organizations/service.js.map +1 -0
- package/dist/organizations/slugs.d.ts +57 -0
- package/dist/organizations/slugs.d.ts.map +1 -0
- package/dist/organizations/slugs.js +130 -0
- package/dist/organizations/slugs.js.map +1 -0
- package/dist/organizations/types.d.ts +146 -0
- package/dist/organizations/types.d.ts.map +1 -0
- package/dist/organizations/types.js +49 -0
- package/dist/organizations/types.js.map +1 -0
- package/dist/rbac/cache.d.ts +110 -0
- package/dist/rbac/cache.d.ts.map +1 -0
- package/dist/rbac/cache.js +271 -0
- package/dist/rbac/cache.js.map +1 -0
- package/dist/rbac/errors.d.ts +34 -0
- package/dist/rbac/errors.d.ts.map +1 -0
- package/dist/rbac/errors.js +43 -0
- package/dist/rbac/errors.js.map +1 -0
- package/dist/rbac/index.d.ts +17 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +21 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/mapping-repository.d.ts +121 -0
- package/dist/rbac/mapping-repository.d.ts.map +1 -0
- package/dist/rbac/mapping-repository.js +224 -0
- package/dist/rbac/mapping-repository.js.map +1 -0
- package/dist/rbac/permission-repository.d.ts +100 -0
- package/dist/rbac/permission-repository.d.ts.map +1 -0
- package/dist/rbac/permission-repository.js +190 -0
- package/dist/rbac/permission-repository.js.map +1 -0
- package/dist/rbac/permission-service.d.ts +85 -0
- package/dist/rbac/permission-service.d.ts.map +1 -0
- package/dist/rbac/permission-service.js +179 -0
- package/dist/rbac/permission-service.js.map +1 -0
- package/dist/rbac/role-repository.d.ts +104 -0
- package/dist/rbac/role-repository.d.ts.map +1 -0
- package/dist/rbac/role-repository.js +202 -0
- package/dist/rbac/role-repository.js.map +1 -0
- package/dist/rbac/role-service.d.ts +111 -0
- package/dist/rbac/role-service.d.ts.map +1 -0
- package/dist/rbac/role-service.js +256 -0
- package/dist/rbac/role-service.js.map +1 -0
- package/dist/rbac/slugs.d.ts +116 -0
- package/dist/rbac/slugs.d.ts.map +1 -0
- package/dist/rbac/slugs.js +178 -0
- package/dist/rbac/slugs.js.map +1 -0
- package/dist/rbac/types.d.ts +187 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +75 -0
- package/dist/rbac/types.js.map +1 -0
- package/dist/rbac/user-role-service.d.ts +101 -0
- package/dist/rbac/user-role-service.d.ts.map +1 -0
- package/dist/rbac/user-role-service.js +166 -0
- package/dist/rbac/user-role-service.js.map +1 -0
- package/dist/routes/applications.d.ts +40 -0
- package/dist/routes/applications.d.ts.map +1 -0
- package/dist/routes/applications.js +284 -0
- package/dist/routes/applications.js.map +1 -0
- package/dist/routes/audit.d.ts +31 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +140 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/branding.d.ts +17 -0
- package/dist/routes/branding.d.ts.map +1 -0
- package/dist/routes/branding.js +104 -0
- package/dist/routes/branding.js.map +1 -0
- package/dist/routes/bulk.d.ts +37 -0
- package/dist/routes/bulk.d.ts.map +1 -0
- package/dist/routes/bulk.js +94 -0
- package/dist/routes/bulk.js.map +1 -0
- package/dist/routes/clients.d.ts +44 -0
- package/dist/routes/clients.d.ts.map +1 -0
- package/dist/routes/clients.js +353 -0
- package/dist/routes/clients.js.map +1 -0
- package/dist/routes/config.d.ts +35 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +115 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/custom-claims.d.ts +38 -0
- package/dist/routes/custom-claims.d.ts.map +1 -0
- package/dist/routes/custom-claims.js +208 -0
- package/dist/routes/custom-claims.js.map +1 -0
- package/dist/routes/exports.d.ts +21 -0
- package/dist/routes/exports.d.ts.map +1 -0
- package/dist/routes/exports.js +98 -0
- package/dist/routes/exports.js.map +1 -0
- package/dist/routes/imports.d.ts +18 -0
- package/dist/routes/imports.d.ts.map +1 -0
- package/dist/routes/imports.js +72 -0
- package/dist/routes/imports.js.map +1 -0
- package/dist/routes/interactions.d.ts +111 -0
- package/dist/routes/interactions.d.ts.map +1 -0
- package/dist/routes/interactions.js +1074 -0
- package/dist/routes/interactions.js.map +1 -0
- package/dist/routes/invitation.d.ts +31 -0
- package/dist/routes/invitation.d.ts.map +1 -0
- package/dist/routes/invitation.js +342 -0
- package/dist/routes/invitation.js.map +1 -0
- package/dist/routes/keys.d.ts +28 -0
- package/dist/routes/keys.d.ts.map +1 -0
- package/dist/routes/keys.js +91 -0
- package/dist/routes/keys.js.map +1 -0
- package/dist/routes/magic-link.d.ts +43 -0
- package/dist/routes/magic-link.d.ts.map +1 -0
- package/dist/routes/magic-link.js +264 -0
- package/dist/routes/magic-link.js.map +1 -0
- package/dist/routes/organizations.d.ts +38 -0
- package/dist/routes/organizations.d.ts.map +1 -0
- package/dist/routes/organizations.js +347 -0
- package/dist/routes/organizations.js.map +1 -0
- package/dist/routes/password-reset.d.ts +65 -0
- package/dist/routes/password-reset.d.ts.map +1 -0
- package/dist/routes/password-reset.js +493 -0
- package/dist/routes/password-reset.js.map +1 -0
- package/dist/routes/permissions.d.ts +33 -0
- package/dist/routes/permissions.d.ts.map +1 -0
- package/dist/routes/permissions.js +166 -0
- package/dist/routes/permissions.js.map +1 -0
- package/dist/routes/roles.d.ts +37 -0
- package/dist/routes/roles.d.ts.map +1 -0
- package/dist/routes/roles.js +222 -0
- package/dist/routes/roles.js.map +1 -0
- package/dist/routes/sessions.d.ts +37 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +121 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/stats.d.ts +28 -0
- package/dist/routes/stats.d.ts.map +1 -0
- package/dist/routes/stats.js +65 -0
- package/dist/routes/stats.js.map +1 -0
- package/dist/routes/two-factor-admin.d.ts +54 -0
- package/dist/routes/two-factor-admin.d.ts.map +1 -0
- package/dist/routes/two-factor-admin.js +344 -0
- package/dist/routes/two-factor-admin.js.map +1 -0
- package/dist/routes/two-factor.d.ts +31 -0
- package/dist/routes/two-factor.d.ts.map +1 -0
- package/dist/routes/two-factor.js +595 -0
- package/dist/routes/two-factor.js.map +1 -0
- package/dist/routes/user-roles.d.ts +33 -0
- package/dist/routes/user-roles.d.ts.map +1 -0
- package/dist/routes/user-roles.js +129 -0
- package/dist/routes/user-roles.js.map +1 -0
- package/dist/routes/users.d.ts +61 -0
- package/dist/routes/users.d.ts.map +1 -0
- package/dist/routes/users.js +868 -0
- package/dist/routes/users.js.map +1 -0
- package/dist/security/decision-context.d.ts +52 -0
- package/dist/security/decision-context.d.ts.map +1 -0
- package/dist/security/decision-context.js +150 -0
- package/dist/security/decision-context.js.map +1 -0
- package/dist/security/decision-event.d.ts +128 -0
- package/dist/security/decision-event.d.ts.map +1 -0
- package/dist/security/decision-event.js +225 -0
- package/dist/security/decision-event.js.map +1 -0
- package/dist/security/transport-decision.d.ts +6 -0
- package/dist/security/transport-decision.d.ts.map +1 -0
- package/dist/security/transport-decision.js +37 -0
- package/dist/security/transport-decision.js.map +1 -0
- package/dist/server.d.ts +50 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +491 -0
- package/dist/server.js.map +1 -0
- package/dist/two-factor/cache.d.ts +47 -0
- package/dist/two-factor/cache.d.ts.map +1 -0
- package/dist/two-factor/cache.js +122 -0
- package/dist/two-factor/cache.js.map +1 -0
- package/dist/two-factor/crypto.d.ts +41 -0
- package/dist/two-factor/crypto.d.ts.map +1 -0
- package/dist/two-factor/crypto.js +94 -0
- package/dist/two-factor/crypto.js.map +1 -0
- package/dist/two-factor/errors.d.ts +82 -0
- package/dist/two-factor/errors.d.ts.map +1 -0
- package/dist/two-factor/errors.js +112 -0
- package/dist/two-factor/errors.js.map +1 -0
- package/dist/two-factor/index.d.ts +18 -0
- package/dist/two-factor/index.d.ts.map +1 -0
- package/dist/two-factor/index.js +25 -0
- package/dist/two-factor/index.js.map +1 -0
- package/dist/two-factor/otp.d.ts +43 -0
- package/dist/two-factor/otp.d.ts.map +1 -0
- package/dist/two-factor/otp.js +57 -0
- package/dist/two-factor/otp.js.map +1 -0
- package/dist/two-factor/recovery.d.ts +45 -0
- package/dist/two-factor/recovery.d.ts.map +1 -0
- package/dist/two-factor/recovery.js +104 -0
- package/dist/two-factor/recovery.js.map +1 -0
- package/dist/two-factor/repository.d.ts +156 -0
- package/dist/two-factor/repository.d.ts.map +1 -0
- package/dist/two-factor/repository.js +251 -0
- package/dist/two-factor/repository.js.map +1 -0
- package/dist/two-factor/service.d.ts +232 -0
- package/dist/two-factor/service.d.ts.map +1 -0
- package/dist/two-factor/service.js +599 -0
- package/dist/two-factor/service.js.map +1 -0
- package/dist/two-factor/totp.d.ts +57 -0
- package/dist/two-factor/totp.d.ts.map +1 -0
- package/dist/two-factor/totp.js +96 -0
- package/dist/two-factor/totp.js.map +1 -0
- package/dist/two-factor/types.d.ts +152 -0
- package/dist/two-factor/types.d.ts.map +1 -0
- package/dist/two-factor/types.js +64 -0
- package/dist/two-factor/types.js.map +1 -0
- package/dist/users/cache.d.ts +49 -0
- package/dist/users/cache.d.ts.map +1 -0
- package/dist/users/cache.js +140 -0
- package/dist/users/cache.js.map +1 -0
- package/dist/users/claims.d.ts +67 -0
- package/dist/users/claims.d.ts.map +1 -0
- package/dist/users/claims.js +104 -0
- package/dist/users/claims.js.map +1 -0
- package/dist/users/errors.d.ts +25 -0
- package/dist/users/errors.d.ts.map +1 -0
- package/dist/users/errors.js +31 -0
- package/dist/users/errors.js.map +1 -0
- package/dist/users/gdpr.d.ts +110 -0
- package/dist/users/gdpr.d.ts.map +1 -0
- package/dist/users/gdpr.js +211 -0
- package/dist/users/gdpr.js.map +1 -0
- package/dist/users/index.d.ts +20 -0
- package/dist/users/index.d.ts.map +1 -0
- package/dist/users/index.js +19 -0
- package/dist/users/index.js.map +1 -0
- package/dist/users/password.d.ts +85 -0
- package/dist/users/password.d.ts.map +1 -0
- package/dist/users/password.js +138 -0
- package/dist/users/password.js.map +1 -0
- package/dist/users/repository.d.ts +263 -0
- package/dist/users/repository.d.ts.map +1 -0
- package/dist/users/repository.js +499 -0
- package/dist/users/repository.js.map +1 -0
- package/dist/users/service.d.ts +299 -0
- package/dist/users/service.d.ts.map +1 -0
- package/dist/users/service.js +698 -0
- package/dist/users/service.js.map +1 -0
- package/dist/users/types.d.ts +220 -0
- package/dist/users/types.d.ts.map +1 -0
- package/dist/users/types.js +77 -0
- package/dist/users/types.js.map +1 -0
- package/locales/default/en/common.json +10 -0
- package/locales/default/en/consent.json +13 -0
- package/locales/default/en/emails.json +17 -0
- package/locales/default/en/errors.json +21 -0
- package/locales/default/en/forgot-password.json +11 -0
- package/locales/default/en/invitation.json +18 -0
- package/locales/default/en/login.json +17 -0
- package/locales/default/en/logout.json +9 -0
- package/locales/default/en/magic-link.json +12 -0
- package/locales/default/en/reset-password.json +16 -0
- package/locales/default/en/two-factor.json +29 -0
- package/migrations/.gitkeep +0 -0
- package/migrations/001_extensions.sql +22 -0
- package/migrations/002_organizations.sql +43 -0
- package/migrations/003_applications.sql +50 -0
- package/migrations/004_clients.sql +74 -0
- package/migrations/005_users.sql +119 -0
- package/migrations/006_roles_permissions.sql +80 -0
- package/migrations/007_custom_claims.sql +55 -0
- package/migrations/008_config.sql +51 -0
- package/migrations/009_audit_log.sql +31 -0
- package/migrations/010_oidc_adapter.sql +34 -0
- package/migrations/011_seed.sql +53 -0
- package/migrations/012_two_factor.sql +88 -0
- package/migrations/013_client_secret_sha256.sql +22 -0
- package/migrations/014_login_methods.sql +34 -0
- package/migrations/015_signing_key_encryption.sql +20 -0
- package/migrations/016_failed_login_count.sql +27 -0
- package/migrations/017_audit_retention.sql +11 -0
- package/migrations/018_admin_api_enhancements.sql +78 -0
- package/migrations/019_invitation_details.sql +27 -0
- package/migrations/020_two_factor_admin_permission.sql +108 -0
- package/migrations/021_auth_recovery_jobs.sql +74 -0
- package/migrations/022_recovery_artifact_ownership.sql +25 -0
- package/migrations/023_magic_link_authority.sql +39 -0
- package/package.json +106 -0
- package/templates/default/emails/invitation.hbs +39 -0
- package/templates/default/emails/invitation.txt.hbs +18 -0
- package/templates/default/emails/magic-link.hbs +30 -0
- package/templates/default/emails/magic-link.txt.hbs +11 -0
- package/templates/default/emails/otp-code.hbs +31 -0
- package/templates/default/emails/otp-code.txt.hbs +15 -0
- package/templates/default/emails/password-changed.hbs +24 -0
- package/templates/default/emails/password-changed.txt.hbs +7 -0
- package/templates/default/emails/password-reset.hbs +30 -0
- package/templates/default/emails/password-reset.txt.hbs +11 -0
- package/templates/default/emails/welcome.hbs +25 -0
- package/templates/default/emails/welcome.txt.hbs +9 -0
- package/templates/default/layouts/main.hbs +49 -0
- package/templates/default/pages/accept-invite.hbs +25 -0
- package/templates/default/pages/consent.hbs +27 -0
- package/templates/default/pages/error.hbs +15 -0
- package/templates/default/pages/forgot-password.hbs +21 -0
- package/templates/default/pages/invite-expired.hbs +6 -0
- package/templates/default/pages/invite-success.hbs +9 -0
- package/templates/default/pages/login.hbs +108 -0
- package/templates/default/pages/logout-success.hbs +5 -0
- package/templates/default/pages/logout.hbs +24 -0
- package/templates/default/pages/magic-link-sent.hbs +10 -0
- package/templates/default/pages/magic-link-success.hbs +17 -0
- package/templates/default/pages/reset-password.hbs +20 -0
- package/templates/default/pages/reset-success.hbs +9 -0
- package/templates/default/pages/two-factor-setup.hbs +65 -0
- package/templates/default/pages/two-factor-verify.hbs +77 -0
- package/templates/default/partials/flash-messages.hbs +10 -0
- package/templates/default/partials/footer.hbs +4 -0
- package/templates/default/partials/header.hbs +8 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOTP (Time-based One-Time Password) utilities.
|
|
3
|
+
*
|
|
4
|
+
* Implements RFC 6238 TOTP using the `otpauth` library. Provides secret
|
|
5
|
+
* generation, otpauth:// URI construction, QR code generation for
|
|
6
|
+
* authenticator app enrollment, and code verification with a ±1 step
|
|
7
|
+
* time window to accommodate clock drift.
|
|
8
|
+
*
|
|
9
|
+
* QR code generation uses the `qrcode` library to produce data URIs
|
|
10
|
+
* that can be displayed inline in Handlebars templates.
|
|
11
|
+
*/
|
|
12
|
+
import { TOTP, Secret } from 'otpauth';
|
|
13
|
+
import QRCode from 'qrcode';
|
|
14
|
+
/** Default TOTP parameters matching the user_totp table defaults. */
|
|
15
|
+
const DEFAULT_ALGORITHM = 'SHA1';
|
|
16
|
+
const DEFAULT_DIGITS = 6;
|
|
17
|
+
const DEFAULT_PERIOD = 30;
|
|
18
|
+
/**
|
|
19
|
+
* Generate a new TOTP secret.
|
|
20
|
+
*
|
|
21
|
+
* Creates a 20-byte (160-bit) random secret, which is the standard
|
|
22
|
+
* size for SHA-1-based TOTP as recommended by RFC 4226 §4.
|
|
23
|
+
* The secret is returned as a base32-encoded string suitable for
|
|
24
|
+
* storage (after encryption) and otpauth:// URI construction.
|
|
25
|
+
*
|
|
26
|
+
* @returns Base32-encoded TOTP secret
|
|
27
|
+
*/
|
|
28
|
+
export function generateTotpSecret() {
|
|
29
|
+
// Secret.fromRaw generates using crypto.randomBytes internally
|
|
30
|
+
const secret = new Secret({ size: 20 });
|
|
31
|
+
return secret.base32;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate an otpauth:// URI for authenticator app enrollment.
|
|
35
|
+
*
|
|
36
|
+
* The URI encodes the secret, issuer, account name, and TOTP parameters
|
|
37
|
+
* in a format understood by Google Authenticator, Authy, 1Password, etc.
|
|
38
|
+
*
|
|
39
|
+
* @param secret - Base32-encoded TOTP secret
|
|
40
|
+
* @param userEmail - User's email address (displayed as account name)
|
|
41
|
+
* @param issuer - Service name (e.g., "Porta" or org slug)
|
|
42
|
+
* @returns otpauth:// URI string
|
|
43
|
+
*/
|
|
44
|
+
export function generateTotpUri(secret, userEmail, issuer) {
|
|
45
|
+
const totp = new TOTP({
|
|
46
|
+
issuer,
|
|
47
|
+
label: userEmail,
|
|
48
|
+
algorithm: DEFAULT_ALGORITHM,
|
|
49
|
+
digits: DEFAULT_DIGITS,
|
|
50
|
+
period: DEFAULT_PERIOD,
|
|
51
|
+
secret: Secret.fromBase32(secret),
|
|
52
|
+
});
|
|
53
|
+
return totp.toString();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate a QR code data URI from an otpauth:// URI.
|
|
57
|
+
*
|
|
58
|
+
* The returned data URI can be used directly in an <img src="..."> tag
|
|
59
|
+
* in Handlebars templates. Uses SVG format for crisp rendering at any size.
|
|
60
|
+
*
|
|
61
|
+
* @param uri - otpauth:// URI to encode
|
|
62
|
+
* @returns Data URI string (data:image/svg+xml;base64,...)
|
|
63
|
+
*/
|
|
64
|
+
export async function generateQrCodeDataUri(uri) {
|
|
65
|
+
// QRCode.toDataURL generates a PNG data URI by default
|
|
66
|
+
// Using SVG would require toBuffer + manual base64, so PNG is simpler
|
|
67
|
+
return QRCode.toDataURL(uri, {
|
|
68
|
+
errorCorrectionLevel: 'M', // Medium error correction — good balance
|
|
69
|
+
margin: 2,
|
|
70
|
+
width: 256,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Verify a TOTP code against a secret.
|
|
75
|
+
*
|
|
76
|
+
* Allows a ±1 step time window (i.e., the current 30-second window
|
|
77
|
+
* plus one window before and one after) to accommodate minor clock
|
|
78
|
+
* drift between the server and the user's authenticator app.
|
|
79
|
+
*
|
|
80
|
+
* @param code - The 6-digit TOTP code entered by the user
|
|
81
|
+
* @param secret - Base32-encoded TOTP secret
|
|
82
|
+
* @returns True if the code is valid within the time window
|
|
83
|
+
*/
|
|
84
|
+
export function verifyTotpCode(code, secret) {
|
|
85
|
+
const totp = new TOTP({
|
|
86
|
+
algorithm: DEFAULT_ALGORITHM,
|
|
87
|
+
digits: DEFAULT_DIGITS,
|
|
88
|
+
period: DEFAULT_PERIOD,
|
|
89
|
+
secret: Secret.fromBase32(secret),
|
|
90
|
+
});
|
|
91
|
+
// validate() returns the time step delta (0 for exact match, ±1 for adjacent)
|
|
92
|
+
// or null if invalid. A window of 1 allows ±1 step.
|
|
93
|
+
const delta = totp.validate({ token: code, window: 1 });
|
|
94
|
+
return delta !== null;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=totp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.js","sourceRoot":"","sources":["../../src/two-factor/totp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,qEAAqE;AACrE,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB;IAChC,+DAA+D;IAC/D,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,SAAiB,EACjB,MAAc;IAEd,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,MAAM;QACN,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,iBAAiB;QAC5B,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAW;IACrD,uDAAuD;IACvD,sEAAsE;IACtE,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QAC3B,oBAAoB,EAAE,GAAG,EAAE,yCAAyC;QACpE,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,GAAG;KACX,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAAc;IACzD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,SAAS,EAAE,iBAAiB;QAC5B,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,oDAAoD;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACxD,OAAO,KAAK,KAAK,IAAI,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-factor authentication types and interfaces.
|
|
3
|
+
*
|
|
4
|
+
* Defines data structures for the 2FA module: method and policy enums,
|
|
5
|
+
* TOTP configuration, email OTP codes, recovery codes, setup results,
|
|
6
|
+
* and status tracking. Also provides row mapping functions for
|
|
7
|
+
* converting snake_case PostgreSQL rows to camelCase TypeScript objects.
|
|
8
|
+
*
|
|
9
|
+
* These types are the foundation for all other two-factor modules
|
|
10
|
+
* (repository, cache, service, routes, CLI).
|
|
11
|
+
*/
|
|
12
|
+
/** The 2FA method a user has configured. */
|
|
13
|
+
export type TwoFactorMethod = 'email' | 'totp';
|
|
14
|
+
/**
|
|
15
|
+
* Organization-level 2FA policy — controls whether 2FA is required for members.
|
|
16
|
+
* - 'optional': users may enable 2FA but it's not required
|
|
17
|
+
* - 'required_email': all users must use email OTP
|
|
18
|
+
* - 'required_totp': all users must use authenticator app (TOTP)
|
|
19
|
+
* - 'required_any': all users must use any supported 2FA method
|
|
20
|
+
*/
|
|
21
|
+
export type TwoFactorPolicy = 'optional' | 'required_email' | 'required_totp' | 'required_any';
|
|
22
|
+
/**
|
|
23
|
+
* TOTP configuration record for a user.
|
|
24
|
+
* Secrets are stored encrypted with AES-256-GCM; the IV and auth tag
|
|
25
|
+
* are needed alongside the encryption key to decrypt.
|
|
26
|
+
*/
|
|
27
|
+
export interface UserTotp {
|
|
28
|
+
id: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
encryptedSecret: string;
|
|
31
|
+
encryptionIv: string;
|
|
32
|
+
encryptionTag: string;
|
|
33
|
+
algorithm: string;
|
|
34
|
+
digits: number;
|
|
35
|
+
period: number;
|
|
36
|
+
/** True after the user has verified their first TOTP code. */
|
|
37
|
+
verified: boolean;
|
|
38
|
+
createdAt: Date;
|
|
39
|
+
updatedAt: Date;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Email OTP code record.
|
|
43
|
+
* The actual 6-digit code is stored as a SHA-256 hash; the plaintext
|
|
44
|
+
* is only ever sent via email and never stored.
|
|
45
|
+
*/
|
|
46
|
+
export interface OtpCode {
|
|
47
|
+
id: string;
|
|
48
|
+
userId: string;
|
|
49
|
+
codeHash: string;
|
|
50
|
+
expiresAt: Date;
|
|
51
|
+
/** Null if unused; set to a timestamp upon successful verification. */
|
|
52
|
+
usedAt: Date | null;
|
|
53
|
+
createdAt: Date;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Recovery code record.
|
|
57
|
+
* Each code is hashed with Argon2id and can only be used once.
|
|
58
|
+
* Users receive 10 codes at 2FA setup time as a backup.
|
|
59
|
+
*/
|
|
60
|
+
export interface RecoveryCode {
|
|
61
|
+
id: string;
|
|
62
|
+
userId: string;
|
|
63
|
+
codeHash: string;
|
|
64
|
+
/** Null if unused; set to a timestamp upon successful verification. */
|
|
65
|
+
usedAt: Date | null;
|
|
66
|
+
createdAt: Date;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Result returned after 2FA setup — contains everything the user needs
|
|
70
|
+
* to complete enrollment. Recovery codes are shown only once.
|
|
71
|
+
*/
|
|
72
|
+
export interface TwoFactorSetupResult {
|
|
73
|
+
method: TwoFactorMethod;
|
|
74
|
+
/** Plaintext recovery codes — displayed once to the user. */
|
|
75
|
+
recoveryCodes: string[];
|
|
76
|
+
/** otpauth:// URI for authenticator app enrollment (TOTP only). */
|
|
77
|
+
totpUri?: string;
|
|
78
|
+
/** Data URI of QR code image for scanning (TOTP only). */
|
|
79
|
+
qrCodeDataUri?: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Current 2FA status for a user — used by the service layer and CLI.
|
|
83
|
+
*/
|
|
84
|
+
export interface TwoFactorStatus {
|
|
85
|
+
enabled: boolean;
|
|
86
|
+
method: TwoFactorMethod | null;
|
|
87
|
+
totpConfigured: boolean;
|
|
88
|
+
recoveryCodesRemaining: number;
|
|
89
|
+
}
|
|
90
|
+
/** Input data for inserting a new TOTP configuration. */
|
|
91
|
+
export interface InsertTotpData {
|
|
92
|
+
userId: string;
|
|
93
|
+
encryptedSecret: string;
|
|
94
|
+
encryptionIv: string;
|
|
95
|
+
encryptionTag: string;
|
|
96
|
+
algorithm?: string;
|
|
97
|
+
digits?: number;
|
|
98
|
+
period?: number;
|
|
99
|
+
}
|
|
100
|
+
/** Raw database row from the user_totp table (snake_case columns). */
|
|
101
|
+
export interface UserTotpRow {
|
|
102
|
+
id: string;
|
|
103
|
+
user_id: string;
|
|
104
|
+
encrypted_secret: string;
|
|
105
|
+
encryption_iv: string;
|
|
106
|
+
encryption_tag: string;
|
|
107
|
+
algorithm: string;
|
|
108
|
+
digits: number;
|
|
109
|
+
period: number;
|
|
110
|
+
verified: boolean;
|
|
111
|
+
created_at: Date;
|
|
112
|
+
updated_at: Date;
|
|
113
|
+
}
|
|
114
|
+
/** Raw database row from the two_factor_otp_codes table. */
|
|
115
|
+
export interface OtpCodeRow {
|
|
116
|
+
id: string;
|
|
117
|
+
user_id: string;
|
|
118
|
+
code_hash: string;
|
|
119
|
+
expires_at: Date;
|
|
120
|
+
used_at: Date | null;
|
|
121
|
+
created_at: Date;
|
|
122
|
+
}
|
|
123
|
+
/** Raw database row from the two_factor_recovery_codes table. */
|
|
124
|
+
export interface RecoveryCodeRow {
|
|
125
|
+
id: string;
|
|
126
|
+
user_id: string;
|
|
127
|
+
code_hash: string;
|
|
128
|
+
used_at: Date | null;
|
|
129
|
+
created_at: Date;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Map a user_totp database row to a UserTotp object.
|
|
133
|
+
*
|
|
134
|
+
* @param row - Raw database row from the user_totp table
|
|
135
|
+
* @returns Mapped UserTotp object with camelCase properties
|
|
136
|
+
*/
|
|
137
|
+
export declare function mapRowToUserTotp(row: UserTotpRow): UserTotp;
|
|
138
|
+
/**
|
|
139
|
+
* Map a two_factor_otp_codes database row to an OtpCode object.
|
|
140
|
+
*
|
|
141
|
+
* @param row - Raw database row from the two_factor_otp_codes table
|
|
142
|
+
* @returns Mapped OtpCode object with camelCase properties
|
|
143
|
+
*/
|
|
144
|
+
export declare function mapRowToOtpCode(row: OtpCodeRow): OtpCode;
|
|
145
|
+
/**
|
|
146
|
+
* Map a two_factor_recovery_codes database row to a RecoveryCode object.
|
|
147
|
+
*
|
|
148
|
+
* @param row - Raw database row from the two_factor_recovery_codes table
|
|
149
|
+
* @returns Mapped RecoveryCode object with camelCase properties
|
|
150
|
+
*/
|
|
151
|
+
export declare function mapRowToRecoveryCode(row: RecoveryCodeRow): RecoveryCode;
|
|
152
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/two-factor/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-factor authentication types and interfaces.
|
|
3
|
+
*
|
|
4
|
+
* Defines data structures for the 2FA module: method and policy enums,
|
|
5
|
+
* TOTP configuration, email OTP codes, recovery codes, setup results,
|
|
6
|
+
* and status tracking. Also provides row mapping functions for
|
|
7
|
+
* converting snake_case PostgreSQL rows to camelCase TypeScript objects.
|
|
8
|
+
*
|
|
9
|
+
* These types are the foundation for all other two-factor modules
|
|
10
|
+
* (repository, cache, service, routes, CLI).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Map a user_totp database row to a UserTotp object.
|
|
14
|
+
*
|
|
15
|
+
* @param row - Raw database row from the user_totp table
|
|
16
|
+
* @returns Mapped UserTotp object with camelCase properties
|
|
17
|
+
*/
|
|
18
|
+
export function mapRowToUserTotp(row) {
|
|
19
|
+
return {
|
|
20
|
+
id: row.id,
|
|
21
|
+
userId: row.user_id,
|
|
22
|
+
encryptedSecret: row.encrypted_secret,
|
|
23
|
+
encryptionIv: row.encryption_iv,
|
|
24
|
+
encryptionTag: row.encryption_tag,
|
|
25
|
+
algorithm: row.algorithm,
|
|
26
|
+
digits: row.digits,
|
|
27
|
+
period: row.period,
|
|
28
|
+
verified: row.verified,
|
|
29
|
+
createdAt: row.created_at,
|
|
30
|
+
updatedAt: row.updated_at,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Map a two_factor_otp_codes database row to an OtpCode object.
|
|
35
|
+
*
|
|
36
|
+
* @param row - Raw database row from the two_factor_otp_codes table
|
|
37
|
+
* @returns Mapped OtpCode object with camelCase properties
|
|
38
|
+
*/
|
|
39
|
+
export function mapRowToOtpCode(row) {
|
|
40
|
+
return {
|
|
41
|
+
id: row.id,
|
|
42
|
+
userId: row.user_id,
|
|
43
|
+
codeHash: row.code_hash,
|
|
44
|
+
expiresAt: row.expires_at,
|
|
45
|
+
usedAt: row.used_at,
|
|
46
|
+
createdAt: row.created_at,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Map a two_factor_recovery_codes database row to a RecoveryCode object.
|
|
51
|
+
*
|
|
52
|
+
* @param row - Raw database row from the two_factor_recovery_codes table
|
|
53
|
+
* @returns Mapped RecoveryCode object with camelCase properties
|
|
54
|
+
*/
|
|
55
|
+
export function mapRowToRecoveryCode(row) {
|
|
56
|
+
return {
|
|
57
|
+
id: row.id,
|
|
58
|
+
userId: row.user_id,
|
|
59
|
+
codeHash: row.code_hash,
|
|
60
|
+
usedAt: row.used_at,
|
|
61
|
+
createdAt: row.created_at,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/two-factor/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgKH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAgB;IAC/C,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,eAAe,EAAE,GAAG,CAAC,gBAAgB;QACrC,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,aAAa,EAAE,GAAG,CAAC,cAAc;QACjC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAe;IAC7C,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAoB;IACvD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User cache — Redis-backed fast lookup layer.
|
|
3
|
+
*
|
|
4
|
+
* Provides get/set/invalidate operations for User objects stored in
|
|
5
|
+
* Redis. Users are cached by ID only (not by email) because:
|
|
6
|
+
* - Email lookups happen during login (which hits DB for password_hash anyway)
|
|
7
|
+
* - ID lookups happen during token validation, userinfo, etc. (cacheable)
|
|
8
|
+
* - Simpler invalidation — one key per user instead of two
|
|
9
|
+
*
|
|
10
|
+
* Date fields are serialized as ISO 8601 strings by JSON.stringify()
|
|
11
|
+
* and restored to Date objects on read. The user cache has 5 nullable
|
|
12
|
+
* date fields: passwordChangedAt, lockedAt, lastLoginAt, createdAt,
|
|
13
|
+
* updatedAt.
|
|
14
|
+
*
|
|
15
|
+
* All Redis errors are caught and logged — cache failures never
|
|
16
|
+
* propagate to callers. The system gracefully degrades to direct
|
|
17
|
+
* database lookups when Redis is unavailable.
|
|
18
|
+
*/
|
|
19
|
+
import type { User } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Get a user from cache by ID.
|
|
22
|
+
*
|
|
23
|
+
* Returns null on cache miss, invalid JSON, or Redis error.
|
|
24
|
+
* Callers should fall back to the database on null.
|
|
25
|
+
*
|
|
26
|
+
* @param id - User UUID
|
|
27
|
+
* @returns Cached user or null
|
|
28
|
+
*/
|
|
29
|
+
export declare function getCachedUserById(id: string): Promise<User | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Store a user in cache under the ID key.
|
|
32
|
+
*
|
|
33
|
+
* Date fields are serialized to ISO 8601 strings automatically
|
|
34
|
+
* by JSON.stringify(). Silent failure — cache write errors are
|
|
35
|
+
* logged but never propagated.
|
|
36
|
+
*
|
|
37
|
+
* @param user - User to cache
|
|
38
|
+
*/
|
|
39
|
+
export declare function cacheUser(user: User): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Invalidate the cache entry for a user.
|
|
42
|
+
*
|
|
43
|
+
* Should be called after any write operation (create, update, status
|
|
44
|
+
* change, password change) to ensure stale data is not served.
|
|
45
|
+
*
|
|
46
|
+
* @param id - User UUID
|
|
47
|
+
*/
|
|
48
|
+
export declare function invalidateUserCache(id: string): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/users/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAgBvC;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAWxE;AAMD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAWzD;AAMD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User cache — Redis-backed fast lookup layer.
|
|
3
|
+
*
|
|
4
|
+
* Provides get/set/invalidate operations for User objects stored in
|
|
5
|
+
* Redis. Users are cached by ID only (not by email) because:
|
|
6
|
+
* - Email lookups happen during login (which hits DB for password_hash anyway)
|
|
7
|
+
* - ID lookups happen during token validation, userinfo, etc. (cacheable)
|
|
8
|
+
* - Simpler invalidation — one key per user instead of two
|
|
9
|
+
*
|
|
10
|
+
* Date fields are serialized as ISO 8601 strings by JSON.stringify()
|
|
11
|
+
* and restored to Date objects on read. The user cache has 5 nullable
|
|
12
|
+
* date fields: passwordChangedAt, lockedAt, lastLoginAt, createdAt,
|
|
13
|
+
* updatedAt.
|
|
14
|
+
*
|
|
15
|
+
* All Redis errors are caught and logged — cache failures never
|
|
16
|
+
* propagate to callers. The system gracefully degrades to direct
|
|
17
|
+
* database lookups when Redis is unavailable.
|
|
18
|
+
*/
|
|
19
|
+
import { getRedis } from '../lib/redis.js';
|
|
20
|
+
import { logger } from '../lib/logger.js';
|
|
21
|
+
import { afterDatabaseCommit } from '../lib/database.js';
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Constants
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/** Cache TTL in seconds (5 minutes — matches organizations) */
|
|
26
|
+
const CACHE_TTL = 300;
|
|
27
|
+
/** Key prefix for ID-based lookups */
|
|
28
|
+
const USER_PREFIX = 'user:id:';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Cache retrieval
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/**
|
|
33
|
+
* Get a user from cache by ID.
|
|
34
|
+
*
|
|
35
|
+
* Returns null on cache miss, invalid JSON, or Redis error.
|
|
36
|
+
* Callers should fall back to the database on null.
|
|
37
|
+
*
|
|
38
|
+
* @param id - User UUID
|
|
39
|
+
* @returns Cached user or null
|
|
40
|
+
*/
|
|
41
|
+
export async function getCachedUserById(id) {
|
|
42
|
+
try {
|
|
43
|
+
const redis = getRedis();
|
|
44
|
+
const data = await redis.get(`${USER_PREFIX}${id}`);
|
|
45
|
+
if (!data)
|
|
46
|
+
return null;
|
|
47
|
+
return deserializeUser(data);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Graceful degradation — log and return null so caller falls back to DB
|
|
51
|
+
logger.warn({ event: 'user-cache-read-failed' }, 'User cache read failed');
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Cache storage
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Store a user in cache under the ID key.
|
|
60
|
+
*
|
|
61
|
+
* Date fields are serialized to ISO 8601 strings automatically
|
|
62
|
+
* by JSON.stringify(). Silent failure — cache write errors are
|
|
63
|
+
* logged but never propagated.
|
|
64
|
+
*
|
|
65
|
+
* @param user - User to cache
|
|
66
|
+
*/
|
|
67
|
+
export async function cacheUser(user) {
|
|
68
|
+
await afterDatabaseCommit(async () => {
|
|
69
|
+
try {
|
|
70
|
+
const redis = getRedis();
|
|
71
|
+
const data = JSON.stringify(user);
|
|
72
|
+
await redis.set(`${USER_PREFIX}${user.id}`, data, 'EX', CACHE_TTL);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Graceful degradation — cache write failure is non-fatal
|
|
76
|
+
logger.warn({ event: 'user-cache-write-failed' }, 'User cache write failed');
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Cache invalidation
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
/**
|
|
84
|
+
* Invalidate the cache entry for a user.
|
|
85
|
+
*
|
|
86
|
+
* Should be called after any write operation (create, update, status
|
|
87
|
+
* change, password change) to ensure stale data is not served.
|
|
88
|
+
*
|
|
89
|
+
* @param id - User UUID
|
|
90
|
+
*/
|
|
91
|
+
export async function invalidateUserCache(id) {
|
|
92
|
+
await afterDatabaseCommit(async () => {
|
|
93
|
+
try {
|
|
94
|
+
const redis = getRedis();
|
|
95
|
+
await redis.del(`${USER_PREFIX}${id}`);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Graceful degradation — cache invalidation failure is non-fatal
|
|
99
|
+
logger.warn({ event: 'user-cache-invalidation-failed' }, 'User cache invalidation failed');
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Serialization helpers
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
/**
|
|
107
|
+
* Deserialize a JSON string from Redis into a User object.
|
|
108
|
+
*
|
|
109
|
+
* Converts ISO 8601 date strings back to Date objects for all date
|
|
110
|
+
* fields. The User interface has 5 date fields: createdAt, updatedAt
|
|
111
|
+
* (always present), and passwordChangedAt, lockedAt, lastLoginAt
|
|
112
|
+
* (nullable — only converted when non-null).
|
|
113
|
+
*
|
|
114
|
+
* @param data - JSON string from Redis
|
|
115
|
+
* @returns User object with proper Date instances, or null if parse fails
|
|
116
|
+
*/
|
|
117
|
+
function deserializeUser(data) {
|
|
118
|
+
try {
|
|
119
|
+
const parsed = JSON.parse(data);
|
|
120
|
+
// Restore required Date objects from ISO string serialization
|
|
121
|
+
parsed.createdAt = new Date(parsed.createdAt);
|
|
122
|
+
parsed.updatedAt = new Date(parsed.updatedAt);
|
|
123
|
+
// Restore nullable Date objects (only convert when non-null)
|
|
124
|
+
if (parsed.passwordChangedAt !== null) {
|
|
125
|
+
parsed.passwordChangedAt = new Date(parsed.passwordChangedAt);
|
|
126
|
+
}
|
|
127
|
+
if (parsed.lockedAt !== null) {
|
|
128
|
+
parsed.lockedAt = new Date(parsed.lockedAt);
|
|
129
|
+
}
|
|
130
|
+
if (parsed.lastLoginAt !== null) {
|
|
131
|
+
parsed.lastLoginAt = new Date(parsed.lastLoginAt);
|
|
132
|
+
}
|
|
133
|
+
return parsed;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
logger.warn('Failed to parse cached user JSON');
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/users/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC Standard Claims builder.
|
|
3
|
+
*
|
|
4
|
+
* Builds OIDC Standard Claims from a User profile based on the granted
|
|
5
|
+
* OAuth2 scopes. Follows the scope-to-claims mapping defined in
|
|
6
|
+
* OpenID Connect Core 1.0, §5.4:
|
|
7
|
+
*
|
|
8
|
+
* - openid → sub (always included)
|
|
9
|
+
* - profile → name, given_name, family_name, middle_name, nickname,
|
|
10
|
+
* preferred_username, profile, picture, website, gender,
|
|
11
|
+
* birthdate, zoneinfo, locale, updated_at
|
|
12
|
+
* - email → email, email_verified
|
|
13
|
+
* - phone → phone_number, phone_number_verified
|
|
14
|
+
* - address → address (structured object per §5.1.1)
|
|
15
|
+
*
|
|
16
|
+
* Custom claims (org_id, org_slug, roles) are handled in RD-08, not here.
|
|
17
|
+
* This module only handles the OIDC Standard Claims specification.
|
|
18
|
+
*/
|
|
19
|
+
import type { User } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* OIDC claims object — flexible key-value with required `sub` field.
|
|
22
|
+
* Uses index signature for the wide variety of standard claim names.
|
|
23
|
+
*/
|
|
24
|
+
export interface OidcClaims {
|
|
25
|
+
sub: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Structured address per OIDC §5.1.1.
|
|
30
|
+
* All fields are optional/nullable — the address object is only
|
|
31
|
+
* included when at least one field has a value.
|
|
32
|
+
*/
|
|
33
|
+
export interface OidcAddress {
|
|
34
|
+
street_address?: string | null;
|
|
35
|
+
locality?: string | null;
|
|
36
|
+
region?: string | null;
|
|
37
|
+
postal_code?: string | null;
|
|
38
|
+
country?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build OIDC Standard Claims from a user profile based on granted scopes.
|
|
42
|
+
*
|
|
43
|
+
* The `sub` claim is always included. Additional claims are added based
|
|
44
|
+
* on which scopes are present in the `scopes` array. Null profile fields
|
|
45
|
+
* are included as null (not omitted) — per the OIDC spec, null indicates
|
|
46
|
+
* "no value" which is different from "not requested".
|
|
47
|
+
*
|
|
48
|
+
* The `updated_at` claim is a Unix timestamp (seconds since epoch) per
|
|
49
|
+
* the OIDC specification, not an ISO 8601 string.
|
|
50
|
+
*
|
|
51
|
+
* @param user - User whose profile claims to build
|
|
52
|
+
* @param scopes - Array of granted OAuth2 scope strings
|
|
53
|
+
* @returns Claims object with `sub` and scope-dependent fields
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildUserClaims(user: User, scopes: string[]): OidcClaims;
|
|
56
|
+
/**
|
|
57
|
+
* Check if a user has any address fields populated.
|
|
58
|
+
*
|
|
59
|
+
* Returns true if at least one address field is non-null/non-empty.
|
|
60
|
+
* Used to decide whether to include the address claim object —
|
|
61
|
+
* per the spec, the address claim should not be an empty object.
|
|
62
|
+
*
|
|
63
|
+
* @param user - User to check
|
|
64
|
+
* @returns true if any address field has a value
|
|
65
|
+
*/
|
|
66
|
+
export declare function hasAddress(user: User): boolean;
|
|
67
|
+
//# sourceMappingURL=claims.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../../src/users/claims.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvC;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAoDxE;AAMD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ9C"}
|