1
1
// Copyright Metatype OÜ, licensed under the Elastic License 2.0.
2
2
// SPDX-License-Identifier: Elastic-2.0
3
3
4
+ import config from "../config.ts" ;
5
+ import { signJWT , verifyJWT } from "../crypto.ts" ;
4
6
import { UploadUrlMeta } from "../engine/query_engine.ts" ;
5
7
import { QueryEngine } from "../engine/query_engine.ts" ;
6
8
7
9
interface TypegraphFile {
8
10
name : string ;
9
- fileHash : string ;
10
- fileSizeInBytes : number ;
11
+ file_hash : string ;
12
+ file_size_in_bytes : number ;
11
13
}
12
14
13
15
function createUploadPath ( origin : string , typegraphName : string ) {
14
16
const rand_path = crypto . randomUUID ( ) ;
15
- return `${ origin } /upload-files/ ${ typegraphName } /files/${ rand_path } ` ;
17
+ return `${ origin } /${ typegraphName } /upload-files /files/${ rand_path } ` ;
16
18
}
17
19
18
20
export async function handleUploadUrl ( request : Request , engine : QueryEngine ) {
19
21
const url = new URL ( request . url ) ;
20
22
const origin = url . origin ;
21
- const { name, fileHash , fileSizeInBytes } : TypegraphFile = await request
23
+ const { name, file_hash , file_size_in_bytes } : TypegraphFile = await request
22
24
. json ( ) ;
23
-
24
25
const uploadUrlMeta : UploadUrlMeta = {
25
26
fileName : name ,
26
- fileHash : fileHash ,
27
- fileSizeInBytes : fileSizeInBytes ,
27
+ fileHash : file_hash ,
28
+ fileSizeInBytes : file_size_in_bytes ,
28
29
urlUsed : false ,
29
30
} ;
30
31
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 } ` ;
32
40
33
41
engine . fileUploadUrlCache . set ( uploadUrl , uploadUrlMeta ) ;
34
42
35
- return new Response ( JSON . stringify ( { uploadUrl : [ uploadUrl ] } ) ) ;
43
+ return new Response ( JSON . stringify ( { uploadUrl : uploadUrl } ) ) ;
36
44
}
37
45
38
46
export async function handleFileUpload (
@@ -52,6 +60,13 @@ export async function handleFileUpload(
52
60
throw new Error ( `Endpoint ${ url . toString ( ) } does not exist` ) ;
53
61
}
54
62
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
+
55
70
const { fileName, fileHash, fileSizeInBytes, urlUsed } : UploadUrlMeta =
56
71
uploadMeta ! ;
57
72
@@ -78,11 +93,14 @@ export async function handleFileUpload(
78
93
}
79
94
80
95
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
+ ) ;
82
99
}
83
100
84
101
// 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` ;
86
104
await Deno . mkdir ( fileStorageDir , { recursive : true } ) ;
87
105
const filePath = `${ fileStorageDir } /${ fileName } .${ fileHash } ` ;
88
106
await Deno . writeFile ( filePath , fileData ) ;
0 commit comments