alepha 0.14.1 → 0.14.3
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 +3 -3
- package/dist/api/audits/index.browser.js +5 -5
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +784 -784
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +13 -13
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +5 -5
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +57 -57
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +71 -71
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +5 -5
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +165 -165
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -10
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +10 -10
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +583 -171
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +12 -12
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +163 -10
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +281 -276
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +196 -91
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.browser.js +19 -19
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +778 -764
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +831 -596
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js +6 -6
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +125 -125
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +6 -6
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bin/index.d.ts +1 -2
- package/dist/bin/index.js +0 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cli/index.d.ts +249 -218
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +951 -821
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +40 -0
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +97 -17
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +14 -18
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +29 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +21 -24
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +21 -24
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.js.map +1 -1
- package/dist/fake/index.js +195 -168
- package/dist/fake/index.js.map +1 -1
- package/dist/file/index.d.ts +8 -0
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +3 -0
- package/dist/file/index.js.map +1 -1
- package/dist/lock/redis/index.js.map +1 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.browser.js +26 -5
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.d.ts +146 -121
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +49 -24
- package/dist/orm/index.js.map +1 -1
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +6 -6
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +29 -29
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +171 -155
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +0 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +2 -0
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.browser.js.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.map +1 -1
- package/dist/server/core/index.js +1 -1
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/health/index.d.ts +17 -17
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.browser.js +22 -6
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +46 -44
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +24 -41
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/security/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +2 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +8 -3
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +12 -4
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.js.map +1 -1
- package/package.json +7 -7
- package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
- package/src/api/audits/entities/audits.ts +5 -5
- package/src/api/audits/index.browser.ts +1 -1
- package/src/api/audits/index.ts +3 -3
- package/src/api/audits/primitives/$audit.spec.ts +276 -0
- package/src/api/audits/services/AuditService.spec.ts +495 -0
- package/src/api/files/__tests__/$bucket.spec.ts +91 -0
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
- package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
- package/src/api/files/controllers/FileController.spec.ts +558 -0
- package/src/api/files/controllers/FileController.ts +4 -5
- package/src/api/files/entities/files.ts +5 -5
- package/src/api/files/index.browser.ts +1 -1
- package/src/api/files/index.ts +4 -4
- package/src/api/files/jobs/FileJobs.spec.ts +52 -0
- package/src/api/files/services/FileService.spec.ts +109 -0
- package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
- package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
- package/src/api/jobs/entities/jobExecutions.ts +5 -5
- package/src/api/jobs/index.ts +3 -3
- package/src/api/jobs/primitives/$job.spec.ts +476 -0
- package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
- package/src/api/notifications/entities/notifications.ts +5 -5
- package/src/api/notifications/index.browser.ts +1 -1
- package/src/api/notifications/index.ts +4 -4
- package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
- package/src/api/parameters/entities/parameters.ts +7 -17
- package/src/api/parameters/index.ts +3 -3
- package/src/api/parameters/primitives/$config.spec.ts +356 -0
- package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
- package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
- package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
- package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
- package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
- package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
- package/src/api/parameters/schemas/index.ts +15 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
- package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
- package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
- package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
- package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
- package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
- package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
- package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
- package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
- package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
- package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
- package/src/api/users/controllers/AdminUserController.ts +116 -0
- package/src/api/users/controllers/UserController.ts +4 -107
- package/src/api/users/controllers/UserRealmController.ts +3 -0
- package/src/api/users/entities/identities.ts +6 -6
- package/src/api/users/entities/sessions.ts +6 -6
- package/src/api/users/entities/users.ts +9 -9
- package/src/api/users/index.ts +13 -6
- package/src/api/users/primitives/$userRealm.ts +13 -8
- package/src/api/users/services/CredentialService.spec.ts +509 -0
- package/src/api/users/services/CredentialService.ts +46 -0
- package/src/api/users/services/IdentityService.ts +15 -0
- package/src/api/users/services/RegistrationService.spec.ts +630 -0
- package/src/api/users/services/RegistrationService.ts +18 -0
- package/src/api/users/services/SessionService.spec.ts +301 -0
- package/src/api/users/services/SessionService.ts +110 -1
- package/src/api/users/services/UserService.ts +67 -2
- package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
- package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
- package/src/api/verifications/entities/verifications.ts +6 -6
- package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
- package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
- package/src/batch/primitives/$batch.spec.ts +766 -0
- package/src/batch/providers/BatchProvider.spec.ts +786 -0
- package/src/bin/index.ts +0 -1
- package/src/bucket/__tests__/shared.ts +194 -0
- package/src/bucket/primitives/$bucket.spec.ts +104 -0
- package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
- package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
- package/src/cache/core/__tests__/shared.ts +377 -0
- package/src/cache/core/primitives/$cache.spec.ts +111 -0
- package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
- package/src/cli/apps/AlephaCli.ts +54 -16
- package/src/cli/apps/AlephaPackageBuilderCli.ts +2 -1
- package/src/cli/assets/appRouterTs.ts +1 -1
- package/src/cli/commands/{ViteCommands.ts → build.ts} +2 -105
- package/src/cli/commands/clean.ts +14 -0
- package/src/cli/commands/{DrizzleCommands.ts → db.ts} +10 -117
- package/src/cli/commands/{DeployCommands.ts → deploy.ts} +1 -1
- package/src/cli/commands/dev.ts +69 -0
- package/src/cli/commands/format.ts +17 -0
- package/src/cli/commands/gen/changelog.spec.ts +315 -0
- package/src/cli/commands/{ChangelogCommands.ts → gen/changelog.ts} +16 -31
- package/src/cli/commands/gen/openapi.ts +71 -0
- package/src/cli/commands/gen.ts +18 -0
- package/src/cli/commands/{CoreCommands.ts → init.ts} +4 -40
- package/src/cli/commands/lint.ts +17 -0
- package/src/cli/commands/root.ts +41 -0
- package/src/cli/commands/run.ts +24 -0
- package/src/cli/commands/test.ts +42 -0
- package/src/cli/commands/typecheck.ts +24 -0
- package/src/cli/commands/{VerifyCommands.ts → verify.ts} +1 -13
- package/src/cli/defineConfig.ts +10 -1
- package/src/cli/index.ts +17 -7
- package/src/cli/services/AlephaCliUtils.ts +71 -32
- package/src/cli/services/GitMessageParser.ts +1 -1
- package/src/command/helpers/Asker.spec.ts +127 -0
- package/src/command/helpers/Runner.spec.ts +126 -0
- package/src/command/primitives/$command.spec.ts +1588 -0
- package/src/command/providers/CliProvider.ts +74 -24
- package/src/core/Alepha.ts +52 -4
- package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
- package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
- package/src/core/__tests__/Alepha-has.spec.ts +41 -0
- package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
- package/src/core/__tests__/Alepha-register.spec.ts +81 -0
- package/src/core/__tests__/Alepha-start.spec.ts +176 -0
- package/src/core/__tests__/Alepha-with.spec.ts +14 -0
- package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
- package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
- package/src/core/__tests__/descriptor.spec.ts +34 -0
- package/src/core/__tests__/fixtures/A.ts +5 -0
- package/src/core/__tests__/pagination.spec.ts +77 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
- package/src/core/primitives/$atom.spec.ts +43 -0
- package/src/core/primitives/$hook.spec.ts +130 -0
- package/src/core/primitives/$inject.spec.ts +175 -0
- package/src/core/primitives/$module.spec.ts +115 -0
- package/src/core/providers/CodecManager.spec.ts +740 -0
- package/src/core/providers/EventManager.spec.ts +762 -0
- package/src/core/providers/EventManager.ts +4 -0
- package/src/core/providers/StateManager.spec.ts +365 -0
- package/src/core/providers/TypeProvider.spec.ts +1607 -0
- package/src/core/providers/TypeProvider.ts +20 -26
- package/src/datetime/primitives/$interval.spec.ts +103 -0
- package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
- package/src/email/primitives/$email.spec.ts +175 -0
- package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
- package/src/fake/__tests__/keyName.example.ts +40 -0
- package/src/fake/__tests__/keyName.spec.ts +152 -0
- package/src/fake/__tests__/module.example.ts +32 -0
- package/src/fake/providers/FakeProvider.spec.ts +438 -0
- package/src/file/providers/FileSystemProvider.ts +8 -0
- package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
- package/src/file/providers/NodeFileSystemProvider.ts +5 -0
- package/src/file/services/FileDetector.spec.ts +591 -0
- package/src/lock/core/__tests__/shared.ts +190 -0
- package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
- package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
- package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
- package/src/logger/primitives/$logger.spec.ts +108 -0
- package/src/logger/services/Logger.spec.ts +295 -0
- package/src/mcp/__tests__/errors.spec.ts +175 -0
- package/src/mcp/__tests__/integration.spec.ts +450 -0
- package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
- package/src/mcp/primitives/$prompt.spec.ts +468 -0
- package/src/mcp/primitives/$resource.spec.ts +390 -0
- package/src/mcp/primitives/$tool.spec.ts +406 -0
- package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
- package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
- package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
- package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
- package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
- package/src/orm/__tests__/$repository-save.spec.ts +37 -0
- package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
- package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
- package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
- package/src/orm/__tests__/delete-returning.spec.ts +256 -0
- package/src/orm/__tests__/deletedAt.spec.ts +80 -0
- package/src/orm/__tests__/enums.spec.ts +315 -0
- package/src/orm/__tests__/execute.spec.ts +72 -0
- package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
- package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
- package/src/orm/__tests__/joins.spec.ts +1114 -0
- package/src/orm/__tests__/page.spec.ts +287 -0
- package/src/orm/__tests__/primaryKey.spec.ts +87 -0
- package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
- package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
- package/src/orm/__tests__/references.spec.ts +102 -0
- package/src/orm/__tests__/security.spec.ts +710 -0
- package/src/orm/__tests__/sqlite.spec.ts +111 -0
- package/src/orm/__tests__/string-operators.spec.ts +429 -0
- package/src/orm/__tests__/timestamps.spec.ts +388 -0
- package/src/orm/__tests__/validation.spec.ts +183 -0
- package/src/orm/__tests__/version.spec.ts +64 -0
- package/src/orm/helpers/parseQueryString.spec.ts +196 -0
- package/src/orm/index.browser.ts +1 -1
- package/src/orm/index.ts +10 -6
- package/src/orm/primitives/$repository.spec.ts +137 -0
- package/src/orm/primitives/$sequence.spec.ts +29 -0
- package/src/orm/primitives/$transaction.spec.ts +82 -0
- package/src/orm/providers/{PostgresTypeProvider.ts → DatabaseTypeProvider.ts} +25 -3
- package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
- package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
- package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
- package/src/orm/services/ModelBuilder.spec.ts +575 -0
- package/src/orm/services/Repository.spec.ts +137 -0
- package/src/queue/core/__tests__/shared.ts +143 -0
- package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
- package/src/queue/core/providers/WorkerProvider.spec.ts +378 -0
- package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
- package/src/redis/__tests__/redis.spec.ts +58 -0
- package/src/retry/primitives/$retry.spec.ts +234 -0
- package/src/retry/providers/RetryProvider.spec.ts +438 -0
- package/src/router/__tests__/match.spec.ts +252 -0
- package/src/router/providers/RouterProvider.spec.ts +197 -0
- package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
- package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
- package/src/scheduler/__tests__/shared.ts +77 -0
- package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
- package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
- package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
- package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
- package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
- package/src/security/primitives/$permission.spec.ts +30 -0
- package/src/security/primitives/$permission.ts +2 -2
- package/src/security/primitives/$realm.spec.ts +101 -0
- package/src/security/primitives/$role.spec.ts +52 -0
- package/src/security/primitives/$serviceAccount.spec.ts +61 -0
- package/src/security/providers/SecurityProvider.spec.ts +350 -0
- package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
- package/src/server/cache/providers/ServerCacheProvider.spec.ts +942 -0
- package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
- package/src/server/compress/providers/ServerCompressProvider.ts +2 -0
- package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
- package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
- package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
- package/src/server/core/primitives/$action.spec.ts +191 -0
- package/src/server/core/primitives/$route.spec.ts +65 -0
- package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
- package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
- package/src/server/core/providers/ServerProvider.ts +3 -1
- package/src/server/core/services/HttpClient.spec.ts +123 -0
- package/src/server/core/services/UserAgentParser.spec.ts +111 -0
- package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
- package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
- package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
- package/src/server/links/__tests__/$action.spec.ts +238 -0
- package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
- package/src/server/links/__tests__/requestId.spec.ts +120 -0
- package/src/server/links/primitives/$remote.spec.ts +228 -0
- package/src/server/links/providers/LinkProvider.spec.ts +54 -0
- package/src/server/links/providers/LinkProvider.ts +49 -3
- package/src/server/links/providers/ServerLinksProvider.ts +1 -53
- package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
- package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
- package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
- package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
- package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
- package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
- package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
- package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
- package/src/server/static/primitives/$serve.spec.ts +193 -0
- package/src/server/swagger/__tests__/ui.spec.ts +52 -0
- package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +18 -8
- package/src/sms/primitives/$sms.spec.ts +165 -0
- package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
- package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
- package/src/thread/primitives/$thread.spec.ts +186 -0
- package/src/topic/core/__tests__/shared.ts +144 -0
- package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
- package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
- package/src/vite/plugins/viteAlephaDev.ts +16 -4
- package/src/vite/tasks/runAlepha.ts +7 -1
- package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
- package/src/websocket/primitives/$channel.spec.ts +30 -0
- package/src/cli/commands/BiomeCommands.ts +0 -29
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
import { Alepha } from "alepha";
|
|
2
|
+
import { $action, AlephaServer } from "alepha/server";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
$basicAuth,
|
|
6
|
+
AlephaServerSecurity,
|
|
7
|
+
ServerBasicAuthProvider,
|
|
8
|
+
} from "../index.ts";
|
|
9
|
+
|
|
10
|
+
describe("Basic Authentication", () => {
|
|
11
|
+
let alepha: Alepha;
|
|
12
|
+
|
|
13
|
+
class TestApp {
|
|
14
|
+
// Action with basic auth enabled via options
|
|
15
|
+
protectedAction = $action({
|
|
16
|
+
secure: {
|
|
17
|
+
basic: {
|
|
18
|
+
username: "admin",
|
|
19
|
+
password: "secret123",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
handler: () => "protected success",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Action without basic auth
|
|
26
|
+
publicAction = $action({
|
|
27
|
+
handler: () => "public success",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Global basic auth for /devtools/*
|
|
31
|
+
devtoolsAuth = $basicAuth({
|
|
32
|
+
username: "dev",
|
|
33
|
+
password: "devpass",
|
|
34
|
+
paths: ["/devtools/*"],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Multiple basic auth instances
|
|
38
|
+
adminAuth = $basicAuth({
|
|
39
|
+
username: "admin",
|
|
40
|
+
password: "adminpass",
|
|
41
|
+
paths: ["/admin/*"],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Basic auth primitive for custom usage
|
|
45
|
+
customAuth = $basicAuth({
|
|
46
|
+
username: "custom",
|
|
47
|
+
password: "custompass",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
customAuthAction = $action({
|
|
51
|
+
handler: async (request) => {
|
|
52
|
+
this.customAuth.check(request);
|
|
53
|
+
return "custom auth success";
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
alepha = Alepha.create()
|
|
60
|
+
.with(AlephaServer)
|
|
61
|
+
.with(AlephaServerSecurity)
|
|
62
|
+
.with(TestApp);
|
|
63
|
+
|
|
64
|
+
await alepha.start();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
afterEach(async () => {
|
|
68
|
+
await alepha.stop();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("Action basicAuth option", () => {
|
|
72
|
+
it("should allow requests with valid credentials", async () => {
|
|
73
|
+
const app = alepha.inject(TestApp);
|
|
74
|
+
|
|
75
|
+
const result = await app.protectedAction.run({
|
|
76
|
+
headers: {
|
|
77
|
+
authorization: `Basic ${Buffer.from("admin:secret123").toString("base64")}`,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(result).toBe("protected success");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should block requests without credentials", async () => {
|
|
85
|
+
const app = alepha.inject(TestApp);
|
|
86
|
+
|
|
87
|
+
await expect(app.protectedAction.run({})).rejects.toThrow(
|
|
88
|
+
"Authentication required",
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should block requests with invalid credentials", async () => {
|
|
93
|
+
const app = alepha.inject(TestApp);
|
|
94
|
+
|
|
95
|
+
await expect(
|
|
96
|
+
app.protectedAction.run({
|
|
97
|
+
headers: {
|
|
98
|
+
authorization: `Basic ${Buffer.from("admin:wrongpass").toString("base64")}`,
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
).rejects.toThrow("Invalid credentials");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should block requests with invalid username", async () => {
|
|
105
|
+
const app = alepha.inject(TestApp);
|
|
106
|
+
|
|
107
|
+
await expect(
|
|
108
|
+
app.protectedAction.run({
|
|
109
|
+
headers: {
|
|
110
|
+
authorization: `Basic ${Buffer.from("wronguser:secret123").toString("base64")}`,
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
).rejects.toThrow("Invalid credentials");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("should allow public actions without authentication", async () => {
|
|
117
|
+
const app = alepha.inject(TestApp);
|
|
118
|
+
|
|
119
|
+
const result = await app.publicAction.run({});
|
|
120
|
+
expect(result).toBe("public success");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should handle malformed authorization header", async () => {
|
|
124
|
+
const app = alepha.inject(TestApp);
|
|
125
|
+
|
|
126
|
+
await expect(
|
|
127
|
+
app.protectedAction.run({
|
|
128
|
+
headers: {
|
|
129
|
+
authorization: "InvalidHeader",
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
).rejects.toThrow("Authentication required");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe("$basicAuth primitive", () => {
|
|
137
|
+
it("should create basic auth primitive with options", () => {
|
|
138
|
+
const app = alepha.inject(TestApp);
|
|
139
|
+
|
|
140
|
+
expect(app.devtoolsAuth).toBeDefined();
|
|
141
|
+
expect(app.devtoolsAuth.name).toBe("devtoolsAuth");
|
|
142
|
+
expect(app.devtoolsAuth.options.username).toBe("dev");
|
|
143
|
+
expect(app.devtoolsAuth.options.password).toBe("devpass");
|
|
144
|
+
expect(app.devtoolsAuth.options.paths).toEqual(["/devtools/*"]);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("should handle custom auth check in action logic", async () => {
|
|
148
|
+
const app = alepha.inject(TestApp);
|
|
149
|
+
|
|
150
|
+
// Should succeed with valid credentials
|
|
151
|
+
const result = await app.customAuthAction.run({
|
|
152
|
+
headers: {
|
|
153
|
+
authorization: `Basic ${Buffer.from("custom:custompass").toString("base64")}`,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
expect(result).toBe("custom auth success");
|
|
157
|
+
|
|
158
|
+
// Should fail without credentials
|
|
159
|
+
await expect(app.customAuthAction.run({})).rejects.toThrow(
|
|
160
|
+
"Authentication required",
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe("Route pattern matching with getRoutes()", () => {
|
|
166
|
+
it("should attach basicAuth to routes matching patterns at startup", () => {
|
|
167
|
+
const provider = alepha.inject(ServerBasicAuthProvider);
|
|
168
|
+
const app = alepha.inject(TestApp);
|
|
169
|
+
|
|
170
|
+
// Verify that auth was registered
|
|
171
|
+
expect(provider.registeredAuths.length).toBeGreaterThanOrEqual(2);
|
|
172
|
+
expect(
|
|
173
|
+
provider.registeredAuths.find((a) => a.username === "dev"),
|
|
174
|
+
).toBeDefined();
|
|
175
|
+
expect(
|
|
176
|
+
provider.registeredAuths.find((a) => a.username === "admin"),
|
|
177
|
+
).toBeDefined();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should register multiple auth instances", () => {
|
|
181
|
+
const provider = alepha.inject(ServerBasicAuthProvider);
|
|
182
|
+
const app = alepha.inject(TestApp);
|
|
183
|
+
|
|
184
|
+
expect(provider.registeredAuths.length).toBeGreaterThanOrEqual(2);
|
|
185
|
+
expect(
|
|
186
|
+
provider.registeredAuths.find((a) => a.username === "dev"),
|
|
187
|
+
).toBeDefined();
|
|
188
|
+
expect(
|
|
189
|
+
provider.registeredAuths.find((a) => a.username === "admin"),
|
|
190
|
+
).toBeDefined();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe("Multiple basic auth instances", () => {
|
|
195
|
+
it("should support multiple auth instances with different credentials", () => {
|
|
196
|
+
const app = alepha.inject(TestApp);
|
|
197
|
+
|
|
198
|
+
expect(app.devtoolsAuth.options.username).toBe("dev");
|
|
199
|
+
expect(app.adminAuth.options.username).toBe("admin");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("should register multiple auth instances", () => {
|
|
203
|
+
const app = alepha.inject(TestApp);
|
|
204
|
+
const provider = alepha.inject(ServerBasicAuthProvider);
|
|
205
|
+
|
|
206
|
+
expect(provider.registeredAuths.length).toBeGreaterThanOrEqual(2);
|
|
207
|
+
expect(
|
|
208
|
+
provider.registeredAuths.find((a) => a.username === "dev"),
|
|
209
|
+
).toBeDefined();
|
|
210
|
+
expect(
|
|
211
|
+
provider.registeredAuths.find((a) => a.username === "admin"),
|
|
212
|
+
).toBeDefined();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("Integration", () => {
|
|
217
|
+
it("should integrate basic auth with action hooks", async () => {
|
|
218
|
+
const app = alepha.inject(TestApp);
|
|
219
|
+
|
|
220
|
+
// Should work with valid credentials
|
|
221
|
+
const result = await app.protectedAction.run({
|
|
222
|
+
headers: {
|
|
223
|
+
authorization: `Basic ${Buffer.from("admin:secret123").toString("base64")}`,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
expect(result).toBe("protected success");
|
|
227
|
+
|
|
228
|
+
// Should fail without credentials
|
|
229
|
+
await expect(app.protectedAction.run({})).rejects.toThrow(
|
|
230
|
+
"Authentication required",
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should work with case-sensitive credentials", async () => {
|
|
235
|
+
const app = alepha.inject(TestApp);
|
|
236
|
+
|
|
237
|
+
// Correct case should work
|
|
238
|
+
const result = await app.protectedAction.run({
|
|
239
|
+
headers: {
|
|
240
|
+
authorization: `Basic ${Buffer.from("admin:secret123").toString("base64")}`,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
expect(result).toBe("protected success");
|
|
244
|
+
|
|
245
|
+
// Wrong case should fail
|
|
246
|
+
await expect(
|
|
247
|
+
app.protectedAction.run({
|
|
248
|
+
headers: {
|
|
249
|
+
authorization: `Basic ${Buffer.from("ADMIN:secret123").toString("base64")}`,
|
|
250
|
+
},
|
|
251
|
+
}),
|
|
252
|
+
).rejects.toThrow("Invalid credentials");
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe("Edge cases", () => {
|
|
257
|
+
it("should handle credentials with colon in password", async () => {
|
|
258
|
+
class EdgeCaseApp {
|
|
259
|
+
colonPasswordAction = $action({
|
|
260
|
+
secure: {
|
|
261
|
+
basic: {
|
|
262
|
+
username: "user",
|
|
263
|
+
password: "pass:word:123",
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
handler: () => "success",
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const edgeAlepha = Alepha.create()
|
|
271
|
+
.with(AlephaServer)
|
|
272
|
+
.with(AlephaServerSecurity)
|
|
273
|
+
.with(EdgeCaseApp);
|
|
274
|
+
|
|
275
|
+
await edgeAlepha.start();
|
|
276
|
+
|
|
277
|
+
const app = edgeAlepha.inject(EdgeCaseApp);
|
|
278
|
+
|
|
279
|
+
const result = await app.colonPasswordAction.run({
|
|
280
|
+
headers: {
|
|
281
|
+
authorization: `Basic ${Buffer.from("user:pass:word:123").toString("base64")}`,
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
expect(result).toBe("success");
|
|
285
|
+
|
|
286
|
+
await edgeAlepha.stop();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("should handle empty password", async () => {
|
|
290
|
+
class EmptyPasswordApp {
|
|
291
|
+
emptyPasswordAction = $action({
|
|
292
|
+
secure: {
|
|
293
|
+
basic: {
|
|
294
|
+
username: "user",
|
|
295
|
+
password: "",
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
handler: () => "success",
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const emptyAlepha = Alepha.create()
|
|
303
|
+
.with(AlephaServer)
|
|
304
|
+
.with(AlephaServerSecurity)
|
|
305
|
+
.with(EmptyPasswordApp);
|
|
306
|
+
|
|
307
|
+
await emptyAlepha.start();
|
|
308
|
+
|
|
309
|
+
const app = emptyAlepha.inject(EmptyPasswordApp);
|
|
310
|
+
|
|
311
|
+
const result = await app.emptyPasswordAction.run({
|
|
312
|
+
headers: {
|
|
313
|
+
authorization: `Basic ${Buffer.from("user:").toString("base64")}`,
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
expect(result).toBe("success");
|
|
317
|
+
|
|
318
|
+
await emptyAlepha.stop();
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("should handle special characters in credentials", async () => {
|
|
322
|
+
class SpecialCharsApp {
|
|
323
|
+
specialCharsAction = $action({
|
|
324
|
+
secure: {
|
|
325
|
+
basic: {
|
|
326
|
+
username: "user@domain.com",
|
|
327
|
+
password: "p@$$w0rd!#$%",
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
handler: () => "success",
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const specialAlepha = Alepha.create()
|
|
335
|
+
.with(AlephaServer)
|
|
336
|
+
.with(AlephaServerSecurity)
|
|
337
|
+
.with(SpecialCharsApp);
|
|
338
|
+
|
|
339
|
+
await specialAlepha.start();
|
|
340
|
+
|
|
341
|
+
const app = specialAlepha.inject(SpecialCharsApp);
|
|
342
|
+
|
|
343
|
+
const result = await app.specialCharsAction.run({
|
|
344
|
+
headers: {
|
|
345
|
+
authorization: `Basic ${Buffer.from("user@domain.com:p@$$w0rd!#$%").toString("base64")}`,
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
expect(result).toBe("success");
|
|
349
|
+
|
|
350
|
+
await specialAlepha.stop();
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it("should handle unicode characters (UTF-8) in credentials - valid", async () => {
|
|
354
|
+
class UnicodeApp {
|
|
355
|
+
unicodeAction = $action({
|
|
356
|
+
secure: {
|
|
357
|
+
basic: {
|
|
358
|
+
username: "用户名",
|
|
359
|
+
password: "密码🔐émoji",
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
handler: () => "success",
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const unicodeAlepha = Alepha.create()
|
|
367
|
+
.with(AlephaServer)
|
|
368
|
+
.with(AlephaServerSecurity)
|
|
369
|
+
.with(UnicodeApp);
|
|
370
|
+
|
|
371
|
+
await unicodeAlepha.start();
|
|
372
|
+
|
|
373
|
+
const app = unicodeAlepha.inject(UnicodeApp);
|
|
374
|
+
|
|
375
|
+
const result = await app.unicodeAction.run({
|
|
376
|
+
headers: {
|
|
377
|
+
authorization: `Basic ${Buffer.from("用户名:密码🔐émoji").toString("base64")}`,
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
expect(result).toBe("success");
|
|
381
|
+
|
|
382
|
+
await unicodeAlepha.stop();
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("should handle unicode characters (UTF-8) in credentials - invalid", async () => {
|
|
386
|
+
class UnicodeApp {
|
|
387
|
+
unicodeAction = $action({
|
|
388
|
+
secure: {
|
|
389
|
+
basic: {
|
|
390
|
+
username: "用户名",
|
|
391
|
+
password: "密码🔐émoji",
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
handler: () => "success",
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const unicodeAlepha = Alepha.create()
|
|
399
|
+
.with(AlephaServer)
|
|
400
|
+
.with(AlephaServerSecurity)
|
|
401
|
+
.with(UnicodeApp);
|
|
402
|
+
|
|
403
|
+
await unicodeAlepha.start();
|
|
404
|
+
|
|
405
|
+
const app = unicodeAlepha.inject(UnicodeApp);
|
|
406
|
+
|
|
407
|
+
// Should fail with wrong unicode password
|
|
408
|
+
await expect(
|
|
409
|
+
app.unicodeAction.run({
|
|
410
|
+
headers: {
|
|
411
|
+
authorization: `Basic ${Buffer.from("用户名:wrongpassword").toString("base64")}`,
|
|
412
|
+
},
|
|
413
|
+
}),
|
|
414
|
+
).rejects.toThrow("Invalid credentials");
|
|
415
|
+
|
|
416
|
+
await unicodeAlepha.stop();
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it("should handle very long credentials", async () => {
|
|
420
|
+
const longUsername = "a".repeat(1000);
|
|
421
|
+
const longPassword = "b".repeat(5000);
|
|
422
|
+
|
|
423
|
+
class LongCredsApp {
|
|
424
|
+
longCredsAction = $action({
|
|
425
|
+
secure: {
|
|
426
|
+
basic: {
|
|
427
|
+
username: longUsername,
|
|
428
|
+
password: longPassword,
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
handler: () => "success",
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const longAlepha = Alepha.create()
|
|
436
|
+
.with(AlephaServer)
|
|
437
|
+
.with(AlephaServerSecurity)
|
|
438
|
+
.with(LongCredsApp);
|
|
439
|
+
|
|
440
|
+
await longAlepha.start();
|
|
441
|
+
|
|
442
|
+
const app = longAlepha.inject(LongCredsApp);
|
|
443
|
+
|
|
444
|
+
const result = await app.longCredsAction.run({
|
|
445
|
+
headers: {
|
|
446
|
+
authorization: `Basic ${Buffer.from(`${longUsername}:${longPassword}`).toString("base64")}`,
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
expect(result).toBe("success");
|
|
450
|
+
|
|
451
|
+
await longAlepha.stop();
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("should handle empty username", async () => {
|
|
455
|
+
class EmptyUsernameApp {
|
|
456
|
+
emptyUsernameAction = $action({
|
|
457
|
+
secure: {
|
|
458
|
+
basic: {
|
|
459
|
+
username: "",
|
|
460
|
+
password: "somepassword",
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
handler: () => "success",
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const emptyUserAlepha = Alepha.create()
|
|
468
|
+
.with(AlephaServer)
|
|
469
|
+
.with(AlephaServerSecurity)
|
|
470
|
+
.with(EmptyUsernameApp);
|
|
471
|
+
|
|
472
|
+
await emptyUserAlepha.start();
|
|
473
|
+
|
|
474
|
+
const app = emptyUserAlepha.inject(EmptyUsernameApp);
|
|
475
|
+
|
|
476
|
+
const result = await app.emptyUsernameAction.run({
|
|
477
|
+
headers: {
|
|
478
|
+
authorization: `Basic ${Buffer.from(":somepassword").toString("base64")}`,
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
expect(result).toBe("success");
|
|
482
|
+
|
|
483
|
+
await emptyUserAlepha.stop();
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it("should reject invalid base64 encoding gracefully", async () => {
|
|
487
|
+
const app = alepha.inject(TestApp);
|
|
488
|
+
|
|
489
|
+
// Invalid base64 (not valid base64 characters)
|
|
490
|
+
await expect(
|
|
491
|
+
app.protectedAction.run({
|
|
492
|
+
headers: {
|
|
493
|
+
authorization: "Basic !!!invalid-base64!!!",
|
|
494
|
+
},
|
|
495
|
+
}),
|
|
496
|
+
).rejects.toThrow("Invalid credentials");
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it("should reject Bearer token (wrong auth type)", async () => {
|
|
500
|
+
const app = alepha.inject(TestApp);
|
|
501
|
+
|
|
502
|
+
await expect(
|
|
503
|
+
app.protectedAction.run({
|
|
504
|
+
headers: {
|
|
505
|
+
authorization: "Bearer some-jwt-token",
|
|
506
|
+
},
|
|
507
|
+
}),
|
|
508
|
+
).rejects.toThrow("Authentication required");
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it("should reject lowercase 'basic' auth type", async () => {
|
|
512
|
+
const app = alepha.inject(TestApp);
|
|
513
|
+
|
|
514
|
+
// Note: HTTP headers are case-insensitive but "Basic" scheme is typically case-sensitive
|
|
515
|
+
await expect(
|
|
516
|
+
app.protectedAction.run({
|
|
517
|
+
headers: {
|
|
518
|
+
authorization: `basic ${Buffer.from("admin:secret123").toString("base64")}`,
|
|
519
|
+
},
|
|
520
|
+
}),
|
|
521
|
+
).rejects.toThrow("Authentication required");
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it("should handle credentials without colon (malformed)", async () => {
|
|
525
|
+
const app = alepha.inject(TestApp);
|
|
526
|
+
|
|
527
|
+
// Base64 of just "admin" without colon
|
|
528
|
+
await expect(
|
|
529
|
+
app.protectedAction.run({
|
|
530
|
+
headers: {
|
|
531
|
+
authorization: `Basic ${Buffer.from("admin").toString("base64")}`,
|
|
532
|
+
},
|
|
533
|
+
}),
|
|
534
|
+
).rejects.toThrow("Invalid credentials");
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it("should handle whitespace in credentials - valid", async () => {
|
|
538
|
+
class WhitespaceApp {
|
|
539
|
+
whitespaceAction = $action({
|
|
540
|
+
secure: {
|
|
541
|
+
basic: {
|
|
542
|
+
username: " user ",
|
|
543
|
+
password: " pass ",
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
handler: () => "success",
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const wsAlepha = Alepha.create()
|
|
551
|
+
.with(AlephaServer)
|
|
552
|
+
.with(AlephaServerSecurity)
|
|
553
|
+
.with(WhitespaceApp);
|
|
554
|
+
|
|
555
|
+
await wsAlepha.start();
|
|
556
|
+
|
|
557
|
+
const app = wsAlepha.inject(WhitespaceApp);
|
|
558
|
+
|
|
559
|
+
// Whitespace should be preserved and matched exactly
|
|
560
|
+
const result = await app.whitespaceAction.run({
|
|
561
|
+
headers: {
|
|
562
|
+
authorization: `Basic ${Buffer.from(" user : pass ").toString("base64")}`,
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
expect(result).toBe("success");
|
|
566
|
+
|
|
567
|
+
await wsAlepha.stop();
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
it("should handle whitespace in credentials - invalid", async () => {
|
|
571
|
+
class WhitespaceApp {
|
|
572
|
+
whitespaceAction = $action({
|
|
573
|
+
secure: {
|
|
574
|
+
basic: {
|
|
575
|
+
username: " user ",
|
|
576
|
+
password: " pass ",
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
handler: () => "success",
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const wsAlepha = Alepha.create()
|
|
584
|
+
.with(AlephaServer)
|
|
585
|
+
.with(AlephaServerSecurity)
|
|
586
|
+
.with(WhitespaceApp);
|
|
587
|
+
|
|
588
|
+
await wsAlepha.start();
|
|
589
|
+
|
|
590
|
+
const app = wsAlepha.inject(WhitespaceApp);
|
|
591
|
+
|
|
592
|
+
// Without whitespace should fail
|
|
593
|
+
await expect(
|
|
594
|
+
app.whitespaceAction.run({
|
|
595
|
+
headers: {
|
|
596
|
+
authorization: `Basic ${Buffer.from("user:pass").toString("base64")}`,
|
|
597
|
+
},
|
|
598
|
+
}),
|
|
599
|
+
).rejects.toThrow("Invalid credentials");
|
|
600
|
+
|
|
601
|
+
await wsAlepha.stop();
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
it("should give same error for wrong username vs wrong password (no info leakage)", async () => {
|
|
605
|
+
const app = alepha.inject(TestApp);
|
|
606
|
+
|
|
607
|
+
// Wrong username
|
|
608
|
+
const wrongUserError = await app.protectedAction
|
|
609
|
+
.run({
|
|
610
|
+
headers: {
|
|
611
|
+
authorization: `Basic ${Buffer.from("wronguser:secret123").toString("base64")}`,
|
|
612
|
+
},
|
|
613
|
+
})
|
|
614
|
+
.catch((e) => e);
|
|
615
|
+
|
|
616
|
+
// Wrong password
|
|
617
|
+
const wrongPassError = await app.protectedAction
|
|
618
|
+
.run({
|
|
619
|
+
headers: {
|
|
620
|
+
authorization: `Basic ${Buffer.from("admin:wrongpass").toString("base64")}`,
|
|
621
|
+
},
|
|
622
|
+
})
|
|
623
|
+
.catch((e) => e);
|
|
624
|
+
|
|
625
|
+
// Both wrong
|
|
626
|
+
const bothWrongError = await app.protectedAction
|
|
627
|
+
.run({
|
|
628
|
+
headers: {
|
|
629
|
+
authorization: `Basic ${Buffer.from("wronguser:wrongpass").toString("base64")}`,
|
|
630
|
+
},
|
|
631
|
+
})
|
|
632
|
+
.catch((e) => e);
|
|
633
|
+
|
|
634
|
+
// All should have the same error message (no information leakage)
|
|
635
|
+
expect(wrongUserError.message).toBe("Invalid credentials");
|
|
636
|
+
expect(wrongPassError.message).toBe("Invalid credentials");
|
|
637
|
+
expect(bothWrongError.message).toBe("Invalid credentials");
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it("should handle different length usernames correctly", async () => {
|
|
641
|
+
const app = alepha.inject(TestApp);
|
|
642
|
+
|
|
643
|
+
// Shorter username
|
|
644
|
+
await expect(
|
|
645
|
+
app.protectedAction.run({
|
|
646
|
+
headers: {
|
|
647
|
+
authorization: `Basic ${Buffer.from("adm:secret123").toString("base64")}`,
|
|
648
|
+
},
|
|
649
|
+
}),
|
|
650
|
+
).rejects.toThrow("Invalid credentials");
|
|
651
|
+
|
|
652
|
+
// Longer username
|
|
653
|
+
await expect(
|
|
654
|
+
app.protectedAction.run({
|
|
655
|
+
headers: {
|
|
656
|
+
authorization: `Basic ${Buffer.from("administrator:secret123").toString("base64")}`,
|
|
657
|
+
},
|
|
658
|
+
}),
|
|
659
|
+
).rejects.toThrow("Invalid credentials");
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
it("should handle different length passwords correctly", async () => {
|
|
663
|
+
const app = alepha.inject(TestApp);
|
|
664
|
+
|
|
665
|
+
// Shorter password
|
|
666
|
+
await expect(
|
|
667
|
+
app.protectedAction.run({
|
|
668
|
+
headers: {
|
|
669
|
+
authorization: `Basic ${Buffer.from("admin:secret").toString("base64")}`,
|
|
670
|
+
},
|
|
671
|
+
}),
|
|
672
|
+
).rejects.toThrow("Invalid credentials");
|
|
673
|
+
|
|
674
|
+
// Longer password
|
|
675
|
+
await expect(
|
|
676
|
+
app.protectedAction.run({
|
|
677
|
+
headers: {
|
|
678
|
+
authorization: `Basic ${Buffer.from("admin:secret123456789").toString("base64")}`,
|
|
679
|
+
},
|
|
680
|
+
}),
|
|
681
|
+
).rejects.toThrow("Invalid credentials");
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
});
|