From 1c3ac35ed1a5c6671bf68d7d2a50fb34fc1e3050 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:32:49 +0700 Subject: [PATCH 1/2] refactor: get index from .env --- .../server/src/controllers/fileController.ts | 20 +++++++++---------- .../src/controllers/searchController.ts | 2 +- .../controllers/subFolderFileController.ts | 20 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Services/server/src/controllers/fileController.ts b/Services/server/src/controllers/fileController.ts index 8c5fb09..6fb9393 100644 --- a/Services/server/src/controllers/fileController.ts +++ b/Services/server/src/controllers/fileController.ts @@ -58,7 +58,7 @@ export class FileController extends Controller { if (!info) throw new Error("Object storage error occured."); const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: pathname, @@ -82,7 +82,7 @@ export class FileController extends Controller { if (!exist) { await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), createdAt: new Date().toISOString(), @@ -96,7 +96,7 @@ export class FileController extends Controller { await esClient.delete({ index: exist._index, id: exist._id }); await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), createdAt: exist._source?.createdAt, @@ -124,7 +124,7 @@ export class FileController extends Controller { attachment: Record; } >({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { prefix: { pathname: `${cabinetName}/${drawerName}/${folderName}/`, @@ -163,7 +163,7 @@ export class FileController extends Controller { @FormField() category?: string, ) { const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${fileName}`, @@ -180,7 +180,7 @@ export class FileController extends Controller { if (!file) { const esResult = await esClient .update({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', id: data._id, doc: { title, @@ -216,7 +216,7 @@ export class FileController extends Controller { await esClient.delete({ index: data._index, id: data._id }); await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), pathname, @@ -253,7 +253,7 @@ export class FileController extends Controller { attachment: Record; } >({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${fileName}`, @@ -267,7 +267,7 @@ export class FileController extends Controller { const esResult = await esClient .delete({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', id: search.hits.hits[0]._id, }) .catch((e) => console.error(e)); @@ -289,7 +289,7 @@ export class FileController extends Controller { @Path() fileName: string, ) { const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${fileName}`, diff --git a/Services/server/src/controllers/searchController.ts b/Services/server/src/controllers/searchController.ts index 08a7b25..5edb848 100644 --- a/Services/server/src/controllers/searchController.ts +++ b/Services/server/src/controllers/searchController.ts @@ -11,7 +11,7 @@ export class SearchController extends Controller { @SuccessResponse(HttpStatusCode.OK) public async searchFile(@Body() search: Search): Promise { const result = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { bool: { must: search.AND?.map((v) => ({ match: { [v.field]: v.value } })), diff --git a/Services/server/src/controllers/subFolderFileController.ts b/Services/server/src/controllers/subFolderFileController.ts index 4162877..af513d9 100644 --- a/Services/server/src/controllers/subFolderFileController.ts +++ b/Services/server/src/controllers/subFolderFileController.ts @@ -61,7 +61,7 @@ export class SubFolderFileController extends Controller { if (!info) throw new Error("Object storage error occured."); const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: pathname, @@ -85,7 +85,7 @@ export class SubFolderFileController extends Controller { if (!exist) { await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), createdAt: new Date().toISOString(), @@ -99,7 +99,7 @@ export class SubFolderFileController extends Controller { await esClient.delete({ index: exist._index, id: exist._id }); await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), createdAt: exist._source?.createdAt, @@ -128,7 +128,7 @@ export class SubFolderFileController extends Controller { attachment: Record; } >({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { prefix: { pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}`, @@ -168,7 +168,7 @@ export class SubFolderFileController extends Controller { @FormField() category?: string, ) { const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, @@ -185,7 +185,7 @@ export class SubFolderFileController extends Controller { if (!file) { const esResult = await esClient .update({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', id: data._id, doc: { title, @@ -221,7 +221,7 @@ export class SubFolderFileController extends Controller { await esClient.delete({ index: data._index, id: data._id }); await esClient.index({ pipeline: "attachment", - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', document: { data: Buffer.from(file.buffer).toString("base64"), pathname, @@ -259,7 +259,7 @@ export class SubFolderFileController extends Controller { attachment: Record; } >({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, @@ -273,7 +273,7 @@ export class SubFolderFileController extends Controller { const esResult = await esClient .delete({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', id: search.hits.hits[0]._id, }) .catch((e) => console.error(e)); @@ -299,7 +299,7 @@ export class SubFolderFileController extends Controller { @Path() fileName: string, ) { const search = await esClient.search }>({ - index: "ehr-api-client", + index: process.env.ELASTICSEARCH_INDEX ?? 'ehr-index', query: { match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, From adfb70b578ad74dd38502c2756eab434a9e81412 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:34:26 +0700 Subject: [PATCH 2/2] fix: response does not wait process to finish --- .../src/controllers/cabinetController.ts | 80 ++++++++++++----- .../src/controllers/drawerController.ts | 80 +++++++++++------ .../src/controllers/folderController.ts | 85 +++++++++++------- .../src/controllers/subFolderController.ts | 87 +++++++++++-------- Services/server/src/middlewares/exception.ts | 2 +- Services/server/src/routes.ts | 14 +-- Services/server/src/swagger.json | 28 ++---- Services/server/src/utils/minio.ts | 21 ++++- 8 files changed, 253 insertions(+), 144 deletions(-) diff --git a/Services/server/src/controllers/cabinetController.ts b/Services/server/src/controllers/cabinetController.ts index e7e7102..655ce60 100644 --- a/Services/server/src/controllers/cabinetController.ts +++ b/Services/server/src/controllers/cabinetController.ts @@ -15,17 +15,24 @@ import { import * as Minio from "minio"; import minioClient from "../storage"; -import { EhrFolder } from "../interfaces/ehr-fs"; +import { EhrFile, EhrFolder } from "../interfaces/ehr-fs"; import HttpStatusCode from "../interfaces/http-status"; -import { listFolder, replaceIllegalChars } from "../utils/minio"; +import { listFolder, listItem, replaceIllegalChars } from "../utils/minio"; +import esClient from "../elasticsearch"; @Route("cabinet") export class CabinetController extends Controller { @Get("/") @Tags("Cabinet") @SuccessResponse(HttpStatusCode.OK) - public listCabinet(): Promise { - return listFolder(); + public async listCabinet(): Promise { + const list = await listFolder().catch((e) => console.error(`Error List Folder: ${e}`)); + + if (!list) { + throw new Error("Error listing folder"); + } + + return list; } @Post("/") @@ -56,32 +63,57 @@ export class CabinetController extends Controller { @Path() cabinetName: string, @Body() body: { name: string }, ): Promise { - return new Promise((resolve, reject) => { - const stream = minioClient.listObjectsV2("ehr", `${cabinetName}/`, true); + const list = await listItem(`${cabinetName}/`, true); - stream.on("data", (v) => { - if (!(v && v.name)) return; + const cond = new Minio.CopyConditions(); - const destination = `${replaceIllegalChars(body.name)}/${v.name.slice( + await Promise.all( + list.map(async (current) => { + if (!current.name) return; + + const destination = `${replaceIllegalChars(body.name)}/${current.name.slice( cabinetName.length + 1, )}`; - const source = `/ehr/${v.name}`; - const cond = new Minio.CopyConditions(); + const source = `/ehr/${current.name}`; - minioClient.copyObject("ehr", destination, source, cond, (e) => { - if (e) { - return reject(new Error("Failed to move.")); - } - return minioClient.removeObject("ehr", v.name); - }); - }); + return await minioClient + .copyObject("ehr", destination, source, cond) + .then(async () => { + if (!current.name) return; - stream.on("end", () => { - this.setStatus(HttpStatusCode.NO_CONTENT); - resolve(); - }); - stream.on("error", () => reject(new Error("Object storage error occured."))); - }); + await minioClient.removeObject("ehr", current.name); + + if (current.name.includes(".keep")) return; + + const search = await esClient.search }>({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + query: { + match: { + pathname: current.name, + }, + }, + }); + + if (search && search.hits.hits.length === 0) { + throw new Error("Data cannot be found in database."); + } + + const data = search.hits.hits[0]; + + await esClient.update({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + id: data._id, + doc: { pathname: destination }, + }); + }) + .catch((e) => { + console.error(e); + throw new Error("Failed to move."); + }); + }), + ); + + return this.setStatus(HttpStatusCode.NO_CONTENT); } @Delete("/{cabinetName}") diff --git a/Services/server/src/controllers/drawerController.ts b/Services/server/src/controllers/drawerController.ts index 6fe5d21..08b512e 100644 --- a/Services/server/src/controllers/drawerController.ts +++ b/Services/server/src/controllers/drawerController.ts @@ -17,15 +17,23 @@ import minioClient from "../storage"; import HttpStatusCode from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -import { listFolder, pathExist, replaceIllegalChars } from "../utils/minio"; +import { listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; +import esClient from "../elasticsearch"; +import { EhrFile, EhrFolder } from "../interfaces/ehr-fs"; @Route("/cabinet/{cabinetName}/drawer") export class DrawerController extends Controller { @Get("/") @Tags("Drawer") @SuccessResponse(HttpStatusCode.OK) - public listDrawer(@Path() cabinetName: string) { - return listFolder(`${cabinetName}/`); + public async listDrawer(@Path() cabinetName: string): Promise { + const fullpath = [cabinetName, ""].join("/"); + + if (!(await pathExist(fullpath))) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "Provided path does not exist."); + } + + return listFolder(fullpath); } @Post("/") @@ -66,35 +74,57 @@ export class DrawerController extends Controller { ): Promise { const fullpath = `${cabinetName}/${drawerName}/`; - if (!(await pathExist(fullpath))) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "Resource cannot be found."); - } + const list = await listItem(fullpath, true); - return new Promise((resolve, reject) => { - const stream = minioClient.listObjectsV2("ehr", fullpath, true); + const cond = new Minio.CopyConditions(); - stream.on("data", (v) => { - if (!(v && v.name)) return; + await Promise.all( + list.map(async (current) => { + if (!current.name) return; - const destination = `${cabinetName}/${replaceIllegalChars(body.name)}/${v.name.slice( + const destination = `${cabinetName}/${replaceIllegalChars(body.name)}/${current.name.slice( fullpath.length, )}`; - const source = `/ehr/${v.name}`; - const cond = new Minio.CopyConditions(); + const source = `/ehr/${current.name}`; - minioClient.copyObject("ehr", destination, source, cond, (e) => { - if (e) { - return reject(new Error("Failed to move.")); - } - return minioClient.removeObject("ehr", v.name); - }); - }); + return await minioClient + .copyObject("ehr", destination, source, cond) + .then(async () => { + if (!current.name) return; - stream.on("end", () => { - resolve(this.setStatus(HttpStatusCode.NO_CONTENT)); - }); - stream.on("error", () => reject(new Error("Object storage error occured."))); - }); + await minioClient.removeObject("ehr", current.name); + + if (current.name.includes(".keep")) return; + + const search = await esClient.search }>({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + query: { + match: { + pathname: current.name, + }, + }, + }); + + if (search && search.hits.hits.length === 0) { + throw new Error("Data cannot be found in database."); + } + + const data = search.hits.hits[0]; + + await esClient.update({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + id: data._id, + doc: { pathname: destination }, + }); + }) + .catch((e) => { + console.error(e); + throw new Error("Failed to move."); + }); + }), + ); + + return this.setStatus(HttpStatusCode.NO_CONTENT); } @Delete("/{drawerName}") diff --git a/Services/server/src/controllers/folderController.ts b/Services/server/src/controllers/folderController.ts index 5c7c35d..a0bb938 100644 --- a/Services/server/src/controllers/folderController.ts +++ b/Services/server/src/controllers/folderController.ts @@ -6,7 +6,6 @@ import { Path, Post, Put, - Query, Request, Route, Security, @@ -17,9 +16,10 @@ import * as Minio from "minio"; import HttpError from "../interfaces/http-error"; import HttpStatusCode from "../interfaces/http-status"; -import { listFolder, pathExist, replaceIllegalChars } from "../utils/minio"; -import { EhrFolder } from "../interfaces/ehr-fs"; +import { listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; +import { EhrFile, EhrFolder } from "../interfaces/ehr-fs"; import minioClient from "../storage"; +import esClient from "../elasticsearch"; @Route("/cabinet/{cabinetName}/drawer/{drawerName}/folder") export class FolderController extends Controller { @@ -30,7 +30,7 @@ export class FolderController extends Controller { @Path() cabinetName: string, @Path() drawerName: string, ): Promise { - const fullpath = [cabinetName, drawerName].join("/") + "/"; + const fullpath = [cabinetName, drawerName, ""].join("/"); if (!(await pathExist(fullpath))) { throw new HttpError(HttpStatusCode.NOT_FOUND, "Provided path does not exist."); @@ -79,44 +79,63 @@ export class FolderController extends Controller { @SuccessResponse(HttpStatusCode.NO_CONTENT) public async editFolder( @Body() body: { name: string }, - @Query() cabinetName: string, - @Query() drawerName: string, - @Query() folderName: string, + @Path() cabinetName: string, + @Path() drawerName: string, + @Path() folderName: string, ) { - const fullpath = [cabinetName, drawerName, folderName].join("/") + "/"; + const fullpath = `${cabinetName}/${drawerName}/${folderName}`; - if (!(await pathExist(fullpath))) { - throw new HttpError( - HttpStatusCode.PRECONDITION_FAILED, - "Provided resource location does not exist.", - ); - } + const list = await listItem(fullpath, true); - return new Promise((resolve, reject) => { - const stream = minioClient.listObjectsV2("ehr", fullpath, true); + const cond = new Minio.CopyConditions(); - stream.on("data", (v) => { - if (!(v && v.name)) return; + await Promise.all( + list.map(async (current) => { + if (!current.name) return; const destination = `${cabinetName}/${drawerName}/${replaceIllegalChars( body.name, - )}/${v.name.slice(fullpath.length)}`; - const source = `/ehr/${v.name}`; - const cond = new Minio.CopyConditions(); + )}/${current.name.slice(fullpath.length)}`; + const source = `/ehr/${current.name}`; - minioClient.copyObject("ehr", destination, source, cond, (e) => { - if (e) { - return reject(new Error("Failed to move.")); - } - return minioClient.removeObject("ehr", v.name); - }); - }); + return await minioClient + .copyObject("ehr", destination, source, cond) + .then(async () => { + if (!current.name) return; - stream.on("end", () => { - resolve(this.setStatus(HttpStatusCode.NO_CONTENT)); - }); - stream.on("error", () => reject(new Error("Object storage error occured."))); - }); + await minioClient.removeObject("ehr", current.name); + + if (current.name.includes(".keep")) return; + + const search = await esClient.search }>({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + query: { + match: { + pathname: current.name, + }, + }, + }); + + if (search && search.hits.hits.length === 0) { + throw new Error("Data cannot be found in database."); + } + + const data = search.hits.hits[0]; + + await esClient.update({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + id: data._id, + doc: { pathname: destination }, + }); + }) + .catch((e) => { + console.error(e); + throw new Error("Failed to move."); + }); + }), + ); + + return this.setStatus(HttpStatusCode.NO_CONTENT); } @Delete("/{folderName}") diff --git a/Services/server/src/controllers/subFolderController.ts b/Services/server/src/controllers/subFolderController.ts index abf6192..2ab4356 100644 --- a/Services/server/src/controllers/subFolderController.ts +++ b/Services/server/src/controllers/subFolderController.ts @@ -6,7 +6,6 @@ import { Path, Post, Put, - Query, Request, Route, Security, @@ -17,9 +16,10 @@ import * as Minio from "minio"; import HttpError from "../interfaces/http-error"; import HttpStatusCode from "../interfaces/http-status"; -import { listFolder, pathExist, replaceIllegalChars } from "../utils/minio"; -import { EhrFolder } from "../interfaces/ehr-fs"; +import { listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; +import { EhrFile, EhrFolder } from "../interfaces/ehr-fs"; import minioClient from "../storage"; +import esClient from "../elasticsearch"; @Route("/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder") export class SubFolderController extends Controller { @@ -31,7 +31,7 @@ export class SubFolderController extends Controller { @Path() drawerName: string, @Path() folderName: string, ): Promise { - const fullpath = [cabinetName, drawerName, folderName].join("/") + "/"; + const fullpath = [cabinetName, drawerName, folderName, ""].join("/"); if (!(await pathExist(fullpath))) { throw new HttpError(HttpStatusCode.NOT_FOUND, "Provided path does not exist."); @@ -84,45 +84,64 @@ export class SubFolderController extends Controller { @SuccessResponse(HttpStatusCode.NO_CONTENT) public async editFolder( @Body() body: { name: string }, - @Query() cabinetName: string, - @Query() drawerName: string, - @Query() folderName: string, - @Query() subFolderName: string, + @Path() cabinetName: string, + @Path() drawerName: string, + @Path() folderName: string, + @Path() subFolderName: string, ) { - const fullpath = [cabinetName, drawerName, folderName, subFolderName].join("/") + "/"; + const fullpath = `${cabinetName}/${drawerName}/${folderName}/${subFolderName}`; - if (!(await pathExist(fullpath))) { - throw new HttpError( - HttpStatusCode.PRECONDITION_FAILED, - "Provided resource location does not exist.", - ); - } + const list = await listItem(fullpath, true); - return new Promise((resolve, reject) => { - const stream = minioClient.listObjectsV2("ehr", fullpath, true); + const cond = new Minio.CopyConditions(); - stream.on("data", (v) => { - if (!(v && v.name)) return; + await Promise.all( + list.map(async (current) => { + if (!current.name) return; const destination = `${cabinetName}/${drawerName}/${folderName}/${replaceIllegalChars( body.name, - )}/${v.name.slice(fullpath.length)}`; - const source = `/ehr/${v.name}`; - const cond = new Minio.CopyConditions(); + )}/${current.name.slice(fullpath.length)}`; + const source = `/ehr/${current.name}`; - minioClient.copyObject("ehr", destination, source, cond, (e) => { - if (e) { - return reject(new Error("Failed to move.")); - } - return minioClient.removeObject("ehr", v.name); - }); - }); + return await minioClient + .copyObject("ehr", destination, source, cond) + .then(async () => { + if (!current.name) return; - stream.on("end", () => { - resolve(this.setStatus(HttpStatusCode.NO_CONTENT)); - }); - stream.on("error", () => reject(new Error("Object storage error occured."))); - }); + await minioClient.removeObject("ehr", current.name); + + if (current.name.includes(".keep")) return; + + const search = await esClient.search }>({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + query: { + match: { + pathname: current.name, + }, + }, + }); + + if (search && search.hits.hits.length === 0) { + throw new Error("Data cannot be found in database."); + } + + const data = search.hits.hits[0]; + + await esClient.update({ + index: process.env.ELASTICSEARCH_INDEX ?? "ehr-index", + id: data._id, + doc: { pathname: destination }, + }); + }) + .catch((e) => { + console.error(e); + throw new Error("Failed to move."); + }); + }), + ); + + return this.setStatus(HttpStatusCode.NO_CONTENT); } @Delete("/{subFolderName}") diff --git a/Services/server/src/middlewares/exception.ts b/Services/server/src/middlewares/exception.ts index ccab12a..243051d 100644 --- a/Services/server/src/middlewares/exception.ts +++ b/Services/server/src/middlewares/exception.ts @@ -19,7 +19,7 @@ function errorHandler(error: Error, _req: Request, res: Response, _next: NextFun }); } - console.error(error); + console.error("Exception Caught:" + error); return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR).json({ status: HttpStatusCode.INTERNAL_SERVER_ERROR, diff --git a/Services/server/src/routes.ts b/Services/server/src/routes.ts index d16e76d..2ee984d 100644 --- a/Services/server/src/routes.ts +++ b/Services/server/src/routes.ts @@ -505,9 +505,9 @@ export function RegisterRoutes(app: Router) { function FolderController_editFolder(request: any, response: any, next: any) { const args = { body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - cabinetName: {"in":"query","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"query","name":"drawerName","required":true,"dataType":"string"}, - folderName: {"in":"query","name":"folderName","required":true,"dataType":"string"}, + cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, + drawerName: {"in":"path","name":"drawerName","required":true,"dataType":"string"}, + folderName: {"in":"path","name":"folderName","required":true,"dataType":"string"}, }; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa @@ -644,10 +644,10 @@ export function RegisterRoutes(app: Router) { function SubFolderController_editFolder(request: any, response: any, next: any) { const args = { body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - cabinetName: {"in":"query","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"query","name":"drawerName","required":true,"dataType":"string"}, - folderName: {"in":"query","name":"folderName","required":true,"dataType":"string"}, - subFolderName: {"in":"query","name":"subFolderName","required":true,"dataType":"string"}, + cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, + drawerName: {"in":"path","name":"drawerName","required":true,"dataType":"string"}, + folderName: {"in":"path","name":"folderName","required":true,"dataType":"string"}, + subFolderName: {"in":"path","name":"subFolderName","required":true,"dataType":"string"}, }; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa diff --git a/Services/server/src/swagger.json b/Services/server/src/swagger.json index 69080a3..d9bde06 100644 --- a/Services/server/src/swagger.json +++ b/Services/server/src/swagger.json @@ -984,12 +984,7 @@ "operationId": "EditFolder", "responses": { "204": { - "description": "", - "content": { - "application/json": { - "schema": {} - } - } + "description": "" } }, "tags": [ @@ -1002,7 +997,7 @@ ], "parameters": [ { - "in": "query", + "in": "path", "name": "cabinetName", "required": true, "schema": { @@ -1010,7 +1005,7 @@ } }, { - "in": "query", + "in": "path", "name": "drawerName", "required": true, "schema": { @@ -1018,7 +1013,7 @@ } }, { - "in": "query", + "in": "path", "name": "folderName", "required": true, "schema": { @@ -1243,12 +1238,7 @@ "operationId": "EditFolder", "responses": { "204": { - "description": "", - "content": { - "application/json": { - "schema": {} - } - } + "description": "" } }, "tags": [ @@ -1261,7 +1251,7 @@ ], "parameters": [ { - "in": "query", + "in": "path", "name": "cabinetName", "required": true, "schema": { @@ -1269,7 +1259,7 @@ } }, { - "in": "query", + "in": "path", "name": "drawerName", "required": true, "schema": { @@ -1277,7 +1267,7 @@ } }, { - "in": "query", + "in": "path", "name": "folderName", "required": true, "schema": { @@ -1285,7 +1275,7 @@ } }, { - "in": "query", + "in": "path", "name": "subFolderName", "required": true, "schema": { diff --git a/Services/server/src/utils/minio.ts b/Services/server/src/utils/minio.ts index 131ee1a..3c3bc49 100644 --- a/Services/server/src/utils/minio.ts +++ b/Services/server/src/utils/minio.ts @@ -1,4 +1,5 @@ import { EhrFolder } from "../interfaces/ehr-fs"; +import * as Minio from "minio"; import minioClient from "../storage"; /** @@ -59,7 +60,12 @@ export function listFolder(path?: string): Promise { stream.on("end", async () => { for (let i = 0; i < folder.length; i++) { - const stat = await minioClient.statObject("ehr", `${folder[i].pathname}.keep`); + const stat = await minioClient + .statObject("ehr", `${folder[i].pathname}.keep`) + .catch((e) => console.error(`Error List Folder: ${folder[i].pathname}`, e)); + + if (!stat) continue; + folder[i] = { ...folder[i], createdAt: stat.metaData.createdat ?? "N/A", @@ -72,3 +78,16 @@ export function listFolder(path?: string): Promise { stream.on("error", () => reject(new Error("Object storage error occured."))); }); } + +export async function listItem(path: string, recursive = false): Promise { + return new Promise((resolve, reject) => { + const stream = minioClient.listObjectsV2("ehr", path, recursive); + const item: Minio.BucketItem[] = []; + + stream.on("data", (v) => { + if (v && v.name) item.push(v); + }); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("Object storage error occured."))); + }); +}