@nocobase/plugin-file-manager 2.1.0-beta.9 → 2.1.1
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/client-v2.d.ts +2 -0
- package/client-v2.js +1 -0
- package/dist/client/867ada653cd02a3e.mjs +6 -0
- package/dist/client/876.ca16d7a6e6387862.js +11 -0
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.js +1 -1
- package/dist/client/locale/index.d.ts +2 -1
- package/dist/client/previewer/filePreviewTypes.d.ts +1 -31
- package/dist/client/templates/file.d.ts +1 -1
- package/dist/client-v2/125.0b8eef1f19b87042.js +10 -0
- package/dist/client-v2/229.bd72c2d7aa088310.js +10 -0
- package/dist/client-v2/336.1dd1b32466d0c778.js +10 -0
- package/dist/client-v2/43.eb45d53ba3e9828b.js +10 -0
- package/dist/client-v2/450.30cc3ed6973d8c4d.js +10 -0
- package/dist/client-v2/867ada653cd02a3e.mjs +6 -0
- package/dist/client-v2/876.22cd8e41ac8631ed.js +11 -0
- package/dist/client-v2/929.d7e783304cc1f236.js +10 -0
- package/dist/client-v2/942.f36d807d763a1b53.js +10 -0
- package/dist/{client/StorageOptions.d.ts → client-v2/components/BaseUrlField.d.ts} +1 -1
- package/dist/client-v2/components/DefaultField.d.ts +18 -0
- package/dist/client-v2/components/FileSizeField.d.ts +10 -0
- package/dist/client-v2/components/MimetypeField.d.ts +10 -0
- package/dist/client-v2/components/NameField.d.ts +10 -0
- package/dist/client-v2/components/ParanoidField.d.ts +10 -0
- package/dist/client-v2/components/PathField.d.ts +18 -0
- package/dist/client-v2/components/RenameModeField.d.ts +10 -0
- package/dist/client-v2/components/TitleField.d.ts +10 -0
- package/dist/client-v2/components/index.d.ts +17 -0
- package/dist/client-v2/index.d.ts +17 -0
- package/dist/client-v2/index.js +10 -0
- package/dist/client-v2/locale.d.ts +10 -0
- package/dist/{client → client-v2}/models/DisplayPreviewFieldModel.d.ts +1 -1
- package/dist/{client → client-v2}/models/UploadActionModel.d.ts +4 -3
- package/dist/{client → client-v2}/models/UploadFieldModel.d.ts +1 -1
- package/dist/client-v2/models/index.d.ts +11 -0
- package/dist/{client → client-v2}/models/uploadFieldUtils.d.ts +8 -0
- package/dist/client-v2/pages/FileStoragePage.d.ts +10 -0
- package/dist/client-v2/plugin.d.ts +89 -0
- package/dist/client-v2/previewer/filePreviewTypes.d.ts +46 -0
- package/dist/client-v2/storage-forms/AliOssStorageForm.d.ts +10 -0
- package/dist/client-v2/storage-forms/LocalStorageForm.d.ts +10 -0
- package/dist/client-v2/storage-forms/S3StorageForm.d.ts +10 -0
- package/dist/client-v2/storage-forms/TxCosStorageForm.d.ts +10 -0
- package/dist/common/collections/attachments.d.ts +1 -0
- package/dist/common/collections/attachments.js +1 -0
- package/dist/common/collections/storages.d.ts +1 -0
- package/dist/common/collections/storages.js +1 -0
- package/dist/externalVersion.js +12 -12
- package/dist/locale/de-DE.json +3 -0
- package/dist/locale/en-US.json +4 -0
- package/dist/locale/es-ES.json +3 -0
- package/dist/locale/fr-FR.json +3 -0
- package/dist/locale/hu-HU.json +4 -1
- package/dist/locale/id-ID.json +4 -1
- package/dist/locale/it-IT.json +3 -0
- package/dist/locale/ja-JP.json +3 -0
- package/dist/locale/ko-KR.json +3 -0
- package/dist/locale/nl-NL.json +3 -0
- package/dist/locale/pt-BR.json +3 -0
- package/dist/locale/ru-RU.json +3 -0
- package/dist/locale/tr-TR.json +3 -0
- package/dist/locale/uk-UA.json +3 -0
- package/dist/locale/vi-VN.json +4 -1
- package/dist/locale/zh-CN.json +4 -0
- package/dist/locale/zh-TW.json +3 -0
- package/dist/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +190 -190
- package/dist/node_modules/@aws-sdk/client-s3/package.json +1 -1
- package/dist/node_modules/@aws-sdk/lib-storage/dist-cjs/index.js +195 -195
- package/dist/node_modules/@aws-sdk/lib-storage/node_modules/buffer/index.d.ts +186 -0
- package/dist/node_modules/@aws-sdk/lib-storage/node_modules/buffer/index.js +1794 -0
- package/dist/node_modules/@aws-sdk/lib-storage/node_modules/buffer/package.json +82 -0
- package/dist/node_modules/@aws-sdk/lib-storage/package.json +1 -1
- package/dist/node_modules/ali-oss/lib/client.js +14 -14
- package/dist/node_modules/ali-oss/package.json +1 -1
- package/dist/node_modules/cos-nodejs-sdk-v5/.github/workflows/auto-changelog.yml +55 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/.prettierrc +10 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/.travis.yml +16 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/LICENSE +21 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/demo/crc64.js +9 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/demo/demo-sts-scope.js +75 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/demo/demo-sts.js +65 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/demo/demo.js +4542 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/demo/util.js +135 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/index.d.ts +2610 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/index.js +220 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/package.json +1 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/advance.js +1659 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/async.js +59 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/base.js +4404 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/cos.js +137 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/event.js +34 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/select-stream.js +181 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/session.js +126 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/task.js +255 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/sdk/util.js +776 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/test/csp.js +1302 -0
- package/dist/node_modules/cos-nodejs-sdk-v5/test/test.js +6119 -0
- package/dist/node_modules/mime-match/index.js +1 -1
- package/dist/node_modules/mime-match/package.json +1 -1
- package/dist/node_modules/mime-types/index.js +3 -3
- package/dist/node_modules/mime-types/package.json +1 -1
- package/dist/node_modules/mkdirp/index.js +1 -1
- package/dist/node_modules/mkdirp/package.json +1 -1
- package/dist/node_modules/url-join/lib/url-join.js +1 -1
- package/dist/node_modules/url-join/package.json +1 -1
- package/dist/server/actions/attachments.js +2 -2
- package/dist/server/actions/index.js +8 -1
- package/dist/server/actions/storage-validation.d.ts +10 -0
- package/dist/server/actions/storage-validation.js +73 -0
- package/dist/server/commands/repair-filenames.d.ts +55 -0
- package/dist/server/commands/repair-filenames.js +283 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/server.d.ts +5 -2
- package/dist/server/server.js +19 -7
- package/dist/server/storages/ali-oss.d.ts +3 -1
- package/dist/server/storages/ali-oss.js +23 -2
- package/dist/server/storages/index.d.ts +7 -1
- package/dist/server/storages/index.js +8 -1
- package/dist/server/storages/local.d.ts +6 -0
- package/dist/server/storages/local.js +76 -11
- package/dist/server/storages/s3.d.ts +2 -0
- package/dist/server/storages/s3.js +26 -0
- package/dist/server/storages/tx-cos.d.ts +18 -1
- package/dist/server/storages/tx-cos.js +138 -10
- package/dist/server/utils.d.ts +3 -0
- package/dist/server/utils.js +72 -4
- package/package.json +8 -3
- package/dist/node_modules/multer-cos/LICENSE +0 -24
- package/dist/node_modules/multer-cos/demo/index.js +0 -39
- package/dist/node_modules/multer-cos/demo/myMulter.js +0 -88
- package/dist/node_modules/multer-cos/index.js +0 -220
- package/dist/node_modules/multer-cos/package.json +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"mime-types","description":"The ultimate javascript content-type utility.","version":"3.0.1","contributors":["Douglas Christopher Wilson <doug@somethingdoug.com>","Jeremiah Senkpiel <fishrock123@rocketmail.com> (https://searchbeam.jit.su)","Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"],"license":"MIT","keywords":["mime","types"],"repository":"jshttp/mime-types","dependencies":{"mime-db":"^1.54.0"},"devDependencies":{"eslint":"8.33.0","eslint-config-standard":"14.1.1","eslint-plugin-import":"2.27.5","eslint-plugin-markdown":"3.0.0","eslint-plugin-node":"11.1.0","eslint-plugin-promise":"6.1.1","eslint-plugin-standard":"4.1.0","mocha":"10.2.0","nyc":"15.1.0"},"files":["HISTORY.md","LICENSE","index.js","mimeScore.js"],"engines":{"node":">= 0.6"},"scripts":{"lint":"eslint .","test":"mocha --reporter spec test/test.js","test-ci":"nyc --reporter=lcov --reporter=text npm test","test-cov":"nyc --reporter=html --reporter=text npm test"},"_lastModified":"2026-
|
|
1
|
+
{"name":"mime-types","description":"The ultimate javascript content-type utility.","version":"3.0.1","contributors":["Douglas Christopher Wilson <doug@somethingdoug.com>","Jeremiah Senkpiel <fishrock123@rocketmail.com> (https://searchbeam.jit.su)","Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"],"license":"MIT","keywords":["mime","types"],"repository":"jshttp/mime-types","dependencies":{"mime-db":"^1.54.0"},"devDependencies":{"eslint":"8.33.0","eslint-config-standard":"14.1.1","eslint-plugin-import":"2.27.5","eslint-plugin-markdown":"3.0.0","eslint-plugin-node":"11.1.0","eslint-plugin-promise":"6.1.1","eslint-plugin-standard":"4.1.0","mocha":"10.2.0","nyc":"15.1.0"},"files":["HISTORY.md","LICENSE","index.js","mimeScore.js"],"engines":{"node":">= 0.6"},"scripts":{"lint":"eslint .","test":"mocha --reporter spec test/test.js","test-ci":"nyc --reporter=lcov --reporter=text npm test","test-cov":"nyc --reporter=html --reporter=text npm test"},"_lastModified":"2026-06-11T01:17:51.156Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(
|
|
1
|
+
(()=>{var e={186:(e,r,i)=>{var t=i(17);var n=i(147);var a=parseInt("0777",8);e.exports=mkdirP.mkdirp=mkdirP.mkdirP=mkdirP;function mkdirP(e,r,i,f){if(typeof r==="function"){i=r;r={}}else if(!r||typeof r!=="object"){r={mode:r}}var c=r.mode;var o=r.fs||n;if(c===undefined){c=a}if(!f)f=null;var s=i||function(){};e=t.resolve(e);o.mkdir(e,c,(function(i){if(!i){f=f||e;return s(null,f)}switch(i.code){case"ENOENT":if(t.dirname(e)===e)return s(i);mkdirP(t.dirname(e),r,(function(i,t){if(i)s(i,t);else mkdirP(e,r,s,t)}));break;default:o.stat(e,(function(e,r){if(e||!r.isDirectory())s(i,f);else s(null,f)}));break}}))}mkdirP.sync=function sync(e,r,i){if(!r||typeof r!=="object"){r={mode:r}}var f=r.mode;var c=r.fs||n;if(f===undefined){f=a}if(!i)i=null;e=t.resolve(e);try{c.mkdirSync(e,f);i=i||e}catch(n){switch(n.code){case"ENOENT":i=sync(t.dirname(e),r,i);sync(e,r,i);break;default:var o;try{o=c.statSync(e)}catch(e){throw n}if(!o.isDirectory())throw n;break}}return i}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __nccwpck_require__(i){var t=r[i];if(t!==undefined){return t.exports}var n=r[i]={exports:{}};var a=true;try{e[i](n,n.exports,__nccwpck_require__);a=false}finally{if(a)delete r[i]}return n.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var i=__nccwpck_require__(186);module.exports=i})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"0.5.6","publishConfig":{"tag":"legacy"},"author":"James Halliday <mail@substack.net> (http://substack.net)","main":"index.js","keywords":["mkdir","directory"],"repository":{"type":"git","url":"https://github.com/substack/node-mkdirp.git"},"scripts":{"test":"tap test/*.js"},"dependencies":{"minimist":"^1.2.6"},"devDependencies":{"tap":"^16.0.1"},"bin":"bin/cmd.js","license":"MIT","files":["bin","index.js"],"_lastModified":"2026-
|
|
1
|
+
{"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"0.5.6","publishConfig":{"tag":"legacy"},"author":"James Halliday <mail@substack.net> (http://substack.net)","main":"index.js","keywords":["mkdir","directory"],"repository":{"type":"git","url":"https://github.com/substack/node-mkdirp.git"},"scripts":{"test":"tap test/*.js"},"dependencies":{"minimist":"^1.2.6"},"devDependencies":{"tap":"^16.0.1"},"bin":"bin/cmd.js","license":"MIT","files":["bin","index.js"],"_lastModified":"2026-06-11T01:17:55.489Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(
|
|
1
|
+
(()=>{var e={821:function(e){(function(r,i,t){if(true&&e.exports)e.exports=t();else if(typeof define==="function"&&define.amd)define(t);else i[r]=t()})("urljoin",this,(function(){function normalize(e){var r=[];if(e.length===0){return""}if(typeof e[0]!=="string"){throw new TypeError("Url must be a string. Received "+e[0])}if(e[0].match(/^[^/:]+:\/*$/)&&e.length>1){var i=e.shift();e[0]=i+e[0]}if(e[0].match(/^file:\/\/\//)){e[0]=e[0].replace(/^([^/:]+):\/*/,"$1:///")}else{e[0]=e[0].replace(/^([^/:]+):\/*/,"$1://")}for(var t=0;t<e.length;t++){var n=e[t];if(typeof n!=="string"){throw new TypeError("Url must be a string. Received "+n)}if(n===""){continue}if(t>0){n=n.replace(/^[\/]+/,"")}if(t<e.length-1){n=n.replace(/[\/]+$/,"")}else{n=n.replace(/[\/]+$/,"/")}r.push(n)}var a=r.join("/");a=a.replace(/\/(\?|&|#[^!])/g,"$1");var f=a.split("?");a=f.shift()+(f.length>0?"?":"")+f.join("&");return a}return function(){var e;if(typeof arguments[0]==="object"){e=arguments[0]}else{e=[].slice.call(arguments)}return normalize(e)}}))}};var r={};function __nccwpck_require__(i){var t=r[i];if(t!==undefined){return t.exports}var n=r[i]={exports:{}};var a=true;try{e[i].call(n.exports,n,n.exports,__nccwpck_require__);a=false}finally{if(a)delete r[i]}return n.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var i=__nccwpck_require__(821);module.exports=i})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"url-join","version":"4.0.1","description":"Join urls and normalize as in path.join.","main":"lib/url-join.js","scripts":{"test":"mocha --require should"},"repository":{"type":"git","url":"git://github.com/jfromaniello/url-join.git"},"keywords":["url","join"],"author":"José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)","license":"MIT","devDependencies":{"conventional-changelog":"^1.1.10","mocha":"^3.2.0","should":"~1.2.1"},"_lastModified":"2026-
|
|
1
|
+
{"name":"url-join","version":"4.0.1","description":"Join urls and normalize as in path.join.","main":"lib/url-join.js","scripts":{"test":"mocha --require should"},"repository":{"type":"git","url":"git://github.com/jfromaniello/url-join.git"},"keywords":["url","join"],"author":"José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)","license":"MIT","devDependencies":{"conventional-changelog":"^1.1.10","mocha":"^3.2.0","should":"~1.2.1"},"_lastModified":"2026-06-11T01:17:50.956Z"}
|
|
@@ -221,10 +221,10 @@ async function createMiddleware(ctx, next) {
|
|
|
221
221
|
const filePath = (values == null ? void 0 : values.path) ?? "";
|
|
222
222
|
const filename = (values == null ? void 0 : values.filename) ?? "";
|
|
223
223
|
try {
|
|
224
|
-
(0, import_local.resolveSafePath)((0, import_local.getDocumentRoot)(storage), filePath, filename);
|
|
224
|
+
(0, import_local.resolveSafePath)((0, import_local.getDocumentRoot)(storage), (0, import_local.normalizeLocalStoragePath)(filePath), filename);
|
|
225
225
|
} catch (error) {
|
|
226
226
|
if (error.code === "PATH_TRAVERSAL") {
|
|
227
|
-
return ctx.throw(400, error);
|
|
227
|
+
return ctx.throw(400, error.message);
|
|
228
228
|
}
|
|
229
229
|
throw error;
|
|
230
230
|
}
|
|
@@ -41,11 +41,18 @@ __export(actions_exports, {
|
|
|
41
41
|
module.exports = __toCommonJS(actions_exports);
|
|
42
42
|
var import_actions = __toESM(require("@nocobase/actions"));
|
|
43
43
|
var import_attachments = require("./attachments");
|
|
44
|
+
var import_storage_validation = require("./storage-validation");
|
|
44
45
|
var storageActions = __toESM(require("./storages"));
|
|
45
46
|
function actions_default({ app }) {
|
|
46
47
|
app.resourcer.define({
|
|
47
48
|
name: "storages",
|
|
48
|
-
actions: storageActions
|
|
49
|
+
actions: storageActions,
|
|
50
|
+
middlewares: [
|
|
51
|
+
{
|
|
52
|
+
only: ["create", "update"],
|
|
53
|
+
handler: import_storage_validation.validateStorageMiddleware
|
|
54
|
+
}
|
|
55
|
+
]
|
|
49
56
|
});
|
|
50
57
|
app.resourcer.use(import_attachments.createMiddleware, { tag: "createMiddleware", after: "auth" });
|
|
51
58
|
app.resourcer.registerActionHandler("upload", import_actions.default.create);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Context, Next } from '@nocobase/actions';
|
|
10
|
+
export declare function validateStorageMiddleware(ctx: Context, next: Next): Promise<never>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var storage_validation_exports = {};
|
|
28
|
+
__export(storage_validation_exports, {
|
|
29
|
+
validateStorageMiddleware: () => validateStorageMiddleware
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(storage_validation_exports);
|
|
32
|
+
var import_local = require("../storages/local");
|
|
33
|
+
async function validateStorageMiddleware(ctx, next) {
|
|
34
|
+
const { actionName, params } = ctx.action;
|
|
35
|
+
const values = params.values || {};
|
|
36
|
+
let storage = values;
|
|
37
|
+
const hasSubmittedDocumentRoot = Object.prototype.hasOwnProperty.call(values.options || {}, "documentRoot");
|
|
38
|
+
if (actionName === "update" && params.filterByTk) {
|
|
39
|
+
const repository = ctx.db.getRepository("storages");
|
|
40
|
+
let existing = await repository.findById(params.filterByTk);
|
|
41
|
+
if (!existing) {
|
|
42
|
+
existing = await repository.findOne({
|
|
43
|
+
filter: {
|
|
44
|
+
name: params.filterByTk
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (existing) {
|
|
49
|
+
const existingValues = existing.toJSON();
|
|
50
|
+
storage = {
|
|
51
|
+
...existingValues,
|
|
52
|
+
...values,
|
|
53
|
+
options: {
|
|
54
|
+
...existingValues.options || {},
|
|
55
|
+
...values.options || {}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
(0, import_local.validateLocalStorageConfig)(storage, { validateDocumentRoot: hasSubmittedDocumentRoot });
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error.code === "PATH_TRAVERSAL") {
|
|
64
|
+
return ctx.throw(400, error.message);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
await next();
|
|
69
|
+
}
|
|
70
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
71
|
+
0 && (module.exports = {
|
|
72
|
+
validateStorageMiddleware
|
|
73
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Application } from '@nocobase/server';
|
|
10
|
+
import { AttachmentModel, StorageClassType, StorageModel } from '../storages';
|
|
11
|
+
export type RepairFilenameStatus = 'pending' | 'repaired' | 'skipped' | 'failed';
|
|
12
|
+
export interface RepairFilenameItem {
|
|
13
|
+
collectionName: string;
|
|
14
|
+
id: number | string;
|
|
15
|
+
storageId: number | string;
|
|
16
|
+
storageType: string;
|
|
17
|
+
oldPath: string;
|
|
18
|
+
oldFilename: string;
|
|
19
|
+
newPath: string;
|
|
20
|
+
newFilename: string;
|
|
21
|
+
oldKey: string;
|
|
22
|
+
newKey: string;
|
|
23
|
+
sourceExists?: boolean;
|
|
24
|
+
targetExists?: boolean;
|
|
25
|
+
status: RepairFilenameStatus;
|
|
26
|
+
reason?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface RepairFilenamesOptions {
|
|
29
|
+
apply?: boolean;
|
|
30
|
+
batchSize?: number;
|
|
31
|
+
limit?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface RepairFilenamesResult {
|
|
34
|
+
dryRun: boolean;
|
|
35
|
+
scanned: number;
|
|
36
|
+
candidates: RepairFilenameItem[];
|
|
37
|
+
repaired: RepairFilenameItem[];
|
|
38
|
+
skipped: RepairFilenameItem[];
|
|
39
|
+
failed: RepairFilenameItem[];
|
|
40
|
+
}
|
|
41
|
+
interface FileManagerLike {
|
|
42
|
+
storageTypes: {
|
|
43
|
+
get(type: string): StorageClassType | undefined;
|
|
44
|
+
};
|
|
45
|
+
loadStorages(): Promise<void>;
|
|
46
|
+
storagesCache: Map<number | string, StorageModel>;
|
|
47
|
+
}
|
|
48
|
+
export declare function replaceInvisibleChars(value?: string | null): string;
|
|
49
|
+
export declare function getRepairedAttachmentValues(record: Pick<AttachmentModel, 'path' | 'filename'>): {
|
|
50
|
+
path: string;
|
|
51
|
+
filename: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function repairAttachmentFilenames(app: Application, fileManager: FileManagerLike, options?: RepairFilenamesOptions): Promise<RepairFilenamesResult>;
|
|
54
|
+
export declare function registerRepairFilenamesCommand(app: Application): void;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var repair_filenames_exports = {};
|
|
28
|
+
__export(repair_filenames_exports, {
|
|
29
|
+
getRepairedAttachmentValues: () => getRepairedAttachmentValues,
|
|
30
|
+
registerRepairFilenamesCommand: () => registerRepairFilenamesCommand,
|
|
31
|
+
repairAttachmentFilenames: () => repairAttachmentFilenames,
|
|
32
|
+
replaceInvisibleChars: () => replaceInvisibleChars
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(repair_filenames_exports);
|
|
35
|
+
var import_sequelize = require("sequelize");
|
|
36
|
+
var import_utils = require("../utils");
|
|
37
|
+
function containsInvisibleChars(value) {
|
|
38
|
+
return Array.from(value || "").some((char) => {
|
|
39
|
+
const code = char.charCodeAt(0);
|
|
40
|
+
return code <= 31 || code >= 127 && code <= 159;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function replaceInvisibleChars(value) {
|
|
44
|
+
return Array.from(value || "").map((char) => {
|
|
45
|
+
const code = char.charCodeAt(0);
|
|
46
|
+
return code <= 31 || code >= 127 && code <= 159 ? "-" : char;
|
|
47
|
+
}).join("");
|
|
48
|
+
}
|
|
49
|
+
function getRepairedAttachmentValues(record) {
|
|
50
|
+
return {
|
|
51
|
+
path: replaceInvisibleChars(record.path),
|
|
52
|
+
filename: replaceInvisibleChars(record.filename)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function updateUrlValue(url, oldKey, newKey) {
|
|
56
|
+
if (!url) {
|
|
57
|
+
return url;
|
|
58
|
+
}
|
|
59
|
+
const encodedOldKey = oldKey.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
60
|
+
const encodedNewKey = newKey.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
61
|
+
return url.split(oldKey).join(newKey).split(encodedOldKey).join(encodedNewKey);
|
|
62
|
+
}
|
|
63
|
+
function formatItem(item) {
|
|
64
|
+
return {
|
|
65
|
+
collectionName: item.collectionName,
|
|
66
|
+
id: item.id,
|
|
67
|
+
storageId: item.storageId,
|
|
68
|
+
storageType: item.storageType,
|
|
69
|
+
oldKey: item.oldKey,
|
|
70
|
+
newKey: item.newKey,
|
|
71
|
+
sourceExists: item.sourceExists,
|
|
72
|
+
targetExists: item.targetExists,
|
|
73
|
+
status: item.status,
|
|
74
|
+
reason: item.reason
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function getFileCollectionNames(app) {
|
|
78
|
+
var _a;
|
|
79
|
+
const repository = app.db.getRepository("collections") || ((_a = app.db.getCollection("collections")) == null ? void 0 : _a.repository);
|
|
80
|
+
if (repository) {
|
|
81
|
+
const collections = await repository.find({
|
|
82
|
+
filter: {
|
|
83
|
+
"options.template": "file"
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return Array.from(/* @__PURE__ */ new Set(["attachments", ...collections.map((collection) => collection.get("name"))]));
|
|
87
|
+
}
|
|
88
|
+
return Array.from(
|
|
89
|
+
/* @__PURE__ */ new Set([
|
|
90
|
+
"attachments",
|
|
91
|
+
...Array.from(app.db.collections.values()).filter((collection) => collection.options.template === "file").map((collection) => collection.name)
|
|
92
|
+
])
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
async function loadFileCollections(app) {
|
|
96
|
+
var _a, _b;
|
|
97
|
+
const collection = app.db.getCollection("collections");
|
|
98
|
+
if (!collection) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const repository = collection.repository;
|
|
102
|
+
await ((_a = repository.setApp) == null ? void 0 : _a.call(repository, app));
|
|
103
|
+
await ((_b = repository.load) == null ? void 0 : _b.call(repository));
|
|
104
|
+
}
|
|
105
|
+
async function repairCollectionAttachmentFilenames({
|
|
106
|
+
app,
|
|
107
|
+
fileManager,
|
|
108
|
+
collectionName,
|
|
109
|
+
result,
|
|
110
|
+
apply,
|
|
111
|
+
batchSize,
|
|
112
|
+
limit
|
|
113
|
+
}) {
|
|
114
|
+
const collection = app.db.getCollection(collectionName);
|
|
115
|
+
if (!collection) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const Model = collection.model;
|
|
119
|
+
let lastId = null;
|
|
120
|
+
while (result.scanned < limit) {
|
|
121
|
+
const rows = await Model.findAll({
|
|
122
|
+
attributes: ["id", "path", "filename", "storageId", "url"],
|
|
123
|
+
where: lastId ? { id: { [import_sequelize.Op.gt]: lastId } } : void 0,
|
|
124
|
+
order: [["id", "ASC"]],
|
|
125
|
+
limit: Math.min(batchSize, limit - result.scanned)
|
|
126
|
+
});
|
|
127
|
+
if (!rows.length) {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
for (const row of rows) {
|
|
131
|
+
result.scanned += 1;
|
|
132
|
+
lastId = row.get("id");
|
|
133
|
+
const record = row.toJSON();
|
|
134
|
+
if (!containsInvisibleChars(record.path) && !containsInvisibleChars(record.filename)) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const storage = fileManager.storagesCache.get(record.storageId);
|
|
138
|
+
const { path: newPath, filename: newFilename } = getRepairedAttachmentValues(record);
|
|
139
|
+
const oldKey = (0, import_utils.getFileKey)(record);
|
|
140
|
+
const newRecord = { ...record, path: newPath, filename: newFilename };
|
|
141
|
+
const newKey = (0, import_utils.getFileKey)(newRecord);
|
|
142
|
+
const item = {
|
|
143
|
+
collectionName,
|
|
144
|
+
id: lastId,
|
|
145
|
+
storageId: record.storageId,
|
|
146
|
+
storageType: (storage == null ? void 0 : storage.type) || "",
|
|
147
|
+
oldPath: record.path || "",
|
|
148
|
+
oldFilename: record.filename,
|
|
149
|
+
newPath,
|
|
150
|
+
newFilename,
|
|
151
|
+
oldKey,
|
|
152
|
+
newKey,
|
|
153
|
+
status: "pending"
|
|
154
|
+
};
|
|
155
|
+
result.candidates.push(item);
|
|
156
|
+
if (!storage) {
|
|
157
|
+
item.status = "skipped";
|
|
158
|
+
item.reason = "storage_not_found";
|
|
159
|
+
result.skipped.push(item);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (oldKey === newKey) {
|
|
163
|
+
item.status = "skipped";
|
|
164
|
+
item.reason = "unchanged";
|
|
165
|
+
result.skipped.push(item);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const StorageClass = fileManager.storageTypes.get(storage.type);
|
|
170
|
+
if (!StorageClass) {
|
|
171
|
+
item.status = "skipped";
|
|
172
|
+
item.reason = "storage_type_not_found";
|
|
173
|
+
result.skipped.push(item);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const storageInstance = new StorageClass(storage);
|
|
177
|
+
item.sourceExists = await storageInstance.exists(record);
|
|
178
|
+
if (!item.sourceExists) {
|
|
179
|
+
item.status = "skipped";
|
|
180
|
+
item.reason = "source_not_found";
|
|
181
|
+
result.skipped.push(item);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
item.targetExists = await storageInstance.exists(newRecord);
|
|
185
|
+
if (item.targetExists) {
|
|
186
|
+
item.status = "skipped";
|
|
187
|
+
item.reason = "target_exists";
|
|
188
|
+
result.skipped.push(item);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (apply) {
|
|
192
|
+
await storageInstance.copy(record, newRecord);
|
|
193
|
+
await row.update({
|
|
194
|
+
path: newPath,
|
|
195
|
+
filename: newFilename,
|
|
196
|
+
url: updateUrlValue(record.url, oldKey, newKey)
|
|
197
|
+
});
|
|
198
|
+
try {
|
|
199
|
+
const [deleted] = await storageInstance.delete([record]);
|
|
200
|
+
if (!deleted) {
|
|
201
|
+
item.reason = "delete_old_failed";
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
item.reason = `delete_old_failed: ${error.message}`;
|
|
205
|
+
}
|
|
206
|
+
item.status = "repaired";
|
|
207
|
+
result.repaired.push(item);
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
item.status = "failed";
|
|
211
|
+
item.reason = error.message;
|
|
212
|
+
result.failed.push(item);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function repairAttachmentFilenames(app, fileManager, options = {}) {
|
|
218
|
+
const apply = !!options.apply;
|
|
219
|
+
const batchSize = options.batchSize || 500;
|
|
220
|
+
const limit = options.limit || Number.POSITIVE_INFINITY;
|
|
221
|
+
const result = {
|
|
222
|
+
dryRun: !apply,
|
|
223
|
+
scanned: 0,
|
|
224
|
+
candidates: [],
|
|
225
|
+
repaired: [],
|
|
226
|
+
skipped: [],
|
|
227
|
+
failed: []
|
|
228
|
+
};
|
|
229
|
+
if (!fileManager.storagesCache.size) {
|
|
230
|
+
await fileManager.loadStorages();
|
|
231
|
+
}
|
|
232
|
+
await loadFileCollections(app);
|
|
233
|
+
for (const collectionName of await getFileCollectionNames(app)) {
|
|
234
|
+
if (result.scanned >= limit) {
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
await repairCollectionAttachmentFilenames({
|
|
238
|
+
app,
|
|
239
|
+
fileManager,
|
|
240
|
+
collectionName,
|
|
241
|
+
result,
|
|
242
|
+
apply,
|
|
243
|
+
batchSize,
|
|
244
|
+
limit
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
function registerRepairFilenamesCommand(app) {
|
|
250
|
+
const command = app.findCommand("file-manager") || app.command("file-manager");
|
|
251
|
+
command.command("repair-filenames").preload().option("--apply", "rename objects and update attachment records").option("--batch-size [batchSize]", "batch size for scanning attachments").option("--limit [limit]", "maximum number of attachment records to scan").action(async (options) => {
|
|
252
|
+
const fileManager = app.pm.get("file-manager");
|
|
253
|
+
const result = await repairAttachmentFilenames(app, fileManager, {
|
|
254
|
+
apply: !!options.apply,
|
|
255
|
+
batchSize: options.batchSize ? Number(options.batchSize) : void 0,
|
|
256
|
+
limit: options.limit ? Number(options.limit) : void 0
|
|
257
|
+
});
|
|
258
|
+
console.log(
|
|
259
|
+
JSON.stringify(
|
|
260
|
+
{
|
|
261
|
+
dryRun: result.dryRun,
|
|
262
|
+
scanned: result.scanned,
|
|
263
|
+
candidates: result.candidates.length,
|
|
264
|
+
repaired: result.repaired.length,
|
|
265
|
+
skipped: result.skipped.length,
|
|
266
|
+
failed: result.failed.length
|
|
267
|
+
},
|
|
268
|
+
null,
|
|
269
|
+
2
|
|
270
|
+
)
|
|
271
|
+
);
|
|
272
|
+
if (result.candidates.length) {
|
|
273
|
+
console.table(result.candidates.map(formatItem));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
278
|
+
0 && (module.exports = {
|
|
279
|
+
getRepairedAttachmentValues,
|
|
280
|
+
registerRepairFilenamesCommand,
|
|
281
|
+
repairAttachmentFilenames,
|
|
282
|
+
replaceInvisibleChars
|
|
283
|
+
});
|
package/dist/server/index.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ import { StorageEngine } from 'multer';
|
|
|
10
10
|
export * from '../constants';
|
|
11
11
|
export { AttachmentModel, default, PluginFileManagerServer, StorageModel } from './server';
|
|
12
12
|
export { cloudFilenameGetter } from './utils';
|
|
13
|
-
export { StorageType } from './storages';
|
|
13
|
+
export { StorageType, GetFileStreamOptions } from './storages';
|
|
14
14
|
export { StorageEngine };
|
package/dist/server/index.js
CHANGED
|
@@ -38,6 +38,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
38
38
|
var server_exports = {};
|
|
39
39
|
__export(server_exports, {
|
|
40
40
|
AttachmentModel: () => import_server.AttachmentModel,
|
|
41
|
+
GetFileStreamOptions: () => import_storages.GetFileStreamOptions,
|
|
41
42
|
PluginFileManagerServer: () => import_server.PluginFileManagerServer,
|
|
42
43
|
StorageEngine: () => import_multer.StorageEngine,
|
|
43
44
|
StorageModel: () => import_server.StorageModel,
|
|
@@ -54,6 +55,7 @@ var import_storages = require("./storages");
|
|
|
54
55
|
// Annotate the CommonJS export names for ESM import in node:
|
|
55
56
|
0 && (module.exports = {
|
|
56
57
|
AttachmentModel,
|
|
58
|
+
GetFileStreamOptions,
|
|
57
59
|
PluginFileManagerServer,
|
|
58
60
|
StorageEngine,
|
|
59
61
|
StorageModel,
|
package/dist/server/server.d.ts
CHANGED
|
@@ -11,22 +11,25 @@ import { Model, Transactionable } from '@nocobase/database';
|
|
|
11
11
|
import { Plugin } from '@nocobase/server';
|
|
12
12
|
import { Registry } from '@nocobase/utils';
|
|
13
13
|
import { Readable } from 'stream';
|
|
14
|
-
import { AttachmentModel, StorageClassType, StorageModel } from './storages';
|
|
14
|
+
import { AttachmentModel, GetFileStreamOptions, StorageClassType, StorageModel } from './storages';
|
|
15
15
|
export type * from './storages';
|
|
16
16
|
export type FileRecordOptions = {
|
|
17
17
|
collectionName: string;
|
|
18
18
|
filePath: string;
|
|
19
19
|
storageName?: string;
|
|
20
|
+
subPath?: string;
|
|
20
21
|
values?: any;
|
|
21
22
|
} & Transactionable;
|
|
22
23
|
export type UploadFileOptions = {
|
|
23
24
|
filePath: string;
|
|
24
25
|
storageName?: string;
|
|
26
|
+
subPath?: string;
|
|
25
27
|
documentRoot?: string;
|
|
26
28
|
};
|
|
27
29
|
export declare class PluginFileManagerServer extends Plugin {
|
|
28
30
|
storageTypes: Registry<StorageClassType>;
|
|
29
31
|
storagesCache: Map<string | number, StorageModel>;
|
|
32
|
+
static staticImport(): Promise<void>;
|
|
30
33
|
afterDestroy: (record: Model, options: any) => Promise<void>;
|
|
31
34
|
registerStorageType(type: string, Type: StorageClassType): void;
|
|
32
35
|
createFileRecord(options: FileRecordOptions): Promise<any>;
|
|
@@ -50,7 +53,7 @@ export declare class PluginFileManagerServer extends Plugin {
|
|
|
50
53
|
load(): Promise<void>;
|
|
51
54
|
getFileURL(file: AttachmentModel, preview?: boolean): Promise<any>;
|
|
52
55
|
isPublicAccessStorage(storageName: any): Promise<boolean>;
|
|
53
|
-
getFileStream(file: AttachmentModel): Promise<{
|
|
56
|
+
getFileStream(file: AttachmentModel, options?: GetFileStreamOptions): Promise<{
|
|
54
57
|
stream: Readable;
|
|
55
58
|
contentType?: string;
|
|
56
59
|
}>;
|
package/dist/server/server.js
CHANGED
|
@@ -54,6 +54,7 @@ var import_local = __toESM(require("./storages/local"));
|
|
|
54
54
|
var import_s3 = __toESM(require("./storages/s3"));
|
|
55
55
|
var import_tx_cos = __toESM(require("./storages/tx-cos"));
|
|
56
56
|
var import_utils2 = require("./utils");
|
|
57
|
+
var import_repair_filenames = require("./commands/repair-filenames");
|
|
57
58
|
const DEFAULT_STORAGE_TYPE = import_constants.STORAGE_TYPE_LOCAL;
|
|
58
59
|
class FileDeleteError extends Error {
|
|
59
60
|
data;
|
|
@@ -66,6 +67,9 @@ class FileDeleteError extends Error {
|
|
|
66
67
|
class PluginFileManagerServer extends import_server.Plugin {
|
|
67
68
|
storageTypes = new import_utils.Registry();
|
|
68
69
|
storagesCache = /* @__PURE__ */ new Map();
|
|
70
|
+
static async staticImport() {
|
|
71
|
+
import_server.Application.addCommand(import_repair_filenames.registerRepairFilenamesCommand);
|
|
72
|
+
}
|
|
69
73
|
afterDestroy = async (record, options) => {
|
|
70
74
|
var _a;
|
|
71
75
|
const { collection } = record.constructor;
|
|
@@ -96,29 +100,34 @@ class PluginFileManagerServer extends import_server.Plugin {
|
|
|
96
100
|
this.storageTypes.register(type, Type);
|
|
97
101
|
}
|
|
98
102
|
async createFileRecord(options) {
|
|
99
|
-
const { values, storageName, collectionName, filePath, transaction } = options;
|
|
103
|
+
const { values, storageName, subPath, collectionName, filePath, transaction } = options;
|
|
100
104
|
const collection = this.db.getCollection(collectionName);
|
|
101
105
|
if (!collection) {
|
|
102
106
|
throw new Error(`collection does not exist`);
|
|
103
107
|
}
|
|
104
108
|
const collectionRepository = this.db.getRepository(collectionName);
|
|
105
109
|
const name = storageName || collection.options.storage;
|
|
106
|
-
const data = await this.uploadFile({ storageName: name, filePath });
|
|
110
|
+
const data = await this.uploadFile({ storageName: name, subPath, filePath });
|
|
107
111
|
return await collectionRepository.create({ values: { ...data, ...values }, transaction });
|
|
108
112
|
}
|
|
109
113
|
parseStorage(instance) {
|
|
110
114
|
return this.app.environment.renderJsonTemplate(instance.toJSON());
|
|
111
115
|
}
|
|
112
116
|
async uploadFile(options) {
|
|
113
|
-
const { storageName, filePath, documentRoot } = options;
|
|
117
|
+
const { storageName, subPath, filePath, documentRoot } = options;
|
|
114
118
|
if (!this.storagesCache.size) {
|
|
115
119
|
await this.loadStorages();
|
|
116
120
|
}
|
|
117
121
|
const storages = Array.from(this.storagesCache.values());
|
|
118
|
-
const
|
|
119
|
-
if (!
|
|
122
|
+
const cachedStorage = storages.find((item) => item.name === storageName) || storages.find((item) => item.default);
|
|
123
|
+
if (!cachedStorage) {
|
|
120
124
|
throw new Error("[file-manager] no linked or default storage provided");
|
|
121
125
|
}
|
|
126
|
+
const storage = {
|
|
127
|
+
...cachedStorage,
|
|
128
|
+
options: { ...cachedStorage.options || {} },
|
|
129
|
+
path: (0, import_utils2.resolveStoragePath)(cachedStorage.path, subPath)
|
|
130
|
+
};
|
|
122
131
|
const fileStream = import_fs.default.createReadStream(filePath);
|
|
123
132
|
if (documentRoot) {
|
|
124
133
|
storage.options["documentRoot"] = documentRoot;
|
|
@@ -212,6 +221,9 @@ class PluginFileManagerServer extends import_server.Plugin {
|
|
|
212
221
|
this.storageTypes.register(import_constants.STORAGE_TYPE_S3, import_s3.default);
|
|
213
222
|
this.storageTypes.register(import_constants.STORAGE_TYPE_TX_COS, import_tx_cos.default);
|
|
214
223
|
const Storage = this.db.getModel("storages");
|
|
224
|
+
Storage.beforeSave((m) => {
|
|
225
|
+
(0, import_local.validateLocalStorageConfig)(m.toJSON());
|
|
226
|
+
});
|
|
215
227
|
Storage.afterSave(async (m, { transaction }) => {
|
|
216
228
|
await this.loadStorages({ transaction });
|
|
217
229
|
this.sendSyncMessage({ type: "reloadStorages" }, { transaction });
|
|
@@ -324,7 +336,7 @@ class PluginFileManagerServer extends import_server.Plugin {
|
|
|
324
336
|
}
|
|
325
337
|
return !!((_a = storage.options) == null ? void 0 : _a.public);
|
|
326
338
|
}
|
|
327
|
-
async getFileStream(file) {
|
|
339
|
+
async getFileStream(file, options) {
|
|
328
340
|
if (!file.storageId) {
|
|
329
341
|
throw new Error("File storageId not found");
|
|
330
342
|
}
|
|
@@ -340,7 +352,7 @@ class PluginFileManagerServer extends import_server.Plugin {
|
|
|
340
352
|
if (!storageInstance) {
|
|
341
353
|
throw new Error(`[file-manager] storage type "${storage.type}" is not defined`);
|
|
342
354
|
}
|
|
343
|
-
return storageInstance.getFileStream(file);
|
|
355
|
+
return storageInstance.getFileStream(file, options);
|
|
344
356
|
}
|
|
345
357
|
}
|
|
346
358
|
var server_default = PluginFileManagerServer;
|
|
@@ -18,7 +18,7 @@ declare class AliYunOssStorage {
|
|
|
18
18
|
filename?: typeof getRandomFilename;
|
|
19
19
|
});
|
|
20
20
|
_handleFile(req: any, file: any, cb: any): any;
|
|
21
|
-
_removeFile(req: any, file: any, cb: any): any
|
|
21
|
+
_removeFile(req: any, file: any, cb: any): Promise<any>;
|
|
22
22
|
}
|
|
23
23
|
export default class extends StorageType {
|
|
24
24
|
static defaults(): {
|
|
@@ -34,6 +34,8 @@ export default class extends StorageType {
|
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
36
|
make(): AliYunOssStorage;
|
|
37
|
+
exists(record: AttachmentModel): Promise<boolean>;
|
|
38
|
+
copy(source: AttachmentModel, target: AttachmentModel): Promise<void>;
|
|
37
39
|
delete(records: AttachmentModel[]): Promise<[number, AttachmentModel[]]>;
|
|
38
40
|
}
|
|
39
41
|
export {};
|