diff --git a/packages/nc-gui/components/project/spreadsheet/components/editableCell/editableAttachmentCell.vue b/packages/nc-gui/components/project/spreadsheet/components/editableCell/editableAttachmentCell.vue index e96d5f45fe..ad4c439a74 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/editableCell/editableAttachmentCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/editableCell/editableAttachmentCell.vue @@ -333,14 +333,14 @@ export default { this.uploading = true for (const file of this.$refs.file.files) { try { - const data = await this.$api.dbViewRow.upload( - 'noco', - this.projectName, - this.meta.title, - this.column.title, { + const data = await this.$api.storage.upload( + { + path: ['noco', this.projectName, this.meta.title, this.column.title].join('/') + }, { files: file, json: '{}' - }) + } + ) this.localState.push(...data) } catch (e) { diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index d3f6fcf87e..d94d2297f3 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -2778,30 +2778,6 @@ export class Api< wrapped: true, ...params, }), - - /** - * No description - * - * @tags DB View row - * @name Upload - * @summary Attachment - * @request POST:/api/v1/db/data-attachment/{orgs}/{projectName}/{tableName}/{columnName} - */ - upload: ( - orgs: string, - projectName: string, - tableName: string, - columnName: string, - data: { files?: any; json?: string }, - params: RequestParams = {} - ) => - this.request({ - path: `/api/v1/db/data-attachment/${orgs}/${projectName}/${tableName}/${columnName}`, - method: 'POST', - body: data, - type: ContentType.FormData, - ...params, - }), }; public = { /** @@ -3355,4 +3331,27 @@ export class Api< ...params, }), }; + storage = { + /** + * No description + * + * @tags Storage + * @name Upload + * @summary Attachment + * @request POST:/api/v1/db/storage/upload + */ + upload: ( + query: { path: string }, + data: { files?: any; json?: string }, + params: RequestParams = {} + ) => + this.request({ + path: `/api/v1/db/storage/upload`, + method: 'POST', + query: query, + body: data, + type: ContentType.FormData, + ...params, + }), + }; } diff --git a/packages/nocodb/src/lib/noco/meta/api/attachmentApis.ts b/packages/nocodb/src/lib/noco/meta/api/attachmentApis.ts index 386e59d0a6..6464f4f7a6 100644 --- a/packages/nocodb/src/lib/noco/meta/api/attachmentApis.ts +++ b/packages/nocodb/src/lib/noco/meta/api/attachmentApis.ts @@ -12,12 +12,9 @@ import NcPluginMgrv2 from '../helpers/NcPluginMgrv2'; // const storageAdapter = new Local(); export async function upload(req: Request, res: Response) { - const filePath = sanitizeUrlPath([ - req.params.orgs, - req.params.projectName, - req.params.tableName, - req.params.columnName - ]); + const filePath = sanitizeUrlPath( + req.query?.path?.toString()?.split('/') || [''] + ); const destPath = path.join('nc', 'uploads', ...filePath); const storageAdapter = await NcPluginMgrv2.storageAdapter(); @@ -31,9 +28,9 @@ export async function upload(req: Request, res: Response) { ); if (!url) { - url = `${ - (req as any).ncSiteUrl - }/api/v1/db/data-attachment/${filePath.join('/')}/${fileName}`; + url = `${(req as any).ncSiteUrl}/download/${filePath.join( + '/' + )}/${fileName}`; } return { @@ -53,11 +50,11 @@ export async function upload(req: Request, res: Response) { export async function fileRead(req, res) { try { const storageAdapter = await NcPluginMgrv2.storageAdapter(); - // const type = mimetypes[path.extname(req.params.fileName).slice(1)] || 'text/plain'; + // const type = mimetypes[path.extname(req.s.fileName).slice(1)] || 'text/plain'; const type = mimetypes[ path - .extname(req.params.fileName) + .extname(req.params?.[0]) .split('/') .pop() .slice(1) @@ -68,11 +65,10 @@ export async function fileRead(req, res) { path.join( 'nc', 'uploads', - req.params.orgs, - req.params.projectName, - req.params.tableName, - req.params.columnName, - req.params.fileName + req.params?.[0] + ?.split('/') + .filter(p => p !== '..') + .join('/') ) ) ); @@ -122,15 +118,12 @@ export function sanitizeUrlPath(paths) { } router.post( - '/api/v1/db/data-attachment/:orgs/:projectName/:tableName/:columnName', + '/api/v1/db/storage/upload', multer({ storage: multer.diskStorage({}) }).any(), ncMetaAclMw(upload, 'upload') ); -router.get( - '/api/v1/db/data-attachment/:orgs/:projectName/:tableName/:columnName/:fileName', - catchError(fileRead) -); +router.get(/^\/download\/(.+)$/, catchError(fileRead)); export default router; diff --git a/packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts b/packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts index 328ce70a8e..6e00734fb5 100644 --- a/packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts +++ b/packages/nocodb/src/lib/noco/meta/api/publicApis/publicDataApis.ts @@ -141,9 +141,9 @@ async function dataInsert( ); if (!url) { - url = `${ - (req as any).ncSiteUrl - }/api/v1/db/data-attachment/${filePath.join('/')}/${fileName}`; + url = `${(req as any).ncSiteUrl}/download/${filePath.join( + '/' + )}/${fileName}`; } attachments[fieldName].push({ diff --git a/packages/nocodb/src/lib/utils/projectAcl.ts b/packages/nocodb/src/lib/utils/projectAcl.ts index a86c8818d1..9fac3569e0 100644 --- a/packages/nocodb/src/lib/utils/projectAcl.ts +++ b/packages/nocodb/src/lib/utils/projectAcl.ts @@ -208,7 +208,9 @@ export default { passwordChange: true, projectList: true }, + super: '*', user: { + upload: true, passwordChange: true, pluginList: true, pluginRead: true, diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index 6aca38d910..3f9a249878 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -3282,68 +3282,6 @@ } }, - "/api/v1/db/data-attachment/{orgs}/{projectName}/{tableName}/{columnName}": { - "post": { - "summary": "Attachment", - "operationId": "db-view-row-upload", - "responses": {}, - "tags": [ - "DB View row" - ], - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "files": {}, - "json": { - "type": "string" - } - } - } - } - }, - "description": "" - } - }, - "parameters": [ - { - "schema": { - "type": "string" - }, - "name": "orgs", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "projectName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "tableName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "columnName", - "in": "path", - "required": true - } - ] - }, - - "/api/v1/db/public/shared-view/{sharedViewUuid}/rows": { "parameters": [ { @@ -4749,6 +4687,43 @@ "DB Table Row" ] } + }, + + "/api/v1/db/storage/upload": { + "post": { + "summary": "Attachment", + "operationId": "storage-upload", + "responses": {}, + "tags": [ + "Storage" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "files": {}, + "json": { + "type": "string" + } + } + } + } + }, + "description": "" + }, + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "path", + "in": "query", + "required": true + } + ] + } } }, "components": {