@unchainedshop/file-upload 1.1.4 → 1.1.9
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/license +274 -0
- package/package.json +9 -7
- package/tests/file-upload-index.test.ts +1 -1
- package/tsconfig.build.json +12 -4
- package/.npm/package/README +0 -7
- package/.npm/package/npm-shrinkwrap.json +0 -351
- package/.versions +0 -53
- package/lib/plugins/gridfs/gridfs-adapter.d.ts +0 -2
- package/lib/plugins/gridfs/gridfs-adapter.js +0 -108
- package/lib/plugins/gridfs/gridfs-adapter.js.map +0 -1
- package/lib/plugins/gridfs/gridfs-webhook.d.ts +0 -1
- package/lib/plugins/gridfs/gridfs-webhook.js +0 -54
- package/lib/plugins/gridfs/gridfs-webhook.js.map +0 -1
- package/lib/plugins/gridfs/index.d.ts +0 -8
- package/lib/plugins/gridfs/index.js +0 -21
- package/lib/plugins/gridfs/index.js.map +0 -1
- package/lib/plugins/gridfs/promisePipe.d.ts +0 -2
- package/lib/plugins/gridfs/promisePipe.js +0 -21
- package/lib/plugins/gridfs/promisePipe.js.map +0 -1
- package/lib/plugins/gridfs/sign.d.ts +0 -2
- package/lib/plugins/gridfs/sign.js +0 -12
- package/lib/plugins/gridfs/sign.js.map +0 -1
- package/lib/plugins/minio-adapter.d.ts +0 -4
- package/lib/plugins/minio-adapter.js +0 -167
- package/lib/plugins/minio-adapter.js.map +0 -1
- package/lib/plugins/minio-webhook.d.ts +0 -1
- package/lib/plugins/minio-webhook.js +0 -45
- package/lib/plugins/minio-webhook.js.map +0 -1
- package/package.js +0 -34
- package/src/plugins/gridfs/gridfs-adapter.ts +0 -137
- package/src/plugins/gridfs/gridfs-webhook.js +0 -60
- package/src/plugins/gridfs/index.js +0 -21
- package/src/plugins/gridfs/promisePipe.js +0 -19
- package/src/plugins/gridfs/sign.js +0 -16
- package/src/plugins/minio-adapter.ts +0 -216
- package/src/plugins/minio-webhook.js +0 -51
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"promisePipe.js","sourceRoot":"","sources":["../../../src/plugins/gridfs/promisePipe.js"],"names":[],"mappings":"AAAA,eAAe,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE;IAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI;YACF,UAAU;iBACP,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACjB,MAAM,CAAC,CAAC,CAAC,CAAC;YACZ,CAAC,CAAC;iBACD,IAAI,CAAC,WAAW,CAAC;iBACjB,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACjB,MAAM,CAAC,CAAC,CAAC,CAAC;YACZ,CAAC,CAAC;iBACD,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;SACN;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,CAAC,CAAC,CAAC,CAAC;SACX;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
|
-
const { UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET } = process.env;
|
|
3
|
-
const sign = (directoryName, hash, expiryTimestamp) => {
|
|
4
|
-
if (!UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET)
|
|
5
|
-
throw new Error('To enable PUT based uploads you have to provide a random UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET environment variable');
|
|
6
|
-
const hmac = crypto.createHmac('sha256', UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET);
|
|
7
|
-
const signature = [directoryName, hash, expiryTimestamp].join(':');
|
|
8
|
-
hmac.update(signature);
|
|
9
|
-
return hmac.digest('hex');
|
|
10
|
-
};
|
|
11
|
-
export default sign;
|
|
12
|
-
//# sourceMappingURL=sign.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sign.js","sourceRoot":"","sources":["../../../src/plugins/gridfs/sign.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,EAAE,kCAAkC,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE3D,MAAM,IAAI,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE;IACpD,IAAI,CAAC,kCAAkC;QACrC,MAAM,IAAI,KAAK,CACb,kHAAkH,CACnH,CAAC;IACJ,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,kCAAkC,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { FileAdapter } from '../director/FileAdapter';
|
|
2
|
-
import { FileDirector } from '../director/FileDirector';
|
|
3
|
-
import https from 'https';
|
|
4
|
-
import http from 'http';
|
|
5
|
-
import { log, LogLevel } from '@unchainedshop/logger';
|
|
6
|
-
import mimeType from 'mime-types';
|
|
7
|
-
import Minio from 'minio';
|
|
8
|
-
import { Readable } from 'stream';
|
|
9
|
-
import { URL } from 'url';
|
|
10
|
-
import buildHashedFilename from '../buildHashedFilename';
|
|
11
|
-
const { MINIO_ACCESS_KEY, MINIO_REGION, MINIO_SECRET_KEY, MINIO_ENDPOINT, MINIO_BUCKET_NAME, NODE_ENV, AMAZON_S3_SESSION_TOKEN, } = process.env;
|
|
12
|
-
const PUT_URL_EXPIRY = 24 * 60 * 60;
|
|
13
|
-
let client;
|
|
14
|
-
export async function connectToMinio(credentialsProvider) {
|
|
15
|
-
if (!MINIO_ENDPOINT || !MINIO_BUCKET_NAME) {
|
|
16
|
-
log('Please configure Minio/S3 by providing MINIO_ENDPOINT & MINIO_BUCKET_NAME to use upload features', { level: LogLevel.Error });
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
const resolvedUrl = new URL(MINIO_ENDPOINT);
|
|
21
|
-
const minioClient = new Minio.Client({
|
|
22
|
-
endPoint: resolvedUrl.hostname,
|
|
23
|
-
useSSL: resolvedUrl.protocol === 'https:',
|
|
24
|
-
port: parseInt(resolvedUrl.port, 10) || undefined,
|
|
25
|
-
region: MINIO_REGION,
|
|
26
|
-
sessionToken: AMAZON_S3_SESSION_TOKEN,
|
|
27
|
-
accessKey: MINIO_ACCESS_KEY,
|
|
28
|
-
secretKey: MINIO_SECRET_KEY,
|
|
29
|
-
});
|
|
30
|
-
if (NODE_ENV === 'development')
|
|
31
|
-
minioClient?.traceOn(process.stdout);
|
|
32
|
-
if (credentialsProvider) {
|
|
33
|
-
await minioClient.setCredentialsProvider(credentialsProvider);
|
|
34
|
-
}
|
|
35
|
-
client = minioClient;
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
log(`Exception while creating Minio client: ${error.message}`, {
|
|
39
|
-
level: LogLevel.Error,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
const generateMinioUrl = (directoryName, hashedFilename) => {
|
|
45
|
-
return `${MINIO_ENDPOINT}/${MINIO_BUCKET_NAME}/${directoryName}/${hashedFilename}`;
|
|
46
|
-
};
|
|
47
|
-
const getMimeType = (extension) => {
|
|
48
|
-
return mimeType.lookup(extension);
|
|
49
|
-
};
|
|
50
|
-
connectToMinio().then((c) => {
|
|
51
|
-
client = c;
|
|
52
|
-
});
|
|
53
|
-
const createDownloadStream = (fileUrl, headers) => {
|
|
54
|
-
const { href, protocol } = new URL(fileUrl);
|
|
55
|
-
return new Promise((resolve, reject) => {
|
|
56
|
-
try {
|
|
57
|
-
if (protocol === 'http:') {
|
|
58
|
-
http.get(href, { headers }, resolve);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
https.get(href, { headers }, resolve);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
reject(e);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
const getObjectStats = async (fileName) => {
|
|
70
|
-
if (!client)
|
|
71
|
-
throw new Error('Minio not connected, check env variables');
|
|
72
|
-
return client.statObject(MINIO_BUCKET_NAME, fileName);
|
|
73
|
-
};
|
|
74
|
-
const bufferToStream = (buffer) => {
|
|
75
|
-
const stream = new Readable();
|
|
76
|
-
stream.push(buffer);
|
|
77
|
-
stream.push(null);
|
|
78
|
-
return stream;
|
|
79
|
-
};
|
|
80
|
-
const getExpiryDate = () => new Date(new Date().getTime() + PUT_URL_EXPIRY);
|
|
81
|
-
export const MinioAdapter = {
|
|
82
|
-
key: 'shop.unchained.file-upload-plugin.minio',
|
|
83
|
-
label: 'Uploads files into an S3 bucket using minio',
|
|
84
|
-
version: '1.0',
|
|
85
|
-
...FileAdapter,
|
|
86
|
-
async createSignedURL(directoryName, fileName) {
|
|
87
|
-
if (!client)
|
|
88
|
-
throw new Error('Minio not connected, check env variables');
|
|
89
|
-
const expiryDate = getExpiryDate();
|
|
90
|
-
const _id = buildHashedFilename(directoryName, fileName, expiryDate);
|
|
91
|
-
const url = await client.presignedPutObject(MINIO_BUCKET_NAME, `${directoryName}/${_id}`, PUT_URL_EXPIRY);
|
|
92
|
-
return {
|
|
93
|
-
_id,
|
|
94
|
-
directoryName,
|
|
95
|
-
expiryDate,
|
|
96
|
-
fileName,
|
|
97
|
-
type: getMimeType(fileName),
|
|
98
|
-
putURL: url,
|
|
99
|
-
url: generateMinioUrl(directoryName, _id),
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
async removeFiles(files) {
|
|
103
|
-
if (!client)
|
|
104
|
-
throw new Error('Minio not connected, check env variables');
|
|
105
|
-
const fileIds = files.map(({ path, _id }) => {
|
|
106
|
-
return `${path}/${_id}`;
|
|
107
|
-
});
|
|
108
|
-
await client.removeObjects(MINIO_BUCKET_NAME, fileIds);
|
|
109
|
-
},
|
|
110
|
-
async uploadFileFromStream(directoryName, rawFile) {
|
|
111
|
-
if (!client)
|
|
112
|
-
throw new Error('Minio not connected, check env variables');
|
|
113
|
-
let stream;
|
|
114
|
-
let fileName;
|
|
115
|
-
if (rawFile instanceof Promise) {
|
|
116
|
-
const { filename: fname, createReadStream } = await rawFile;
|
|
117
|
-
fileName = fname;
|
|
118
|
-
stream = createReadStream();
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
fileName = rawFile.filename;
|
|
122
|
-
stream = bufferToStream(Buffer.from(rawFile.buffer, 'base64'));
|
|
123
|
-
}
|
|
124
|
-
const _id = buildHashedFilename(directoryName, fileName, new Date());
|
|
125
|
-
const type = rawFile?.mimetype || getMimeType(fileName);
|
|
126
|
-
const metaData = {
|
|
127
|
-
'Content-Type': type,
|
|
128
|
-
};
|
|
129
|
-
await client.putObject(MINIO_BUCKET_NAME, `${directoryName}/${_id}`, stream, undefined, metaData);
|
|
130
|
-
const { size } = await getObjectStats(`${directoryName}/${_id}`);
|
|
131
|
-
return {
|
|
132
|
-
_id,
|
|
133
|
-
directoryName,
|
|
134
|
-
expiryDate: null,
|
|
135
|
-
fileName,
|
|
136
|
-
size,
|
|
137
|
-
type,
|
|
138
|
-
url: generateMinioUrl(directoryName, _id),
|
|
139
|
-
};
|
|
140
|
-
},
|
|
141
|
-
async uploadFileFromURL(directoryName, { fileLink, fileName: fname, headers }) {
|
|
142
|
-
if (!client)
|
|
143
|
-
throw new Error('Minio not connected, check env variables');
|
|
144
|
-
const { href } = new URL(fileLink);
|
|
145
|
-
const fileName = fname || href.split('/').pop();
|
|
146
|
-
const _id = buildHashedFilename(directoryName, fileName, new Date());
|
|
147
|
-
const stream = await createDownloadStream(fileLink, headers);
|
|
148
|
-
const type = stream?.headers?.['content-type'] || getMimeType(fileName);
|
|
149
|
-
const metaData = {
|
|
150
|
-
'Content-Type': type,
|
|
151
|
-
};
|
|
152
|
-
await client.putObject(MINIO_BUCKET_NAME, `${directoryName}/${_id}`, stream, undefined, metaData);
|
|
153
|
-
const { size } = await getObjectStats(`${directoryName}/${_id}`);
|
|
154
|
-
return {
|
|
155
|
-
_id,
|
|
156
|
-
directoryName,
|
|
157
|
-
expiryDate: null,
|
|
158
|
-
fileName,
|
|
159
|
-
size,
|
|
160
|
-
type,
|
|
161
|
-
url: generateMinioUrl(directoryName, _id),
|
|
162
|
-
};
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
FileDirector.registerAdapter(MinioAdapter);
|
|
166
|
-
export default MinioAdapter;
|
|
167
|
-
//# sourceMappingURL=minio-adapter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"minio-adapter.js","sourceRoot":"","sources":["../../src/plugins/minio-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { useMiddlewareWithCurrentContext } from 'meteor/unchained:api';
|
|
2
|
-
import { log, LogLevel } from '@unchainedshop/logger';
|
|
3
|
-
import bodyParser from 'body-parser';
|
|
4
|
-
const { MINIO_WEBHOOK_AUTH_TOKEN } = process.env;
|
|
5
|
-
const isAuthorized = ({ authorization = '' }) => {
|
|
6
|
-
const [type, token] = authorization.split(' ');
|
|
7
|
-
return type === 'Bearer' && token === MINIO_WEBHOOK_AUTH_TOKEN;
|
|
8
|
-
};
|
|
9
|
-
useMiddlewareWithCurrentContext('/minio/', bodyParser.json({
|
|
10
|
-
strict: false,
|
|
11
|
-
}));
|
|
12
|
-
useMiddlewareWithCurrentContext('/minio/', async (req, res) => {
|
|
13
|
-
try {
|
|
14
|
-
if (req.method === 'POST' && req.body) {
|
|
15
|
-
const { headers } = req;
|
|
16
|
-
const { Records = [], EventName } = req.body;
|
|
17
|
-
if (EventName === 's3:ObjectCreated:Put' && isAuthorized(headers)) {
|
|
18
|
-
const [{ s3 }] = Records;
|
|
19
|
-
const { object } = s3;
|
|
20
|
-
const { size, contentType: type } = object;
|
|
21
|
-
const [fileId] = object.key.split('.');
|
|
22
|
-
const { services } = req.unchainedContext;
|
|
23
|
-
await services.files.linkFile({ fileId, type, size }, req.unchainedContext);
|
|
24
|
-
res.writeHead(200);
|
|
25
|
-
res.end();
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
res.writeHead(404);
|
|
30
|
-
res.end();
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
log(e.message, { level: LogLevel.Error });
|
|
35
|
-
res.writeHead(503);
|
|
36
|
-
res.end(JSON.stringify(e));
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
/*
|
|
40
|
-
|
|
41
|
-
curl -X PUT -T /Users/pozylon/Desktop/Bildschirmfoto\ 2022-02-17\ um\ 16.47.22.png http://localhost:4010/gridfs/3e0cd78ac07f0028890ce36c391057dd0c5fb46f4c147fb73e54bd8a7ffee389/user-avatars/avatar.png?e=1645883865878&s=e7466b30039593e5790e23cab92878e0144289c3710344a55b78c9a916e2f78c
|
|
42
|
-
curl -X PUT -T /Users/pozylon/Desktop/Bildschirmfoto\ 2022-02-17\ um\ 16.47.22.png https://minio.dev.shared.ucc.dev/unchained-test-bucket/user-avatars/9aedd551499b2850e9483b07cd4c8cff7ad1d710f49933c183861bf40183bc5a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=unchained-test%2F20220225%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220225T140957Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=22807026db1210370170cd5cf49bfbb9e86010425c9d1834a56e049faf39b368
|
|
43
|
-
|
|
44
|
-
*/
|
|
45
|
-
//# sourceMappingURL=minio-webhook.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"minio-webhook.js","sourceRoot":"","sources":["../../src/plugins/minio-webhook.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,UAAU,MAAM,aAAa,CAAC;AAErC,MAAM,EAAE,wBAAwB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAEjD,MAAM,YAAY,GAAG,CAAC,EAAE,aAAa,GAAG,EAAE,EAAE,EAAE,EAAE;IAC9C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAK,wBAAwB,CAAC;AACjE,CAAC,CAAC;AAEF,+BAA+B,CAC7B,SAAS,EACT,UAAU,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,KAAK;CACd,CAAC,CACH,CAAC;AAEF,+BAA+B,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAC5D,IAAI;QACF,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;YACxB,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;YAC7C,IAAI,SAAS,KAAK,sBAAsB,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE;gBACjE,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC;gBACzB,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBACtB,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;gBAC3C,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACvC,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,gBAAgB,CAAC;gBAC1C,MAAM,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBAC5E,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;aACR;SACF;QACD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;KACR;IAAC,OAAO,CAAC,EAAE;QACV,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1C,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5B;AACH,CAAC,CAAC,CAAC;AAEH;;;;;EAKE"}
|
package/package.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
Package.describe({
|
|
2
|
-
name: 'unchained:file-upload',
|
|
3
|
-
version: '1.1.4',
|
|
4
|
-
summary: 'Unchained Engine: Core File Upload',
|
|
5
|
-
git: 'https://github.com/unchainedshop/unchained',
|
|
6
|
-
documentation: 'README.md',
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
Npm.depends({
|
|
10
|
-
minio: '7.0.18',
|
|
11
|
-
'mime-types': '2.1.32',
|
|
12
|
-
'base-x': '4.0.0',
|
|
13
|
-
'@unchainedshop/logger': '1.1.3',
|
|
14
|
-
'@unchainedshop/utils': '1.1.3',
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
Package.onUse((api) => {
|
|
18
|
-
api.versionsFrom('2.7.3');
|
|
19
|
-
api.use('ecmascript');
|
|
20
|
-
api.use('typescript');
|
|
21
|
-
|
|
22
|
-
api.mainModule('src/file-upload-index.ts', 'server');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
Package.onTest((api) => {
|
|
26
|
-
api.use('meteortesting:mocha');
|
|
27
|
-
api.use('ecmascript');
|
|
28
|
-
api.use('typescript');
|
|
29
|
-
|
|
30
|
-
api.use('unchained:mongodb@1.1.3');
|
|
31
|
-
api.use('unchained:file-upload@1.1.4');
|
|
32
|
-
|
|
33
|
-
api.mainModule('tests/file-upload-index.test.ts');
|
|
34
|
-
});
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { IFileAdapter } from '@unchainedshop/types/files';
|
|
2
|
-
import { FileAdapter } from '../../director/FileAdapter';
|
|
3
|
-
import { FileDirector } from '../../director/FileDirector';
|
|
4
|
-
import https from 'https';
|
|
5
|
-
import http, { OutgoingHttpHeaders } from 'http';
|
|
6
|
-
import mimeType from 'mime-types';
|
|
7
|
-
import { URL } from 'url';
|
|
8
|
-
import { Readable } from 'stream';
|
|
9
|
-
import sign from './sign';
|
|
10
|
-
import promisePipe from './promisePipe';
|
|
11
|
-
import buildHashedFilename from '../../buildHashedFilename';
|
|
12
|
-
|
|
13
|
-
const { UNCHAINED_PUT_URL_EXPIRY, ROOT_URL } = process.env;
|
|
14
|
-
|
|
15
|
-
const getExpiryDate = () =>
|
|
16
|
-
new Date(new Date().getTime() + (parseInt(UNCHAINED_PUT_URL_EXPIRY, 10) || 24 * 60 * 60 * 1000));
|
|
17
|
-
|
|
18
|
-
const bufferToStream = (buffer: any) => {
|
|
19
|
-
const stream = new Readable();
|
|
20
|
-
stream.push(buffer);
|
|
21
|
-
stream.push(null);
|
|
22
|
-
|
|
23
|
-
return stream;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const createDownloadStream = (fileUrl: string, headers: OutgoingHttpHeaders): Promise<Readable> => {
|
|
27
|
-
const { href, protocol } = new URL(fileUrl);
|
|
28
|
-
return new Promise((resolve, reject) => {
|
|
29
|
-
try {
|
|
30
|
-
if (protocol === 'http:') {
|
|
31
|
-
http.get(href, { headers }, resolve);
|
|
32
|
-
} else {
|
|
33
|
-
https.get(href, { headers }, resolve);
|
|
34
|
-
}
|
|
35
|
-
} catch (e) {
|
|
36
|
-
reject(e);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const GridFSAdapter: IFileAdapter = {
|
|
42
|
-
key: 'shop.unchained.file-upload-plugin.gridfs',
|
|
43
|
-
label: 'Uploads files to Database using GridFS',
|
|
44
|
-
version: '1.0',
|
|
45
|
-
|
|
46
|
-
...FileAdapter,
|
|
47
|
-
|
|
48
|
-
async createSignedURL(directoryName, fileName) {
|
|
49
|
-
const expiryDate = getExpiryDate();
|
|
50
|
-
const _id = buildHashedFilename(directoryName, fileName, expiryDate);
|
|
51
|
-
const signature = sign(directoryName, _id, expiryDate.getTime());
|
|
52
|
-
|
|
53
|
-
const putURL = new URL(
|
|
54
|
-
`/gridfs/${directoryName}/${encodeURIComponent(
|
|
55
|
-
fileName,
|
|
56
|
-
)}?e=${expiryDate.getTime()}&s=${signature}`,
|
|
57
|
-
ROOT_URL,
|
|
58
|
-
).href;
|
|
59
|
-
const url = `/gridfs/${directoryName}/${_id}`;
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
_id,
|
|
63
|
-
directoryName,
|
|
64
|
-
expiryDate,
|
|
65
|
-
fileName,
|
|
66
|
-
type: mimeType.lookup(fileName),
|
|
67
|
-
putURL,
|
|
68
|
-
url,
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
async uploadFileFromStream(directoryName: string, rawFile: any, { modules }: any) {
|
|
73
|
-
let stream;
|
|
74
|
-
let fileName;
|
|
75
|
-
if (rawFile instanceof Promise) {
|
|
76
|
-
const { filename: f, createReadStream } = await rawFile;
|
|
77
|
-
fileName = f;
|
|
78
|
-
stream = createReadStream();
|
|
79
|
-
} else {
|
|
80
|
-
fileName = rawFile.filename;
|
|
81
|
-
stream = bufferToStream(Buffer.from(rawFile.buffer, 'base64'));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const expiryDate = getExpiryDate();
|
|
85
|
-
const _id = buildHashedFilename(directoryName, fileName, expiryDate);
|
|
86
|
-
|
|
87
|
-
const writeStream = await modules.gridfsFileUploads.createWriteStream(directoryName, _id, fileName);
|
|
88
|
-
|
|
89
|
-
const file = await promisePipe(stream, writeStream);
|
|
90
|
-
const url = `/gridfs/${directoryName}/${_id}`;
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
_id,
|
|
94
|
-
directoryName,
|
|
95
|
-
expiryDate: null,
|
|
96
|
-
fileName,
|
|
97
|
-
size: file.length,
|
|
98
|
-
type: mimeType.lookup(fileName) || (await Promise.resolve(rawFile)).mimetype,
|
|
99
|
-
url,
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
async uploadFileFromURL(
|
|
104
|
-
directoryName: string,
|
|
105
|
-
{ fileLink, fileName: fname, headers }: any,
|
|
106
|
-
{ modules }: any,
|
|
107
|
-
) {
|
|
108
|
-
const { href } = new URL(fileLink);
|
|
109
|
-
const fileName = fname || href.split('/').pop();
|
|
110
|
-
|
|
111
|
-
const expiryDate = getExpiryDate();
|
|
112
|
-
const _id = buildHashedFilename(directoryName, fileName, expiryDate);
|
|
113
|
-
|
|
114
|
-
const downloadStream = await createDownloadStream(href, headers);
|
|
115
|
-
const writeStream = await modules.gridfsFileUploads.createWriteStream(directoryName, _id, fileName);
|
|
116
|
-
const file = await promisePipe(downloadStream, writeStream);
|
|
117
|
-
const url = `/gridfs/${directoryName}/${_id}`;
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
_id,
|
|
121
|
-
directoryName,
|
|
122
|
-
expiryDate: null,
|
|
123
|
-
fileName,
|
|
124
|
-
size: file.length,
|
|
125
|
-
type: mimeType.lookup(fileName),
|
|
126
|
-
url,
|
|
127
|
-
};
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
async removeFiles(files, { modules }: any) {
|
|
131
|
-
await Promise.all(
|
|
132
|
-
files.map(async ({ _id, path }) => modules.gridfsFileUploads.removeFileFromBucket(path, _id)),
|
|
133
|
-
);
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
FileDirector.registerAdapter(GridFSAdapter);
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { useMiddlewareWithCurrentContext } from 'meteor/unchained:api';
|
|
2
|
-
import { log, LogLevel } from '@unchainedshop/logger';
|
|
3
|
-
import sign from './sign';
|
|
4
|
-
import promisePipe from './promisePipe';
|
|
5
|
-
import buildHashedFilename from '../../buildHashedFilename';
|
|
6
|
-
|
|
7
|
-
const { ROOT_URL } = process.env;
|
|
8
|
-
|
|
9
|
-
/*
|
|
10
|
-
curl -vvv -X PUT -T /Users/pozylon/Downloads/grafik.png http://localhost:4010/gridfs/user-avatars/hans.png?e=1653059591506&s=df8626a1c9b9006249d7f1928fd530579fed57216f1bdcb83c28a8322cdc90b1
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
useMiddlewareWithCurrentContext('/gridfs', async (req, res) => {
|
|
14
|
-
try {
|
|
15
|
-
const { services, modules } = req.unchainedContext;
|
|
16
|
-
const url = new URL(req.url, ROOT_URL);
|
|
17
|
-
const [, directoryName, fileName] = url.pathname.split('/');
|
|
18
|
-
|
|
19
|
-
if (req.method === 'PUT') {
|
|
20
|
-
const { s: signature, e: expiryTimestamp } = req.query;
|
|
21
|
-
const expiryDate = new Date(parseInt(expiryTimestamp, 10));
|
|
22
|
-
const fileId = buildHashedFilename(directoryName, fileName, expiryDate);
|
|
23
|
-
if (sign(directoryName, fileId, expiryDate.getTime()) === signature) {
|
|
24
|
-
const file = await modules.files.findFile({ fileId });
|
|
25
|
-
if (file.expires === null) {
|
|
26
|
-
res.writeHead(503);
|
|
27
|
-
res.end('File already linked');
|
|
28
|
-
}
|
|
29
|
-
const writeStream = await modules.gridfsFileUploads.createWriteStream(
|
|
30
|
-
directoryName,
|
|
31
|
-
fileId,
|
|
32
|
-
fileName,
|
|
33
|
-
);
|
|
34
|
-
const { length } = await promisePipe(req, writeStream);
|
|
35
|
-
await services.files.linkFile({ fileId, size: length }, req.unchainedContext);
|
|
36
|
-
res.writeHead(200);
|
|
37
|
-
res.end();
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
res.writeHead(403);
|
|
41
|
-
res.end();
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (req.method === 'GET') {
|
|
45
|
-
const fileId = fileName;
|
|
46
|
-
const readStream = await modules.gridfsFileUploads.createReadStream(directoryName, fileId);
|
|
47
|
-
await promisePipe(readStream, res);
|
|
48
|
-
res.writeHead(200);
|
|
49
|
-
res.end();
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
res.writeHead(404);
|
|
53
|
-
res.end();
|
|
54
|
-
return;
|
|
55
|
-
} catch (e) {
|
|
56
|
-
log(e.message, { level: LogLevel.Error });
|
|
57
|
-
res.writeHead(503);
|
|
58
|
-
res.end(JSON.stringify(e));
|
|
59
|
-
}
|
|
60
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import mongodb from 'mongodb';
|
|
2
|
-
|
|
3
|
-
export const configureGridFSFileUploadModule = ({ db }) => {
|
|
4
|
-
return {
|
|
5
|
-
createWriteStream: async (directoryName, fileId, fileName) => {
|
|
6
|
-
const options = { bucketName: `file_uploads_${directoryName}`, chunkSizeBytes: 5 * 1024 * 1024 };
|
|
7
|
-
const bucket = new mongodb.GridFSBucket(db, options);
|
|
8
|
-
return bucket.openUploadStreamWithId(fileId, fileName);
|
|
9
|
-
},
|
|
10
|
-
createReadStream: async (directoryName, fileId) => {
|
|
11
|
-
const options = { bucketName: `file_uploads_${directoryName}`, chunkSizeBytes: 5 * 1024 * 1024 };
|
|
12
|
-
const bucket = new mongodb.GridFSBucket(db, options);
|
|
13
|
-
return bucket.openDownloadStream(fileId);
|
|
14
|
-
},
|
|
15
|
-
removeFileFromBucket: async (directoryName, fileId) => {
|
|
16
|
-
const options = { bucketName: `file_uploads_${directoryName}`, chunkSizeBytes: 5 * 1024 * 1024 };
|
|
17
|
-
const bucket = new mongodb.GridFSBucket(db, options);
|
|
18
|
-
return bucket.delete(fileId);
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export default async (readStream, writeStream) => {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
try {
|
|
4
|
-
readStream
|
|
5
|
-
.on('error', (e) => {
|
|
6
|
-
reject(e);
|
|
7
|
-
})
|
|
8
|
-
.pipe(writeStream)
|
|
9
|
-
.on('error', (e) => {
|
|
10
|
-
reject(e);
|
|
11
|
-
})
|
|
12
|
-
.on('finish', async (file) => {
|
|
13
|
-
resolve(file);
|
|
14
|
-
});
|
|
15
|
-
} catch (e) {
|
|
16
|
-
reject(e);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
|
-
|
|
3
|
-
const { UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET } = process.env;
|
|
4
|
-
|
|
5
|
-
const sign = (directoryName, hash, expiryTimestamp) => {
|
|
6
|
-
if (!UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET)
|
|
7
|
-
throw new Error(
|
|
8
|
-
'To enable PUT based uploads you have to provide a random UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET environment variable',
|
|
9
|
-
);
|
|
10
|
-
const hmac = crypto.createHmac('sha256', UNCHAINED_GRIDFS_PUT_UPLOAD_SECRET);
|
|
11
|
-
const signature = [directoryName, hash, expiryTimestamp].join(':');
|
|
12
|
-
hmac.update(signature);
|
|
13
|
-
return hmac.digest('hex');
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default sign;
|