Skip to content

Commit 0708bab

Browse files
committed
feat(gate): sign upload url
1 parent 167216e commit 0708bab

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

typegate/src/services/file_upload_service.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,46 @@
11
// Copyright Metatype OÜ, licensed under the Elastic License 2.0.
22
// SPDX-License-Identifier: Elastic-2.0
33

4+
import config from "../config.ts";
5+
import { signJWT, verifyJWT } from "../crypto.ts";
46
import { UploadUrlMeta } from "../engine/query_engine.ts";
57
import { QueryEngine } from "../engine/query_engine.ts";
68

79
interface TypegraphFile {
810
name: string;
9-
fileHash: string;
10-
fileSizeInBytes: number;
11+
file_hash: string;
12+
file_size_in_bytes: number;
1113
}
1214

1315
function createUploadPath(origin: string, typegraphName: string) {
1416
const rand_path = crypto.randomUUID();
15-
return `${origin}/upload-files/${typegraphName}/files/${rand_path}`;
17+
return `${origin}/${typegraphName}/upload-files/files/${rand_path}`;
1618
}
1719

1820
export async function handleUploadUrl(request: Request, engine: QueryEngine) {
1921
const url = new URL(request.url);
2022
const origin = url.origin;
21-
const { name, fileHash, fileSizeInBytes }: TypegraphFile = await request
23+
const { name, file_hash, file_size_in_bytes }: TypegraphFile = await request
2224
.json();
23-
2425
const uploadUrlMeta: UploadUrlMeta = {
2526
fileName: name,
26-
fileHash: fileHash,
27-
fileSizeInBytes: fileSizeInBytes,
27+
fileHash: file_hash,
28+
fileSizeInBytes: file_size_in_bytes,
2829
urlUsed: false,
2930
};
3031

31-
const uploadUrl = createUploadPath(origin, engine.name);
32+
let uploadUrl = createUploadPath(origin, engine.name);
33+
34+
const expiresIn = 5 * 60; // 5 minutes
35+
const payload = {
36+
"expiresIn": expiresIn,
37+
};
38+
const token = await signJWT(payload, expiresIn);
39+
uploadUrl = `${uploadUrl}?token=${token}`;
3240

3341
engine.fileUploadUrlCache.set(uploadUrl, uploadUrlMeta);
3442

35-
return new Response(JSON.stringify({ uploadUrl: [uploadUrl] }));
43+
return new Response(JSON.stringify({ uploadUrl: uploadUrl }));
3644
}
3745

3846
export async function handleFileUpload(
@@ -52,6 +60,13 @@ export async function handleFileUpload(
5260
throw new Error(`Endpoint ${url.toString()} does not exist`);
5361
}
5462

63+
const token = url.searchParams.get("token");
64+
try {
65+
const _ = await verifyJWT(token!);
66+
} catch (e) {
67+
throw new Error("Invalid token: " + e.toString());
68+
}
69+
5570
const { fileName, fileHash, fileSizeInBytes, urlUsed }: UploadUrlMeta =
5671
uploadMeta!;
5772

@@ -78,11 +93,14 @@ export async function handleFileUpload(
7893
}
7994

8095
if (bytesRead !== fileSizeInBytes) {
81-
throw new Error("File size does not match");
96+
throw new Error(
97+
`File size does not match ${bytesRead}, ${JSON.stringify(uploadMeta)}`,
98+
);
8299
}
83100

84101
// adjust relative to the root path
85-
const fileStorageDir = `metatype_artifacts/${engine.name}/files`;
102+
const fileStorageDir =
103+
`${config.tmp_dir}/metatype_artifacts/${engine.name}/files`;
86104
await Deno.mkdir(fileStorageDir, { recursive: true });
87105
const filePath = `${fileStorageDir}/${fileName}.${fileHash}`;
88106
await Deno.writeFile(filePath, fileData);

0 commit comments

Comments
 (0)