alepha 0.21.2 → 0.22.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/README.md +0 -1
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +393 -403
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +25 -56
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +31 -1
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +313 -208
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +152 -42
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +2 -2
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +289 -292
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +39 -33
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +211 -216
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +188 -195
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/oauth/index.d.ts +71 -76
- package/dist/api/oauth/index.d.ts.map +1 -1
- package/dist/api/oauth/index.js.map +1 -1
- package/dist/api/organizations/index.browser.js.map +1 -1
- package/dist/api/organizations/index.d.ts +104 -109
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/organizations/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +43 -16
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +488 -344
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +175 -35
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +396 -402
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/subscriptions/index.d.ts +644 -652
- package/dist/api/subscriptions/index.d.ts.map +1 -1
- package/dist/api/subscriptions/index.js +1 -1
- package/dist/api/subscriptions/index.js.map +1 -1
- package/dist/api/users/index.browser.js +7 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +1073 -1006
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +283 -61
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +134 -140
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/background/index.d.ts +95 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +121 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/index.workerd.js +110 -0
- package/dist/background/index.workerd.js.map +1 -0
- package/dist/batch/index.d.ts +5 -7
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/bucket/index.d.ts +76 -54
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +58 -11
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +200 -5
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +7 -10
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cache/database/index.d.ts +22 -26
- package/dist/cache/database/index.d.ts.map +1 -1
- package/dist/cache/database/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +4 -7
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/captcha/index.d.ts +3 -6
- package/dist/captcha/index.d.ts.map +1 -1
- package/dist/captcha/index.js.map +1 -1
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +417 -214
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +325 -563
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +3 -5
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/i18n/index.d.ts +8 -12
- package/dist/cli/i18n/index.d.ts.map +1 -1
- package/dist/cli/i18n/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +126 -1342
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +136 -2374
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/platform-lib/index.d.ts +1446 -0
- package/dist/cli/platform-lib/index.d.ts.map +1 -0
- package/dist/cli/platform-lib/index.js +2597 -0
- package/dist/cli/platform-lib/index.js.map +1 -0
- package/dist/cli/vendor/index.d.ts +17 -21
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.d.ts +21 -20
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +39 -10
- package/dist/command/index.js.map +1 -1
- package/dist/{containers → container}/core/index.d.ts +13 -15
- package/dist/container/core/index.d.ts.map +1 -0
- package/dist/{containers → container}/core/index.js +23 -14
- package/dist/container/core/index.js.map +1 -0
- package/dist/{containers → container}/core/index.workerd.js +37 -22
- package/dist/container/core/index.workerd.js.map +1 -0
- package/dist/core/index.browser.js +27 -1
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +48 -24
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -1
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -1
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.browser.js.map +1 -1
- package/dist/crypto/index.d.ts +5 -8
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/datetime/index.d.ts +3 -4
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/brevo/index.d.ts +2 -4
- package/dist/email/brevo/index.d.ts.map +1 -1
- package/dist/email/brevo/index.js.map +1 -1
- package/dist/email/cloudflare/index.d.ts +20 -7
- package/dist/email/cloudflare/index.d.ts.map +1 -1
- package/dist/email/cloudflare/index.js +46 -9
- package/dist/email/cloudflare/index.js.map +1 -1
- package/dist/email/core/index.d.ts +6 -9
- package/dist/email/core/index.d.ts.map +1 -1
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.d.ts +10 -13
- package/dist/email/smtp/index.d.ts.map +1 -1
- package/dist/email/smtp/index.js +107 -32
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +1 -2
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +9 -14
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts +2 -4
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/lock/redis/index.js.map +1 -1
- package/dist/logger/index.d.ts +105 -76
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +196 -174
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +16 -20
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +19 -1
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +76 -62
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +20 -2
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +28 -20
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +12 -15
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/core/index.workerd.js.map +1 -1
- package/dist/queue/redis/index.d.ts +3 -5
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/queue/redis/index.js.map +1 -1
- package/dist/react/auth/index.browser.js +9 -2
- package/dist/react/auth/index.browser.js.map +1 -1
- package/dist/react/auth/index.d.ts +14 -9
- package/dist/react/auth/index.d.ts.map +1 -1
- package/dist/react/auth/index.js +9 -2
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +7 -8
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +6 -3
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +2 -4
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.browser.js.map +1 -1
- package/dist/react/head/index.d.ts +2 -4
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +47 -11
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +33 -1
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.d.ts +1 -2
- package/dist/react/intro/index.d.ts.map +1 -1
- package/dist/react/intro/index.js +2 -2
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +65 -19
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +327 -222
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +65 -29
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/index.d.ts +1 -2
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +16 -17
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +20 -25
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +17 -19
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +2 -4
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +10 -13
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +45 -48
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.browser.js.map +1 -1
- package/dist/server/auth/index.d.ts +167 -172
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +4 -8
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.browser.js.map +1 -1
- package/dist/server/cookies/index.d.ts +5 -7
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +88 -73
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +19 -0
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +11 -14
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/etag/index.d.ts +6 -9
- package/dist/server/etag/index.d.ts.map +1 -1
- package/dist/server/etag/index.js.map +1 -1
- package/dist/server/health/index.d.ts +18 -21
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/links/index.browser.js +2 -0
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +63 -67
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +2 -0
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +5 -7
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +3 -5
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +10 -13
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +3 -5
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +5 -8
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -5
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.d.ts +2 -4
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/index.workerd.js.map +1 -1
- package/dist/topic/core/index.d.ts +4 -6
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +5 -8
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/topic/redis/index.js.map +1 -1
- package/package.json +45 -22
- package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
- package/src/api/audits/controllers/AdminAuditController.ts +14 -0
- package/src/api/audits/services/AuditService.ts +21 -88
- package/src/api/files/__tests__/FileService.spec.ts +207 -2
- package/src/api/files/index.ts +3 -0
- package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
- package/src/api/files/schemas/fileResourceSchema.ts +10 -1
- package/src/api/files/services/FileService.ts +170 -72
- package/src/api/jobs/__tests__/$job.spec.ts +24 -1
- package/src/api/jobs/index.ts +4 -3
- package/src/api/jobs/primitives/$job.ts +7 -3
- package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
- package/src/api/jobs/providers/JobProvider.ts +53 -24
- package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
- package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
- package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
- package/src/api/parameters/audits/ParameterAudits.ts +17 -0
- package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
- package/src/api/parameters/index.ts +3 -0
- package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
- package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
- package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
- package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
- package/src/api/parameters/services/ParameterProvider.ts +69 -6
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
- package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
- package/src/api/users/audits/SessionAudits.ts +33 -0
- package/src/api/users/audits/UserAudits.ts +19 -43
- package/src/api/users/controllers/AdminUserController.ts +66 -1
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/entities/users.ts +2 -0
- package/src/api/users/index.ts +9 -1
- package/src/api/users/primitives/$realm.ts +3 -0
- package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
- package/src/api/users/schemas/updateUserSchema.ts +1 -8
- package/src/api/users/schemas/userQuerySchema.ts +7 -0
- package/src/api/users/services/CredentialService.ts +15 -6
- package/src/api/users/services/IdentityService.ts +2 -1
- package/src/api/users/services/RegistrationService.ts +2 -1
- package/src/api/users/services/SessionCrudService.ts +19 -2
- package/src/api/users/services/SessionService.ts +39 -19
- package/src/api/users/services/UserService.ts +106 -8
- package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
- package/src/background/index.ts +37 -0
- package/src/background/index.workerd.ts +28 -0
- package/src/background/providers/BackgroundTaskProvider.ts +70 -0
- package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
- package/src/bucket/__tests__/$bucket.spec.ts +18 -0
- package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
- package/src/bucket/__tests__/shared.ts +30 -0
- package/src/bucket/index.ts +5 -5
- package/src/bucket/index.workerd.ts +11 -4
- package/src/bucket/primitives/$bucket.ts +27 -0
- package/src/bucket/providers/FileStorageProvider.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
- package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
- package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
- package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
- package/src/cli/core/__tests__/init.spec.ts +0 -219
- package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
- package/src/cli/core/commands/build.ts +108 -30
- package/src/cli/core/commands/init.ts +0 -12
- package/src/cli/core/commands/pack.ts +133 -0
- package/src/cli/core/index.ts +3 -0
- package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
- package/src/cli/core/services/PackageManagerUtils.ts +0 -16
- package/src/cli/core/services/ProjectScaffolder.ts +29 -291
- package/src/cli/core/tasks/BuildCloudflareTask.ts +353 -47
- package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
- package/src/cli/core/tasks/BuildTask.ts +34 -0
- package/src/cli/core/templates/apiIndexTs.ts +1 -22
- package/src/cli/core/templates/mainCss.ts +0 -1
- package/src/cli/core/templates/webAppRouterTs.ts +0 -99
- package/src/cli/core/templates/webIndexTs.ts +1 -22
- package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
- package/src/cli/platform/commands/SecretsCommand.ts +8 -6
- package/src/cli/platform/commands/platform.ts +192 -46
- package/src/cli/platform/index.ts +12 -52
- package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
- package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
- package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
- package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +402 -165
- package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
- package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
- package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
- package/src/cli/platform-lib/index.ts +67 -0
- package/src/cli/platform-lib/services/NamingService.ts +136 -0
- package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
- package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
- package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
- package/src/command/__tests__/Runner.spec.ts +20 -0
- package/src/command/helpers/EnvUtils.ts +19 -3
- package/src/command/helpers/Runner.ts +12 -2
- package/src/command/providers/CliProvider.ts +34 -1
- package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
- package/src/{containers → container}/core/index.ts +4 -4
- package/src/{containers → container}/core/index.workerd.ts +19 -3
- package/src/{containers → container}/core/primitives/$container.ts +1 -1
- package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
- package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
- package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
- package/src/core/Alepha.ts +49 -1
- package/src/core/__tests__/$env.spec.ts +42 -0
- package/src/core/__tests__/dump.spec.ts +47 -0
- package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
- package/src/email/cloudflare/index.ts +14 -5
- package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
- package/src/logger/__tests__/Logger.spec.ts +55 -0
- package/src/logger/index.ts +13 -0
- package/src/logger/services/Logger.ts +31 -1
- package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
- package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
- package/src/orm/core/interfaces/PgQuery.ts +4 -1
- package/src/orm/core/services/Repository.ts +27 -11
- package/src/react/auth/hooks/useAuth.ts +10 -5
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
- package/src/react/core/hooks/useAction.ts +14 -3
- package/src/react/core/hooks/useQuery.ts +24 -4
- package/src/react/i18n/components/Translate.tsx +47 -0
- package/src/react/i18n/index.ts +2 -0
- package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
- package/src/react/router/__tests__/$page.spec.tsx +3 -2
- package/src/react/router/__tests__/page-can.spec.ts +18 -13
- package/src/react/router/hooks/useQueryParams.ts +114 -14
- package/src/react/router/primitives/$page.ts +85 -4
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +3 -7
- package/src/react/router/providers/ReactServerProvider.ts +4 -13
- package/src/react/ui/services/SchemaControl.ts +3 -4
- package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
- package/src/server/links/providers/LinkProvider.ts +10 -0
- package/dist/containers/core/index.d.ts.map +0 -1
- package/dist/containers/core/index.js.map +0 -1
- package/dist/containers/core/index.workerd.js.map +0 -1
- package/src/cli/core/templates/componentsJsonTs.ts +0 -39
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
- package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
- package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
- package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
- package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
- package/src/cli/platform/services/NamingService.ts +0 -54
- /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
- /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
- /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
- /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
package/dist/api/users/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $atom, $context, $inject, $module, Alepha, AlephaError, t } from "alepha";
|
|
2
|
-
import {
|
|
2
|
+
import { $audit } from "alepha/api/audits";
|
|
3
3
|
import { $bucket } from "alepha/bucket";
|
|
4
4
|
import { $issuer, $permission, $secure, CryptoProvider, InvalidCredentialsError, SecurityProvider } from "alepha/security";
|
|
5
5
|
import { $action, BadRequestError, ConflictError, HttpError, UnauthorizedError, okSchema } from "alepha/server";
|
|
@@ -21,35 +21,65 @@ import { AlephaApiKeys, ApiKeyService } from "alepha/api/keys";
|
|
|
21
21
|
import { AlephaOAuth, OAuthClientService, oauthOptions } from "alepha/api/oauth";
|
|
22
22
|
import { $parameter, AlephaApiParameters } from "alepha/api/parameters";
|
|
23
23
|
import { mcpStreamableHttpOptions } from "alepha/mcp";
|
|
24
|
-
//#region ../../src/api/users/audits/
|
|
24
|
+
//#region ../../src/api/users/audits/SessionAudits.ts
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Authentication & session-security audit events.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
28
|
+
* Holds two audit types:
|
|
29
|
+
* - `auth` — login / logout / token refresh / MFA.
|
|
30
|
+
* - `security` — rate limiting, session invalidation, and related guards.
|
|
29
31
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
+
* Failed events are logged with `success: false`; severity (`warning`) is
|
|
33
|
+
* derived centrally in `AuditService.create`. Register as a module variant
|
|
34
|
+
* and log via the exposed primitives:
|
|
35
|
+
* `sessionAudits(realm)?.auth.log("login", { success: false, … })`.
|
|
36
|
+
*/
|
|
37
|
+
var SessionAudits = class {
|
|
38
|
+
auth = $audit({
|
|
39
|
+
type: "auth",
|
|
40
|
+
description: "Authentication events (login, logout, token refresh, MFA).",
|
|
41
|
+
actions: [
|
|
42
|
+
"login",
|
|
43
|
+
"logout",
|
|
44
|
+
"token_refresh",
|
|
45
|
+
"mfa_setup",
|
|
46
|
+
"mfa_verify"
|
|
47
|
+
]
|
|
48
|
+
});
|
|
49
|
+
security = $audit({
|
|
50
|
+
type: "security",
|
|
51
|
+
description: "Security events (rate limiting, session invalidation, blocked access).",
|
|
52
|
+
actions: [
|
|
53
|
+
"rate_limited",
|
|
54
|
+
"sessions_invalidated",
|
|
55
|
+
"permission_denied",
|
|
56
|
+
"blocked"
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region ../../src/api/users/audits/UserAudits.ts
|
|
62
|
+
/**
|
|
63
|
+
* User-management audit events.
|
|
64
|
+
*
|
|
65
|
+
* Holds the `user` audit type. Mirrors the `$notification`/`$job` holder
|
|
66
|
+
* pattern (see {@link UserNotifications}) — register as a module variant and
|
|
67
|
+
* log via the exposed primitive: `userAudits(realm)?.user.log("create", …)`.
|
|
32
68
|
*/
|
|
33
69
|
var UserAudits = class {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Record a generic audit event.
|
|
49
|
-
*/
|
|
50
|
-
record(category, action, context) {
|
|
51
|
-
return this.auditService.record(category, action, context);
|
|
52
|
-
}
|
|
70
|
+
user = $audit({
|
|
71
|
+
type: "user",
|
|
72
|
+
description: "User management events (create, update, delete, role/password changes).",
|
|
73
|
+
actions: [
|
|
74
|
+
"create",
|
|
75
|
+
"update",
|
|
76
|
+
"delete",
|
|
77
|
+
"role_change",
|
|
78
|
+
"password_change",
|
|
79
|
+
"enable",
|
|
80
|
+
"disable"
|
|
81
|
+
]
|
|
82
|
+
});
|
|
53
83
|
};
|
|
54
84
|
//#endregion
|
|
55
85
|
//#region ../../src/api/users/buckets/UserBuckets.ts
|
|
@@ -105,6 +135,7 @@ const users = $entity({
|
|
|
105
135
|
picture: t.optional(t.string()),
|
|
106
136
|
enabled: db.default(t.boolean(), true),
|
|
107
137
|
emailVerified: db.default(t.boolean(), false),
|
|
138
|
+
lastLoginAt: t.optional(t.datetime()),
|
|
108
139
|
organizationId: db.organization()
|
|
109
140
|
}),
|
|
110
141
|
indexes: [
|
|
@@ -281,6 +312,12 @@ const sessions = $entity({
|
|
|
281
312
|
*/
|
|
282
313
|
lastUsedAt: t.optional(t.datetime()),
|
|
283
314
|
ip: t.optional(t.text()),
|
|
315
|
+
/**
|
|
316
|
+
* ISO 3166-1 alpha-2 country code derived from the request geo headers
|
|
317
|
+
* (`cf-ipcountry` on Cloudflare, CDN equivalents elsewhere) at login time.
|
|
318
|
+
* `null` on pre-migration rows and where geo isn't available.
|
|
319
|
+
*/
|
|
320
|
+
country: t.optional(t.text({ maxLength: 2 })),
|
|
284
321
|
userAgent: t.optional(t.object({
|
|
285
322
|
os: t.text(),
|
|
286
323
|
browser: t.text(),
|
|
@@ -437,7 +474,8 @@ var IdentityService = class {
|
|
|
437
474
|
userId: identity.userId
|
|
438
475
|
});
|
|
439
476
|
const realm = this.realmProvider.getRealm(userRealmName);
|
|
440
|
-
await this.userAudits(userRealmName)?.
|
|
477
|
+
await this.userAudits(userRealmName)?.user.log("update", {
|
|
478
|
+
resourceType: "user",
|
|
441
479
|
userRealm: realm.name,
|
|
442
480
|
resourceId: identity.userId,
|
|
443
481
|
description: `Identity provider disconnected: ${identity.provider}`,
|
|
@@ -515,6 +553,22 @@ var AdminIdentityController = class {
|
|
|
515
553
|
const sessionQuerySchema = t.extend(pageQuerySchema, { userId: t.optional(t.uuid()) });
|
|
516
554
|
//#endregion
|
|
517
555
|
//#region ../../src/api/users/schemas/sessionResourceSchema.ts
|
|
556
|
+
/**
|
|
557
|
+
* Slim view of the session's owner — embedded by the admin listing so the
|
|
558
|
+
* UI can render a human-readable identifier instead of just a UUID. Comes
|
|
559
|
+
* back via a left join, so it's optional (a session whose user was deleted
|
|
560
|
+
* still returns; `user` is undefined).
|
|
561
|
+
*/
|
|
562
|
+
const sessionUserSummarySchema = t.object({
|
|
563
|
+
id: t.uuid(),
|
|
564
|
+
email: t.optional(t.string({ format: "email" })),
|
|
565
|
+
username: t.optional(t.shortText({
|
|
566
|
+
minLength: 3,
|
|
567
|
+
maxLength: 30
|
|
568
|
+
})),
|
|
569
|
+
firstName: t.optional(t.string()),
|
|
570
|
+
lastName: t.optional(t.string())
|
|
571
|
+
});
|
|
518
572
|
const sessionResourceSchema = t.object({
|
|
519
573
|
id: t.uuid(),
|
|
520
574
|
version: t.number(),
|
|
@@ -524,6 +578,7 @@ const sessionResourceSchema = t.object({
|
|
|
524
578
|
userId: t.uuid(),
|
|
525
579
|
expiresAt: t.datetime(),
|
|
526
580
|
ip: t.optional(t.string()),
|
|
581
|
+
country: t.optional(t.string()),
|
|
527
582
|
userAgent: t.optional(t.object({
|
|
528
583
|
os: t.string(),
|
|
529
584
|
browser: t.string(),
|
|
@@ -532,10 +587,21 @@ const sessionResourceSchema = t.object({
|
|
|
532
587
|
"DESKTOP",
|
|
533
588
|
"TABLET"
|
|
534
589
|
])
|
|
535
|
-
}))
|
|
590
|
+
})),
|
|
591
|
+
user: t.optional(sessionUserSummarySchema)
|
|
536
592
|
});
|
|
537
593
|
//#endregion
|
|
538
594
|
//#region ../../src/api/users/services/SessionCrudService.ts
|
|
595
|
+
/**
|
|
596
|
+
* Relation map embedding a slim user summary on every session row, so the
|
|
597
|
+
* admin UI can render `user.email`/`user.username` instead of a bare UUID.
|
|
598
|
+
* Left-join (default) so sessions whose owner was deleted still come back
|
|
599
|
+
* with `user: undefined`.
|
|
600
|
+
*/
|
|
601
|
+
const withUser = { user: {
|
|
602
|
+
join: users,
|
|
603
|
+
on: ["userId", users.cols.id]
|
|
604
|
+
} };
|
|
539
605
|
var SessionCrudService = class {
|
|
540
606
|
log = $logger();
|
|
541
607
|
realmProvider = $inject(RealmProvider);
|
|
@@ -553,7 +619,10 @@ var SessionCrudService = class {
|
|
|
553
619
|
q.sort ??= "-createdAt";
|
|
554
620
|
const where = this.sessions(userRealmName).createQueryWhere();
|
|
555
621
|
if (q.userId) where.userId = { eq: q.userId };
|
|
556
|
-
const result = await this.sessions(userRealmName).paginate(q, {
|
|
622
|
+
const result = await this.sessions(userRealmName).paginate(q, {
|
|
623
|
+
where,
|
|
624
|
+
with: withUser
|
|
625
|
+
}, { count: true });
|
|
557
626
|
this.log.debug("Sessions found", {
|
|
558
627
|
count: result.content.length,
|
|
559
628
|
total: result.page.totalElements
|
|
@@ -568,7 +637,10 @@ var SessionCrudService = class {
|
|
|
568
637
|
id,
|
|
569
638
|
userRealmName
|
|
570
639
|
});
|
|
571
|
-
const session = await this.sessions(userRealmName).
|
|
640
|
+
const session = await this.sessions(userRealmName).getOne({
|
|
641
|
+
where: { id: { eq: id } },
|
|
642
|
+
with: withUser
|
|
643
|
+
});
|
|
572
644
|
this.log.debug("Session retrieved", {
|
|
573
645
|
id,
|
|
574
646
|
userId: session.userId
|
|
@@ -692,13 +764,18 @@ const updateUserSchema = t.partial(t.omit(users.insertSchema, [
|
|
|
692
764
|
"id",
|
|
693
765
|
"version",
|
|
694
766
|
"createdAt",
|
|
695
|
-
"updatedAt"
|
|
696
|
-
"username",
|
|
697
|
-
"emailVerified"
|
|
767
|
+
"updatedAt"
|
|
698
768
|
]));
|
|
699
769
|
//#endregion
|
|
700
770
|
//#region ../../src/api/users/schemas/userQuerySchema.ts
|
|
701
771
|
const userQuerySchema = t.extend(pageQuerySchema, {
|
|
772
|
+
/**
|
|
773
|
+
* Free-text search applied (case-insensitive) across `email`,
|
|
774
|
+
* `username`, `firstName`, and `lastName`. Matches with a leading and
|
|
775
|
+
* trailing wildcard, so `?search=foo` finds any user whose email,
|
|
776
|
+
* username, or name contains `foo`.
|
|
777
|
+
*/
|
|
778
|
+
search: t.optional(t.string()),
|
|
702
779
|
email: t.optional(t.string()),
|
|
703
780
|
enabled: t.optional(t.boolean()),
|
|
704
781
|
emailVerified: t.optional(t.boolean()),
|
|
@@ -863,6 +940,7 @@ var UserService = class {
|
|
|
863
940
|
log = $logger();
|
|
864
941
|
verificationController = $client();
|
|
865
942
|
realmProvider = $inject(RealmProvider);
|
|
943
|
+
cryptoProvider = $inject(CryptoProvider);
|
|
866
944
|
userAudits(realmName) {
|
|
867
945
|
if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
|
|
868
946
|
}
|
|
@@ -977,7 +1055,8 @@ var UserService = class {
|
|
|
977
1055
|
type
|
|
978
1056
|
});
|
|
979
1057
|
const realm = this.realmProvider.getRealm(userRealmName);
|
|
980
|
-
await this.userAudits(userRealmName)?.
|
|
1058
|
+
await this.userAudits(userRealmName)?.user.log("update", {
|
|
1059
|
+
resourceType: "user",
|
|
981
1060
|
userId: user.id,
|
|
982
1061
|
userEmail: email,
|
|
983
1062
|
userRealm: realm.name,
|
|
@@ -1009,6 +1088,15 @@ var UserService = class {
|
|
|
1009
1088
|
});
|
|
1010
1089
|
q.sort ??= "-createdAt";
|
|
1011
1090
|
const where = this.users(userRealmName).createQueryWhere();
|
|
1091
|
+
if (q.search) {
|
|
1092
|
+
const pattern = `%${q.search}%`;
|
|
1093
|
+
where.or = [
|
|
1094
|
+
{ email: { ilike: pattern } },
|
|
1095
|
+
{ username: { ilike: pattern } },
|
|
1096
|
+
{ firstName: { ilike: pattern } },
|
|
1097
|
+
{ lastName: { ilike: pattern } }
|
|
1098
|
+
];
|
|
1099
|
+
}
|
|
1012
1100
|
if (q.email) where.email = { like: q.email };
|
|
1013
1101
|
if (q.enabled !== void 0) where.enabled = { eq: q.enabled };
|
|
1014
1102
|
if (q.emailVerified !== void 0) where.emailVerified = { eq: q.emailVerified };
|
|
@@ -1078,7 +1166,8 @@ var UserService = class {
|
|
|
1078
1166
|
username: user.username,
|
|
1079
1167
|
email: user.email
|
|
1080
1168
|
});
|
|
1081
|
-
await this.userAudits(userRealmName)?.
|
|
1169
|
+
await this.userAudits(userRealmName)?.user.log("create", {
|
|
1170
|
+
resourceType: "user",
|
|
1082
1171
|
userRealm: realm.name,
|
|
1083
1172
|
resourceId: user.id,
|
|
1084
1173
|
description: "User created",
|
|
@@ -1099,16 +1188,33 @@ var UserService = class {
|
|
|
1099
1188
|
userRealmName
|
|
1100
1189
|
});
|
|
1101
1190
|
const before = await this.getUserById(id, userRealmName);
|
|
1102
|
-
const user = await this.users(userRealmName).updateById(id, data);
|
|
1103
|
-
this.log.debug("User updated", { userId: id });
|
|
1104
1191
|
const realm = this.realmProvider.getRealm(userRealmName);
|
|
1192
|
+
const users = this.users(userRealmName);
|
|
1193
|
+
if (data.username !== void 0 && data.username !== null && data.username !== before.username) {
|
|
1194
|
+
const existing = await users.findOne({ where: {
|
|
1195
|
+
realm: realm.name,
|
|
1196
|
+
username: { ilike: data.username }
|
|
1197
|
+
} });
|
|
1198
|
+
if (existing && existing.id !== id) throw new ConflictError("User with this username already exists");
|
|
1199
|
+
}
|
|
1200
|
+
if (data.email !== void 0 && data.email !== null && data.email !== before.email) {
|
|
1201
|
+
const existing = await users.findOne({ where: {
|
|
1202
|
+
realm: realm.name,
|
|
1203
|
+
email: { eq: data.email }
|
|
1204
|
+
} });
|
|
1205
|
+
if (existing && existing.id !== id) throw new ConflictError("User with this email already exists");
|
|
1206
|
+
data.emailVerified = false;
|
|
1207
|
+
}
|
|
1208
|
+
const user = await users.updateById(id, data);
|
|
1209
|
+
this.log.debug("User updated", { userId: id });
|
|
1105
1210
|
const changes = {};
|
|
1106
1211
|
for (const key of Object.keys(data)) if (data[key] !== void 0 && before[key] !== data[key]) changes[key] = {
|
|
1107
1212
|
from: before[key],
|
|
1108
1213
|
to: data[key]
|
|
1109
1214
|
};
|
|
1110
1215
|
const isRoleChange = data.roles !== void 0 && JSON.stringify(before.roles) !== JSON.stringify(data.roles);
|
|
1111
|
-
await this.userAudits(userRealmName)?.
|
|
1216
|
+
await this.userAudits(userRealmName)?.user.log(isRoleChange ? "role_change" : "update", {
|
|
1217
|
+
resourceType: "user",
|
|
1112
1218
|
userRealm: realm.name,
|
|
1113
1219
|
resourceId: user.id,
|
|
1114
1220
|
description: isRoleChange ? "User roles changed" : `User updated: ${Object.keys(changes).join(", ")}`,
|
|
@@ -1117,6 +1223,46 @@ var UserService = class {
|
|
|
1117
1223
|
return user;
|
|
1118
1224
|
}
|
|
1119
1225
|
/**
|
|
1226
|
+
* Set (or reset) a user's password. Upserts a "credentials" identity
|
|
1227
|
+
* with the new hash. Used by admin password-set flows; does NOT
|
|
1228
|
+
* verify any old password or token — the caller is responsible for
|
|
1229
|
+
* authorization.
|
|
1230
|
+
*/
|
|
1231
|
+
async setPassword(id, newPassword, userRealmName) {
|
|
1232
|
+
this.log.trace("Setting password", {
|
|
1233
|
+
id,
|
|
1234
|
+
userRealmName
|
|
1235
|
+
});
|
|
1236
|
+
const user = await this.getUserById(id, userRealmName);
|
|
1237
|
+
const realm = this.realmProvider.getRealm(userRealmName);
|
|
1238
|
+
const settings = await realm.getSettings();
|
|
1239
|
+
if (settings.passwordPolicy) {
|
|
1240
|
+
const policy = settings.passwordPolicy;
|
|
1241
|
+
if (policy.minLength && newPassword.length < policy.minLength) throw new BadRequestError(`Password must be at least ${policy.minLength} characters`);
|
|
1242
|
+
}
|
|
1243
|
+
const hash = await this.cryptoProvider.hashPassword(newPassword);
|
|
1244
|
+
const identities = this.realmProvider.identityRepository(userRealmName);
|
|
1245
|
+
const existing = await identities.findOne({ where: {
|
|
1246
|
+
userId: { eq: id },
|
|
1247
|
+
provider: { eq: "credentials" }
|
|
1248
|
+
} });
|
|
1249
|
+
if (existing) await identities.updateById(existing.id, { password: hash });
|
|
1250
|
+
else await identities.create({
|
|
1251
|
+
userId: id,
|
|
1252
|
+
provider: "credentials",
|
|
1253
|
+
password: hash
|
|
1254
|
+
});
|
|
1255
|
+
await this.userAudits(userRealmName)?.user.log("password_change", {
|
|
1256
|
+
resourceType: "user",
|
|
1257
|
+
userId: id,
|
|
1258
|
+
userEmail: user.email ?? void 0,
|
|
1259
|
+
userRealm: realm.name,
|
|
1260
|
+
resourceId: id,
|
|
1261
|
+
severity: "warning",
|
|
1262
|
+
description: "Password set by admin"
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1120
1266
|
* Delete a user by ID.
|
|
1121
1267
|
*/
|
|
1122
1268
|
async deleteUser(id, userRealmName) {
|
|
@@ -1130,7 +1276,8 @@ var UserService = class {
|
|
|
1130
1276
|
await this.users(userRealmName).deleteById(id);
|
|
1131
1277
|
this.log.info("User deleted", { userId: id });
|
|
1132
1278
|
const realm = this.realmProvider.getRealm(userRealmName);
|
|
1133
|
-
await this.userAudits(userRealmName)?.
|
|
1279
|
+
await this.userAudits(userRealmName)?.user.log("delete", {
|
|
1280
|
+
resourceType: "user",
|
|
1134
1281
|
userRealm: realm.name,
|
|
1135
1282
|
resourceId: id,
|
|
1136
1283
|
severity: "warning",
|
|
@@ -1148,6 +1295,32 @@ var AdminUserController = class {
|
|
|
1148
1295
|
url = "/users";
|
|
1149
1296
|
group = "admin:users";
|
|
1150
1297
|
userService = $inject(UserService);
|
|
1298
|
+
securityProvider = $inject(SecurityProvider);
|
|
1299
|
+
/**
|
|
1300
|
+
* List roles available in a realm. Used by the admin UI to render the
|
|
1301
|
+
* role picker and grey out defaults (which cannot be removed).
|
|
1302
|
+
*/
|
|
1303
|
+
findRoles = $action({
|
|
1304
|
+
path: "/metadata/roles",
|
|
1305
|
+
group: this.group,
|
|
1306
|
+
use: [$secure({ permissions: ["admin:user:read"] })],
|
|
1307
|
+
description: "List roles available in a realm",
|
|
1308
|
+
schema: {
|
|
1309
|
+
query: t.object({ userRealmName: t.optional(t.string()) }),
|
|
1310
|
+
response: t.array(t.object({
|
|
1311
|
+
name: t.string(),
|
|
1312
|
+
default: t.optional(t.boolean()),
|
|
1313
|
+
description: t.optional(t.string())
|
|
1314
|
+
}))
|
|
1315
|
+
},
|
|
1316
|
+
handler: ({ query }) => {
|
|
1317
|
+
return this.securityProvider.getRoles(query.userRealmName).map((r) => ({
|
|
1318
|
+
name: r.name,
|
|
1319
|
+
default: r.default,
|
|
1320
|
+
description: r.description
|
|
1321
|
+
}));
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1151
1324
|
/**
|
|
1152
1325
|
* Find users with pagination and filtering.
|
|
1153
1326
|
*/
|
|
@@ -1214,6 +1387,31 @@ var AdminUserController = class {
|
|
|
1214
1387
|
handler: ({ params, body, query }) => this.userService.updateUser(params.id, body, query.userRealmName)
|
|
1215
1388
|
});
|
|
1216
1389
|
/**
|
|
1390
|
+
* Set (or reset) a user's password. Admin-only flow — does NOT
|
|
1391
|
+
* require knowing the previous password. Hash is stored as a
|
|
1392
|
+
* "credentials" identity for the user (upsert).
|
|
1393
|
+
*/
|
|
1394
|
+
setUserPassword = $action({
|
|
1395
|
+
method: "POST",
|
|
1396
|
+
path: `${this.url}/:id/password`,
|
|
1397
|
+
group: this.group,
|
|
1398
|
+
use: [$secure({ permissions: ["admin:user:update"] })],
|
|
1399
|
+
description: "Set a user's password",
|
|
1400
|
+
schema: {
|
|
1401
|
+
params: t.object({ id: t.uuid() }),
|
|
1402
|
+
query: t.object({ userRealmName: t.optional(t.string()) }),
|
|
1403
|
+
body: t.object({ password: t.string({ minLength: 1 }) }),
|
|
1404
|
+
response: okSchema
|
|
1405
|
+
},
|
|
1406
|
+
handler: async ({ params, body, query }) => {
|
|
1407
|
+
await this.userService.setPassword(params.id, body.password, query.userRealmName);
|
|
1408
|
+
return {
|
|
1409
|
+
ok: true,
|
|
1410
|
+
id: params.id
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
/**
|
|
1217
1415
|
* Delete a user.
|
|
1218
1416
|
*/
|
|
1219
1417
|
deleteUser = $action({
|
|
@@ -1421,6 +1619,9 @@ var CredentialService = class {
|
|
|
1421
1619
|
userAudits(realmName) {
|
|
1422
1620
|
if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
|
|
1423
1621
|
}
|
|
1622
|
+
sessionAudits(realmName) {
|
|
1623
|
+
if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(SessionAudits);
|
|
1624
|
+
}
|
|
1424
1625
|
userNotifications(realmName) {
|
|
1425
1626
|
if (this.realmProvider.getRealm(realmName).features.notifications) return this.alepha.inject(UserNotifications);
|
|
1426
1627
|
}
|
|
@@ -1572,7 +1773,8 @@ var CredentialService = class {
|
|
|
1572
1773
|
userId: intent.userId,
|
|
1573
1774
|
email: intent.email
|
|
1574
1775
|
});
|
|
1575
|
-
await this.userAudits(intent.realmName)?.
|
|
1776
|
+
await this.userAudits(intent.realmName)?.user.log("update", {
|
|
1777
|
+
resourceType: "user",
|
|
1576
1778
|
userId: intent.userId,
|
|
1577
1779
|
userEmail: intent.email,
|
|
1578
1780
|
userRealm: realm.name,
|
|
@@ -1580,7 +1782,7 @@ var CredentialService = class {
|
|
|
1580
1782
|
description: "Password reset completed",
|
|
1581
1783
|
metadata: { email: intent.email }
|
|
1582
1784
|
});
|
|
1583
|
-
await this.
|
|
1785
|
+
await this.sessionAudits(intent.realmName)?.security.log("sessions_invalidated", {
|
|
1584
1786
|
userId: intent.userId,
|
|
1585
1787
|
userEmail: intent.email,
|
|
1586
1788
|
userRealm: realm.name,
|
|
@@ -1629,7 +1831,8 @@ var CredentialService = class {
|
|
|
1629
1831
|
const hashedPassword = await this.cryptoProvider.hashPassword(newPassword);
|
|
1630
1832
|
await this.identities(userRealmName).updateById(identity.id, { password: hashedPassword });
|
|
1631
1833
|
await this.sessions(userRealmName).deleteMany({ userId: { eq: user.id } });
|
|
1632
|
-
await this.userAudits(userRealmName)?.
|
|
1834
|
+
await this.userAudits(userRealmName)?.user.log("update", {
|
|
1835
|
+
resourceType: "user",
|
|
1633
1836
|
userId: user.id,
|
|
1634
1837
|
userEmail: email,
|
|
1635
1838
|
userRealm: realm.name,
|
|
@@ -1637,7 +1840,7 @@ var CredentialService = class {
|
|
|
1637
1840
|
description: "Password reset completed (legacy)",
|
|
1638
1841
|
metadata: { email }
|
|
1639
1842
|
});
|
|
1640
|
-
await this.
|
|
1843
|
+
await this.sessionAudits(userRealmName)?.security.log("sessions_invalidated", {
|
|
1641
1844
|
userId: user.id,
|
|
1642
1845
|
userEmail: email,
|
|
1643
1846
|
userRealm: realm.name,
|
|
@@ -1986,7 +2189,8 @@ var RegistrationService = class {
|
|
|
1986
2189
|
email: user.email,
|
|
1987
2190
|
username: user.username
|
|
1988
2191
|
});
|
|
1989
|
-
await this.userAudits(userRealmName)?.
|
|
2192
|
+
await this.userAudits(userRealmName)?.user.log("create", {
|
|
2193
|
+
resourceType: "user",
|
|
1990
2194
|
userId: user.id,
|
|
1991
2195
|
userEmail: user.email ?? void 0,
|
|
1992
2196
|
userRealm: realm.name,
|
|
@@ -2409,6 +2613,9 @@ var SessionService = class SessionService {
|
|
|
2409
2613
|
userAudits(realmName) {
|
|
2410
2614
|
if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
|
|
2411
2615
|
}
|
|
2616
|
+
sessionAudits(realmName) {
|
|
2617
|
+
if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(SessionAudits);
|
|
2618
|
+
}
|
|
2412
2619
|
userNotifications(realmName) {
|
|
2413
2620
|
if (this.realmProvider.getRealm(realmName).features.notifications) return this.alepha.inject(UserNotifications);
|
|
2414
2621
|
}
|
|
@@ -2444,7 +2651,8 @@ var SessionService = class SessionService {
|
|
|
2444
2651
|
username: user.username,
|
|
2445
2652
|
realm: name
|
|
2446
2653
|
});
|
|
2447
|
-
await this.userAudits(userRealmName)?.
|
|
2654
|
+
await this.userAudits(userRealmName)?.user.log("role_change", {
|
|
2655
|
+
resourceType: "user",
|
|
2448
2656
|
userId: user.id,
|
|
2449
2657
|
userEmail: user.email ?? void 0,
|
|
2450
2658
|
userRealm: name,
|
|
@@ -2541,8 +2749,9 @@ var SessionService = class SessionService {
|
|
|
2541
2749
|
username,
|
|
2542
2750
|
realm: name
|
|
2543
2751
|
});
|
|
2544
|
-
await this.
|
|
2752
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2545
2753
|
userRealm: name,
|
|
2754
|
+
success: false,
|
|
2546
2755
|
description: "Username does not match required format",
|
|
2547
2756
|
metadata: {
|
|
2548
2757
|
provider,
|
|
@@ -2561,8 +2770,9 @@ var SessionService = class SessionService {
|
|
|
2561
2770
|
username,
|
|
2562
2771
|
realm: name
|
|
2563
2772
|
});
|
|
2564
|
-
await this.
|
|
2773
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2565
2774
|
userRealm: name,
|
|
2775
|
+
success: false,
|
|
2566
2776
|
description: "Invalid login identifier format",
|
|
2567
2777
|
metadata: {
|
|
2568
2778
|
provider,
|
|
@@ -2578,8 +2788,9 @@ var SessionService = class SessionService {
|
|
|
2578
2788
|
username,
|
|
2579
2789
|
realm: name
|
|
2580
2790
|
});
|
|
2581
|
-
await this.
|
|
2791
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2582
2792
|
userRealm: name,
|
|
2793
|
+
success: false,
|
|
2583
2794
|
description: "User not found",
|
|
2584
2795
|
metadata: {
|
|
2585
2796
|
provider,
|
|
@@ -2587,7 +2798,7 @@ var SessionService = class SessionService {
|
|
|
2587
2798
|
}
|
|
2588
2799
|
});
|
|
2589
2800
|
if (ipKey) {
|
|
2590
|
-
if (await this.recordFailedLogin(ipKey, loginRateLimit.ipMaxAttempts, loginRateLimit.windowMs)) await this.
|
|
2801
|
+
if (await this.recordFailedLogin(ipKey, loginRateLimit.ipMaxAttempts, loginRateLimit.windowMs)) await this.sessionAudits(userRealmName)?.security.log("rate_limited", {
|
|
2591
2802
|
userRealm: name,
|
|
2592
2803
|
success: false,
|
|
2593
2804
|
description: "IP temporarily locked due to too many failed login attempts",
|
|
@@ -2601,8 +2812,9 @@ var SessionService = class SessionService {
|
|
|
2601
2812
|
userId: user.id,
|
|
2602
2813
|
realm: name
|
|
2603
2814
|
});
|
|
2604
|
-
await this.
|
|
2815
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2605
2816
|
userRealm: name,
|
|
2817
|
+
success: false,
|
|
2606
2818
|
resourceId: user.id,
|
|
2607
2819
|
description: "Login attempt for disabled account",
|
|
2608
2820
|
metadata: {
|
|
@@ -2640,8 +2852,9 @@ var SessionService = class SessionService {
|
|
|
2640
2852
|
username,
|
|
2641
2853
|
realm: name
|
|
2642
2854
|
});
|
|
2643
|
-
await this.
|
|
2855
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2644
2856
|
userRealm: name,
|
|
2857
|
+
success: false,
|
|
2645
2858
|
resourceId: user.id,
|
|
2646
2859
|
description: "Invalid password",
|
|
2647
2860
|
metadata: {
|
|
@@ -2650,7 +2863,7 @@ var SessionService = class SessionService {
|
|
|
2650
2863
|
}
|
|
2651
2864
|
});
|
|
2652
2865
|
if (ipKey) {
|
|
2653
|
-
if (await this.recordFailedLogin(ipKey, loginRateLimit.ipMaxAttempts, loginRateLimit.windowMs)) await this.
|
|
2866
|
+
if (await this.recordFailedLogin(ipKey, loginRateLimit.ipMaxAttempts, loginRateLimit.windowMs)) await this.sessionAudits(userRealmName)?.security.log("rate_limited", {
|
|
2654
2867
|
userRealm: name,
|
|
2655
2868
|
success: false,
|
|
2656
2869
|
description: "IP temporarily locked due to too many failed login attempts",
|
|
@@ -2658,7 +2871,7 @@ var SessionService = class SessionService {
|
|
|
2658
2871
|
});
|
|
2659
2872
|
}
|
|
2660
2873
|
if (await this.recordFailedLogin(accountKey, loginRateLimit.accountMaxAttempts, loginRateLimit.windowMs)) {
|
|
2661
|
-
await this.
|
|
2874
|
+
await this.sessionAudits(userRealmName)?.security.log("rate_limited", {
|
|
2662
2875
|
userRealm: name,
|
|
2663
2876
|
resourceId: user.id,
|
|
2664
2877
|
success: false,
|
|
@@ -2678,7 +2891,7 @@ var SessionService = class SessionService {
|
|
|
2678
2891
|
}
|
|
2679
2892
|
throw new InvalidCredentialsError();
|
|
2680
2893
|
}
|
|
2681
|
-
await this.
|
|
2894
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2682
2895
|
userId: user.id,
|
|
2683
2896
|
userEmail: user.email ?? void 0,
|
|
2684
2897
|
userRealm: name,
|
|
@@ -2705,15 +2918,18 @@ var SessionService = class SessionService {
|
|
|
2705
2918
|
const request = this.alepha.store.get("alepha.http.request");
|
|
2706
2919
|
const refreshToken = this.cryptoProvider.randomUUID();
|
|
2707
2920
|
const expiresAt = this.dateTimeProvider.now().add(expiresIn, "seconds").toISOString();
|
|
2921
|
+
const nowIso = this.dateTimeProvider.nowISOString();
|
|
2708
2922
|
const session = await this.sessions(userRealmName).create({
|
|
2709
2923
|
userId: user.id,
|
|
2710
2924
|
expiresAt,
|
|
2711
|
-
lastUsedAt:
|
|
2925
|
+
lastUsedAt: nowIso,
|
|
2712
2926
|
ip: request?.ip,
|
|
2927
|
+
country: request?.geo?.country,
|
|
2713
2928
|
userAgent: request?.userAgent,
|
|
2714
2929
|
refreshToken,
|
|
2715
2930
|
clientId
|
|
2716
2931
|
});
|
|
2932
|
+
await this.users(userRealmName).updateById(user.id, { lastLoginAt: nowIso });
|
|
2717
2933
|
this.log.info("Session created", {
|
|
2718
2934
|
sessionId: session.id,
|
|
2719
2935
|
userId: user.id,
|
|
@@ -2780,7 +2996,7 @@ var SessionService = class SessionService {
|
|
|
2780
2996
|
this.log.debug("Session deleted");
|
|
2781
2997
|
if (session) {
|
|
2782
2998
|
const { name } = this.realmProvider.getRealm(userRealmName);
|
|
2783
|
-
await this.
|
|
2999
|
+
await this.sessionAudits(userRealmName)?.auth.log("logout", {
|
|
2784
3000
|
userId: session.userId,
|
|
2785
3001
|
userRealm: name,
|
|
2786
3002
|
sessionId: session.id,
|
|
@@ -2808,7 +3024,7 @@ var SessionService = class SessionService {
|
|
|
2808
3024
|
userId: identity.userId
|
|
2809
3025
|
});
|
|
2810
3026
|
const user = await users.getById(identity.userId);
|
|
2811
|
-
await this.
|
|
3027
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2812
3028
|
userId: user.id,
|
|
2813
3029
|
userEmail: user.email ?? void 0,
|
|
2814
3030
|
userRealm: realm.name,
|
|
@@ -2856,7 +3072,7 @@ var SessionService = class SessionService {
|
|
|
2856
3072
|
providerUserId: profile.sub,
|
|
2857
3073
|
userId: existing.id
|
|
2858
3074
|
});
|
|
2859
|
-
await this.
|
|
3075
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2860
3076
|
userId: existing.id,
|
|
2861
3077
|
userEmail: existing.email ?? void 0,
|
|
2862
3078
|
userRealm: realm.name,
|
|
@@ -2918,7 +3134,8 @@ var SessionService = class SessionService {
|
|
|
2918
3134
|
email: user.email,
|
|
2919
3135
|
username: user.username
|
|
2920
3136
|
});
|
|
2921
|
-
await this.userAudits(userRealmName)?.
|
|
3137
|
+
await this.userAudits(userRealmName)?.user.log("create", {
|
|
3138
|
+
resourceType: "user",
|
|
2922
3139
|
userId: user.id,
|
|
2923
3140
|
userEmail: user.email ?? void 0,
|
|
2924
3141
|
userRealm: realm.name,
|
|
@@ -2931,7 +3148,7 @@ var SessionService = class SessionService {
|
|
|
2931
3148
|
email: user.email
|
|
2932
3149
|
}
|
|
2933
3150
|
});
|
|
2934
|
-
await this.
|
|
3151
|
+
await this.sessionAudits(userRealmName)?.auth.log("login", {
|
|
2935
3152
|
userId: user.id,
|
|
2936
3153
|
userEmail: user.email ?? void 0,
|
|
2937
3154
|
userRealm: realm.name,
|
|
@@ -2986,7 +3203,10 @@ const $realm = (options = {}) => {
|
|
|
2986
3203
|
}
|
|
2987
3204
|
const realmRegistration = realmProvider.register(name, options);
|
|
2988
3205
|
if (features.avatars) alepha.with(UserBuckets);
|
|
2989
|
-
if (features.audits)
|
|
3206
|
+
if (features.audits) {
|
|
3207
|
+
alepha.with(UserAudits);
|
|
3208
|
+
alepha.with(SessionAudits);
|
|
3209
|
+
}
|
|
2990
3210
|
if (features.jobs) alepha.with(UserJobs);
|
|
2991
3211
|
if (features.notifications) {
|
|
2992
3212
|
alepha.with(UserNotifications);
|
|
@@ -3008,6 +3228,7 @@ const $realm = (options = {}) => {
|
|
|
3008
3228
|
permissions: [{ name: "*" }]
|
|
3009
3229
|
}, {
|
|
3010
3230
|
name: "user",
|
|
3231
|
+
default: true,
|
|
3011
3232
|
permissions: [{
|
|
3012
3233
|
name: "*",
|
|
3013
3234
|
ownership: true,
|
|
@@ -3194,10 +3415,11 @@ const AlephaApiUsers = $module({
|
|
|
3194
3415
|
UserJobs,
|
|
3195
3416
|
UserNotifications,
|
|
3196
3417
|
UserAudits,
|
|
3418
|
+
SessionAudits,
|
|
3197
3419
|
UserBuckets
|
|
3198
3420
|
]
|
|
3199
3421
|
});
|
|
3200
3422
|
//#endregion
|
|
3201
|
-
export { $realm, AdminIdentityController, AdminSessionController, AdminUserController, AlephaApiUsers, CredentialService, DEFAULT_USER_REALM_NAME, IdentityService, RealmController, RealmProvider, RegistrationService, SessionCrudService, SessionService, UserAudits, UserBuckets, UserController, UserJobs, UserNotifications, UserService, UsernameSlugger, completePasswordResetRequestSchema, completeRegistrationRequestSchema, createUserSchema, identities, identityQuerySchema, identityResourceSchema, loginSchema, passwordResetIntentResponseSchema, realmAuthSettingsAtom, realmConfigSchema, registerSchema, registrationIntentResponseSchema, resetPasswordRequestSchema, resetPasswordSchema, sessionQuerySchema, sessionResourceSchema, sessions, updateUserSchema, userQuerySchema, userResourceSchema, users };
|
|
3423
|
+
export { $realm, AdminIdentityController, AdminSessionController, AdminUserController, AlephaApiUsers, CredentialService, DEFAULT_USER_REALM_NAME, IdentityService, RealmController, RealmProvider, RegistrationService, SessionAudits, SessionCrudService, SessionService, UserAudits, UserBuckets, UserController, UserJobs, UserNotifications, UserService, UsernameSlugger, completePasswordResetRequestSchema, completeRegistrationRequestSchema, createUserSchema, identities, identityQuerySchema, identityResourceSchema, loginSchema, passwordResetIntentResponseSchema, realmAuthSettingsAtom, realmConfigSchema, registerSchema, registrationIntentResponseSchema, resetPasswordRequestSchema, resetPasswordSchema, sessionQuerySchema, sessionResourceSchema, sessionUserSummarySchema, sessions, updateUserSchema, userQuerySchema, userResourceSchema, users };
|
|
3202
3424
|
|
|
3203
3425
|
//# sourceMappingURL=index.js.map
|