alepha 0.20.7 → 0.21.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 +30 -19
- package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/dist/api/audits/index.d.ts +2 -2
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.browser.js +25 -0
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +72 -2
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +82 -7
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +7 -5
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +4 -2
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +3 -0
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js +2 -0
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/oauth/index.d.ts +287 -0
- package/dist/api/oauth/index.d.ts.map +1 -0
- package/dist/api/oauth/index.js +578 -0
- package/dist/api/oauth/index.js.map +1 -0
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/parameters/index.d.ts +2 -2
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +2 -2
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +2 -0
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js +5 -4
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/subscriptions/index.d.ts.map +1 -1
- package/dist/api/users/index.browser.js +8 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +286 -5039
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +59 -8
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +2 -0
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +4 -2
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +2 -0
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +3 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +5 -0
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +9 -5
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +5 -3
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cli/core/index.d.ts +157 -18
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +309 -44
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js +10 -6
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/i18n/index.d.ts +136 -0
- package/dist/cli/i18n/index.d.ts.map +1 -0
- package/dist/cli/i18n/index.js +245 -0
- package/dist/cli/i18n/index.js.map +1 -0
- package/dist/cli/platform/index.d.ts +39 -1
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +123 -5
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +34 -9
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +55 -28
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/core/index.d.ts +0 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -22
- package/dist/core/index.js.map +1 -1
- package/dist/crypto/index.browser.js +73 -0
- package/dist/crypto/index.browser.js.map +1 -1
- package/dist/crypto/index.d.ts +10 -0
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js +60 -0
- package/dist/crypto/index.js.map +1 -1
- package/dist/mcp/index.d.ts +40 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +33 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.bun.js +1254 -1070
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +1494 -6228
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +2174 -2011
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +13 -20
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/react/form/index.d.ts +0 -28
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +18 -4
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.browser.js +3 -0
- package/dist/react/head/index.browser.js.map +1 -1
- package/dist/react/head/index.d.ts +13 -0
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/head/index.js +3 -0
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +3 -0
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/index.js +3 -3
- package/dist/react/testing/index.js.map +1 -1
- package/dist/redis/index.bun.js +2 -6
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/security/index.d.ts +14 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +11 -7
- package/dist/security/index.js.map +1 -1
- package/dist/server/core/index.d.ts +2 -1
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +3 -3
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/links/index.browser.js +18 -2
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +1 -0
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +18 -2
- package/dist/server/links/index.js.map +1 -1
- package/dist/system/index.d.ts +159 -128
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +249 -181
- package/dist/system/index.js.map +1 -1
- package/package.json +36 -15
- package/src/api/files/__tests__/FileAccessProvider.spec.ts +87 -0
- package/src/api/files/__tests__/FileController.spec.ts +4 -0
- package/src/api/files/controllers/FileController.ts +14 -4
- package/src/api/files/entities/files.ts +25 -0
- package/src/api/files/index.ts +9 -1
- package/src/api/files/providers/FileAccessProvider.ts +52 -0
- package/src/api/files/services/FileService.ts +2 -0
- package/src/api/jobs/providers/JobProvider.ts +4 -2
- package/src/api/keys/controllers/ApiKeyController.ts +1 -0
- package/src/api/keys/schemas/listApiKeyResponseSchema.ts +1 -0
- package/src/api/oauth/__tests__/OAuthClientService.spec.ts +123 -0
- package/src/api/oauth/__tests__/OAuthController.spec.ts +233 -0
- package/src/api/oauth/controllers/OAuthController.ts +275 -0
- package/src/api/oauth/entities/oauthClientEntity.ts +31 -0
- package/src/api/oauth/helpers/consentPage.ts +65 -0
- package/src/api/oauth/helpers/oauthMetadata.ts +29 -0
- package/src/api/oauth/index.ts +38 -0
- package/src/api/oauth/schemas/authorizeDecisionBodySchema.ts +18 -0
- package/src/api/oauth/schemas/authorizeQuerySchema.ts +15 -0
- package/src/api/oauth/schemas/registerClientBodySchema.ts +16 -0
- package/src/api/oauth/schemas/tokenRequestBodySchema.ts +16 -0
- package/src/api/oauth/services/OAuthClientService.ts +267 -0
- package/src/api/parameters/services/ParameterProvider.ts +2 -2
- package/src/api/payments/providers/MemoryPaymentProvider.ts +6 -4
- package/src/api/users/__tests__/ApiKeys.spec.ts +30 -0
- package/src/api/users/__tests__/realmOauth.spec.ts +52 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +7 -0
- package/src/api/users/entities/sessions.ts +8 -0
- package/src/api/users/primitives/$realm.ts +83 -2
- package/src/api/users/services/CredentialService.ts +1 -2
- package/src/api/users/services/RegistrationService.ts +8 -7
- package/src/api/users/services/SessionService.ts +2 -0
- package/src/api/verifications/services/VerificationService.ts +4 -2
- package/src/batch/providers/BatchProvider.ts +3 -1
- package/src/bucket/providers/CloudflareR2Provider.ts +3 -1
- package/src/bucket/providers/LocalFileStorageProvider.ts +3 -2
- package/src/bucket/providers/MemoryFileStorageProvider.ts +3 -2
- package/src/bucket/providers/NodeS3BucketProvider.ts +3 -1
- package/src/cli/core/__tests__/BuildDockerTask.spec.ts +306 -0
- package/src/cli/core/__tests__/init.spec.ts +28 -9
- package/src/cli/core/atoms/buildOptions.ts +45 -0
- package/src/cli/core/commands/build.ts +27 -0
- package/src/cli/core/commands/db.ts +4 -1
- package/src/cli/core/commands/init.ts +0 -3
- package/src/cli/core/commands/lint.ts +4 -8
- package/src/cli/core/commands/test.ts +21 -10
- package/src/cli/core/commands/typecheck.ts +4 -10
- package/src/cli/core/commands/verify.ts +4 -3
- package/src/cli/core/services/AlephaCliUtils.ts +57 -1
- package/src/cli/core/services/PackageManagerUtils.ts +8 -24
- package/src/cli/core/services/ProjectScaffolder.ts +41 -5
- package/src/cli/core/tasks/BuildDockerTask.ts +191 -14
- package/src/cli/core/templates/agentMd.ts +7 -0
- package/src/cli/core/templates/alephaConfigTs.ts +14 -0
- package/src/cli/core/templates/dummySpecTs.ts +15 -3
- package/src/cli/core/templates/vscodeSettingsJson.ts +21 -0
- package/src/cli/devtools/index.ts +10 -6
- package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +128 -0
- package/src/cli/i18n/atoms/i18nOptions.ts +51 -0
- package/src/cli/i18n/commands/I18nCommand.ts +81 -0
- package/src/cli/i18n/index.ts +52 -0
- package/src/cli/i18n/services/I18nCheckService.ts +144 -0
- package/src/cli/platform/adapters/CloudflareAdapter.ts +123 -31
- package/src/cli/platform/commands/SecretsCommand.ts +8 -4
- package/src/cli/platform/schemas/cloudflare.ts +24 -0
- package/src/cli/platform/services/CloudflareApi.ts +44 -0
- package/src/cli/vendor/__tests__/VendorService.spec.ts +32 -14
- package/src/cli/vendor/atoms/vendorOptions.ts +11 -1
- package/src/cli/vendor/commands/VendorCommand.ts +15 -3
- package/src/cli/vendor/services/VendorService.ts +55 -19
- package/src/core/index.ts +0 -32
- package/src/core/interfaces/Run.ts +0 -5
- package/src/crypto/__tests__/BrowserCryptoProvider.browser.spec.ts +58 -0
- package/src/crypto/providers/BrowserCryptoProvider.ts +115 -0
- package/src/crypto/providers/CryptoProvider.ts +99 -0
- package/src/mcp/__tests__/StreamableHttpMcpTransport.spec.ts +117 -0
- package/src/mcp/transports/StreamableHttpMcpTransport.ts +48 -0
- package/src/orm/__tests__/$sequence.spec.ts +87 -2
- package/src/orm/core/entities/alephaSequences.ts +42 -0
- package/src/orm/core/index.bun.ts +21 -20
- package/src/orm/core/index.shared-server.ts +2 -0
- package/src/orm/core/index.ts +2 -0
- package/src/orm/core/primitives/$sequence.ts +68 -27
- package/src/orm/core/providers/SequenceProvider.ts +103 -0
- package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +7 -2
- package/src/orm/core/services/Repository.ts +22 -1
- package/src/orm/postgres/index.bun.ts +5 -12
- package/src/react/form/__tests__/useForm.browser.spec.tsx +434 -0
- package/src/react/form/hooks/useForm.ts +32 -5
- package/src/react/head/interfaces/Head.ts +13 -0
- package/src/react/head/providers/BrowserHeadProvider.ts +9 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +4 -0
- package/src/redis/index.bun.ts +2 -6
- package/src/security/primitives/$issuer.ts +14 -0
- package/src/security/providers/ServerSecurityProvider.ts +20 -19
- package/src/server/core/__tests__/BunHttpServerProvider.bun.spec.ts +6 -6
- package/src/server/core/providers/ServerRouterProvider.ts +5 -2
- package/src/server/links/services/BatchCollector.ts +36 -2
- package/src/system/__tests__/BunShellProvider.bun.spec.ts +74 -0
- package/src/system/index.ts +13 -4
- package/src/system/providers/BunShellProvider.ts +81 -0
|
@@ -580,9 +580,9 @@ declare class AdminAuditController {
|
|
|
580
580
|
}>;
|
|
581
581
|
query: _$typebox.TObject<{
|
|
582
582
|
type: _$typebox.TOptional<_$typebox.TString>;
|
|
583
|
+
search: _$typebox.TOptional<_$typebox.TString>;
|
|
583
584
|
action: _$typebox.TOptional<_$typebox.TString>;
|
|
584
585
|
severity: _$typebox.TOptional<_$typebox.TUnsafe<"info" | "warning" | "critical">>;
|
|
585
|
-
search: _$typebox.TOptional<_$typebox.TString>;
|
|
586
586
|
sort: _$typebox.TOptional<_$typebox.TString>;
|
|
587
587
|
userRealm: _$typebox.TOptional<_$typebox.TString>;
|
|
588
588
|
resourceType: _$typebox.TOptional<_$typebox.TString>;
|
|
@@ -625,9 +625,9 @@ declare class AdminAuditController {
|
|
|
625
625
|
}>;
|
|
626
626
|
query: _$typebox.TObject<{
|
|
627
627
|
type: _$typebox.TOptional<_$typebox.TString>;
|
|
628
|
+
search: _$typebox.TOptional<_$typebox.TString>;
|
|
628
629
|
action: _$typebox.TOptional<_$typebox.TString>;
|
|
629
630
|
severity: _$typebox.TOptional<_$typebox.TUnsafe<"info" | "warning" | "critical">>;
|
|
630
|
-
search: _$typebox.TOptional<_$typebox.TString>;
|
|
631
631
|
sort: _$typebox.TOptional<_$typebox.TString>;
|
|
632
632
|
userId: _$typebox.TOptional<_$typebox.TString>;
|
|
633
633
|
userRealm: _$typebox.TOptional<_$typebox.TString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/audits/entities/audits.ts","../../../src/api/audits/schemas/auditQuerySchema.ts","../../../src/api/audits/schemas/createAuditSchema.ts","../../../src/api/audits/services/AuditService.ts","../../../src/api/audits/controllers/AdminAuditController.ts","../../../src/api/audits/primitives/$audit.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/audits/schemas/auditResourceSchema.ts","../../../src/api/audits/index.ts"],"mappings":";;;;;;;;;;;;;;cAOa,mBAAA,EAGX,SAAA,CAH8B,OAAA;AAAA,KAKpB,aAAA,GAAgB,MAAA,QAAc,mBAAA;;;;;;;;;;cAW7B,MAAA,EAAM,aAAA,CAAA,eAAA,WAAA,OAAA;gDAyGjB,SAAA,CAAA,OAAA;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/audits/entities/audits.ts","../../../src/api/audits/schemas/auditQuerySchema.ts","../../../src/api/audits/schemas/createAuditSchema.ts","../../../src/api/audits/services/AuditService.ts","../../../src/api/audits/controllers/AdminAuditController.ts","../../../src/api/audits/primitives/$audit.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/audits/schemas/auditResourceSchema.ts","../../../src/api/audits/index.ts"],"mappings":"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"}
|
|
@@ -15,10 +15,35 @@ const files = $entity({
|
|
|
15
15
|
creatorName: t.optional(t.string()),
|
|
16
16
|
bucket: t.text(),
|
|
17
17
|
expirationDate: t.optional(t.datetime()),
|
|
18
|
+
/**
|
|
19
|
+
* Display name. Mutable via `FileService.updateFile` — can be renamed
|
|
20
|
+
* by callers (e.g. an Archive UI letting users rename uploaded blobs).
|
|
21
|
+
* Initialized to the uploader's filename at upload time. Use
|
|
22
|
+
* `originalName` if you need the as-uploaded filename after a rename.
|
|
23
|
+
*/
|
|
18
24
|
name: t.text(),
|
|
25
|
+
/**
|
|
26
|
+
* Immutable record of the uploader's filename at upload time. Set once
|
|
27
|
+
* by `FileService.uploadFile` and the `bucket:file:uploaded` hook;
|
|
28
|
+
* `FileService.updateFile` never touches it. Useful for download
|
|
29
|
+
* headers (Content-Disposition), audit trails, and any UI that wants
|
|
30
|
+
* to show "originally uploaded as X" alongside a renamed file.
|
|
31
|
+
*/
|
|
32
|
+
originalName: t.optional(t.string()),
|
|
19
33
|
size: t.number(),
|
|
20
34
|
mimeType: t.string(),
|
|
35
|
+
/**
|
|
36
|
+
* Free-form taxonomy. Normalized server-side (trim/lowercase/dedupe is
|
|
37
|
+
* caller's responsibility for now). Use with `FileQuery.tags` to
|
|
38
|
+
* filter via array-contains.
|
|
39
|
+
*/
|
|
21
40
|
tags: t.optional(t.array(t.text())),
|
|
41
|
+
/**
|
|
42
|
+
* SHA-256 hex digest of the file content (64 lowercase hex chars).
|
|
43
|
+
* Computed at upload time by `FileService.calculateChecksum`. Stable
|
|
44
|
+
* — never recomputed after upload. Use for integrity verification,
|
|
45
|
+
* content-based dedup, or downstream virus-scan correlation.
|
|
46
|
+
*/
|
|
22
47
|
checksum: t.optional(t.string())
|
|
23
48
|
}),
|
|
24
49
|
indexes: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/api/files/entities/files.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const files = $entity({\n name: \"files\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n blobId: t.text(),\n creator: t.optional(t.uuid()),\n creatorRealm: t.optional(t.string()),\n creatorName: t.optional(t.string()),\n bucket: t.text(),\n expirationDate: t.optional(t.datetime()),\n name: t.text(),\n size: t.number(),\n mimeType: t.string(),\n tags: t.optional(t.array(t.text())),\n checksum: t.optional(t.string()),\n }),\n indexes: [\n \"expirationDate\",\n \"bucket\",\n \"creator\",\n \"createdAt\",\n \"mimeType\",\n {\n columns: [\"bucket\", \"createdAt\"],\n },\n ],\n});\n\nexport type FileEntity = Static<typeof files.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const fileQuerySchema = t.extend(pageQuerySchema, {\n bucket: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n name: t.optional(t.string()),\n mimeType: t.optional(t.string()),\n creator: t.optional(t.uuid()),\n createdAfter: t.optional(t.datetime()),\n createdBefore: t.optional(t.datetime()),\n});\n\nexport type FileQuery = Static<typeof fileQuerySchema>;\n","import { type Static, t } from \"alepha\";\nimport { files } from \"../entities/files.ts\";\n\nexport const fileResourceSchema = t.extend(\n files.schema,\n {},\n {\n title: \"FileResource\",\n description: \"A file resource representing a file stored in the system.\",\n },\n);\n\nexport type FileResource = Static<typeof fileResourceSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const bucketStatsSchema = t.object({\n bucket: t.string(),\n totalSize: t.number(),\n fileCount: t.number(),\n});\n\nexport const mimeTypeStatsSchema = t.object({\n mimeType: t.string(),\n fileCount: t.number(),\n});\n\nexport const storageStatsSchema = t.object({\n totalSize: t.number(),\n totalFiles: t.number(),\n byBucket: t.array(bucketStatsSchema),\n byMimeType: t.array(mimeTypeStatsSchema),\n});\n\nexport type BucketStats = Static<typeof bucketStatsSchema>;\nexport type MimeTypeStats = Static<typeof mimeTypeStatsSchema>;\nexport type StorageStats = Static<typeof storageStatsSchema>;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type * from \"./controllers/AdminFileStatsController.ts\";\nexport type * from \"./controllers/FileController.ts\";\nexport * from \"./entities/files.ts\";\nexport * from \"./schemas/fileQuerySchema.ts\";\nexport * from \"./schemas/fileResourceSchema.ts\";\nexport * from \"./schemas/storageStatsSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiFiles = $module({\n name: \"alepha.api.files\",\n services: [],\n});\n"],"mappings":";;;AAGA,MAAa,QAAQ,QAAQ;CAC3B,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,SAAS,GAAG,SAAS;EACrB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EACzB,gBAAgB,GAAG,cAAc;EACjC,QAAQ,EAAE,MAAM;EAChB,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;EAC7B,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC;EACpC,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;EACnC,QAAQ,EAAE,MAAM;EAChB,gBAAgB,EAAE,SAAS,EAAE,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/api/files/entities/files.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const files = $entity({\n name: \"files\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n blobId: t.text(),\n creator: t.optional(t.uuid()),\n creatorRealm: t.optional(t.string()),\n creatorName: t.optional(t.string()),\n bucket: t.text(),\n expirationDate: t.optional(t.datetime()),\n /**\n * Display name. Mutable via `FileService.updateFile` — can be renamed\n * by callers (e.g. an Archive UI letting users rename uploaded blobs).\n * Initialized to the uploader's filename at upload time. Use\n * `originalName` if you need the as-uploaded filename after a rename.\n */\n name: t.text(),\n /**\n * Immutable record of the uploader's filename at upload time. Set once\n * by `FileService.uploadFile` and the `bucket:file:uploaded` hook;\n * `FileService.updateFile` never touches it. Useful for download\n * headers (Content-Disposition), audit trails, and any UI that wants\n * to show \"originally uploaded as X\" alongside a renamed file.\n */\n originalName: t.optional(t.string()),\n size: t.number(),\n mimeType: t.string(),\n /**\n * Free-form taxonomy. Normalized server-side (trim/lowercase/dedupe is\n * caller's responsibility for now). Use with `FileQuery.tags` to\n * filter via array-contains.\n */\n tags: t.optional(t.array(t.text())),\n /**\n * SHA-256 hex digest of the file content (64 lowercase hex chars).\n * Computed at upload time by `FileService.calculateChecksum`. Stable\n * — never recomputed after upload. Use for integrity verification,\n * content-based dedup, or downstream virus-scan correlation.\n */\n checksum: t.optional(t.string()),\n }),\n indexes: [\n \"expirationDate\",\n \"bucket\",\n \"creator\",\n \"createdAt\",\n \"mimeType\",\n {\n columns: [\"bucket\", \"createdAt\"],\n },\n ],\n});\n\nexport type FileEntity = Static<typeof files.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const fileQuerySchema = t.extend(pageQuerySchema, {\n bucket: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n name: t.optional(t.string()),\n mimeType: t.optional(t.string()),\n creator: t.optional(t.uuid()),\n createdAfter: t.optional(t.datetime()),\n createdBefore: t.optional(t.datetime()),\n});\n\nexport type FileQuery = Static<typeof fileQuerySchema>;\n","import { type Static, t } from \"alepha\";\nimport { files } from \"../entities/files.ts\";\n\nexport const fileResourceSchema = t.extend(\n files.schema,\n {},\n {\n title: \"FileResource\",\n description: \"A file resource representing a file stored in the system.\",\n },\n);\n\nexport type FileResource = Static<typeof fileResourceSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const bucketStatsSchema = t.object({\n bucket: t.string(),\n totalSize: t.number(),\n fileCount: t.number(),\n});\n\nexport const mimeTypeStatsSchema = t.object({\n mimeType: t.string(),\n fileCount: t.number(),\n});\n\nexport const storageStatsSchema = t.object({\n totalSize: t.number(),\n totalFiles: t.number(),\n byBucket: t.array(bucketStatsSchema),\n byMimeType: t.array(mimeTypeStatsSchema),\n});\n\nexport type BucketStats = Static<typeof bucketStatsSchema>;\nexport type MimeTypeStats = Static<typeof mimeTypeStatsSchema>;\nexport type StorageStats = Static<typeof storageStatsSchema>;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type * from \"./controllers/AdminFileStatsController.ts\";\nexport type * from \"./controllers/FileController.ts\";\nexport * from \"./entities/files.ts\";\nexport * from \"./schemas/fileQuerySchema.ts\";\nexport * from \"./schemas/fileResourceSchema.ts\";\nexport * from \"./schemas/storageStatsSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiFiles = $module({\n name: \"alepha.api.files\",\n services: [],\n});\n"],"mappings":";;;AAGA,MAAa,QAAQ,QAAQ;CAC3B,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,SAAS,GAAG,SAAS;EACrB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EACzB,gBAAgB,GAAG,cAAc;EACjC,QAAQ,EAAE,MAAM;EAChB,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;EAC7B,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC;EACpC,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;EACnC,QAAQ,EAAE,MAAM;EAChB,gBAAgB,EAAE,SAAS,EAAE,UAAU,CAAC;;;;;;;EAOxC,MAAM,EAAE,MAAM;;;;;;;;EAQd,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC;EACpC,MAAM,EAAE,QAAQ;EAChB,UAAU,EAAE,QAAQ;;;;;;EAMpB,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;;;;;;;EAOnC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;EACjC,CAAC;CACF,SAAS;EACP;EACA;EACA;EACA;EACA;EACA,EACE,SAAS,CAAC,UAAU,YAAY,EACjC;EACF;CACF,CAAC;;;ACtDF,MAAa,kBAAkB,EAAE,OAAO,iBAAiB;CACvD,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;CAC9B,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;CACrC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC;CAC5B,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;CAChC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;CAC7B,cAAc,EAAE,SAAS,EAAE,UAAU,CAAC;CACtC,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC;CACxC,CAAC;;;ACTF,MAAa,qBAAqB,EAAE,OAClC,MAAM,QACN,EAAE,EACF;CACE,OAAO;CACP,aAAa;CACd,CACF;;;ACPD,MAAa,oBAAoB,EAAE,OAAO;CACxC,QAAQ,EAAE,QAAQ;CAClB,WAAW,EAAE,QAAQ;CACrB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,MAAa,sBAAsB,EAAE,OAAO;CAC1C,UAAU,EAAE,QAAQ;CACpB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,MAAa,qBAAqB,EAAE,OAAO;CACzC,WAAW,EAAE,QAAQ;CACrB,YAAY,EAAE,QAAQ;CACtB,UAAU,EAAE,MAAM,kBAAkB;CACpC,YAAY,EAAE,MAAM,oBAAoB;CACzC,CAAC;;;ACNF,MAAa,iBAAiB,QAAQ;CACpC,MAAM;CACN,UAAU,EAAE;CACb,CAAC"}
|
|
@@ -25,10 +25,35 @@ declare const files: _$alepha_orm0.EntityPrimitive<_$typebox.TObject<{
|
|
|
25
25
|
creatorName: _$typebox.TOptional<_$typebox.TString>;
|
|
26
26
|
bucket: _$typebox.TString;
|
|
27
27
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
28
|
+
/**
|
|
29
|
+
* Display name. Mutable via `FileService.updateFile` — can be renamed
|
|
30
|
+
* by callers (e.g. an Archive UI letting users rename uploaded blobs).
|
|
31
|
+
* Initialized to the uploader's filename at upload time. Use
|
|
32
|
+
* `originalName` if you need the as-uploaded filename after a rename.
|
|
33
|
+
*/
|
|
28
34
|
name: _$typebox.TString;
|
|
35
|
+
/**
|
|
36
|
+
* Immutable record of the uploader's filename at upload time. Set once
|
|
37
|
+
* by `FileService.uploadFile` and the `bucket:file:uploaded` hook;
|
|
38
|
+
* `FileService.updateFile` never touches it. Useful for download
|
|
39
|
+
* headers (Content-Disposition), audit trails, and any UI that wants
|
|
40
|
+
* to show "originally uploaded as X" alongside a renamed file.
|
|
41
|
+
*/
|
|
42
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
29
43
|
size: _$typebox.TNumber;
|
|
30
44
|
mimeType: _$typebox.TString;
|
|
45
|
+
/**
|
|
46
|
+
* Free-form taxonomy. Normalized server-side (trim/lowercase/dedupe is
|
|
47
|
+
* caller's responsibility for now). Use with `FileQuery.tags` to
|
|
48
|
+
* filter via array-contains.
|
|
49
|
+
*/
|
|
31
50
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
51
|
+
/**
|
|
52
|
+
* SHA-256 hex digest of the file content (64 lowercase hex chars).
|
|
53
|
+
* Computed at upload time by `FileService.calculateChecksum`. Stable
|
|
54
|
+
* — never recomputed after upload. Use for integrity verification,
|
|
55
|
+
* content-based dedup, or downstream virus-scan correlation.
|
|
56
|
+
*/
|
|
32
57
|
checksum: _$typebox.TOptional<_$typebox.TString>;
|
|
33
58
|
}>>;
|
|
34
59
|
type FileEntity = Static<typeof files.schema>;
|
|
@@ -368,6 +393,7 @@ declare const fileResourceSchema: _$typebox.TObject<{
|
|
|
368
393
|
bucket: _$typebox.TString;
|
|
369
394
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
370
395
|
name: _$typebox.TString;
|
|
396
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
371
397
|
size: _$typebox.TNumber;
|
|
372
398
|
mimeType: _$typebox.TString;
|
|
373
399
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
@@ -421,6 +447,7 @@ declare class FileService {
|
|
|
421
447
|
bucket: _$typebox.TString;
|
|
422
448
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
423
449
|
name: _$typebox.TString;
|
|
450
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
424
451
|
size: _$typebox.TNumber;
|
|
425
452
|
mimeType: _$typebox.TString;
|
|
426
453
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
@@ -584,6 +611,39 @@ declare class AdminFileStatsController {
|
|
|
584
611
|
}>;
|
|
585
612
|
}
|
|
586
613
|
//#endregion
|
|
614
|
+
//#region ../../src/api/files/providers/FileAccessProvider.d.ts
|
|
615
|
+
/**
|
|
616
|
+
* Authorization policy for file reads served through `FileController.streamFile`.
|
|
617
|
+
*
|
|
618
|
+
* Default: the caller must be the uploader (`file.creator === user.id`). Any
|
|
619
|
+
* other access path — public buckets, shared attachments, avatars — must be
|
|
620
|
+
* opted in by overriding this provider in the consuming app:
|
|
621
|
+
*
|
|
622
|
+
* ```ts
|
|
623
|
+
* class MyAccess extends FileAccessProvider {
|
|
624
|
+
* async assertReadable(file, user) {
|
|
625
|
+
* if (file.bucket === "avatars") return; // public
|
|
626
|
+
* if (file.bucket === "campaign-icons") return this.checkCampaignVisible(file, user);
|
|
627
|
+
* return super.assertReadable(file, user);
|
|
628
|
+
* }
|
|
629
|
+
* }
|
|
630
|
+
* Alepha.create().with({ provide: FileAccessProvider, use: MyAccess });
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* Why this exists: prior to introducing this gate, `streamFile` only required
|
|
634
|
+
* the framework-wide `file:read` permission. The default `user` role grants
|
|
635
|
+
* `*`, so every authenticated user could download any file by UUID — turning
|
|
636
|
+
* the 128-bit id into the sole security boundary across tenants.
|
|
637
|
+
*/
|
|
638
|
+
declare class FileAccessProvider {
|
|
639
|
+
/**
|
|
640
|
+
* Throws `ForbiddenError` when `user` may not read `file`. Override to
|
|
641
|
+
* implement bucket-aware or relationship-aware policies. The default
|
|
642
|
+
* implementation is strict: only the uploader passes.
|
|
643
|
+
*/
|
|
644
|
+
assertReadable(file: FileEntity, user: UserAccountToken | undefined): Promise<void>;
|
|
645
|
+
}
|
|
646
|
+
//#endregion
|
|
587
647
|
//#region ../../src/api/files/controllers/FileController.d.ts
|
|
588
648
|
/**
|
|
589
649
|
* REST API controller for file management operations.
|
|
@@ -593,6 +653,7 @@ declare class FileController {
|
|
|
593
653
|
protected readonly url = "/files";
|
|
594
654
|
protected readonly group = "files";
|
|
595
655
|
protected readonly fileService: FileService;
|
|
656
|
+
protected readonly fileAccess: FileAccessProvider;
|
|
596
657
|
/**
|
|
597
658
|
* GET /files - Lists files with optional filtering and pagination.
|
|
598
659
|
* Supports filtering by bucket and tags.
|
|
@@ -623,6 +684,7 @@ declare class FileController {
|
|
|
623
684
|
bucket: _$typebox.TString;
|
|
624
685
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
625
686
|
name: _$typebox.TString;
|
|
687
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
626
688
|
size: _$typebox.TNumber;
|
|
627
689
|
mimeType: _$typebox.TString;
|
|
628
690
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
@@ -681,6 +743,7 @@ declare class FileController {
|
|
|
681
743
|
bucket: _$typebox.TString;
|
|
682
744
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
683
745
|
name: _$typebox.TString;
|
|
746
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
684
747
|
size: _$typebox.TNumber;
|
|
685
748
|
mimeType: _$typebox.TString;
|
|
686
749
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
@@ -713,6 +776,7 @@ declare class FileController {
|
|
|
713
776
|
bucket: _$typebox.TString;
|
|
714
777
|
expirationDate: _$typebox.TOptional<_$typebox.TString>;
|
|
715
778
|
name: _$typebox.TString;
|
|
779
|
+
originalName: _$typebox.TOptional<_$typebox.TString>;
|
|
716
780
|
size: _$typebox.TNumber;
|
|
717
781
|
mimeType: _$typebox.TString;
|
|
718
782
|
tags: _$typebox.TOptional<_$typebox.TArray<_$typebox.TString>>;
|
|
@@ -722,7 +786,13 @@ declare class FileController {
|
|
|
722
786
|
/**
|
|
723
787
|
* GET /files/:id - Streams/downloads a file by its ID.
|
|
724
788
|
* Returns the file content with appropriate Content-Type header.
|
|
725
|
-
*
|
|
789
|
+
*
|
|
790
|
+
* Authorization is delegated to `FileAccessProvider.assertReadable`. The
|
|
791
|
+
* default policy is creator-only — override the provider via DI to widen
|
|
792
|
+
* access (e.g. avatars, shared attachments). See `FileAccessProvider`.
|
|
793
|
+
*
|
|
794
|
+
* Cache-Control is `private` because the per-user authorization decision
|
|
795
|
+
* cannot be cached by shared proxies/CDNs. Client-side ETag still works.
|
|
726
796
|
*/
|
|
727
797
|
readonly streamFile: _$alepha_server0.ActionPrimitiveFn<{
|
|
728
798
|
params: _$typebox.TObject<{
|
|
@@ -774,5 +844,5 @@ declare module "alepha/bucket" {
|
|
|
774
844
|
*/
|
|
775
845
|
declare const AlephaApiFiles: _$alepha.Service<_$alepha.Module>;
|
|
776
846
|
//#endregion
|
|
777
|
-
export { AdminFileStatsController, AlephaApiFiles, BucketStats, FileController, FileEntity, FileJobs, FileService, MimeTypeStats, StorageStats, bucketStatsSchema, files, mimeTypeStatsSchema, storageStatsSchema };
|
|
847
|
+
export { AdminFileStatsController, AlephaApiFiles, BucketStats, FileAccessProvider, FileController, FileEntity, FileJobs, FileService, MimeTypeStats, StorageStats, bucketStatsSchema, files, mimeTypeStatsSchema, storageStatsSchema };
|
|
778
848
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/files/entities/files.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/services/FileService.ts","../../../src/api/files/controllers/AdminFileStatsController.ts","../../../src/api/files/controllers/FileController.ts","../../../src/api/files/jobs/FileJobs.ts","../../../src/api/files/index.ts"],"mappings":";;;;;;;;;;;;;;;cAGa,KAAA,EAAK,aAAA,CAAA,eAAA,WAAA,OAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/files/entities/files.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/services/FileService.ts","../../../src/api/files/controllers/AdminFileStatsController.ts","../../../src/api/files/providers/FileAccessProvider.ts","../../../src/api/files/controllers/FileController.ts","../../../src/api/files/jobs/FileJobs.ts","../../../src/api/files/index.ts"],"mappings":"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"}
|
package/dist/api/files/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { $hook, $inject, $module, Alepha, t } from "alepha";
|
|
|
2
2
|
import { $bucket, AlephaBucket, FileNotFoundError } from "alepha/bucket";
|
|
3
3
|
import { $etag, AlephaServerEtag } from "alepha/server/etag";
|
|
4
4
|
import { $secure } from "alepha/security";
|
|
5
|
-
import { $action, NotFoundError, okSchema } from "alepha/server";
|
|
5
|
+
import { $action, ForbiddenError, NotFoundError, okSchema } from "alepha/server";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import { DateTimeProvider } from "alepha/datetime";
|
|
8
8
|
import { $logger } from "alepha/logger";
|
|
@@ -40,10 +40,35 @@ const files = $entity({
|
|
|
40
40
|
creatorName: t.optional(t.string()),
|
|
41
41
|
bucket: t.text(),
|
|
42
42
|
expirationDate: t.optional(t.datetime()),
|
|
43
|
+
/**
|
|
44
|
+
* Display name. Mutable via `FileService.updateFile` — can be renamed
|
|
45
|
+
* by callers (e.g. an Archive UI letting users rename uploaded blobs).
|
|
46
|
+
* Initialized to the uploader's filename at upload time. Use
|
|
47
|
+
* `originalName` if you need the as-uploaded filename after a rename.
|
|
48
|
+
*/
|
|
43
49
|
name: t.text(),
|
|
50
|
+
/**
|
|
51
|
+
* Immutable record of the uploader's filename at upload time. Set once
|
|
52
|
+
* by `FileService.uploadFile` and the `bucket:file:uploaded` hook;
|
|
53
|
+
* `FileService.updateFile` never touches it. Useful for download
|
|
54
|
+
* headers (Content-Disposition), audit trails, and any UI that wants
|
|
55
|
+
* to show "originally uploaded as X" alongside a renamed file.
|
|
56
|
+
*/
|
|
57
|
+
originalName: t.optional(t.string()),
|
|
44
58
|
size: t.number(),
|
|
45
59
|
mimeType: t.string(),
|
|
60
|
+
/**
|
|
61
|
+
* Free-form taxonomy. Normalized server-side (trim/lowercase/dedupe is
|
|
62
|
+
* caller's responsibility for now). Use with `FileQuery.tags` to
|
|
63
|
+
* filter via array-contains.
|
|
64
|
+
*/
|
|
46
65
|
tags: t.optional(t.array(t.text())),
|
|
66
|
+
/**
|
|
67
|
+
* SHA-256 hex digest of the file content (64 lowercase hex chars).
|
|
68
|
+
* Computed at upload time by `FileService.calculateChecksum`. Stable
|
|
69
|
+
* — never recomputed after upload. Use for integrity verification,
|
|
70
|
+
* content-based dedup, or downstream virus-scan correlation.
|
|
71
|
+
*/
|
|
47
72
|
checksum: t.optional(t.string())
|
|
48
73
|
}),
|
|
49
74
|
indexes: [
|
|
@@ -72,6 +97,7 @@ var FileService = class {
|
|
|
72
97
|
blobId: id,
|
|
73
98
|
mimeType: file.type,
|
|
74
99
|
name: file.name,
|
|
100
|
+
originalName: file.name,
|
|
75
101
|
size: file.size,
|
|
76
102
|
creator: options.user?.id,
|
|
77
103
|
creatorRealm: options.user?.realm,
|
|
@@ -189,6 +215,7 @@ var FileService = class {
|
|
|
189
215
|
blobId,
|
|
190
216
|
mimeType: file.type,
|
|
191
217
|
name: file.name,
|
|
218
|
+
originalName: file.name,
|
|
192
219
|
size: file.size,
|
|
193
220
|
creator: options.user?.id,
|
|
194
221
|
creatorRealm: options.user?.realm,
|
|
@@ -371,6 +398,44 @@ var AdminFileStatsController = class {
|
|
|
371
398
|
});
|
|
372
399
|
};
|
|
373
400
|
//#endregion
|
|
401
|
+
//#region ../../src/api/files/providers/FileAccessProvider.ts
|
|
402
|
+
/**
|
|
403
|
+
* Authorization policy for file reads served through `FileController.streamFile`.
|
|
404
|
+
*
|
|
405
|
+
* Default: the caller must be the uploader (`file.creator === user.id`). Any
|
|
406
|
+
* other access path — public buckets, shared attachments, avatars — must be
|
|
407
|
+
* opted in by overriding this provider in the consuming app:
|
|
408
|
+
*
|
|
409
|
+
* ```ts
|
|
410
|
+
* class MyAccess extends FileAccessProvider {
|
|
411
|
+
* async assertReadable(file, user) {
|
|
412
|
+
* if (file.bucket === "avatars") return; // public
|
|
413
|
+
* if (file.bucket === "campaign-icons") return this.checkCampaignVisible(file, user);
|
|
414
|
+
* return super.assertReadable(file, user);
|
|
415
|
+
* }
|
|
416
|
+
* }
|
|
417
|
+
* Alepha.create().with({ provide: FileAccessProvider, use: MyAccess });
|
|
418
|
+
* ```
|
|
419
|
+
*
|
|
420
|
+
* Why this exists: prior to introducing this gate, `streamFile` only required
|
|
421
|
+
* the framework-wide `file:read` permission. The default `user` role grants
|
|
422
|
+
* `*`, so every authenticated user could download any file by UUID — turning
|
|
423
|
+
* the 128-bit id into the sole security boundary across tenants.
|
|
424
|
+
*/
|
|
425
|
+
var FileAccessProvider = class {
|
|
426
|
+
/**
|
|
427
|
+
* Throws `ForbiddenError` when `user` may not read `file`. Override to
|
|
428
|
+
* implement bucket-aware or relationship-aware policies. The default
|
|
429
|
+
* implementation is strict: only the uploader passes.
|
|
430
|
+
*/
|
|
431
|
+
async assertReadable(file, user) {
|
|
432
|
+
if (!user) throw new ForbiddenError("File access requires authentication");
|
|
433
|
+
if (user.ownership === false) return;
|
|
434
|
+
if (file.creator && file.creator === user.id) return;
|
|
435
|
+
throw new ForbiddenError("File access denied");
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
//#endregion
|
|
374
439
|
//#region ../../src/api/files/schemas/fileQuerySchema.ts
|
|
375
440
|
const fileQuerySchema = t.extend(pageQuerySchema, {
|
|
376
441
|
bucket: t.optional(t.string()),
|
|
@@ -397,6 +462,7 @@ var FileController = class {
|
|
|
397
462
|
url = "/files";
|
|
398
463
|
group = "files";
|
|
399
464
|
fileService = $inject(FileService);
|
|
465
|
+
fileAccess = $inject(FileAccessProvider);
|
|
400
466
|
/**
|
|
401
467
|
* GET /files - Lists files with optional filtering and pagination.
|
|
402
468
|
* Supports filtering by bucket and tags.
|
|
@@ -496,14 +562,20 @@ var FileController = class {
|
|
|
496
562
|
/**
|
|
497
563
|
* GET /files/:id - Streams/downloads a file by its ID.
|
|
498
564
|
* Returns the file content with appropriate Content-Type header.
|
|
499
|
-
*
|
|
565
|
+
*
|
|
566
|
+
* Authorization is delegated to `FileAccessProvider.assertReadable`. The
|
|
567
|
+
* default policy is creator-only — override the provider via DI to widen
|
|
568
|
+
* access (e.g. avatars, shared attachments). See `FileAccessProvider`.
|
|
569
|
+
*
|
|
570
|
+
* Cache-Control is `private` because the per-user authorization decision
|
|
571
|
+
* cannot be cached by shared proxies/CDNs. Client-side ETag still works.
|
|
500
572
|
*/
|
|
501
573
|
streamFile = $action({
|
|
502
574
|
path: `${this.url}/:id`,
|
|
503
575
|
group: this.group,
|
|
504
576
|
description: "Download a file",
|
|
505
577
|
use: [$secure({ permissions: ["file:read"] }), $etag({ control: {
|
|
506
|
-
|
|
578
|
+
private: true,
|
|
507
579
|
maxAge: [1, "year"],
|
|
508
580
|
immutable: true
|
|
509
581
|
} })],
|
|
@@ -511,8 +583,10 @@ var FileController = class {
|
|
|
511
583
|
params: t.object({ id: t.uuid() }),
|
|
512
584
|
response: t.file()
|
|
513
585
|
},
|
|
514
|
-
handler: async ({ params }) => {
|
|
515
|
-
|
|
586
|
+
handler: async ({ params, user }) => {
|
|
587
|
+
const file = await this.fileService.getFileById(params.id);
|
|
588
|
+
await this.fileAccess.assertReadable(file, user);
|
|
589
|
+
return await this.fileService.streamFile(file.id);
|
|
516
590
|
}
|
|
517
591
|
});
|
|
518
592
|
};
|
|
@@ -549,11 +623,12 @@ const AlephaApiFiles = $module({
|
|
|
549
623
|
FileController,
|
|
550
624
|
AdminFileStatsController,
|
|
551
625
|
FileJobs,
|
|
552
|
-
FileService
|
|
626
|
+
FileService,
|
|
627
|
+
FileAccessProvider
|
|
553
628
|
],
|
|
554
629
|
imports: [AlephaBucket, AlephaServerEtag]
|
|
555
630
|
});
|
|
556
631
|
//#endregion
|
|
557
|
-
export { AdminFileStatsController, AlephaApiFiles, FileController, FileJobs, FileService, bucketStatsSchema, files, mimeTypeStatsSchema, storageStatsSchema };
|
|
632
|
+
export { AdminFileStatsController, AlephaApiFiles, FileAccessProvider, FileController, FileJobs, FileService, bucketStatsSchema, files, mimeTypeStatsSchema, storageStatsSchema };
|
|
558
633
|
|
|
559
634
|
//# sourceMappingURL=index.js.map
|