@arcote.tech/arc-files 0.7.27 → 0.7.29
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/package.json +4 -4
- package/src/aggregates/file.ts +38 -5
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-files",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.29",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Generic file upload fragment for Arc framework — S3 presigned upload + provider file_id binding",
|
|
7
7
|
"main": "./src/index.ts",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"type-check": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@arcote.tech/arc": "^0.7.
|
|
14
|
-
"@arcote.tech/arc-ds": "^0.7.
|
|
15
|
-
"@arcote.tech/platform": "^0.7.
|
|
13
|
+
"@arcote.tech/arc": "^0.7.29",
|
|
14
|
+
"@arcote.tech/arc-ds": "^0.7.29",
|
|
15
|
+
"@arcote.tech/platform": "^0.7.29",
|
|
16
16
|
"@aws-sdk/client-s3": "^3.658.0",
|
|
17
17
|
"@aws-sdk/s3-request-presigner": "^3.658.0",
|
|
18
18
|
"lucide-react": ">=0.400.0",
|
package/src/aggregates/file.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
string,
|
|
9
9
|
type ArcAggregateElement,
|
|
10
10
|
type ArcId,
|
|
11
|
+
type ArcRawShape,
|
|
11
12
|
} from "@arcote.tech/arc";
|
|
12
13
|
import type { S3Bridge } from "../s3/s3-client";
|
|
13
14
|
import type { FileProviderName } from "../types";
|
|
@@ -51,9 +52,20 @@ export function createFileTypeAggregate<const Data extends FileTypeData>(
|
|
|
51
52
|
const metadataShape = data.metadata;
|
|
52
53
|
const fullShape = mergeUnsafe(builtInFields, metadataShape);
|
|
53
54
|
|
|
54
|
-
// `requestUpload` params
|
|
55
|
-
//
|
|
56
|
-
//
|
|
55
|
+
// `requestUpload` params = built-in (name, mime, size) + custom metadata,
|
|
56
|
+
// ale metadata są OPCJONALNE. Pola scope (accountId itd.) są wyprowadzane
|
|
57
|
+
// autorytatywnie z aktywnego tokena server-side (patrz handler niżej), więc
|
|
58
|
+
// klient nie musi — i nie powinien — ich wysyłać. Consumer może pominąć
|
|
59
|
+
// wartość pochodzącą z tokena; serwer i tak ją nadpisze wartością z tokena.
|
|
60
|
+
const optionalMetadata: ArcRawShape = {};
|
|
61
|
+
for (const [key, element] of Object.entries(metadataShape)) {
|
|
62
|
+
// `validate(undefined) === false` → element już jest opcjonalny
|
|
63
|
+
// (ArcOptional), nie owijaj ponownie (ArcOptional nie ma `.optional()`).
|
|
64
|
+
const alreadyOptional = (element as any).validate?.(undefined) === false;
|
|
65
|
+
optionalMetadata[key] = alreadyOptional
|
|
66
|
+
? element
|
|
67
|
+
: (element as any).optional();
|
|
68
|
+
}
|
|
57
69
|
const requestUploadParams = mergeUnsafe(
|
|
58
70
|
{
|
|
59
71
|
_id: fileId,
|
|
@@ -61,7 +73,7 @@ export function createFileTypeAggregate<const Data extends FileTypeData>(
|
|
|
61
73
|
mime: string(),
|
|
62
74
|
size: number(),
|
|
63
75
|
},
|
|
64
|
-
|
|
76
|
+
optionalMetadata,
|
|
65
77
|
);
|
|
66
78
|
|
|
67
79
|
// `fileRequested` event payload = `requestUploadParams` + s3 fields
|
|
@@ -142,6 +154,27 @@ export function createFileTypeAggregate<const Data extends FileTypeData>(
|
|
|
142
154
|
const s3Key = `${data.name}/${p._id}/${p.name}`;
|
|
143
155
|
const uploadUrl = await s3.presignUpload(s3Key, p.name && p.mime);
|
|
144
156
|
|
|
157
|
+
// Pola scope (accountId itd.) bierzemy AUTORYTATYWNIE z aktywnego
|
|
158
|
+
// tokena — nigdy z params klienta. `protection.check(tokenPayload)`
|
|
159
|
+
// zwraca dokładnie mapowanie token→metadata (`{accountId: p.accountId}`),
|
|
160
|
+
// to samo, którego arc-core używa do restrykcji scope. Zapobiega
|
|
161
|
+
// podszyciu pod cudze accountId i znosi wymóg wysyłania go przez
|
|
162
|
+
// klienta (który przed załadowaniem `me` słał undefined → padała
|
|
163
|
+
// walidacja wejścia).
|
|
164
|
+
const auth = (ctx as any).$auth as
|
|
165
|
+
| { params: any; tokenName: string }
|
|
166
|
+
| undefined;
|
|
167
|
+
const derived: Record<string, any> = {};
|
|
168
|
+
if (auth?.tokenName) {
|
|
169
|
+
for (const protection of data.protections) {
|
|
170
|
+
if ((protection.token as any).name !== auth.tokenName) continue;
|
|
171
|
+
const restriction = protection.check(auth.params);
|
|
172
|
+
if (restriction && typeof restriction === "object") {
|
|
173
|
+
Object.assign(derived, restriction);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
145
178
|
const payload: Record<string, any> = {
|
|
146
179
|
_id: p._id,
|
|
147
180
|
name: p.name,
|
|
@@ -151,7 +184,7 @@ export function createFileTypeAggregate<const Data extends FileTypeData>(
|
|
|
151
184
|
s3Key,
|
|
152
185
|
};
|
|
153
186
|
for (const key of Object.keys(metadataShape)) {
|
|
154
|
-
payload[key] = p[key];
|
|
187
|
+
payload[key] = key in derived ? derived[key] : p[key];
|
|
155
188
|
}
|
|
156
189
|
await (ctx as any).fileRequested.emit(payload);
|
|
157
190
|
|