@opengis/fastify-table 2.3.5 → 2.4.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/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -9
- package/dist/server/plugins/access/funcs/getAdminAccess.d.ts +1 -4
- package/dist/server/plugins/access/funcs/getAdminAccess.d.ts.map +1 -1
- package/dist/server/plugins/access/funcs/getAdminAccess.js +3 -2
- package/dist/server/plugins/auth/funcs/getQuery.d.ts.map +1 -1
- package/dist/server/plugins/auth/funcs/getQuery.js +2 -1
- package/dist/server/plugins/auth/funcs/loginFile.d.ts +1 -4
- package/dist/server/plugins/auth/funcs/loginFile.d.ts.map +1 -1
- package/dist/server/plugins/auth/funcs/loginFile.js +10 -5
- package/dist/server/plugins/auth/funcs/loginUser.d.ts.map +1 -1
- package/dist/server/plugins/auth/funcs/loginUser.js +25 -18
- package/dist/server/plugins/auth/index.d.ts.map +1 -1
- package/dist/server/plugins/auth/index.js +3 -4
- package/dist/server/plugins/crud/funcs/dataInsert.js +1 -1
- package/dist/server/plugins/extra/extraData.d.ts.map +1 -1
- package/dist/server/plugins/extra/extraData.js +3 -2
- package/dist/server/plugins/extra/extraDataGet.d.ts +1 -4
- package/dist/server/plugins/extra/extraDataGet.d.ts.map +1 -1
- package/dist/server/plugins/extra/extraDataGet.js +4 -6
- package/dist/server/plugins/file/uploadMultiPart.js +1 -1
- package/dist/server/plugins/grpc/utils/html2doc.d.ts +0 -6
- package/dist/server/plugins/grpc/utils/html2doc.d.ts.map +1 -1
- package/dist/server/plugins/grpc/utils/html2doc.js +3 -8
- package/dist/server/plugins/grpc/utils/html2img.d.ts +0 -6
- package/dist/server/plugins/grpc/utils/html2img.d.ts.map +1 -1
- package/dist/server/plugins/grpc/utils/html2img.js +3 -8
- package/dist/server/plugins/grpc/utils/html2pdf.d.ts +0 -6
- package/dist/server/plugins/grpc/utils/html2pdf.d.ts.map +1 -1
- package/dist/server/plugins/grpc/utils/html2pdf.js +7 -12
- package/dist/server/plugins/grpc/utils/mergePdf.d.ts +0 -7
- package/dist/server/plugins/grpc/utils/mergePdf.d.ts.map +1 -1
- package/dist/server/plugins/grpc/utils/mergePdf.js +4 -9
- package/dist/server/plugins/logger/checkUserAccess.d.ts +1 -4
- package/dist/server/plugins/logger/checkUserAccess.d.ts.map +1 -1
- package/dist/server/plugins/logger/checkUserAccess.js +4 -6
- package/dist/server/plugins/logger/errorMessage.d.ts +1 -1
- package/dist/server/plugins/logger/errorMessage.d.ts.map +1 -1
- package/dist/server/plugins/logger/errorMessage.js +7 -8
- package/dist/server/plugins/logger/errorStatus.d.ts.map +1 -1
- package/dist/server/plugins/logger/errorStatus.js +6 -0
- package/dist/server/plugins/logger/index.d.ts +2 -2
- package/dist/server/plugins/logger/index.d.ts.map +1 -1
- package/dist/server/plugins/logger/index.js +16 -18
- package/dist/server/plugins/pg/funcs/getMeta.d.ts.map +1 -1
- package/dist/server/plugins/pg/funcs/getMeta.js +5 -3
- package/dist/server/plugins/policy/funcs/checkJWT.d.ts +0 -9
- package/dist/server/plugins/policy/funcs/checkJWT.d.ts.map +1 -1
- package/dist/server/plugins/policy/funcs/checkJWT.js +6 -5
- package/dist/server/plugins/policy/funcs/checkPermissions.d.ts +1 -4
- package/dist/server/plugins/policy/funcs/checkPermissions.d.ts.map +1 -1
- package/dist/server/plugins/policy/funcs/checkPermissions.js +2 -1
- package/dist/server/plugins/policy/funcs/checkPolicy.d.ts +1 -4
- package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
- package/dist/server/plugins/policy/funcs/checkPolicy.js +8 -7
- package/dist/server/plugins/policy/index.d.ts.map +1 -1
- package/dist/server/plugins/policy/index.js +2 -11
- package/dist/server/plugins/table/funcs/getFilterSQL/index.d.ts +1 -15
- package/dist/server/plugins/table/funcs/getFilterSQL/index.d.ts.map +1 -1
- package/dist/server/plugins/table/funcs/getFilterSQL/index.js +6 -4
- package/dist/server/plugins/table/funcs/gisIRColumn.d.ts +0 -22
- package/dist/server/plugins/table/funcs/gisIRColumn.d.ts.map +1 -1
- package/dist/server/plugins/table/funcs/gisIRColumn.js +5 -3
- package/dist/server/plugins/upload/index.d.ts.map +1 -1
- package/dist/server/plugins/upload/index.js +7 -0
- package/dist/server/plugins/upload/s3.d.ts +7 -1
- package/dist/server/plugins/upload/s3.d.ts.map +1 -1
- package/dist/server/plugins/upload/s3.js +54 -10
- package/dist/server/plugins/upload/s3minio.d.ts +59 -0
- package/dist/server/plugins/upload/s3minio.d.ts.map +1 -0
- package/dist/server/plugins/upload/s3minio.js +199 -0
- package/dist/server/plugins/upload/startUpload.d.ts.map +1 -1
- package/dist/server/plugins/upload/startUpload.js +16 -8
- package/dist/server/plugins/upload/uploadChunk.d.ts.map +1 -1
- package/dist/server/plugins/upload/uploadChunk.js +14 -9
- package/dist/server/plugins/usercls/index.js +1 -1
- package/dist/server/routes/access/controllers/access.group.d.ts.map +1 -1
- package/dist/server/routes/access/controllers/access.group.js +3 -5
- package/dist/server/routes/access/controllers/access.group.post.d.ts.map +1 -1
- package/dist/server/routes/access/controllers/access.group.post.js +3 -5
- package/dist/server/routes/access/controllers/access.interface.d.ts.map +1 -1
- package/dist/server/routes/access/controllers/access.interface.js +1 -4
- package/dist/server/routes/access/controllers/access.user.d.ts +5 -1
- package/dist/server/routes/access/controllers/access.user.d.ts.map +1 -1
- package/dist/server/routes/access/controllers/access.user.js +4 -5
- package/dist/server/routes/access/controllers/access.user.post.d.ts.map +1 -1
- package/dist/server/routes/access/controllers/access.user.post.js +4 -5
- package/dist/server/routes/access/index.d.ts.map +1 -1
- package/dist/server/routes/access/index.js +10 -6
- package/dist/server/routes/auth/controllers/2factor/providers/totp.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/providers/totp.js +4 -3
- package/dist/server/routes/auth/controllers/2factor/qrcode.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/qrcode.js +6 -10
- package/dist/server/routes/auth/controllers/2factor/recovery.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/recovery.js +14 -23
- package/dist/server/routes/auth/controllers/2factor/reset.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/reset.js +3 -5
- package/dist/server/routes/auth/controllers/2factor/verify.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/verify.js +30 -43
- package/dist/server/routes/auth/controllers/core/login.d.ts +1 -4
- package/dist/server/routes/auth/controllers/core/login.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/core/passwordRecovery.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/core/passwordRecovery.js +7 -8
- package/dist/server/routes/auth/controllers/core/registration.d.ts +1 -4
- package/dist/server/routes/auth/controllers/core/registration.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/core/registration.js +10 -24
- package/dist/server/routes/auth/controllers/core/updateUserInfo.d.ts +1 -2
- package/dist/server/routes/auth/controllers/core/updateUserInfo.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/core/updateUserInfo.js +3 -2
- package/dist/server/routes/auth/controllers/euSign/authByData.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/euSign/authByData.js +4 -7
- package/dist/server/routes/auth/controllers/jwt/authorize.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/jwt/authorize.js +6 -9
- package/dist/server/routes/auth/controllers/jwt/token.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/jwt/token.js +9 -12
- package/dist/server/routes/auth/controllers/page/login2faTemplate.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/page/login2faTemplate.js +3 -2
- package/dist/server/routes/auth/index.d.ts +1 -2
- package/dist/server/routes/auth/index.d.ts.map +1 -1
- package/dist/server/routes/auth/index.js +4 -3
- package/dist/server/routes/cron/controllers/cronApi.d.ts.map +1 -1
- package/dist/server/routes/cron/controllers/cronApi.js +3 -4
- package/dist/server/routes/cron/index.js +1 -1
- package/dist/server/routes/crud/controllers/deleteCrud.d.ts.map +1 -1
- package/dist/server/routes/crud/controllers/deleteCrud.js +11 -33
- package/dist/server/routes/crud/controllers/insert.d.ts +1 -1
- package/dist/server/routes/crud/controllers/insert.d.ts.map +1 -1
- package/dist/server/routes/crud/controllers/insert.js +17 -31
- package/dist/server/routes/crud/controllers/table.d.ts.map +1 -1
- package/dist/server/routes/crud/controllers/table.js +14 -18
- package/dist/server/routes/crud/controllers/update.d.ts.map +1 -1
- package/dist/server/routes/crud/controllers/update.js +16 -28
- package/dist/server/routes/crud/index.d.ts.map +1 -1
- package/dist/server/routes/crud/index.js +14 -4
- package/dist/server/routes/dblist/controllers/setItem.d.ts +0 -6
- package/dist/server/routes/dblist/controllers/setItem.d.ts.map +1 -1
- package/dist/server/routes/dblist/controllers/setItem.js +3 -2
- package/dist/server/routes/dblist/index.d.ts.map +1 -1
- package/dist/server/routes/dblist/index.js +5 -3
- package/dist/server/routes/file/controllers/delete.d.ts +4 -1
- package/dist/server/routes/file/controllers/delete.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/delete.js +8 -8
- package/dist/server/routes/file/controllers/download.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/download.js +5 -8
- package/dist/server/routes/file/controllers/export.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/export.js +8 -8
- package/dist/server/routes/file/controllers/files.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/files.js +6 -8
- package/dist/server/routes/file/controllers/resize.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/resize.js +4 -12
- package/dist/server/routes/file/index.d.ts.map +1 -1
- package/dist/server/routes/file/index.js +10 -7
- package/dist/server/routes/grpc/controllers/file2geojson.d.ts.map +1 -1
- package/dist/server/routes/grpc/controllers/file2geojson.js +7 -7
- package/dist/server/routes/grpc/controllers/filePreview.d.ts.map +1 -1
- package/dist/server/routes/grpc/controllers/filePreview.js +5 -4
- package/dist/server/routes/grpc/index.d.ts.map +1 -1
- package/dist/server/routes/grpc/index.js +3 -2
- package/dist/server/routes/logger/controllers/logger.file.d.ts +1 -1
- package/dist/server/routes/logger/controllers/logger.file.d.ts.map +1 -1
- package/dist/server/routes/logger/controllers/logger.file.js +4 -5
- package/dist/server/routes/logger/controllers/logger.metrics.d.ts.map +1 -1
- package/dist/server/routes/logger/controllers/logger.metrics.js +1 -4
- package/dist/server/routes/logger/index.d.ts.map +1 -1
- package/dist/server/routes/logger/index.js +4 -2
- package/dist/server/routes/menu/controllers/getMenu.d.ts.map +1 -1
- package/dist/server/routes/menu/controllers/getMenu.js +2 -1
- package/dist/server/routes/menu/index.d.ts.map +1 -1
- package/dist/server/routes/menu/index.js +9 -2
- package/dist/server/routes/notifications/controllers/addUserNotification.d.ts +1 -2
- package/dist/server/routes/notifications/controllers/addUserNotification.d.ts.map +1 -1
- package/dist/server/routes/notifications/controllers/addUserNotification.js +5 -6
- package/dist/server/routes/notifications/controllers/deleteUserNotification.d.ts +1 -2
- package/dist/server/routes/notifications/controllers/deleteUserNotification.d.ts.map +1 -1
- package/dist/server/routes/notifications/controllers/deleteUserNotification.js +5 -6
- package/dist/server/routes/notifications/controllers/editUserNotification.d.ts +1 -2
- package/dist/server/routes/notifications/controllers/editUserNotification.d.ts.map +1 -1
- package/dist/server/routes/notifications/controllers/editUserNotification.js +6 -9
- package/dist/server/routes/notifications/controllers/readNotifications.d.ts +4 -2
- package/dist/server/routes/notifications/controllers/readNotifications.d.ts.map +1 -1
- package/dist/server/routes/notifications/controllers/readNotifications.js +4 -3
- package/dist/server/routes/notifications/controllers/userNotifications.d.ts +5 -2
- package/dist/server/routes/notifications/controllers/userNotifications.d.ts.map +1 -1
- package/dist/server/routes/notifications/controllers/userNotifications.js +4 -5
- package/dist/server/routes/notifications/index.d.ts +1 -2
- package/dist/server/routes/notifications/index.d.ts.map +1 -1
- package/dist/server/routes/notifications/index.js +3 -1
- package/dist/server/routes/properties/controllers/properties.get.d.ts +5 -2
- package/dist/server/routes/properties/controllers/properties.get.d.ts.map +1 -1
- package/dist/server/routes/properties/controllers/properties.get.js +6 -5
- package/dist/server/routes/properties/controllers/properties.post.d.ts +1 -1
- package/dist/server/routes/properties/controllers/properties.post.d.ts.map +1 -1
- package/dist/server/routes/properties/controllers/properties.post.js +7 -6
- package/dist/server/routes/properties/index.d.ts.map +1 -1
- package/dist/server/routes/properties/index.js +4 -7
- package/dist/server/routes/table/controllers/card.d.ts +1 -1
- package/dist/server/routes/table/controllers/card.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/card.js +9 -7
- package/dist/server/routes/table/controllers/cardData.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/cardData.js +4 -6
- package/dist/server/routes/table/controllers/cardTabData.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/cardTabData.js +3 -2
- package/dist/server/routes/table/controllers/dataInfo.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/dataInfo.js +4 -3
- package/dist/server/routes/table/controllers/filter.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/filter.js +3 -2
- package/dist/server/routes/table/controllers/form.d.ts +1 -1
- package/dist/server/routes/table/controllers/form.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/form.js +7 -5
- package/dist/server/routes/table/controllers/getFormByTable.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/getFormByTable.js +12 -12
- package/dist/server/routes/table/controllers/suggest.d.ts +1 -1
- package/dist/server/routes/table/controllers/suggest.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/suggest.js +14 -29
- package/dist/server/routes/table/controllers/tableInfo.d.ts +1 -2
- package/dist/server/routes/table/controllers/tableInfo.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/tableInfo.js +9 -8
- package/dist/server/routes/table/controllers/tokenInfo.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/tokenInfo.js +2 -1
- package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
- package/dist/server/routes/table/functions/getData.js +19 -25
- package/dist/server/routes/table/index.d.ts.map +1 -1
- package/dist/server/routes/table/index.js +15 -13
- package/dist/server/routes/templates/controllers/getTemplate.d.ts.map +1 -1
- package/dist/server/routes/templates/controllers/getTemplate.js +9 -5
- package/dist/server/routes/templates/index.d.ts.map +1 -1
- package/dist/server/routes/templates/index.js +2 -1
- package/dist/server/routes/upload/index.d.ts.map +1 -1
- package/dist/server/routes/upload/index.js +31 -20
- package/dist/server/routes/usercls/controllers/addUserCls.d.ts.map +1 -1
- package/dist/server/routes/usercls/controllers/addUserCls.js +2 -1
- package/dist/server/routes/usercls/controllers/deleteUserCls.d.ts.map +1 -1
- package/dist/server/routes/usercls/controllers/deleteUserCls.js +2 -1
- package/dist/server/routes/usercls/controllers/editUserCls.d.ts.map +1 -1
- package/dist/server/routes/usercls/controllers/editUserCls.js +2 -1
- package/dist/server/routes/usercls/controllers/getUserCls.d.ts +1 -1
- package/dist/server/routes/usercls/controllers/getUserCls.d.ts.map +1 -1
- package/dist/server/routes/usercls/controllers/getUserCls.js +4 -3
- package/dist/server/routes/usercls/index.d.ts.map +1 -1
- package/dist/server/routes/usercls/index.js +12 -5
- package/dist/server/routes/util/controllers/api.list.d.ts +19 -0
- package/dist/server/routes/util/controllers/api.list.d.ts.map +1 -0
- package/dist/server/routes/util/controllers/api.list.js +58 -0
- package/dist/server/routes/util/controllers/code.generator.d.ts.map +1 -1
- package/dist/server/routes/util/controllers/code.generator.js +7 -6
- package/dist/server/routes/util/controllers/user.tokens.d.ts +1 -2
- package/dist/server/routes/util/controllers/user.tokens.d.ts.map +1 -1
- package/dist/server/routes/util/controllers/user.tokens.js +6 -5
- package/dist/server/routes/util/index.d.ts.map +1 -1
- package/dist/server/routes/util/index.js +8 -7
- package/dist/server/routes/widget/controllers/file.edit.d.ts.map +1 -1
- package/dist/server/routes/widget/controllers/file.edit.js +5 -4
- package/dist/server/routes/widget/controllers/widget.del.d.ts.map +1 -1
- package/dist/server/routes/widget/controllers/widget.del.js +6 -7
- package/dist/server/routes/widget/controllers/widget.get.d.ts.map +1 -1
- package/dist/server/routes/widget/controllers/widget.get.js +4 -3
- package/dist/server/routes/widget/controllers/widget.set.d.ts.map +1 -1
- package/dist/server/routes/widget/controllers/widget.set.js +5 -4
- package/dist/server/routes/widget/index.d.ts.map +1 -1
- package/dist/server/routes/widget/index.js +3 -2
- package/package.json +3 -1
- package/dist/module/core/cls/constraint_type.json +0 -14
- package/dist/module/core/cls/constraint_type_table.json +0 -18
- package/dist/server/migrations/oauth.sql.sql +0 -77
- package/dist/server/plugins/auth/funcs/getUserPermissions.d.ts +0 -2
- package/dist/server/plugins/auth/funcs/getUserPermissions.d.ts.map +0 -1
- package/dist/server/plugins/auth/funcs/getUserPermissions.js +0 -24
- package/dist/server/plugins/auth/onRequest.d.ts +0 -4
- package/dist/server/plugins/auth/onRequest.d.ts.map +0 -1
- package/dist/server/plugins/auth/onRequest.js +0 -104
- package/dist/server/plugins/migration/index.d.ts +0 -3
- package/dist/server/plugins/migration/index.d.ts.map +0 -1
- package/dist/server/plugins/migration/index.js +0 -5
- package/dist/server/plugins/policy/funcs/checkAuth.d.ts +0 -4
- package/dist/server/plugins/policy/funcs/checkAuth.d.ts.map +0 -1
- package/dist/server/plugins/policy/funcs/checkAuth.js +0 -104
- package/dist/server/routes/access/controllers/access.resources.d.ts +0 -6
- package/dist/server/routes/access/controllers/access.resources.d.ts.map +0 -1
- package/dist/server/routes/access/controllers/access.resources.js +0 -14
- package/dist/server/routes/access/controllers/resources.d.ts +0 -11
- package/dist/server/routes/access/controllers/resources.d.ts.map +0 -1
- package/dist/server/routes/access/controllers/resources.js +0 -14
- package/dist/server/routes/access/functions/resources.d.ts +0 -6
- package/dist/server/routes/access/functions/resources.d.ts.map +0 -1
- package/dist/server/routes/access/functions/resources.js +0 -11
- package/dist/server/types/errors.d.ts +0 -14
- package/dist/server/types/errors.d.ts.map +0 -1
- package/dist/server/types/errors.js +0 -4
|
@@ -138,6 +138,7 @@ export async function refreshUploadTTL(id, ttl = UPLOAD_TTL_SECONDS, s3 = s3Clie
|
|
|
138
138
|
}
|
|
139
139
|
export async function deleteUploadMeta(id, key) {
|
|
140
140
|
clearUploadTimeout(id);
|
|
141
|
+
await deleteUploadParts(id);
|
|
141
142
|
if (!config.redis) {
|
|
142
143
|
const meta = uploads.get(id);
|
|
143
144
|
uploads.delete(id);
|
|
@@ -295,6 +296,39 @@ export async function startUpload({ Bucket, Key, ContentType, fileSize, }, s3 =
|
|
|
295
296
|
UploadId: res.UploadId,
|
|
296
297
|
};
|
|
297
298
|
}
|
|
299
|
+
const uploadPartsKey = (id) => `upload:${id}:parts`;
|
|
300
|
+
// non-redis in-memory parts cache
|
|
301
|
+
const uploadParts = new Map();
|
|
302
|
+
export async function savePart(id, part) {
|
|
303
|
+
if (!config.redis) {
|
|
304
|
+
const existing = uploadParts.get(id) || [];
|
|
305
|
+
// overwrite existing part number (S3 semantics)
|
|
306
|
+
const filtered = existing.filter((p) => p.PartNumber !== part.PartNumber);
|
|
307
|
+
filtered.push(part);
|
|
308
|
+
uploadParts.set(id, filtered);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
// use redis hash keyed by part number
|
|
312
|
+
await rclient.hset(uploadPartsKey(id), String(part.PartNumber), JSON.stringify(part));
|
|
313
|
+
// keep ttl aligned with upload meta
|
|
314
|
+
await rclient.expire(uploadPartsKey(id), REDIS_TTL);
|
|
315
|
+
}
|
|
316
|
+
export async function getStoredParts(id) {
|
|
317
|
+
if (!config.redis) {
|
|
318
|
+
return (uploadParts.get(id) || []).sort((a, b) => a.PartNumber - b.PartNumber);
|
|
319
|
+
}
|
|
320
|
+
const parts = await rclient.hgetall(uploadPartsKey(id));
|
|
321
|
+
return Object.values(parts)
|
|
322
|
+
.map((v) => JSON.parse(v))
|
|
323
|
+
.sort((a, b) => a.PartNumber - b.PartNumber);
|
|
324
|
+
}
|
|
325
|
+
export async function deleteUploadParts(id) {
|
|
326
|
+
if (!config.redis) {
|
|
327
|
+
uploadParts.delete(id);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
await rclient.del(uploadPartsKey(id));
|
|
331
|
+
}
|
|
298
332
|
export async function uploadChunk({ id, chunk, partNumber, }, s3 = s3Client) {
|
|
299
333
|
if (!s3)
|
|
300
334
|
throw new Error("No S3 client");
|
|
@@ -305,13 +339,17 @@ export async function uploadChunk({ id, chunk, partNumber, }, s3 = s3Client) {
|
|
|
305
339
|
if (upload.parts.some((p) => p.PartNumber === partNumber)) {
|
|
306
340
|
throw new Error(`Part ${partNumber} already uploaded`);
|
|
307
341
|
}
|
|
308
|
-
await s3.send(new UploadPartCommand({
|
|
342
|
+
const res = await s3.send(new UploadPartCommand({
|
|
309
343
|
Bucket: upload.Bucket,
|
|
310
344
|
Key: upload.Key,
|
|
311
345
|
UploadId: upload.UploadId,
|
|
312
346
|
PartNumber: partNumber,
|
|
313
347
|
Body: chunk,
|
|
314
348
|
}));
|
|
349
|
+
await savePart(id, {
|
|
350
|
+
ETag: res.ETag,
|
|
351
|
+
PartNumber: partNumber,
|
|
352
|
+
});
|
|
315
353
|
await refreshUploadTTL(id, UPLOAD_TTL_SECONDS, s3);
|
|
316
354
|
return upload;
|
|
317
355
|
}
|
|
@@ -321,25 +359,30 @@ export async function finishUpload({ id, }, s3 = s3Client) {
|
|
|
321
359
|
const redisCache = await getUploadMeta(id);
|
|
322
360
|
const { fileSize: cachedSize, Key, Bucket } = redisCache || {};
|
|
323
361
|
const size = cachedSize ? Number(cachedSize) : undefined;
|
|
324
|
-
const upload = await findUpload({ id }, s3);
|
|
325
|
-
if (!upload?.uploaded) {
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
if (size && size !== upload.uploaded) {
|
|
329
|
-
|
|
330
|
-
}
|
|
362
|
+
// const upload = await findUpload({ id }, s3);
|
|
363
|
+
// if (!upload?.uploaded) {
|
|
364
|
+
// throw new Error("File not uploaded");
|
|
365
|
+
// }
|
|
366
|
+
// if (size && size !== upload.uploaded) {
|
|
367
|
+
// throw new Error("File size mismatch");
|
|
368
|
+
// }
|
|
369
|
+
const parts = await getStoredParts(id);
|
|
331
370
|
await s3.send(new CompleteMultipartUploadCommand({
|
|
332
371
|
Bucket,
|
|
333
372
|
Key,
|
|
334
373
|
UploadId: id,
|
|
335
374
|
MultipartUpload: {
|
|
336
|
-
Parts:
|
|
375
|
+
Parts: parts.sort((a, b) => a.PartNumber - b.PartNumber),
|
|
376
|
+
// Parts: upload.parts.sort(
|
|
377
|
+
// (a: any, b: any) => a.PartNumber - b.PartNumber
|
|
378
|
+
// ),
|
|
337
379
|
},
|
|
338
380
|
}));
|
|
339
381
|
await deleteUploadMeta(id, Key);
|
|
340
382
|
return {
|
|
341
383
|
finished: true,
|
|
342
|
-
uploaded: upload.uploaded,
|
|
384
|
+
// uploaded: upload.uploaded,
|
|
385
|
+
uploaded: size,
|
|
343
386
|
filepath: Key.replace(config.folder, ""),
|
|
344
387
|
};
|
|
345
388
|
}
|
|
@@ -379,6 +422,7 @@ export async function getUploadStatus({ id, Key, Bucket, }, s3 = s3Client) {
|
|
|
379
422
|
uploaded: res?.ContentLength,
|
|
380
423
|
};
|
|
381
424
|
}
|
|
425
|
+
// const parts = id ? await getStoredParts(id) : { Parts: [] };
|
|
382
426
|
const parts = await s3
|
|
383
427
|
.send(new ListPartsCommand({
|
|
384
428
|
Bucket: redisBucket,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export declare function close(): void;
|
|
2
|
+
export declare function startUpload({ Bucket, Key, fileSize: size, ContentType, }: {
|
|
3
|
+
Bucket?: string;
|
|
4
|
+
Key: string;
|
|
5
|
+
fileSize: number;
|
|
6
|
+
ContentType: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
UploadId: any;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function findUpload({ Bucket, Key, id: UploadId, }: {
|
|
11
|
+
Bucket?: string;
|
|
12
|
+
Key?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
UploadId: string;
|
|
16
|
+
fileSize: any;
|
|
17
|
+
} | {
|
|
18
|
+
UploadId: any;
|
|
19
|
+
fileSize?: undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function uploadChunk({ id: UploadId, chunk: Body, partNumber: PartNumber, }: {
|
|
22
|
+
id: string;
|
|
23
|
+
chunk: any;
|
|
24
|
+
partNumber: number;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
uploaded: any;
|
|
27
|
+
ETag: any;
|
|
28
|
+
PartNumber: number;
|
|
29
|
+
}>;
|
|
30
|
+
export declare function finishUpload({ id: UploadId }: {
|
|
31
|
+
id: string;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
finished: boolean;
|
|
34
|
+
uploaded: any;
|
|
35
|
+
filepath: any;
|
|
36
|
+
}>;
|
|
37
|
+
export declare function getUploadStatus({ id, Bucket, Key, }: {
|
|
38
|
+
id?: string;
|
|
39
|
+
Key?: string;
|
|
40
|
+
Bucket?: string;
|
|
41
|
+
}): Promise<{
|
|
42
|
+
exists: boolean;
|
|
43
|
+
finished: boolean;
|
|
44
|
+
uploaded: any;
|
|
45
|
+
id: any;
|
|
46
|
+
size: number | undefined;
|
|
47
|
+
parts: {
|
|
48
|
+
ETag: any;
|
|
49
|
+
PartNumber: any;
|
|
50
|
+
}[];
|
|
51
|
+
}>;
|
|
52
|
+
export declare function cleanupMultipartUploads({ Bucket, }?: {
|
|
53
|
+
Bucket: string;
|
|
54
|
+
}): Promise<PromiseSettledResult<{
|
|
55
|
+
Key: any;
|
|
56
|
+
UploadId: any;
|
|
57
|
+
}>[]>;
|
|
58
|
+
export declare function deleteUploadMeta(id: string): Promise<void>;
|
|
59
|
+
//# sourceMappingURL=s3minio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3minio.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/s3minio.ts"],"names":[],"mappings":"AAuBA,wBAAgB,KAAK,SAIpB;AAwBD,wBAAsB,WAAW,CAAC,EAChC,MAA2C,EAC3C,GAAG,EACH,QAAQ,EAAE,IAAI,EACd,WAAW,GACZ,EAAE;IACD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;;GAqBA;AAED,wBAAsB,UAAU,CAAC,EAC/B,MAA2C,EAC3C,GAAG,EACH,EAAE,EAAE,QAAQ,GACb,EAAE;IACD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;;;;;;GAuBA;AAED,wBAAsB,WAAW,CAAC,EAChC,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,UAAU,GACvB,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;;;;GA8BA;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;GAwClE;AAED,wBAAsB,eAAe,CAAC,EACpC,EAAE,EACF,MAAM,EACN,GAAG,GACJ,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;GA4CA;AAED,wBAAsB,uBAAuB,CAC3C,EACE,MAAM,GACP,GAAE;IACD,MAAM,EAAE,MAAM,CAAC;CACiC;;;MAqCnD;AAED,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,iBAEhD"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import https from "node:https";
|
|
3
|
+
import { Client } from "minio";
|
|
4
|
+
import config from "../../../config.js";
|
|
5
|
+
import rclient from "../../plugins/redis/client.js";
|
|
6
|
+
import { BadRequestError, NotFoundError } from "../../../errors.js";
|
|
7
|
+
const [protocol, endPoint, port] = config.s3?.endpoint?.split?.(":") || [];
|
|
8
|
+
const useSSL = config.s3?.useSSL || protocol === "https";
|
|
9
|
+
const agent = useSSL
|
|
10
|
+
? new https.Agent({
|
|
11
|
+
keepAlive: true,
|
|
12
|
+
maxSockets: 100,
|
|
13
|
+
})
|
|
14
|
+
: new http.Agent({
|
|
15
|
+
keepAlive: true,
|
|
16
|
+
maxSockets: 100,
|
|
17
|
+
});
|
|
18
|
+
export function close() {
|
|
19
|
+
console.log("closing minio connections");
|
|
20
|
+
agent.destroy();
|
|
21
|
+
console.log("closed minio agent");
|
|
22
|
+
}
|
|
23
|
+
const minio = endPoint
|
|
24
|
+
? new Client({
|
|
25
|
+
endPoint: endPoint.substring(2), // trim "//" after split of http://ip:port
|
|
26
|
+
port: port,
|
|
27
|
+
useSSL,
|
|
28
|
+
accessKey: config.s3.user,
|
|
29
|
+
secretKey: config.s3.password,
|
|
30
|
+
// transport: agent,
|
|
31
|
+
})
|
|
32
|
+
: null;
|
|
33
|
+
if (minio) {
|
|
34
|
+
minio.setRequestOptions({
|
|
35
|
+
agent,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const UPLOAD_TTL_SECONDS = 60 * 60 * 24;
|
|
39
|
+
const CLEANUP_OLDER_THAN_MS = 1000 * 60 * 60 * 24;
|
|
40
|
+
const uploadCacheKey = (id) => `multipart:upload:${id}`;
|
|
41
|
+
export async function startUpload({ Bucket = config.s3?.containerName || "work", Key, fileSize: size, ContentType, }) {
|
|
42
|
+
if (!minio)
|
|
43
|
+
throw new Error("s3 not configured");
|
|
44
|
+
if (!size)
|
|
45
|
+
throw new BadRequestError("invalid params: size");
|
|
46
|
+
if (!Key)
|
|
47
|
+
throw new BadRequestError("not enough params: Key");
|
|
48
|
+
if (!ContentType)
|
|
49
|
+
throw new BadRequestError("not enough params: ContentType");
|
|
50
|
+
const res = await minio.initiateNewMultipartUpload(Bucket, Key, {
|
|
51
|
+
"Content-Type": ContentType,
|
|
52
|
+
});
|
|
53
|
+
const redisKey = uploadCacheKey(res);
|
|
54
|
+
await rclient.set(redisKey, JSON.stringify({ Bucket, Key, ContentType, size }), "EX", UPLOAD_TTL_SECONDS);
|
|
55
|
+
return {
|
|
56
|
+
UploadId: res,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export async function findUpload({ Bucket = config.s3?.containerName || "work", Key, id: UploadId, }) {
|
|
60
|
+
if (!minio)
|
|
61
|
+
throw new Error("s3 not configured");
|
|
62
|
+
if (UploadId) {
|
|
63
|
+
const redisKey = uploadCacheKey(UploadId);
|
|
64
|
+
const cache = await rclient
|
|
65
|
+
.get(redisKey)
|
|
66
|
+
.then((r) => JSON.parse(r || "{}"));
|
|
67
|
+
return {
|
|
68
|
+
UploadId,
|
|
69
|
+
fileSize: cache.size,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (!Key)
|
|
73
|
+
throw new BadRequestError("not enough params: Key");
|
|
74
|
+
const uploads = await minio.listIncompleteUploads(Bucket, Key, true);
|
|
75
|
+
const found = uploads.find((u) => u.key === Key);
|
|
76
|
+
return {
|
|
77
|
+
UploadId: found?.uploadId,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export async function uploadChunk({ id: UploadId, chunk: Body, partNumber: PartNumber, }) {
|
|
81
|
+
if (!minio)
|
|
82
|
+
throw new Error("s3 not configured");
|
|
83
|
+
const redisKey = uploadCacheKey(UploadId);
|
|
84
|
+
const cache = await rclient
|
|
85
|
+
.get(redisKey)
|
|
86
|
+
.then((r) => JSON.parse(r || "{}"));
|
|
87
|
+
if (!cache.Key) {
|
|
88
|
+
throw NotFoundError("multipart upload not found");
|
|
89
|
+
}
|
|
90
|
+
const etag = await minio.uploadPart({
|
|
91
|
+
bucketName: cache.Bucket,
|
|
92
|
+
objectName: cache.Key,
|
|
93
|
+
uploadID: UploadId,
|
|
94
|
+
partNumber: PartNumber,
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": cache.contentType,
|
|
97
|
+
},
|
|
98
|
+
}, Body);
|
|
99
|
+
return {
|
|
100
|
+
uploaded: Body.length,
|
|
101
|
+
ETag: etag,
|
|
102
|
+
PartNumber,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export async function finishUpload({ id: UploadId }) {
|
|
106
|
+
if (!minio)
|
|
107
|
+
throw new Error("s3 not configured");
|
|
108
|
+
const redisKey = uploadCacheKey(UploadId);
|
|
109
|
+
const cache = await rclient
|
|
110
|
+
.get(redisKey)
|
|
111
|
+
.then((r) => JSON.parse(r || "{}"));
|
|
112
|
+
if (!cache.Bucket || !cache.Key) {
|
|
113
|
+
throw NotFoundError("s3 upload not found");
|
|
114
|
+
}
|
|
115
|
+
const parts = cache.Bucket && cache.Key
|
|
116
|
+
? await minio.listParts(cache.Bucket, cache.Key, UploadId)
|
|
117
|
+
: [];
|
|
118
|
+
const uploaded = parts.reduce((acc, curr) => acc + (curr.size || 0), 0) || 0;
|
|
119
|
+
const sortedParts = parts
|
|
120
|
+
.map((p) => ({
|
|
121
|
+
part: p.part,
|
|
122
|
+
etag: p.etag,
|
|
123
|
+
}))
|
|
124
|
+
.sort((a, b) => a.part - b.part);
|
|
125
|
+
await minio.completeMultipartUpload(cache.Bucket, cache.Key, UploadId, sortedParts);
|
|
126
|
+
await rclient.del(redisKey);
|
|
127
|
+
return {
|
|
128
|
+
finished: true,
|
|
129
|
+
uploaded,
|
|
130
|
+
filepath: cache.Key.replace(config.folder, ""),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export async function getUploadStatus({ id, Bucket, Key, }) {
|
|
134
|
+
if (!minio)
|
|
135
|
+
throw new Error("s3 not configured");
|
|
136
|
+
if (!id && !(Bucket && Key)) {
|
|
137
|
+
throw new BadRequestError("not enough params: id / Bucket && Key");
|
|
138
|
+
}
|
|
139
|
+
const UploadId = id || (await findUpload({ Bucket, Key }).then((r) => r.UploadId));
|
|
140
|
+
const cache = UploadId
|
|
141
|
+
? await rclient
|
|
142
|
+
.get(uploadCacheKey(UploadId))
|
|
143
|
+
.then((r) => JSON.parse(r || "{}"))
|
|
144
|
+
: {};
|
|
145
|
+
let stat;
|
|
146
|
+
let parts = [];
|
|
147
|
+
const Key1 = id ? cache.Key : Key;
|
|
148
|
+
const Bucket1 = id ? cache.Bucket : Bucket;
|
|
149
|
+
if (Bucket1 && Key1 && UploadId) {
|
|
150
|
+
try {
|
|
151
|
+
stat = await minio.statObject(Bucket1, Key1);
|
|
152
|
+
}
|
|
153
|
+
catch { }
|
|
154
|
+
try {
|
|
155
|
+
parts = await minio.listParts(Bucket1, Key1, UploadId);
|
|
156
|
+
}
|
|
157
|
+
catch { }
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
exists: !!stat || !!parts.length,
|
|
161
|
+
finished: !!stat,
|
|
162
|
+
uploaded: stat
|
|
163
|
+
? stat.size
|
|
164
|
+
: parts.reduce((acc, curr) => acc + (curr.size || 0), 0),
|
|
165
|
+
id: UploadId,
|
|
166
|
+
size: cache.size ? Number(cache.size) : undefined,
|
|
167
|
+
parts: parts.map((p) => ({
|
|
168
|
+
ETag: p.etag,
|
|
169
|
+
PartNumber: p.part,
|
|
170
|
+
})),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export async function cleanupMultipartUploads({ Bucket, } = { Bucket: config.s3?.containerName || "work" }) {
|
|
174
|
+
if (!minio)
|
|
175
|
+
throw new Error("s3 not configured");
|
|
176
|
+
console.log("minio cleanupMultipartUploads start");
|
|
177
|
+
const stream = minio.listIncompleteUploads(Bucket, "", true);
|
|
178
|
+
const uploads = [];
|
|
179
|
+
for await (const upload of stream) {
|
|
180
|
+
uploads.push(upload);
|
|
181
|
+
}
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const staleUploads = uploads.filter((u) => u.initiated &&
|
|
184
|
+
now - new Date(u.initiated).getTime() > CLEANUP_OLDER_THAN_MS);
|
|
185
|
+
const results = await Promise.allSettled(staleUploads.map(async (upload) => {
|
|
186
|
+
await minio.removeIncompleteUpload(Bucket, upload.key);
|
|
187
|
+
const redisKey = uploadCacheKey(upload.uploadId);
|
|
188
|
+
await rclient.del(redisKey);
|
|
189
|
+
return {
|
|
190
|
+
Key: upload.key,
|
|
191
|
+
UploadId: upload.uploadId,
|
|
192
|
+
};
|
|
193
|
+
}));
|
|
194
|
+
return results;
|
|
195
|
+
}
|
|
196
|
+
export async function deleteUploadMeta(id) {
|
|
197
|
+
if (rclient && id)
|
|
198
|
+
await rclient.del(id);
|
|
199
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startUpload.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/startUpload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"startUpload.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/startUpload.ts"],"names":[],"mappings":"AAoBA,wBAA8B,WAAW,CAAC,EACxC,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,gBAyFA"}
|
|
@@ -6,12 +6,11 @@ import getUploadStatus from "./getUploadStatus.js";
|
|
|
6
6
|
import { prefix, fileDir, metaDir, uploadChunkDirectory, fetchTimeoutMs, } from "./index.js";
|
|
7
7
|
import mimes from "../file/providers/mime/mimes.js";
|
|
8
8
|
import { startUpload as startUploadS3 } from "./s3.js";
|
|
9
|
+
import { BadRequestError } from "../../../errors.js";
|
|
10
|
+
const { chunkSize = 5242880 } = config;
|
|
9
11
|
export default async function startUpload({ host, id, fileName, size, subdir, }) {
|
|
10
12
|
if (subdir && (typeof subdir !== "string" || subdir.includes(".."))) {
|
|
11
|
-
|
|
12
|
-
error: "invalid params: subdir",
|
|
13
|
-
code: 400,
|
|
14
|
-
};
|
|
13
|
+
throw BadRequestError("invalid params: subdir");
|
|
15
14
|
}
|
|
16
15
|
if (!host) {
|
|
17
16
|
const id1 = id || randomUUID();
|
|
@@ -20,14 +19,19 @@ export default async function startUpload({ host, id, fileName, size, subdir, })
|
|
|
20
19
|
.join(uploadChunkDirectory, subdir || "")
|
|
21
20
|
.replace(/\\/g, "/");
|
|
22
21
|
if (config.s3) {
|
|
23
|
-
const filepath = path.posix.join(config.folder ||
|
|
22
|
+
const filepath = path.posix.join(config.folder || "", relativeDirpath, `${id1}.${extension}`);
|
|
24
23
|
const { UploadId } = await startUploadS3({
|
|
25
24
|
Bucket: config.s3?.containerName || "work",
|
|
26
25
|
Key: filepath[0] === "/" ? filepath?.slice(1) : filepath,
|
|
27
26
|
ContentType: mimes[extension],
|
|
28
27
|
fileSize: size,
|
|
29
28
|
});
|
|
30
|
-
return {
|
|
29
|
+
return {
|
|
30
|
+
id: UploadId,
|
|
31
|
+
UploadId,
|
|
32
|
+
provider: "s3",
|
|
33
|
+
chunkSize,
|
|
34
|
+
};
|
|
31
35
|
}
|
|
32
36
|
const key = id1.split("-").pop();
|
|
33
37
|
const meta = {
|
|
@@ -57,10 +61,14 @@ export default async function startUpload({ host, id, fileName, size, subdir, })
|
|
|
57
61
|
subdir,
|
|
58
62
|
metaPath: undefined,
|
|
59
63
|
relativeDirpath,
|
|
60
|
-
provider: "fs"
|
|
64
|
+
provider: "fs",
|
|
61
65
|
};
|
|
62
66
|
await writeFile(path.join(metaDir, `${id1}.json`), JSON.stringify(metaData, null, 2));
|
|
63
|
-
return {
|
|
67
|
+
return {
|
|
68
|
+
...meta,
|
|
69
|
+
metaPath: undefined,
|
|
70
|
+
chunkSize,
|
|
71
|
+
};
|
|
64
72
|
}
|
|
65
73
|
const res = await fetch(`${host}/${prefix}/start`, {
|
|
66
74
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/uploadChunk.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/uploadChunk.ts"],"names":[],"mappings":"AAwBA,wBAA8B,WAAW,CAAC,EACxC,IAAI,EACJ,EAAE,EACF,IAAI,EACJ,MAAM,EACN,GAAG,EACH,IAAI,GACL,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,GAAG,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,gBA4IA"}
|
|
@@ -7,11 +7,16 @@ import uploadFile from "../file/uploadFile.js";
|
|
|
7
7
|
import applyHook from "../hook/applyHook.js";
|
|
8
8
|
import getFileSize from "../file/getFileSize.js";
|
|
9
9
|
import { finishUpload as finishUploadS3, uploadChunk as uploadChunkS3, getUploadStatus as getUploadStatusS3, findUpload as findUploadS3, } from "./s3.js";
|
|
10
|
+
import { BadRequestError, ConflictError, NotFoundError } from "../../../errors.js";
|
|
11
|
+
const { chunkSize = 5242880 } = config;
|
|
10
12
|
export default async function uploadChunk({ host, id, body, offset, end, size, }) {
|
|
11
13
|
if (!host) {
|
|
12
14
|
if (config.s3) {
|
|
13
|
-
const partNumber = Math.floor(offset /
|
|
14
|
-
const { fileSize } = await findUploadS3({ id });
|
|
15
|
+
const partNumber = Math.floor(offset / chunkSize) + 1;
|
|
16
|
+
const { UploadId, fileSize } = await findUploadS3({ id });
|
|
17
|
+
if (!UploadId) {
|
|
18
|
+
throw NotFoundError("upload not found");
|
|
19
|
+
}
|
|
15
20
|
await uploadChunkS3({
|
|
16
21
|
id,
|
|
17
22
|
chunk: body,
|
|
@@ -26,17 +31,17 @@ export default async function uploadChunk({ host, id, body, offset, end, size, }
|
|
|
26
31
|
}
|
|
27
32
|
const metaExists = existsSync(path.join(metaDir, `${id}.json`));
|
|
28
33
|
if (!metaExists) {
|
|
29
|
-
|
|
34
|
+
throw NotFoundError("File not found");
|
|
30
35
|
}
|
|
31
36
|
const meta = JSON.parse(await readFile(path.join(metaDir, `${id}.json`), "utf8"));
|
|
32
37
|
if (size !== meta.size) {
|
|
33
|
-
|
|
38
|
+
throw BadRequestError("Total size mismatch");
|
|
34
39
|
}
|
|
35
40
|
if (offset !== meta.uploaded) {
|
|
36
|
-
|
|
41
|
+
throw ConflictError("Wrong offset");
|
|
37
42
|
}
|
|
38
43
|
if (body?.length !== end - offset + 1) {
|
|
39
|
-
|
|
44
|
+
throw BadRequestError("Chunk size mismatch with Content-Range");
|
|
40
45
|
}
|
|
41
46
|
const relpath = path.posix.join(uploadChunkDirectory, `${id}.${meta.extension}`);
|
|
42
47
|
const res = await getFileSize(relpath, { fallback: false }).catch((err) => ({
|
|
@@ -46,10 +51,10 @@ export default async function uploadChunk({ host, id, body, offset, end, size, }
|
|
|
46
51
|
if (res.error &&
|
|
47
52
|
res.error !== "Error: file not found" &&
|
|
48
53
|
res.code !== "ENOENT") {
|
|
49
|
-
throw
|
|
54
|
+
throw Error(res.error);
|
|
50
55
|
}
|
|
51
56
|
if (!res.error && res > meta.size) {
|
|
52
|
-
throw
|
|
57
|
+
throw BadRequestError("uploaded size exceeds file size");
|
|
53
58
|
}
|
|
54
59
|
// append chunk to existing file
|
|
55
60
|
await uploadFile(path
|
|
@@ -84,7 +89,7 @@ export default async function uploadChunk({ host, id, body, offset, end, size, }
|
|
|
84
89
|
return { uploaded: meta.uploaded, finished };
|
|
85
90
|
}
|
|
86
91
|
if (!end || !size) {
|
|
87
|
-
|
|
92
|
+
throw BadRequestError("not enough params: offset/end/size");
|
|
88
93
|
}
|
|
89
94
|
const url = `${host}/${prefix}/${id}`;
|
|
90
95
|
const range = `bytes ${offset || 0}-${end}/${size}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.group.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"access.group.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAKzD,wBAA8B,WAAW,CACvC,EACE,EAAqB,EACrB,MAAM,EACN,IAAS,GACV,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,EAED,KAAK,EAAE,YAAY;;;;GAwCpB"}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { pgClients, getAdminAccess } from "../../../../utils.js";
|
|
2
|
+
import { BadRequestError } from "../../../../errors.js";
|
|
2
3
|
export default async function accessGroup({ pg = pgClients.client, params, user = {}, }, reply) {
|
|
3
4
|
if (!params?.id) {
|
|
4
|
-
|
|
5
|
+
throw BadRequestError("not enough params: id");
|
|
5
6
|
}
|
|
6
7
|
// restrict access - admin only
|
|
7
|
-
|
|
8
|
+
await getAdminAccess({
|
|
8
9
|
id: params.id,
|
|
9
10
|
user,
|
|
10
11
|
});
|
|
11
|
-
if (check?.message && check?.status && process.env.NODE_ENV !== "test") {
|
|
12
|
-
return reply.status(check?.status).send(check?.message);
|
|
13
|
-
}
|
|
14
12
|
const routes = await pg
|
|
15
13
|
.query(`select a.route_id as path, b.actions from admin.routes a
|
|
16
14
|
left join admin.role_access b on a.route_id=b.route_id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.group.post.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.group.post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"access.group.post.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.group.post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAMzD,wBAA8B,eAAe,CAC3C,EACE,EAAqB,EACrB,MAAM,EACN,IAAS,EACT,IAAS,GACV,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,EACD,KAAK,EAAE,YAAY;;;;GA4GpB"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { pgClients, getAdminAccess } from "../../../../utils.js";
|
|
2
2
|
import accessGroup from "./access.group.js";
|
|
3
|
+
import { UnauthorizedError } from "../../../../errors.js";
|
|
3
4
|
export default async function accessGroupPost({ pg = pgClients.client, params, user = {}, body = {}, }, reply) {
|
|
4
5
|
const { id } = params;
|
|
5
6
|
if (!user?.uid) {
|
|
6
|
-
|
|
7
|
+
throw UnauthorizedError("unauthorized");
|
|
7
8
|
}
|
|
8
9
|
// restrict access - admin only
|
|
9
|
-
|
|
10
|
-
if (check?.message && check?.status && process.env.NODE_ENV !== "test") {
|
|
11
|
-
return reply.status(check?.status).send(check?.message);
|
|
12
|
-
}
|
|
10
|
+
await getAdminAccess({ id, user });
|
|
13
11
|
const { users = [], routes = [] } = body;
|
|
14
12
|
if (!routes?.length) {
|
|
15
13
|
await pg.query("delete from admin.role_access where role_id=$1", [id]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.interface.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAqB5C,wBAA8B,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY;;
|
|
1
|
+
{"version":3,"file":"access.interface.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAqB5C,wBAA8B,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY;;GAkB1E"}
|
|
@@ -18,13 +18,10 @@ where $1 in (a.route_id, a.alias, a.table_name) and coalesce(b.user_uid, d.user_
|
|
|
18
18
|
export default async function accessInterface(req, reply) {
|
|
19
19
|
const { pg = pgClients.client, params = {}, user = {}, unittest } = req;
|
|
20
20
|
// restrict access - admin only
|
|
21
|
-
|
|
21
|
+
await getAdminAccess({
|
|
22
22
|
id: params.name,
|
|
23
23
|
user,
|
|
24
24
|
});
|
|
25
|
-
if (check?.message && check?.status && !unittest) {
|
|
26
|
-
return reply.status(check?.status).send(check?.message);
|
|
27
|
-
}
|
|
28
25
|
const { rows = [] } = await pg.query(q, [params.name]);
|
|
29
26
|
const cls = {
|
|
30
27
|
user_uid: "core.user_uid",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.user.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.user.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"access.user.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.user.ts"],"names":[],"mappings":"AAGA,wBAA8B,UAAU,CAAC,GAAG,EAAE,GAAG;;;;GAmChD"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import { BadRequestError } from "../../../../errors.js";
|
|
1
2
|
import { pgClients } from "../../../../utils.js";
|
|
2
|
-
export default async function accessUser(req
|
|
3
|
+
export default async function accessUser(req) {
|
|
3
4
|
if (!req.params?.id) {
|
|
4
|
-
|
|
5
|
-
.status(400)
|
|
6
|
-
.send({ error: "not enough params: id", code: 400 });
|
|
5
|
+
throw BadRequestError("not enough params: id");
|
|
7
6
|
}
|
|
8
7
|
const { pg = pgClients.client } = req;
|
|
9
8
|
const routes = await pg
|
|
@@ -21,5 +20,5 @@ where resource_id is not null and user_uid=$1`, [req.params.id])
|
|
|
21
20
|
left join admin.users b on a.user_uid=b.uid
|
|
22
21
|
where a.user_uid=$1`, [req.params.id])
|
|
23
22
|
.then((el) => el.rows?.[0]);
|
|
24
|
-
return
|
|
23
|
+
return { routes, resources, user };
|
|
25
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.user.post.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.user.post.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"access.user.post.d.ts","sourceRoot":"","sources":["../../../../../server/routes/access/controllers/access.user.post.ts"],"names":[],"mappings":"AAKA,wBAA8B,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAuDhE"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
+
import { BadRequestError, UnauthorizedError } from "../../../../errors.js";
|
|
1
2
|
import { pgClients } from "../../../../utils.js";
|
|
2
3
|
import accessUser from "./access.user.js";
|
|
3
4
|
export default async function accessUserPost(req, reply) {
|
|
4
5
|
const { pg = pgClients.client, params, body, user } = req;
|
|
5
6
|
if (!params?.id) {
|
|
6
|
-
|
|
7
|
-
.status(400)
|
|
8
|
-
.send({ error: "not enough params: id", code: 400 });
|
|
7
|
+
throw BadRequestError("not enough params: id");
|
|
9
8
|
}
|
|
10
9
|
if (!user?.uid) {
|
|
11
|
-
|
|
10
|
+
throw UnauthorizedError("unauthorized");
|
|
12
11
|
}
|
|
13
12
|
await pg.query("delete from admin.role_access where user_uid=$1", [
|
|
14
13
|
params.id,
|
|
@@ -28,6 +27,6 @@ export default async function accessUserPost(req, reply) {
|
|
|
28
27
|
await Promise.all(body.routes
|
|
29
28
|
.filter((el) => el.resource && el.actions)
|
|
30
29
|
.map((el) => pg.query("insert into admin.role_access(user_uid,resource_id,actions) values ($1,$2,$3)", [params.id, el.resource, el.actions])));
|
|
31
|
-
const result = await accessUser({ pg, params }
|
|
30
|
+
const result = await accessUser({ pg, params });
|
|
32
31
|
return result;
|
|
33
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/access/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/access/index.ts"],"names":[],"mappings":"AAkBA,wBAA8B,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAE,GAAQ,iBAqC9D"}
|