diff --git a/Services/server/src/controllers/cabinetController.ts b/Services/server/src/controllers/cabinetController.ts deleted file mode 100644 index c9b541c..0000000 --- a/Services/server/src/controllers/cabinetController.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { - Body, - Controller, - Delete, - Get, - Path, - Post, - Put, - Route, - Security, - SuccessResponse, - Tags, - Request, - Response, - Example, -} from "tsoa"; - -import minioClient from "../minio"; -import esClient from "../elasticsearch"; - -import { copyCond, listFolder, listItem, replaceIllegalChars } from "../utils/minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile, StorageFolder } from "../interfaces/storage-fs"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route("cabinet") -export class CabinetController extends Controller { - @Get("/") - @Tags("ตู้เอกสาร") - @Security("bearerAuth") - @Response( - HttpStatusCode.INTERNAL_SERVER_ERROR, - "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการตู้เอกสารได้ กรุณาลองใหม่ในภายหลัง", - ) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - path: "ตู้เอกสาร 1/", - name: "ตู้เอกสาร 1", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - }, - { - path: "ตู้เอกสาร 2/", - name: "ตู้เอกสาร 2", - createdAt: "2022-01-23T16:05:02.114Z", - createdBy: "admin", - }, - ]) - public async listCabinet(): Promise { - const list = await listFolder(DEFAULT_BUCKET!).catch((e) => - console.error(`Error List Folder: ${e}`), - ); - if (!list) - throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการตู้เอกสารได้ กรุณาลองใหม่ในภายหลัง"); - return list; - } - - @Post("/") - @Tags("ตู้เอกสาร") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์") - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - public async createCabinet( - @Request() request: { user: { preferred_username: string } }, - @Body() - body: { - /** - * @example "ตู้เอกสาร 1" - */ - name: string; - }, - ) { - const meta = { - createdAt: new Date().toISOString(), - createdBy: request.user.preferred_username, - }; - - const created = await minioClient - .putObject(DEFAULT_BUCKET!, `${replaceIllegalChars(body.name)}/.keep`, "", 0, meta) - .catch((e) => console.error(e)); - - if (!created) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - - const io = getInstance(); - io?.emit("CreateFolder", { - pathname: `${replaceIllegalChars(body.name)}/`, - name: replaceIllegalChars(body.name), - ...meta, - }); - - return this.setStatus(HttpStatusCode.CREATED); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - */ - @Put("/{cabinetName}") - @Tags("ตู้เอกสาร") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้") - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async editCabinet( - @Path() cabinetName: string, - @Body() - body: { - /** - * @example "ตู้เอกสารใหม่" - */ - name: string; - }, - ): Promise { - const path = `${cabinetName}/`; - const list = await listItem(DEFAULT_BUCKET!, path, true); - - await Promise.all( - list.map(async (current) => { - if (!current.name) return; - - const base = `${replaceIllegalChars(body.name)}/`; - const destination = `${base}${current.name.slice(path.length)}`; - const source = `/${DEFAULT_BUCKET}/${current.name}`; - - return await minioClient - .copyObject(DEFAULT_BUCKET!, destination, source, copyCond) - .then(async () => { - if (current.name.includes(".keep")) { - return await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - } - - const search = await esClient.search< - StorageFile & { attachment: Record } - >({ - index: DEFAULT_INDEX!, - query: { match: { pathname: current.name } }, - }); - - if (search && search.hits.hits.length === 0) throw new Error("ไม่พบข้อมูลในฐานข้อมูล"); - - const data = search.hits.hits[0]; - - await esClient.update({ - index: DEFAULT_INDEX!, - id: data._id, - doc: { - pathname: destination, - path: destination.split("/").slice(0, -1).join("/") + "/", - }, - refresh: "wait_for", - }); - - await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - }) - .catch((e) => { - console.error(e); - throw new Error("เกิดข้อผิดพลาด ไม่สามารถย้ายไฟล์ได้"); - }); - }), - ); - - const io = getInstance(); - io?.emit("EditFolder", { from: `${cabinetName}/`, to: `${replaceIllegalChars(body.name)}/` }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - */ - @Delete("/{cabinetName}") - @Tags("ตู้เอกสาร") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้") - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async deleteCabinet(@Path() cabinetName: string) { - await new Promise((resolve, reject) => { - const objects: string[] = []; - const stream = minioClient.listObjectsV2(DEFAULT_BUCKET!, `${cabinetName}/`, true); - - stream.on("data", (v) => { - if (v && v.name) objects.push(v.name); - }); - stream.on("close", async () => - resolve(await minioClient.removeObjects(DEFAULT_BUCKET!, objects)), - ); - stream.on("error", () => reject(new Error("เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้"))); - }); - - const io = getInstance(); - io?.emit("DeleteFolder", { pathname: `${cabinetName}/` }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - */ - @Get("/{cabinetName}/size") - @Tags("ตู้เอกสาร") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async calc(@Path() cabinetName: string) { - const list = await listItem(DEFAULT_BUCKET!, `${cabinetName}/`, true).catch((e) => - console.error(`Error List Folder: ${e}`), - ); - - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - - return { size: list.reduce((a, c) => a + c.size, 0) }; - } -} diff --git a/Services/server/src/controllers/drawerController.ts b/Services/server/src/controllers/drawerController.ts deleted file mode 100644 index a761fd5..0000000 --- a/Services/server/src/controllers/drawerController.ts +++ /dev/null @@ -1,245 +0,0 @@ -import { - Body, - Controller, - Delete, - Get, - Path, - Post, - Put, - Route, - Security, - SuccessResponse, - Tags, - Request, - Response, - Example, -} from "tsoa"; - -import minioClient from "../minio"; -import esClient from "../elasticsearch"; - -import { copyCond, listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile, StorageFolder } from "../interfaces/storage-fs"; -import HttpError from "../interfaces/http-error"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route("/cabinet/{cabinetName}/drawer") -export class DrawerController extends Controller { - /** - * @example cabinetName "ตู้เอกสาร 1" - */ - @Get("/") - @Tags("ลิ้นชัก") - @Security("bearerAuth") - @Response( - HttpStatusCode.INTERNAL_SERVER_ERROR, - "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการลิ้นชักได้ กรุณาลองใหม่ในภายหลัง", - ) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/", - name: "ลิ้นชัก 1", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - }, - { - path: "ตู้เอกสาร 1/ลิ้นชัก 2/", - name: "ลิ้นชัก 2", - createdAt: "2022-01-23T16:05:02.114Z", - createdBy: "admin", - }, - ]) - public async listDrawer(@Path() cabinetName: string): Promise { - const list = await listFolder(DEFAULT_BUCKET!, `${cabinetName}/`).catch((e) => - console.error(`Error List Folder: ${e}`), - ); - if (!list) - throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการลิ้นชักได้ กรุณาลองใหม่ในภายหลัง"); - return list; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - */ - @Post("/") - @Tags("ลิ้นชัก") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.NOT_FOUND, "ไม่พบลิ้นชัก") - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์") - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - public async createDrawer( - @Request() request: { user: { preferred_username: string } }, - @Path() cabinetName: string, - @Body() - body: { - /** - * @example "ลิ้นชัก 1" - */ - name: string; - }, - ) { - const basePath = `${cabinetName}/`; - - if (!(await pathExist(DEFAULT_BUCKET!, basePath))) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างลิ้นชัก"); - } - - const meta = { - createdAt: new Date().toISOString(), - createdBy: request.user.preferred_username, - }; - - const created = await minioClient - .putObject(DEFAULT_BUCKET!, `${basePath}${replaceIllegalChars(body.name)}/.keep`, "", 0, meta) - .catch((e) => console.error(e)); - - if (!created) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - - const io = getInstance(); - io?.emit("CreateFolder", { - pathname: `${basePath}${replaceIllegalChars(body.name)}/`, - name: replaceIllegalChars(body.name), - ...meta, - }); - - return this.setStatus(HttpStatusCode.CREATED); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - */ - @Put("/{drawerName}") - @Tags("ลิ้นชัก") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้") - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async editDrawer( - @Path() cabinetName: string, - @Path() drawerName: string, - @Body() - body: { - /** - * @example "ลิ้นชักใหม่" - */ - name: string; - }, - ): Promise { - const path = `${cabinetName}/${drawerName}/`; - const list = await listItem(DEFAULT_BUCKET!, path, true); - - await Promise.all( - list.map(async (current) => { - if (!current.name) return; - - const base = `${cabinetName}/${replaceIllegalChars(body.name)}/`; - const destination = `${base}${current.name.slice(path.length)}`; - const source = `/${DEFAULT_BUCKET}/${current.name}`; - - return await minioClient - .copyObject(DEFAULT_BUCKET!, destination, source, copyCond) - .then(async () => { - if (current.name.includes(".keep")) { - return await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - } - - const search = await esClient.search< - StorageFile & { attachment: Record } - >({ - index: DEFAULT_INDEX!, - query: { match: { pathname: current.name } }, - }); - - if (search && search.hits.hits.length === 0) throw new Error("ไม่พบข้อมูลในฐานข้อมูล"); - - const data = search.hits.hits[0]; - - await esClient.update({ - index: DEFAULT_INDEX!, - id: data._id, - doc: { - pathname: destination, - path: destination.split("/").slice(0, -1).join("/") + "/", - }, - refresh: "wait_for", - }); - - await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - }) - .catch((e) => { - console.error(e); - throw new Error("เกิดข้อผิดพลาด ไม่สามารถย้ายไฟล์ได้"); - }); - }), - ); - - const io = getInstance(); - io?.emit("EditFolder", { - from: `${cabinetName}/${drawerName}/`, - to: `${cabinetName}/${replaceIllegalChars(body.name)}/`, - }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - */ - @Delete("/{drawerName}") - @Tags("ลิ้นชัก") - @Security("bearerAuth", ["admin", "management-role"]) - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async deleteDrawer(@Path() cabinetName: string, @Path() drawerName: string) { - await new Promise((resolve, reject) => { - const objects: string[] = []; - const stream = minioClient.listObjectsV2( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/`, - true, - ); - - stream.on("data", (v) => { - if (v && v.name) objects.push(v.name); - }); - stream.on("close", async () => - resolve(await minioClient.removeObjects(DEFAULT_BUCKET!, objects)), - ); - stream.on("error", () => reject(new Error("เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้"))); - }); - - const io = getInstance(); - io?.emit("DeleteFolder", { - pathname: `${cabinetName}/${drawerName}/`, - }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - */ - @Get("/{drawerName}/size") - @Tags("ลิ้นชัก") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async calc(@Path() cabinetName: string, @Path() drawerName: string) { - const list = await listItem(DEFAULT_BUCKET!, `${cabinetName}/${drawerName}/`, true).catch((e) => - console.error(`Error List Folder: ${e}`), - ); - - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - - return { size: list.reduce((a, c) => a + c.size, 0) }; - } -} diff --git a/Services/server/src/controllers/fileController.ts b/Services/server/src/controllers/fileController.ts deleted file mode 100644 index 94bd207..0000000 --- a/Services/server/src/controllers/fileController.ts +++ /dev/null @@ -1,438 +0,0 @@ -import { - Body, - Controller, - Delete, - Example, - Get, - Patch, - Path, - Post, - Request, - Response, - Route, - Security, - SuccessResponse, - Tags, -} from "tsoa"; - -import esClient from "../elasticsearch"; -import minioClient from "../minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile } from "../interfaces/storage-fs"; -import HttpError from "../interfaces/http-error"; - -import { copyCond, pathExist, replaceIllegalChars } from "../utils/minio"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route("/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/file") -export class FileController extends Controller { - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Get("/") - @Tags("ไฟล์") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1", - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", - title: "เอกสาร", - description: "เอกสารการเงิน", - category: ["บัญชี"], - keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], - upload: false, - fileName: "เอกสาร 1", - fileSize: 10240, - fileType: "application/pdf", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - updatedAt: "2021-07-20T12:33:13.018Z", - updatedBy: "admin", - }, - ]) - public async getFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ): Promise { - const search = await esClient.search }>({ - index: DEFAULT_INDEX!, - query: { - match: { - path: `${cabinetName}/${drawerName}/${folderName}/`, - }, - }, - size: 10000, - }); - - const records = search.hits.hits - .map((v) => { - if (v._source) { - const { attachment, ...rest } = v._source; - return rest satisfies StorageFile; - } - }) - .filter((v: StorageFile | undefined): v is StorageFile => !!v); - - return records; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Post("/") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @Response( - HttpStatusCode.NOT_FOUND, - "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ", - ) - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - @Example({ - pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1", - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", - title: "เอกสาร", - description: "เอกสารการเงิน", - category: ["บัญชี"], - keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], - upload: false, - fileName: "เอกสาร 1", - fileSize: 10240, - fileType: "application/pdf", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - updatedAt: "2021-07-20T12:33:13.018Z", - updatedBy: "admin", - }) - public async uploadFile( - @Request() request: { user: { preferred_username: string } }, - @Body() - body: { - /** - * @example "เอกสาร 1" - */ - file: string; - /** - * @example "เอกสาร" - */ - title?: string; - /** - * @example "เอกสารการเงิน" - */ - description?: string; - /** - * @example ["บัญชี"] - */ - category?: string[]; - /** - * @example ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"] - */ - keyword?: string[]; - }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ) { - if (body.file.length > 85) { - throw new HttpError(HttpStatusCode.BAD_REQUEST, "ชื่อไฟล์ยาวเกินกำหนด"); - } - - const basePath = `${cabinetName}/${drawerName}/${folderName}/`; - const pathname = `${basePath}${replaceIllegalChars(body.file)}`; - - if (!(await pathExist(DEFAULT_BUCKET!, basePath))) { - throw new HttpError( - HttpStatusCode.NOT_FOUND, - "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ", - ); - } - - const result = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - - // pathname is unique and should not have multiple record with same path - if (result && result.hits.hits.length > 0 && result.hits.hits[0]._source) { - await esClient - .delete({ - index: DEFAULT_INDEX!, - id: result.hits.hits[0]._id, - }) - .catch((e) => console.error(e)); - } - - const rec = result && result.hits.hits.length > 0 ? result.hits.hits[0]._source : false; - - const metadata: Partial = { - pathname, - path: basePath, - fileName: replaceIllegalChars(body.file), - fileSize: 0, - fileType: "", - title: body.title ?? "", - description: body.description ?? "", - category: body.category ?? [], - keyword: body.keyword ?? [], - upload: false, - createdAt: new Date().toISOString(), - createdBy: rec ? rec.createdBy : "n/a", - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - - await esClient.index({ - index: DEFAULT_INDEX!, - document: metadata, - refresh: "wait_for", - }); - - const io = getInstance(); - io?.emit("FileUploadRequest", metadata); - - return { - ...body, - createdAt: metadata.createdAt, - createdBy: metadata.createdBy, - updatedAt: metadata.updatedAt, - updatedBy: metadata.updatedBy, - upload: await minioClient.presignedPutObject(DEFAULT_BUCKET!, pathname), - }; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example fileName "เอกสาร 1" - */ - @Patch("/{fileName}") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม") - @Response(HttpStatusCode.NO_CONTENT, "สำเร็จ") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async updateFile( - @Request() request: { user: { preferred_username: string } }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() fileName: string, - @Body() - body: { - /** - * @example "เอกสารใหม่" - */ - file?: string; - /** - * @example "เอกสารการเงิน" - */ - title?: string; - /** - * @example "เอกสารการเงินฉบับใหม่" - */ - description?: string; - /** - * @example ["บัญชี"] - */ - category?: string[]; - /** - * @example ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"] - */ - keyword?: string[]; - }, - ): Promise { - if (body.file && body.file.length > 85) { - throw new HttpError(HttpStatusCode.BAD_REQUEST, "ชื่อไฟล์ยาวเกินกำหนด"); - } - - const basePath = `${cabinetName}/${drawerName}/${folderName}/`; - const pathname = `${basePath}${fileName}`; - - if ( - !Boolean( - await minioClient.statObject(DEFAULT_BUCKET!, `${pathname}`).catch((e) => { - if (e.code === "NotFound") return false; - throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - }), - ) - ) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์"); - } - - const { file, ...metadata } = body; - - // assume user will probably replace file by re-upload but maybe just rename - if (file) { - const destination = `${basePath}${replaceIllegalChars(file)}`; - const source = `/${DEFAULT_BUCKET}/${basePath}${fileName}`; - const copy = await minioClient.copyObject(DEFAULT_BUCKET!, destination, source, copyCond); - - if (copy) { - const search = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - - if (search && search.hits.hits.length > 0 && search.hits.hits[0]._source) { - const { _index: index, _id: id } = search.hits.hits[0]; - const meta = { - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - await esClient - .update({ - index, - id, - doc: { - ...metadata, - pathname: destination, - path: basePath, - fileName: replaceIllegalChars(file), - ...meta, - }, - refresh: "wait_for", - }) - .then(() => minioClient.removeObject(DEFAULT_BUCKET!, pathname)); - - const io = getInstance(); - io?.emit("FileUpdateMove", { - from: search.hits.hits[0]._source, - to: { - ...search.hits.hits[0]._source, - ...metadata, - pathname: destination, - path: basePath, - fileName: replaceIllegalChars(file), - ...meta, - }, - }); - } else { - await minioClient.removeObject(DEFAULT_BUCKET!, pathname); - } - } - } else { - const search = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - - if (search && search.hits.hits.length > 0 && search.hits.hits[0]._source) { - const { _index: index, _id: id } = search.hits.hits[0]; - const meta = { - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - await esClient.update({ - index, - id, - doc: { ...metadata, ...meta }, - refresh: "wait_for", - }); - - const updated: StorageFile = { - ...search.hits.hits[0]._source, - ...metadata, - ...meta, - }; - - const io = getInstance(); - io?.emit("FileUpdate", updated); - } - } - - return body.file - ? { - upload: await minioClient.presignedPutObject( - DEFAULT_BUCKET!, - `${basePath}${replaceIllegalChars(body.file) ?? fileName}`, - ), - } - : this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example fileName "เอกสารใหม่" - */ - @Delete("/{fileName}") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async deleteFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() fileName: string, - ) { - await minioClient.removeObject( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${fileName}`, - ); - await esClient.deleteByQuery({ - index: DEFAULT_INDEX!, - query: { - match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${fileName}` }, - }, - }); - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example fileName "เอกสารใหม่" - */ - @Get("/{fileName}") - @Tags("ดาวน์โหลด") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async downloadFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() fileName: string, - ) { - const search = await esClient.search }>({ - index: DEFAULT_INDEX!, - query: { - match: { pathname: `${cabinetName}/${drawerName}/${folderName}/${fileName}` }, - }, - }); - - if (search && search.hits.hits.length === 0) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "Not found"); - } - - const { attachment, ...rest } = search.hits.hits[0]._source!; - - return { - ...rest, - download: await minioClient.presignedGetObject( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${fileName}`, - ), - }; - } -} diff --git a/Services/server/src/controllers/folderController.ts b/Services/server/src/controllers/folderController.ts deleted file mode 100644 index 358cb23..0000000 --- a/Services/server/src/controllers/folderController.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { - Body, - Controller, - Delete, - Get, - Path, - Post, - Put, - Route, - Security, - SuccessResponse, - Tags, - Request, - Response, - Example, -} from "tsoa"; - -import minioClient from "../minio"; -import esClient from "../elasticsearch"; - -import { copyCond, listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile, StorageFolder } from "../interfaces/storage-fs"; -import HttpError from "../interfaces/http-error"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route("/cabinet/{cabinetName}/drawer/{drawerName}/folder") -export class FolderController extends Controller { - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - */ - @Get("/") - @Tags("แฟ้ม") - @Security("bearerAuth") - @Response( - HttpStatusCode.INTERNAL_SERVER_ERROR, - "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง", - ) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1", - name: "แฟ้ม 1", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - }, - { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2", - name: "แฟ้ม 2", - createdAt: "2022-01-23T16:05:02.114Z", - createdBy: "admin", - }, - ]) - public async listFolder( - @Path() cabinetName: string, - @Path() drawerName: string, - ): Promise { - const list = await listFolder(DEFAULT_BUCKET!, `${cabinetName}/${drawerName}`).catch((e) => - console.error(`Error List Folder: ${e}`), - ); - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - return list; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - */ - @Post("/") - @Tags("แฟ้ม") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม") - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์") - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - public async createFolder( - @Request() request: { user: { preferred_username: string } }, - @Body() - body: { - /** - * @example "แฟ้ม 1" - */ - name: string; - }, - @Path() cabinetName: string, - @Path() drawerName: string, - ) { - const basePath = `${cabinetName}/${drawerName}/`; - - if (!(await pathExist(DEFAULT_BUCKET!, basePath))) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างลิ้นชัก"); - } - - const meta = { - createdAt: new Date().toISOString(), - createdBy: request.user.preferred_username, - }; - - const created = await minioClient - .putObject(DEFAULT_BUCKET!, `${basePath}${replaceIllegalChars(body.name)}/.keep`, "", 0, meta) - .catch((e) => console.error(e)); - - if (!created) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - - const io = getInstance(); - io?.emit("CreateFolder", { - pathname: `${basePath}${replaceIllegalChars(body.name)}/`, - name: replaceIllegalChars(body.name), - ...meta, - }); - - return this.setStatus(HttpStatusCode.CREATED); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Put("/{folderName}") - @Tags("แฟ้ม") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้") - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async editFolder( - @Body() - body: { - /** - * @example "แฟ้มใหม่" - */ - name: string; - }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ) { - const path = `${cabinetName}/${drawerName}/${folderName}/`; - const list = await listItem(DEFAULT_BUCKET!, path, true); - - await Promise.all( - list.map(async (current) => { - if (!current.name) return; - - const base = `${cabinetName}/${drawerName}/${replaceIllegalChars(body.name)}/`; - const destination = `${base}${current.name.slice(path.length)}`; - const source = `/${DEFAULT_BUCKET}/${current.name}`; - - return await minioClient - .copyObject(DEFAULT_BUCKET!, destination, source, copyCond) - .then(async () => { - if (current.name.includes(".keep")) { - return await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - } - - const search = await esClient.search< - StorageFile & { attachment: Record } - >({ - index: DEFAULT_INDEX!, - query: { match: { pathname: current.name } }, - }); - - if (search && search.hits.hits.length === 0) throw new Error("ไม่พบข้อมูลในฐานข้อมูล"); - - const data = search.hits.hits[0]; - - await esClient.update({ - index: DEFAULT_INDEX!, - id: data._id, - doc: { - pathname: destination, - path: destination.split("/").slice(0, -1).join("/") + "/", - }, - refresh: "wait_for", - }); - - await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - }) - .catch((e) => { - console.error(e); - throw new Error("เกิดข้อผิดพลาด ไม่สามารถย้ายไฟล์ได้"); - }); - }), - ); - - const io = getInstance(); - io?.emit("EditFolder", { - from: `${cabinetName}/${drawerName}/${folderName}/`, - to: `${cabinetName}/${drawerName}/${replaceIllegalChars(body.name)}/`, - }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Delete("/{folderName}") - @Tags("แฟ้ม") - @Security("bearerAuth", ["admin", "management-role"]) - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async deleteFolder( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ) { - await new Promise((resolve, reject) => { - const objects: string[] = []; - const stream = minioClient.listObjectsV2( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}`, - true, - ); - - stream.on("data", (v) => { - if (v && v.name) objects.push(v.name); - }); - stream.on("close", async () => - resolve(await minioClient.removeObjects(DEFAULT_BUCKET!, objects)), - ); - stream.on("error", () => reject(new Error("เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้"))); - }); - - const io = getInstance(); - io?.emit("DeleteFolder", { pathname: `${cabinetName}/${drawerName}/${folderName}/` }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Get("/{folderName}/size") - @Tags("แฟ้ม") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async calc( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ) { - const list = await listItem( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/`, - true, - ).catch((e) => console.error(`Error List Folder: ${e}`)); - - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - - return { size: list.reduce((a, c) => a + c.size, 0) }; - } -} diff --git a/Services/server/src/controllers/searchController.ts b/Services/server/src/controllers/searchController.ts index 502b74b..394e02a 100644 --- a/Services/server/src/controllers/searchController.ts +++ b/Services/server/src/controllers/searchController.ts @@ -11,7 +11,7 @@ if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified." @Route("/search") export class SearchController extends Controller { @Post("/") - @Tags("ค้นหา") + @Tags("Search") @Security("bearerAuth") @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") public async searchFile(@Body() search: Search): Promise { diff --git a/Services/server/src/controllers/storageController.ts b/Services/server/src/controllers/storageController.ts index a6bbc9e..347e13b 100644 --- a/Services/server/src/controllers/storageController.ts +++ b/Services/server/src/controllers/storageController.ts @@ -6,6 +6,7 @@ import { Post, Put, Request, + Response, Route, Security, SuccessResponse, @@ -114,6 +115,10 @@ interface DownloadFileBody { file: string; } +function stripLeadingSlash(str: string) { + return str.replace(/^\//, ""); +} + async function folderSize(path: string[]) { const size = await new Promise((resolve, reject) => { const stream = minioClient.listObjectsV2( @@ -138,7 +143,7 @@ async function listFolder(path: string[], hidden: boolean = false) { const stream = minioClient.listObjectsV2( DEFAULT_BUCKET, - path.length === 0 ? "" : path.join("/") + "/", + stripLeadingSlash(`${path.join("/")}/`), ); stream.on("data", (v) => { if (v && v.prefix) @@ -182,7 +187,7 @@ async function listFile(path: string[], hidden: boolean = false) { sort: [{ pathname: "asc" }], query: { bool: { - must: { match: { path: path.join("/") + "/" } }, + must: { match: { path: stripLeadingSlash(`${path.join("/")}/`) } }, must_not: !hidden ? { match: { hidden: true } } : undefined, }, }, @@ -202,14 +207,14 @@ async function listFile(path: string[], hidden: boolean = false) { return records; } -async function checkPathExist(bucket: string, path: string) { - if (path.split("/").filter(Boolean).length === 0) return true; // root does not contain any mark - return await checkFileExist(bucket, `${path}/.keep`); +async function checkPathExist(bucket: string, path: string[]) { + if (path.filter(Boolean).length === 0) return true; // root does not contain any mark + return await checkFileExist(bucket, `${path.filter(Boolean).join("/")}/.keep`); } async function checkFileExist(bucket: string, pathname: string) { return Boolean( - await minioClient.statObject(bucket, pathname).catch((e) => { + await minioClient.statObject(bucket, stripLeadingSlash(pathname)).catch((e) => { if (e.code === "NotFound") return false; console.error(`Storage Error: ${e}`); throw new Error(MINIO_ERROR_MESSAGE); @@ -219,16 +224,21 @@ async function checkFileExist(bucket: string, pathname: string) { @Route("storage") export class StorageController extends Controller { + /** + * @summary แสดงรายการแฟ้มหรือไฟล์ + */ @Post("list") + @Tags("Storage Folder", "Storage File") + @Security("bearerAuth") @Example([ { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1", + path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", name: "แฟ้ม 1", createdAt: "2021-07-20T12:33:13.018Z", createdBy: "admin", }, { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2", + path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2/", name: "แฟ้ม 2", createdAt: "2022-01-23T16:05:02.114Z", createdBy: "admin", @@ -243,6 +253,7 @@ export class StorageController extends Controller { category: ["บัญชี"], keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], upload: false, + hidden: false, fileName: "เอกสาร 1.pdf", fileSize: 10240, fileType: "application/pdf", @@ -252,15 +263,21 @@ export class StorageController extends Controller { updatedBy: "admin", }, ]) - @Tags("Storage Folder", "Storage File") - @Security("bearerAuth") + @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") public async getList(@Body() body: ListRequestBody) { const path = body.path.filter(Boolean); + if (!(await checkPathExist(DEFAULT_BUCKET, path))) { + throw new HttpError(HttpStatusCode.NOT_FOUND, PATH_NOT_FOUND_MESSAGE); + } + if (body.operation === "folder") return await listFolder(path, body.hidden); if (body.operation === "file") return await listFile(path); } + /** + * @summary สร้างแฟ้ม + */ @Post("folder") @Tags("Storage Folder") @Security("bearerAuth", ["management-role", "admin"]) @@ -271,7 +288,7 @@ export class StorageController extends Controller { ) { const { path, name } = body; - if (!(await checkPathExist(DEFAULT_BUCKET, path.join("/")))) { + if (!(await checkPathExist(DEFAULT_BUCKET, path))) { throw new HttpError(HttpStatusCode.NOT_FOUND, PATH_NOT_FOUND_MESSAGE); } @@ -283,7 +300,7 @@ export class StorageController extends Controller { const created = await minioClient .putObject( DEFAULT_BUCKET, - `${path.join("/")}/${name.replace(/[/\\?%*:|"<>#]/g, "-").trim()}/.keep`, + stripLeadingSlash(`${path.join("/")}/${name.replace(/[/\\?%*:|"<>#]/g, "-").trim()}/.keep`), "", 0, meta, @@ -293,7 +310,9 @@ export class StorageController extends Controller { if (!created) throw new Error(MINIO_ERROR_MESSAGE); io.getInstance()?.emit("FolderCreate", { - pathname: `${path.join("/")}/${name.replace(/[/\\?%*:|"<>#]/g, "-").trim()}/`, + pathname: stripLeadingSlash( + `${path.join("/")}/${name.replace(/[/\\?%*:|"<>#]/g, "-").trim()}/`, + ), name: name.replace(/[/\\?%*:|"<>#]/g, "-").trim(), ...meta, }); @@ -302,23 +321,26 @@ export class StorageController extends Controller { } /** - * ยา้ย Folder ภายใต้ Folder (Path) หนึ่ง ไปภายใน Folder (Path) หนึ่งและสามารถเปลี่ยนชื่อได้ + * ยา้ยแฟ้มภายในตำแหน่งหนึ่งไปภายในอีกแฟ้มหนึ่ง + * หรือเปลี่ยนชื่อได้ + * + * @summary ยา้ยแฟ้ม */ @Put("folder") @Tags("Storage Folder") @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") public async moveFolder(@Body() body: PutFolderBody) { - const src = `${body.from.path.join("/")}/${body.from.name}`; - const dst = `${body.to.path.join("/")}/${body.to.name}`; + const src = stripLeadingSlash(`${body.from.path.join("/")}/${body.from.name}`); + const dst = stripLeadingSlash(`${body.to.path.join("/")}/${body.to.name}`); - if (!(await checkPathExist(DEFAULT_BUCKET, src))) { + if (!(await checkPathExist(DEFAULT_BUCKET, src.split("/")))) { throw new HttpError(HttpStatusCode.NOT_FOUND, PATH_NOT_FOUND_MESSAGE); } - if (await checkPathExist(DEFAULT_BUCKET, dst)) { + if (await checkPathExist(DEFAULT_BUCKET, dst.split("/"))) { throw new HttpError(HttpStatusCode.CONFLICT, PATH_ALREADY_EXIST); } - if (!(await checkPathExist(DEFAULT_BUCKET, body.to.path.join("/")))) { + if (!(await checkPathExist(DEFAULT_BUCKET, body.to.path))) { throw new HttpError(HttpStatusCode.PRECONDITION_FAILED, "ไม่พบตำแหน่งที่ต้องการย้าย"); } @@ -336,7 +358,7 @@ export class StorageController extends Controller { await Promise.all( list.map(async (v) => { const from = `/${DEFAULT_BUCKET}/${v.pathname}`; - const to = `${dst}/${v.pathname.slice(`${src}/`.length)}`; + const to = stripLeadingSlash(`${dst}/${v.pathname.slice(`${src}/`.length)}`); const result = await minioClient .copyObject(DEFAULT_BUCKET, to, from, copyCond) @@ -376,7 +398,7 @@ export class StorageController extends Controller { id: data._id, doc: { pathname: to, - path: to.split("/").slice(0, -1).join("/") + "/", + path: stripLeadingSlash(`${to.split("/").slice(0, -1).join("/")}/`), }, refresh: "wait_for", }) @@ -390,8 +412,8 @@ export class StorageController extends Controller { ); io.getInstance()?.emit("FolderMove", { - from: `${src}/`, - to: `${dst}/`, + from: stripLeadingSlash(`${src}/`), + to: stripLeadingSlash(`${dst}/`), }); return this.setStatus(HttpStatusCode.NO_CONTENT); @@ -400,6 +422,10 @@ export class StorageController extends Controller { @Post("folder/size") @Tags("Storage Folder") @Security("bearerAuth", ["management-role", "admin"]) + @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") + @Example({ + size: 10240, + }) public async folderSize(@Body() body: FolderBody) { return { size: await folderSize([...body.path, body.name]) }; } @@ -412,9 +438,17 @@ export class StorageController extends Controller { @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") public async deleteStorage(@Body() body: DeleteFolderBody) { + if (body.path.length === 0) { + throw new HttpError(HttpStatusCode.BAD_REQUEST, "ไม่สามารถลบได้"); + } + await new Promise((resolve, reject) => { const objects: string[] = []; - const stream = minioClient.listObjectsV2(DEFAULT_BUCKET, body.path.join("/") + "/", true); + const stream = minioClient.listObjectsV2( + DEFAULT_BUCKET, + stripLeadingSlash(`${body.path.join("/")}/`), + true, + ); stream.on("data", (v) => v && v.name && objects.push(v.name)); stream.on("close", async () => { @@ -435,30 +469,53 @@ export class StorageController extends Controller { @Tags("Storage File") @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") + @Example({ + pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1.pdf", + path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", + title: "เอกสาร", + description: "เอกสารการเงิน", + category: ["บัญชี"], + keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], + upload: false, + hidden: false, + fileName: "เอกสาร 1.pdf", + fileSize: 10240, + fileType: "application/pdf", + createdAt: "2021-07-20T12:33:13.018Z", + createdBy: "admin", + updatedAt: "2021-07-20T12:33:13.018Z", + updatedBy: "admin", + uploadUrl: "s3.storage.upload", + }) public async postFile( @Request() request: { user: { preferred_username: string } }, @Body() body: FileBody, ) { const { path, file } = body; + const validFileName = file.replace(/[/\\?%*:|"<>#]/g, "-").trim(); - if (!(await checkPathExist(DEFAULT_BUCKET, path.join("/")))) { + if (!(await checkPathExist(DEFAULT_BUCKET, path))) { throw new HttpError(HttpStatusCode.NOT_FOUND, PATH_NOT_FOUND_MESSAGE); } const result = await esClient .search }>({ index: DEFAULT_INDEX!, - query: { match: { pathname: path.join("/") + "/" } }, + query: { + match: { + pathname: stripLeadingSlash(`${path.join("/")}/${validFileName}`), + }, + }, }) .catch((e) => console.error(`MinIO Error: ${e}`)); const metadata: StorageFile = { - path: path.join("/") + "/", - pathname: path.join("/") + "/" + file.replace(/[/\\?%*:|"<>#]/g, "-").trim(), - fileName: file.replace(/[/\\?%*:|"<>#]/g, "-").trim(), + path: stripLeadingSlash(`${path.join("/")}/`), + pathname: stripLeadingSlash(`${path.join("/")}/${validFileName}`), + fileName: validFileName, fileSize: 0, // Will be get by minio object storage after file is uploaded fileType: "", // Will be determined by minio object storage after file is uploaded - title: body.title ?? file.replace(/[/\\?%*:|"<>#]/g, "-").trim(), // default to same as filename + title: body.title ?? validFileName, // default to same as filename description: body.description ?? "", category: body.category ?? [], keyword: body.keyword ?? [], @@ -504,6 +561,8 @@ export class StorageController extends Controller { @Tags("Storage File") @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") + @Response(HttpStatusCode.NO_CONTENT, "สำเร็จ") + @Example({ uploadUrl: "s3.storage.upload" }) public async moveFile( @Request() request: { user: { preferred_username: string } }, @Body() body: PutFileBody, @@ -512,7 +571,9 @@ export class StorageController extends Controller { .search }>({ index: DEFAULT_INDEX, query: { - match: { pathname: body.from.path.join("/") + `/${body.from.file}` }, + match: { + pathname: stripLeadingSlash(`${body.from.path.join("/")}/${body.from.file}`), + }, }, }) .catch((e) => console.error(`ElasticSearch Error: ${e}`)); @@ -523,7 +584,12 @@ export class StorageController extends Controller { if (search && search.hits.hits.length === 0) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์ดังกล่าว"); } - if (!(await checkFileExist(DEFAULT_BUCKET, body.from.path.join("/") + `/${body.from.file}`))) { + if ( + !(await checkFileExist( + DEFAULT_BUCKET, + stripLeadingSlash(`${body.from.path.join("/")}/${body.from.file}`), + )) + ) { await esClient.delete({ index: DEFAULT_INDEX, id: search.hits.hits[0]._id, @@ -531,10 +597,15 @@ export class StorageController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์ดังกล่าว"); } if (body.to && JSON.stringify(body.from) !== JSON.stringify(body.to)) { - if (!(await checkPathExist(DEFAULT_BUCKET, body.to.path.join("/")))) { + if (!(await checkPathExist(DEFAULT_BUCKET, body.to.path))) { throw new HttpError(HttpStatusCode.PRECONDITION_FAILED, "ไม่พบตำแหน่งที่ต้องการย้าย"); } - if (await checkFileExist(DEFAULT_BUCKET, body.to.path.join("/") + `/${body.to.file}`)) { + if ( + await checkFileExist( + DEFAULT_BUCKET, + stripLeadingSlash(`${body.to.path.join("/")}/${body.to.file}`), + ) + ) { throw new HttpError( HttpStatusCode.PRECONDITION_FAILED, "พบไฟล์ในต้ำแหน่งปลายทาง ไม่สามารถย้ายได้", @@ -563,7 +634,7 @@ export class StorageController extends Controller { if (from && to && JSON.stringify(from) !== JSON.stringify(to)) { const src = [DEFAULT_BUCKET, ...from.path, ""].join("/") + from.file; - const dst = to.path.join("/") + `/${to.file}`; + const dst = stripLeadingSlash(`${to.path.join("/")}/${to.file}`); const result = await minioClient.copyObject(DEFAULT_BUCKET, dst, src, copyCond).catch((e) => { console.error(`MinIO Error: ${e}`); @@ -577,7 +648,7 @@ export class StorageController extends Controller { id: id, doc: { ...metadata, - path: to.path.join("/") + "/", + path: stripLeadingSlash(`${to.path.join("/")}/`), pathname: dst, fileName: to.file, ...dateMeta, @@ -586,7 +657,10 @@ export class StorageController extends Controller { }) .then( async () => - await minioClient.removeObject(DEFAULT_BUCKET, from.path.join("/") + `/${from.file}`), + await minioClient.removeObject( + DEFAULT_BUCKET, + stripLeadingSlash(`${from.path.join("/")}/${from.file}`), + ), ) .catch((e) => console.error(`ElasticSearch Error: ${e}`)); @@ -595,7 +669,7 @@ export class StorageController extends Controller { to: { ...source, ...metadata, - path: to.path.join("/") + "/", + path: stripLeadingSlash(`${to.path.join("/")}/`), pathname: dst, fileName: to.file, ...dateMeta, @@ -633,7 +707,7 @@ export class StorageController extends Controller { }); if (upload) { - const src = from.path.join("/") + `/${from.file}`; + const src = stripLeadingSlash(`${from.path.join("/")}/${from.file}`); const presignedUrl = await minioClient.presignedPutObject(DEFAULT_BUCKET, src); return { uploadUrl: presignedUrl }; } @@ -650,7 +724,7 @@ export class StorageController extends Controller { @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") public async deleteFile(@Body() body: DeleteFileBody) { - const pathname = body.path.join("/") + `/${body.file}`; + const pathname = stripLeadingSlash(`${body.path.join("/")}/${body.file}`); await minioClient .removeObject(DEFAULT_BUCKET, pathname) @@ -671,8 +745,26 @@ export class StorageController extends Controller { @Tags("Download") @Security("bearerAuth", ["management-role", "admin"]) @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") + @Example({ + pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1.pdf", + path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", + title: "เอกสาร", + description: "เอกสารการเงิน", + category: ["บัญชี"], + keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], + upload: false, + hidden: false, + fileName: "เอกสาร 1.pdf", + fileSize: 10240, + fileType: "application/pdf", + createdAt: "2021-07-20T12:33:13.018Z", + createdBy: "admin", + updatedAt: "2021-07-20T12:33:13.018Z", + updatedBy: "admin", + downloadUrl: "s3.storage.download", + }) public async downloadFile(@Body() body: DownloadFileBody) { - const pathname = body.path.join("/") + `/${body.file}`; + const pathname = stripLeadingSlash(`${body.path.join("/")}/${body.file}`); const search = await esClient.search }>({ index: DEFAULT_INDEX, diff --git a/Services/server/src/controllers/subFolderController.ts b/Services/server/src/controllers/subFolderController.ts deleted file mode 100644 index d7ad4b8..0000000 --- a/Services/server/src/controllers/subFolderController.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { - Body, - Controller, - Delete, - Get, - Path, - Post, - Put, - Route, - Security, - SuccessResponse, - Tags, - Request, - Response, - Example, -} from "tsoa"; - -import minioClient from "../minio"; -import esClient from "../elasticsearch"; - -import { copyCond, listFolder, listItem, pathExist, replaceIllegalChars } from "../utils/minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile, StorageFolder } from "../interfaces/storage-fs"; -import HttpError from "../interfaces/http-error"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route("/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder") -export class SubFolderController extends Controller { - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Get("/") - @Tags("แฟ้มย่อย") - @Security("bearerAuth") - @Response( - HttpStatusCode.INTERNAL_SERVER_ERROR, - "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง", - ) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1", - name: "แฟ้มย่อย 1", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - }, - { - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 2", - name: "แฟ้มย่อย 2", - createdAt: "2022-01-23T16:05:02.114Z", - createdBy: "admin", - }, - ]) - public async listFolder( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ): Promise { - const list = await listFolder( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}`, - ).catch((e) => console.error(`Error List Folder: ${e}`)); - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - return list; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - */ - @Post("/") - @Tags("แฟ้มย่อย") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.NOT_FOUND, "ไม่พบของแฟ้ม") - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์") - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - public async createFolder( - @Request() request: { user: { preferred_username: string } }, - @Body() body: { name: string }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - ) { - const basePath = `${cabinetName}/${drawerName}/${folderName}/`; - - if (!(await pathExist(DEFAULT_BUCKET!, basePath))) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างลิ้นชัก"); - } - const meta = { - createdAt: new Date().toISOString(), - createdBy: request.user.preferred_username, - }; - - const created = await minioClient - .putObject(DEFAULT_BUCKET!, `${basePath}${replaceIllegalChars(body.name)}/.keep`, "", 0, meta) - .catch((e) => console.error(e)); - - if (!created) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - - const io = getInstance(); - io?.emit("CreateFolder", { - pathname: `${basePath}${replaceIllegalChars(body.name)}/`, - name: replaceIllegalChars(body.name), - ...meta, - }); - - return this.setStatus(HttpStatusCode.CREATED); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - */ - @Put("/{subFolderName}") - @Tags("แฟ้มย่อย") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้") - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async editFolder( - @Body() - body: { - /** - * @example "แฟ้มใหม่" - */ - name: string; - }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - ) { - const path = `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`; - const list = await listItem(DEFAULT_BUCKET!, path, true); - - await Promise.all( - list.map(async (current) => { - if (!current.name) return; - - const base = `${cabinetName}/${drawerName}/${folderName}/${replaceIllegalChars( - body.name, - )}/`; - const destination = `${base}${current.name.slice(path.length)}`; - const source = `/${DEFAULT_BUCKET}/${current.name}`; - - return await minioClient - .copyObject(DEFAULT_BUCKET!, destination, source, copyCond) - .then(async () => { - if (current.name.includes(".keep")) { - return await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - } - - const search = await esClient.search< - StorageFile & { attachment: Record } - >({ - index: DEFAULT_INDEX!, - query: { match: { pathname: current.name } }, - }); - - if (search && search.hits.hits.length === 0) throw new Error("ไม่พบข้อมูลในฐานข้อมูล"); - - const data = search.hits.hits[0]; - - await esClient.update({ - index: DEFAULT_INDEX!, - id: data._id, - doc: { - pathname: destination, - path: destination.split("/").slice(0, -1).join("/") + "/", - }, - refresh: "wait_for", - }); - - await minioClient.removeObject(DEFAULT_BUCKET!, current.name); - }) - .catch((e) => { - console.error(e); - throw new Error("เกิดข้อผิดพลาด ไม่สามารถย้ายไฟล์ได้"); - }); - }), - ); - - const io = getInstance(); - io?.emit("EditFolder", { - from: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`, - to: `${cabinetName}/${drawerName}/${folderName}/${replaceIllegalChars(body.name)}/`, - }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - */ - @Delete("/{subFolderName}") - @Tags("แฟ้มย่อย") - @Security("bearerAuth", ["admin", "management-role"]) - @SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ") - public async deleteFolder( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - ) { - await new Promise((resolve, reject) => { - const objects: string[] = []; - const stream = minioClient.listObjectsV2( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${subFolderName}`, - true, - ); - - stream.on("data", (v) => { - if (v && v.name) objects.push(v.name); - }); - stream.on("close", async () => - resolve(await minioClient.removeObjects(DEFAULT_BUCKET!, objects)), - ); - stream.on("error", () => reject(new Error("เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้"))); - }); - - const io = getInstance(); - io?.emit("DeleteFolder", { - pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`, - }); - - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - */ - @Get("/{subFolderName}/size") - @Tags("แฟ้มย่อย") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async calc( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - ) { - const list = await listItem( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${subFolderName}`, - true, - ).catch((e) => console.error(`Error List Folder: ${e}`)); - - if (!list) throw new Error("เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง"); - - return { size: list.reduce((a, c) => a + c.size, 0) }; - } -} diff --git a/Services/server/src/controllers/subFolderFileController.ts b/Services/server/src/controllers/subFolderFileController.ts deleted file mode 100644 index acbf655..0000000 --- a/Services/server/src/controllers/subFolderFileController.ts +++ /dev/null @@ -1,455 +0,0 @@ -import { - Body, - Controller, - Delete, - Example, - Get, - Patch, - Path, - Post, - Request, - Response, - Route, - Security, - SuccessResponse, - Tags, -} from "tsoa"; - -import esClient from "../elasticsearch"; -import minioClient from "../minio"; - -import HttpStatusCode from "../interfaces/http-status"; -import { StorageFile } from "../interfaces/storage-fs"; -import HttpError from "../interfaces/http-error"; - -import { copyCond, pathExist, replaceIllegalChars } from "../utils/minio"; -import { getInstance } from "../lib/websocket"; - -const DEFAULT_BUCKET = process.env.MINIO_BUCKET; -const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; - -if (!DEFAULT_BUCKET) throw Error("Default MinIO bucket must be specified."); -if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified."); - -@Route( - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}/file", -) -export class SubFolderFileController extends Controller { - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - */ - @Get("/") - @Tags("ไฟล์") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - @Example([ - { - pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/เอกสาร 1", - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/", - title: "เอกสาร", - description: "เอกสารการเงิน", - category: ["บัญชี"], - keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], - upload: false, - fileName: "เอกสาร 1", - fileSize: 10240, - fileType: "application/pdf", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - updatedAt: "2021-07-20T12:33:13.018Z", - updatedBy: "admin", - }, - ]) - public async getFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - ): Promise { - const search = await esClient.search }>({ - index: DEFAULT_INDEX!, - query: { - match: { - path: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`, - }, - }, - size: 10000, - }); - - const records = search.hits.hits - .map((v) => { - if (v._source) { - const { attachment, ...rest } = v._source; - return rest satisfies StorageFile; - } - }) - .filter((v: StorageFile | undefined): v is StorageFile => !!v); - - return records; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - */ - @Post("/") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @Response( - HttpStatusCode.NOT_FOUND, - "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ", - ) - @SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ") - @Example({ - pathname: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/เอกสาร 1", - path: "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/", - title: "เอกสาร", - description: "เอกสารการเงิน", - category: ["บัญชี"], - keyword: ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"], - upload: false, - fileName: "เอกสาร 1", - fileSize: 10240, - fileType: "application/pdf", - createdAt: "2021-07-20T12:33:13.018Z", - createdBy: "admin", - updatedAt: "2021-07-20T12:33:13.018Z", - updatedBy: "admin", - }) - public async uploadFile( - @Request() request: { user: { preferred_username: string } }, - @Body() - body: { - /** - * @example "เอกสาร 1" - */ - file: string; - /** - * @example "เอกสาร" - */ - title?: string; - /** - * @example "เอกสารการเงิน" - */ - description?: string; - /** - * @example ["บัญชี"] - */ - category?: string[]; - /** - * @example ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"] - */ - keyword?: string[]; - }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - ) { - if (body.file && body.file.length > 85) { - throw new HttpError(HttpStatusCode.BAD_REQUEST, "ชื่อไฟล์ยาวเกินกำหนด"); - } - - const basePath = `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`; - const pathname = `${basePath}${replaceIllegalChars(body.file)}`; - - if (!(await pathExist(DEFAULT_BUCKET!, basePath))) { - throw new HttpError( - HttpStatusCode.NOT_FOUND, - "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ", - ); - } - - const result = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - - // pathname is unique and should not have multiple record with same path - if (result && result.hits.hits.length > 0 && result.hits.hits[0]._source) { - await esClient - .delete({ - index: DEFAULT_INDEX!, - id: result.hits.hits[0]._id, - }) - .catch((e) => console.error(e)); - } - - const rec = result && result.hits.hits.length > 0 ? result.hits.hits[0]._source : false; - - const metadata: Partial = { - pathname, - path: basePath, - fileName: replaceIllegalChars(body.file), - fileSize: 0, - fileType: "", - title: body.title ?? "", - description: body.description ?? "", - category: body.category ?? [], - keyword: body.keyword ?? [], - upload: false, - createdAt: new Date().toISOString(), - createdBy: rec ? rec.createdBy : "n/a", - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - - await esClient.index({ - index: DEFAULT_INDEX!, - document: metadata, - refresh: "wait_for", - }); - - const io = getInstance(); - io?.emit("FileUploadRequest", metadata); - - return { - ...body, - createdAt: metadata.createdAt, - createdBy: metadata.createdBy, - updatedAt: metadata.updatedAt, - updatedBy: metadata.updatedBy, - upload: await minioClient.presignedPutObject(DEFAULT_BUCKET!, pathname), - }; - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - * @example fileName "เอกสาร 1" - */ - @Patch("/{fileName}") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม") - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async updateFile( - @Request() request: { user: { preferred_username: string } }, - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - @Path() fileName: string, - @Body() - body: { - /** - * @example "เอกสารใหม่" - */ - file?: string; - /** - * @example "เอกสารการเงิน" - */ - title?: string; - /** - * @example "เอกสารการเงินฉบับใหม่" - */ - description?: string; - /** - * @example ["บัญชี"] - */ - category?: string[]; - /** - * @example ["เงิน", "บัญชี", "รายจ่าย", "รายรับ"] - */ - keyword?: string[]; - }, - ) { - if (body.file && body.file.length > 85) { - throw new HttpError(HttpStatusCode.BAD_REQUEST, "ชื่อไฟล์ยาวเกินกำหนด"); - } - - const basePath = `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/`; - const pathname = `${basePath}${fileName}`; - - if ( - !Boolean( - await minioClient.statObject(DEFAULT_BUCKET!, `${pathname}`).catch((e) => { - if (e.code === "NotFound") return false; - throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); - }), - ) - ) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์"); - } - - const { file, ...metadata } = body; - - // assume user will probably replace file by re-upload but maybe just rename - if (file) { - const destination = `${basePath}${replaceIllegalChars(file)}`; - const source = `/${DEFAULT_BUCKET}/${basePath}${fileName}`; - const copy = await minioClient.copyObject(DEFAULT_BUCKET!, destination, source, copyCond); - - if (copy) { - const search = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - const meta = { - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - if (search && search.hits.hits.length > 0 && search.hits.hits[0]._source) { - const { _index: index, _id: id } = search.hits.hits[0]; - await esClient - .update({ - index, - id, - doc: { - ...metadata, - pathname: destination, - path: basePath, - fileName: replaceIllegalChars(file), - ...meta, - }, - refresh: "wait_for", - }) - .then(() => minioClient.removeObject(DEFAULT_BUCKET!, pathname)); - - const io = getInstance(); - io?.emit("FileUpdateMove", { - from: search.hits.hits[0]._source, - to: { - ...search.hits.hits[0]._source, - ...metadata, - pathname: destination, - path: basePath, - fileName: replaceIllegalChars(file), - ...meta, - }, - }); - } else { - await minioClient.removeObject(DEFAULT_BUCKET!, pathname); - } - } - } else { - const search = await esClient - .search }>({ - index: DEFAULT_INDEX!, - query: { match: { pathname } }, - }) - .catch((e) => console.error(e)); - - if (search && search.hits.hits.length > 0 && search.hits.hits[0]._source) { - const { _index: index, _id: id } = search.hits.hits[0]; - const meta = { - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }; - await esClient.update({ - index, - id, - doc: { - ...metadata, - updatedAt: new Date().toISOString(), - updatedBy: request.user.preferred_username ?? "n/a", - }, - refresh: "wait_for", - }); - const updated: StorageFile = { - ...search.hits.hits[0]._source, - ...metadata, - ...meta, - }; - - const io = getInstance(); - io?.emit("FileUpdate", updated); - } - } - - return body.file - ? { - upload: await minioClient.presignedPutObject( - DEFAULT_BUCKET!, - `${basePath}${replaceIllegalChars(body.file) ?? fileName}`, - ), - } - : this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example subFolderName "แฟ้มย่อย 1" - * @example fileName "เอกสาร 1" - */ - @Delete("/{fileName}") - @Tags("ไฟล์") - @Security("bearerAuth", ["admin", "management-role"]) - @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") - public async deleteFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - @Path() fileName: string, - ) { - await minioClient.removeObject( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, - ); - await esClient.deleteByQuery({ - index: DEFAULT_INDEX!, - query: { - match: { - pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, - }, - }, - }); - return this.setStatus(HttpStatusCode.NO_CONTENT); - } - - /** - * @example cabinetName "ตู้เอกสาร 1" - * @example drawerName "ลิ้นชัก 1" - * @example folderName "แฟ้ม 1" - * @example folderName "แฟ้มย่อย 1" - * @example fileName "เอกสาร 1" - */ - @Get("/{fileName}") - @Tags("ดาวน์โหลด") - @Security("bearerAuth") - @SuccessResponse(HttpStatusCode.OK) - public async downloadFile( - @Path() cabinetName: string, - @Path() drawerName: string, - @Path() folderName: string, - @Path() subFolderName: string, - @Path() fileName: string, - ) { - const search = await esClient.search }>({ - index: DEFAULT_INDEX!, - query: { - match: { - pathname: `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, - }, - }, - }); - - if (search && search.hits.hits.length === 0) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "Not found"); - } - - const { attachment, ...rest } = search.hits.hits[0]._source!; - - return { - ...rest, - download: await minioClient.presignedGetObject( - DEFAULT_BUCKET!, - `${cabinetName}/${drawerName}/${folderName}/${subFolderName}/${fileName}`, - ), - }; - } -} diff --git a/Services/server/src/rabbitmq/handler.ts b/Services/server/src/rabbitmq/handler.ts index 55fe0bb..d843aa8 100644 --- a/Services/server/src/rabbitmq/handler.ts +++ b/Services/server/src/rabbitmq/handler.ts @@ -111,7 +111,7 @@ async function handleNotFoundRecord( buffer: Buffer, stat: { size: number; type: string }, ) { - const path = pathname.split("/").slice(0, -1).join("/") + "/"; + const path = stripLeadingSlash(pathname.split("/").slice(0, -1).join("/") + "/"); const filename = pathname.split("/").at(-1); const base64 = Buffer.from(buffer).toString("base64"); @@ -175,3 +175,7 @@ async function handleFoundRecord( return true; } + +function stripLeadingSlash(str: string) { + return str.replace(/^\//, ""); +} diff --git a/Services/server/src/routes.ts b/Services/server/src/routes.ts index 03fad76..459fc1d 100644 --- a/Services/server/src/routes.ts +++ b/Services/server/src/routes.ts @@ -3,22 +3,10 @@ // 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 import { Controller, ValidationService, FieldErrors, ValidateError, TsoaRoute, HttpStatusCodeLiteral, TsoaResponse, fetchMiddlewares } from '@tsoa/runtime'; // 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 -import { CabinetController } from './controllers/cabinetController'; -// 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 -import { DrawerController } from './controllers/drawerController'; -// 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 -import { FileController } from './controllers/fileController'; -// 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 -import { FolderController } from './controllers/folderController'; -// 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 import { SearchController } from './controllers/searchController'; // 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 import { StorageController } from './controllers/storageController'; // 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 -import { SubFolderController } from './controllers/subFolderController'; -// 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 -import { SubFolderFileController } from './controllers/subFolderFileController'; -// 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 import { VersionController } from './controllers/versionController'; import { expressAuthentication } from './utils/auth'; // @ts-ignore - no great way to install types from subpackage @@ -28,17 +16,6 @@ import type { RequestHandler, Router } from 'express'; // 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 const models: TsoaRoute.Models = { - "StorageFolder": { - "dataType": "refObject", - "properties": { - "pathname": {"dataType":"string","required":true}, - "name": {"dataType":"string","required":true}, - "createdAt": {"dataType":"union","subSchemas":[{"dataType":"string"},{"dataType":"datetime"}],"required":true}, - "createdBy": {"dataType":"union","subSchemas":[{"dataType":"string"},{"dataType":"datetime"}],"required":true}, - }, - "additionalProperties": false, - }, - // 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 "StorageFile": { "dataType": "refObject", "properties": { @@ -71,6 +48,17 @@ const models: TsoaRoute.Models = { "additionalProperties": false, }, // 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 + "StorageFolder": { + "dataType": "refObject", + "properties": { + "pathname": {"dataType":"string","required":true}, + "name": {"dataType":"string","required":true}, + "createdAt": {"dataType":"union","subSchemas":[{"dataType":"string"},{"dataType":"datetime"}],"required":true}, + "createdBy": {"dataType":"union","subSchemas":[{"dataType":"string"},{"dataType":"datetime"}],"required":true}, + }, + "additionalProperties": false, + }, + // 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 "ListRequestBody": { "dataType": "refObject", "properties": { @@ -124,11 +112,11 @@ const models: TsoaRoute.Models = { "PutFileBody": { "dataType": "refObject", "properties": { + "hidden": {"dataType":"boolean"}, + "keyword": {"dataType":"array","array":{"dataType":"string"}}, "title": {"dataType":"string"}, "description": {"dataType":"string"}, "category": {"dataType":"array","array":{"dataType":"string"}}, - "keyword": {"dataType":"array","array":{"dataType":"string"}}, - "hidden": {"dataType":"boolean"}, "from": {"dataType":"nestedObjectLiteral","nestedProperties":{"file":{"dataType":"string","required":true},"path":{"dataType":"array","array":{"dataType":"string"},"required":true}},"required":true}, "to": {"dataType":"nestedObjectLiteral","nestedProperties":{"file":{"dataType":"string","required":true},"path":{"dataType":"array","array":{"dataType":"string"},"required":true}}}, "upload": {"dataType":"boolean"}, @@ -164,561 +152,6 @@ export function RegisterRoutes(app: Router) { // NOTE: If you do not see routes for all of your controllers in this file, then you might not have informed tsoa of where to look // Please look into the "controllerPathGlobs" config option described in the readme: https://github.com/lukeautry/tsoa // ########################################################################################################### - app.get('/cabinet', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(CabinetController)), - ...(fetchMiddlewares(CabinetController.prototype.listCabinet)), - - function CabinetController_listCabinet(request: any, response: any, next: any) { - const args = { - }; - - // 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new CabinetController(); - - - const promise = controller.listCabinet.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(CabinetController)), - ...(fetchMiddlewares(CabinetController.prototype.createCabinet)), - - function CabinetController_createCabinet(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - }; - - // 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new CabinetController(); - - - const promise = controller.createCabinet.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.put('/cabinet/:cabinetName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(CabinetController)), - ...(fetchMiddlewares(CabinetController.prototype.editCabinet)), - - function CabinetController_editCabinet(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - }; - - // 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new CabinetController(); - - - const promise = controller.editCabinet.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(CabinetController)), - ...(fetchMiddlewares(CabinetController.prototype.deleteCabinet)), - - function CabinetController_deleteCabinet(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new CabinetController(); - - - const promise = controller.deleteCabinet.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/size', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(CabinetController)), - ...(fetchMiddlewares(CabinetController.prototype.calc)), - - function CabinetController_calc(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new CabinetController(); - - - const promise = controller.calc.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(DrawerController)), - ...(fetchMiddlewares(DrawerController.prototype.listDrawer)), - - function DrawerController_listDrawer(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new DrawerController(); - - - const promise = controller.listDrawer.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet/:cabinetName/drawer', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(DrawerController)), - ...(fetchMiddlewares(DrawerController.prototype.createDrawer)), - - function DrawerController_createDrawer(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - }; - - // 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new DrawerController(); - - - const promise = controller.createDrawer.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.put('/cabinet/:cabinetName/drawer/:drawerName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(DrawerController)), - ...(fetchMiddlewares(DrawerController.prototype.editDrawer)), - - function DrawerController_editDrawer(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"path","name":"drawerName","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - }; - - // 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new DrawerController(); - - - const promise = controller.editDrawer.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName/drawer/:drawerName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(DrawerController)), - ...(fetchMiddlewares(DrawerController.prototype.deleteDrawer)), - - function DrawerController_deleteDrawer(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"path","name":"drawerName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new DrawerController(); - - - const promise = controller.deleteDrawer.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/size', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(DrawerController)), - ...(fetchMiddlewares(DrawerController.prototype.calc)), - - function DrawerController_calc(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"path","name":"drawerName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new DrawerController(); - - - const promise = controller.calc.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/file', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(FileController)), - ...(fetchMiddlewares(FileController.prototype.getFile)), - - function FileController_getFile(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FileController(); - - - const promise = controller.getFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/file', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FileController)), - ...(fetchMiddlewares(FileController.prototype.uploadFile)), - - function FileController_uploadFile(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"keyword":{"dataType":"array","array":{"dataType":"string"}},"category":{"dataType":"array","array":{"dataType":"string"}},"description":{"dataType":"string"},"title":{"dataType":"string"},"file":{"dataType":"string","required":true}}}, - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FileController(); - - - const promise = controller.uploadFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.patch('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FileController)), - ...(fetchMiddlewares(FileController.prototype.updateFile)), - - function FileController_updateFile(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - 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"}, - fileName: {"in":"path","name":"fileName","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"keyword":{"dataType":"array","array":{"dataType":"string"}},"category":{"dataType":"array","array":{"dataType":"string"}},"description":{"dataType":"string"},"title":{"dataType":"string"},"file":{"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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FileController(); - - - const promise = controller.updateFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FileController)), - ...(fetchMiddlewares(FileController.prototype.deleteFile)), - - function FileController_deleteFile(request: any, response: any, next: any) { - const args = { - 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"}, - fileName: {"in":"path","name":"fileName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FileController(); - - - const promise = controller.deleteFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(FileController)), - ...(fetchMiddlewares(FileController.prototype.downloadFile)), - - function FileController_downloadFile(request: any, response: any, next: any) { - const args = { - 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"}, - fileName: {"in":"path","name":"fileName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FileController(); - - - const promise = controller.downloadFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(FolderController)), - ...(fetchMiddlewares(FolderController.prototype.listFolder)), - - function FolderController_listFolder(request: any, response: any, next: any) { - const args = { - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"path","name":"drawerName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FolderController(); - - - const promise = controller.listFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet/:cabinetName/drawer/:drawerName/folder', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FolderController)), - ...(fetchMiddlewares(FolderController.prototype.createFolder)), - - function FolderController_createFolder(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - cabinetName: {"in":"path","name":"cabinetName","required":true,"dataType":"string"}, - drawerName: {"in":"path","name":"drawerName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FolderController(); - - - const promise = controller.createFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.put('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FolderController)), - ...(fetchMiddlewares(FolderController.prototype.editFolder)), - - 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":"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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FolderController(); - - - const promise = controller.editFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(FolderController)), - ...(fetchMiddlewares(FolderController.prototype.deleteFolder)), - - function FolderController_deleteFolder(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FolderController(); - - - const promise = controller.deleteFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/size', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(FolderController)), - ...(fetchMiddlewares(FolderController.prototype.calc)), - - function FolderController_calc(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new FolderController(); - - - const promise = controller.calc.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 app.post('/search', authenticateMiddleware([{"bearerAuth":[]}]), ...(fetchMiddlewares(SearchController)), @@ -765,7 +198,7 @@ export function RegisterRoutes(app: Router) { const promise = controller.getList.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, undefined, next); + promiseHandler(controller, promise, response, 200, next); } catch (err) { return next(err); } @@ -844,7 +277,7 @@ export function RegisterRoutes(app: Router) { const promise = controller.folderSize.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, undefined, next); + promiseHandler(controller, promise, response, 200, next); } catch (err) { return next(err); } @@ -975,304 +408,6 @@ export function RegisterRoutes(app: Router) { const controller = new StorageController(); - const promise = controller.downloadFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(SubFolderController)), - ...(fetchMiddlewares(SubFolderController.prototype.listFolder)), - - function SubFolderController_listFolder(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderController(); - - - const promise = controller.listFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderController)), - ...(fetchMiddlewares(SubFolderController.prototype.createFolder)), - - function SubFolderController_createFolder(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"name":{"dataType":"string","required":true}}}, - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderController(); - - - const promise = controller.createFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.put('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderController)), - ...(fetchMiddlewares(SubFolderController.prototype.editFolder)), - - 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":"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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderController(); - - - const promise = controller.editFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderController)), - ...(fetchMiddlewares(SubFolderController.prototype.deleteFolder)), - - function SubFolderController_deleteFolder(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderController(); - - - const promise = controller.deleteFolder.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 204, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/size', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(SubFolderController)), - ...(fetchMiddlewares(SubFolderController.prototype.calc)), - - function SubFolderController_calc(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderController(); - - - const promise = controller.calc.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/file', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(SubFolderFileController)), - ...(fetchMiddlewares(SubFolderFileController.prototype.getFile)), - - function SubFolderFileController_getFile(request: any, response: any, next: any) { - const args = { - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderFileController(); - - - const promise = controller.getFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.post('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/file', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderFileController)), - ...(fetchMiddlewares(SubFolderFileController.prototype.uploadFile)), - - function SubFolderFileController_uploadFile(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"keyword":{"dataType":"array","array":{"dataType":"string"}},"category":{"dataType":"array","array":{"dataType":"string"}},"description":{"dataType":"string"},"title":{"dataType":"string"},"file":{"dataType":"string","required":true}}}, - 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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderFileController(); - - - const promise = controller.uploadFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 201, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.patch('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderFileController)), - ...(fetchMiddlewares(SubFolderFileController.prototype.updateFile)), - - function SubFolderFileController_updateFile(request: any, response: any, next: any) { - const args = { - request: {"in":"request","name":"request","required":true,"dataType":"object"}, - 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"}, - fileName: {"in":"path","name":"fileName","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"keyword":{"dataType":"array","array":{"dataType":"string"}},"category":{"dataType":"array","array":{"dataType":"string"}},"description":{"dataType":"string"},"title":{"dataType":"string"},"file":{"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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderFileController(); - - - const promise = controller.updateFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.delete('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]), - ...(fetchMiddlewares(SubFolderFileController)), - ...(fetchMiddlewares(SubFolderFileController.prototype.deleteFile)), - - function SubFolderFileController_deleteFile(request: any, response: any, next: any) { - const args = { - 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"}, - fileName: {"in":"path","name":"fileName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderFileController(); - - - const promise = controller.deleteFile.apply(controller, validatedArgs as any); - promiseHandler(controller, promise, response, 200, next); - } catch (err) { - return next(err); - } - }); - // 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 - app.get('/cabinet/:cabinetName/drawer/:drawerName/folder/:folderName/subfolder/:subFolderName/file/:fileName', - authenticateMiddleware([{"bearerAuth":[]}]), - ...(fetchMiddlewares(SubFolderFileController)), - ...(fetchMiddlewares(SubFolderFileController.prototype.downloadFile)), - - function SubFolderFileController_downloadFile(request: any, response: any, next: any) { - const args = { - 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"}, - fileName: {"in":"path","name":"fileName","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 - - let validatedArgs: any[] = []; - try { - validatedArgs = getValidatedArgs(args, request, response); - - const controller = new SubFolderFileController(); - - const promise = controller.downloadFile.apply(controller, validatedArgs as any); promiseHandler(controller, promise, response, 200, next); } catch (err) { diff --git a/Services/server/src/swagger.json b/Services/server/src/swagger.json index d6ab43e..4a78f84 100644 --- a/Services/server/src/swagger.json +++ b/Services/server/src/swagger.json @@ -6,46 +6,6 @@ "requestBodies": {}, "responses": {}, "schemas": { - "StorageFolder": { - "properties": { - "pathname": { - "type": "string" - }, - "name": { - "type": "string" - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "createdBy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - } - }, - "required": [ - "pathname", - "name", - "createdAt", - "createdBy" - ], - "type": "object", - "additionalProperties": false - }, "StorageFile": { "properties": { "pathname": { @@ -188,6 +148,46 @@ "type": "object", "additionalProperties": false }, + "StorageFolder": { + "properties": { + "pathname": { + "type": "string" + }, + "name": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "date-time" + } + ] + }, + "createdBy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "date-time" + } + ] + } + }, + "required": [ + "pathname", + "name", + "createdAt", + "createdBy" + ], + "type": "object", + "additionalProperties": false + }, "ListRequestBody": { "properties": { "operation": { @@ -374,6 +374,21 @@ }, "PutFileBody": { "properties": { + "hidden": { + "type": "boolean", + "example": false + }, + "keyword": { + "items": { + "type": "string" + }, + "type": "array", + "example": [ + "การเงิน", + "รายรับ", + "รายจ่าย" + ] + }, "title": { "type": "string", "example": "การเงิน" @@ -392,21 +407,6 @@ "รายงาน" ] }, - "keyword": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "การเงิน", - "รายรับ", - "รายจ่าย" - ] - }, - "hidden": { - "type": "boolean", - "example": false - }, "from": { "properties": { "file": { @@ -538,1437 +538,6 @@ }, "openapi": "3.0.0", "paths": { - "/cabinet": { - "get": { - "operationId": "ListCabinet", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFolder" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "path": "ตู้เอกสาร 1/", - "name": "ตู้เอกสาร 1", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin" - }, - { - "path": "ตู้เอกสาร 2/", - "name": "ตู้เอกสาร 2", - "createdAt": "2022-01-23T16:05:02.114Z", - "createdBy": "admin" - } - ] - } - } - } - } - }, - "500": { - "description": "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการตู้เอกสารได้ กรุณาลองใหม่ในภายหลัง" - } - }, - "tags": [ - "ตู้เอกสาร" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [] - }, - "post": { - "operationId": "CreateCabinet", - "responses": { - "201": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาดกับระบบจัดการไฟล์" - } - }, - "tags": [ - "ตู้เอกสาร" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "ตู้เอกสาร 1" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}": { - "put": { - "operationId": "EditCabinet", - "responses": { - "204": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้" - } - }, - "tags": [ - "ตู้เอกสาร" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "ตู้เอกสารใหม่" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteCabinet", - "responses": { - "204": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้" - } - }, - "tags": [ - "ตู้เอกสาร" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - } - ] - } - }, - "/cabinet/{cabinetName}/size": { - "get": { - "operationId": "Calc", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "size": { - "type": "number", - "format": "double" - } - }, - "required": [ - "size" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "ตู้เอกสาร" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer": { - "get": { - "operationId": "ListDrawer", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFolder" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/", - "name": "ลิ้นชัก 1", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin" - }, - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 2/", - "name": "ลิ้นชัก 2", - "createdAt": "2022-01-23T16:05:02.114Z", - "createdBy": "admin" - } - ] - } - } - } - } - }, - "500": { - "description": "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการลิ้นชักได้ กรุณาลองใหม่ในภายหลัง" - } - }, - "tags": [ - "ลิ้นชัก" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - } - ] - }, - "post": { - "operationId": "CreateDrawer", - "responses": { - "201": { - "description": "สำเร็จ" - }, - "404": { - "description": "ไม่พบลิ้นชัก" - }, - "500": { - "description": "เกิดข้อผิดพลาดกับระบบจัดการไฟล์" - } - }, - "tags": [ - "ลิ้นชัก" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "ลิ้นชัก 1" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}": { - "put": { - "operationId": "EditDrawer", - "responses": { - "204": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้" - } - }, - "tags": [ - "ลิ้นชัก" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "ลิ้นชักใหม่" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteDrawer", - "responses": { - "204": { - "description": "สำเร็จ" - } - }, - "tags": [ - "ลิ้นชัก" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/size": { - "get": { - "operationId": "Calc", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "size": { - "type": "number", - "format": "double" - } - }, - "required": [ - "size" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "ลิ้นชัก" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/file": { - "get": { - "operationId": "GetFile", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFile" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1", - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", - "title": "เอกสาร", - "description": "เอกสารการเงิน", - "category": [ - "บัญชี" - ], - "keyword": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ], - "upload": false, - "fileName": "เอกสาร 1", - "fileSize": 10240, - "fileType": "application/pdf", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin", - "updatedAt": "2021-07-20T12:33:13.018Z", - "updatedBy": "admin" - } - ] - } - } - } - } - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ] - }, - "post": { - "operationId": "UploadFile", - "responses": { - "201": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array" - }, - "category": { - "items": { - "type": "string" - }, - "type": "array" - }, - "description": { - "type": "string" - }, - "title": { - "type": "string" - }, - "file": { - "type": "string" - }, - "upload": { - "type": "string" - }, - "updatedBy": { - "type": "string" - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - } - }, - "required": [ - "file", - "upload", - "updatedBy", - "updatedAt", - "createdBy", - "createdAt" - ], - "type": "object" - }, - "examples": { - "Example 1": { - "value": { - "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1", - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", - "title": "เอกสาร", - "description": "เอกสารการเงิน", - "category": [ - "บัญชี" - ], - "keyword": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ], - "upload": false, - "fileName": "เอกสาร 1", - "fileSize": 10240, - "fileType": "application/pdf", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin", - "updatedAt": "2021-07-20T12:33:13.018Z", - "updatedBy": "admin" - } - } - } - } - } - }, - "404": { - "description": "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ] - }, - "category": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "บัญชี" - ] - }, - "description": { - "type": "string", - "example": "เอกสารการเงิน" - }, - "title": { - "type": "string", - "example": "เอกสาร" - }, - "file": { - "type": "string", - "example": "เอกสาร 1" - } - }, - "required": [ - "file" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/file/{fileName}": { - "patch": { - "operationId": "UpdateFile", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "anyOf": [ - {}, - { - "properties": { - "upload": { - "type": "string" - } - }, - "required": [ - "upload" - ], - "type": "object" - } - ] - } - } - } - }, - "204": { - "description": "สำเร็จ" - }, - "404": { - "description": "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสาร 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ] - }, - "category": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "บัญชี" - ] - }, - "description": { - "type": "string", - "example": "เอกสารการเงินฉบับใหม่" - }, - "title": { - "type": "string", - "example": "เอกสารการเงิน" - }, - "file": { - "type": "string", - "example": "เอกสารใหม่" - } - }, - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteFile", - "responses": { - "200": { - "description": "สำเร็จ" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสารใหม่" - } - ] - }, - "get": { - "operationId": "DownloadFile", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "createdBy": { - "type": "string" - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "updatedBy": { - "type": "string" - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "hidden": { - "type": "boolean" - }, - "upload": { - "type": "boolean" - }, - "path": { - "type": "string" - }, - "keyword": { - "items": { - "type": "string" - }, - "type": "array" - }, - "category": { - "items": { - "type": "string" - }, - "type": "array" - }, - "description": { - "type": "string" - }, - "title": { - "type": "string" - }, - "fileType": { - "type": "string" - }, - "fileSize": { - "type": "number", - "format": "double" - }, - "fileName": { - "type": "string" - }, - "pathname": { - "type": "string" - }, - "download": { - "type": "string" - } - }, - "required": [ - "createdBy", - "createdAt", - "updatedBy", - "updatedAt", - "hidden", - "upload", - "path", - "keyword", - "category", - "description", - "title", - "fileType", - "fileSize", - "fileName", - "pathname", - "download" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "ดาวน์โหลด" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสารใหม่" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder": { - "get": { - "operationId": "ListFolder", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFolder" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1", - "name": "แฟ้ม 1", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin" - }, - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2", - "name": "แฟ้ม 2", - "createdAt": "2022-01-23T16:05:02.114Z", - "createdBy": "admin" - } - ] - } - } - } - } - }, - "500": { - "description": "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง" - } - }, - "tags": [ - "แฟ้ม" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - } - ] - }, - "post": { - "operationId": "CreateFolder", - "responses": { - "201": { - "description": "สำเร็จ" - }, - "404": { - "description": "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม" - }, - "500": { - "description": "เกิดข้อผิดพลาดกับระบบจัดการไฟล์" - } - }, - "tags": [ - "แฟ้ม" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "แฟ้ม 1" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}": { - "put": { - "operationId": "EditFolder", - "responses": { - "204": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้" - } - }, - "tags": [ - "แฟ้ม" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "แฟ้มใหม่" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteFolder", - "responses": { - "204": { - "description": "สำเร็จ" - } - }, - "tags": [ - "แฟ้ม" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/size": { - "get": { - "operationId": "Calc", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "size": { - "type": "number", - "format": "double" - } - }, - "required": [ - "size" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "แฟ้ม" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ] - } - }, "/search": { "post": { "operationId": "SearchFile", @@ -1988,7 +557,7 @@ } }, "tags": [ - "ค้นหา" + "Search" ], "security": [ { @@ -2013,7 +582,7 @@ "operationId": "GetList", "responses": { "200": { - "description": "Ok", + "description": "สำเร็จ", "content": { "application/json": { "schema": { @@ -2036,13 +605,13 @@ "Example 1": { "value": [ { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1", + "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", "name": "แฟ้ม 1", "createdAt": "2021-07-20T12:33:13.018Z", "createdBy": "admin" }, { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2", + "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 2/", "name": "แฟ้ม 2", "createdAt": "2022-01-23T16:05:02.114Z", "createdBy": "admin" @@ -2066,6 +635,7 @@ "รายรับ" ], "upload": false, + "hidden": false, "fileName": "เอกสาร 1.pdf", "fileSize": 10240, "fileType": "application/pdf", @@ -2081,6 +651,7 @@ } } }, + "summary": "แสดงรายการแฟ้มหรือไฟล์", "tags": [ "Storage Folder", "Storage File" @@ -2111,6 +682,7 @@ "description": "สำเร็จ" } }, + "summary": "สร้างแฟ้ม", "tags": [ "Storage Folder" ], @@ -2141,7 +713,8 @@ "description": "สำเร็จ" } }, - "description": "ยา้ย Folder ภายใต้ Folder (Path) หนึ่ง ไปภายใน Folder (Path) หนึ่งและสามารถเปลี่ยนชื่อได้", + "description": "ยา้ยแฟ้มภายในตำแหน่งหนึ่งไปภายในอีกแฟ้มหนึ่ง\nหรือเปลี่ยนชื่อได้", + "summary": "ยา้ยแฟ้ม", "tags": [ "Storage Folder" ], @@ -2202,7 +775,7 @@ "operationId": "FolderSize", "responses": { "200": { - "description": "Ok", + "description": "สำเร็จ", "content": { "application/json": { "schema": { @@ -2216,6 +789,13 @@ "size" ], "type": "object" + }, + "examples": { + "Example 1": { + "value": { + "size": 10240 + } + } } } } @@ -2346,6 +926,35 @@ "uploadUrl" ], "type": "object" + }, + "examples": { + "Example 1": { + "value": { + "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1.pdf", + "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", + "title": "เอกสาร", + "description": "เอกสารการเงิน", + "category": [ + "บัญชี" + ], + "keyword": [ + "เงิน", + "บัญชี", + "รายจ่าย", + "รายรับ" + ], + "upload": false, + "hidden": false, + "fileName": "เอกสาร 1.pdf", + "fileSize": 10240, + "fileType": "application/pdf", + "createdAt": "2021-07-20T12:33:13.018Z", + "createdBy": "admin", + "updatedAt": "2021-07-20T12:33:13.018Z", + "updatedBy": "admin", + "uploadUrl": "s3.storage.upload" + } + } } } } @@ -2397,9 +1006,19 @@ "type": "object" } ] + }, + "examples": { + "Example 1": { + "value": { + "uploadUrl": "s3.storage.upload" + } + } } } } + }, + "204": { + "description": "สำเร็จ" } }, "tags": [ @@ -2558,6 +1177,35 @@ "downloadUrl" ], "type": "object" + }, + "examples": { + "Example 1": { + "value": { + "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/เอกสาร 1.pdf", + "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/", + "title": "เอกสาร", + "description": "เอกสารการเงิน", + "category": [ + "บัญชี" + ], + "keyword": [ + "เงิน", + "บัญชี", + "รายจ่าย", + "รายรับ" + ], + "upload": false, + "hidden": false, + "fileName": "เอกสาร 1.pdf", + "fileSize": 10240, + "fileType": "application/pdf", + "createdAt": "2021-07-20T12:33:13.018Z", + "createdBy": "admin", + "updatedAt": "2021-07-20T12:33:13.018Z", + "updatedBy": "admin", + "downloadUrl": "s3.storage.download" + } + } } } } @@ -2587,1034 +1235,6 @@ } } }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder": { - "get": { - "operationId": "ListFolder", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFolder" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1", - "name": "แฟ้มย่อย 1", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin" - }, - { - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 2", - "name": "แฟ้มย่อย 2", - "createdAt": "2022-01-23T16:05:02.114Z", - "createdBy": "admin" - } - ] - } - } - } - } - }, - "500": { - "description": "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการแฟ้มได้ กรุณาลองใหม่ในภายหลัง" - } - }, - "tags": [ - "แฟ้มย่อย" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ] - }, - "post": { - "operationId": "CreateFolder", - "responses": { - "201": { - "description": "สำเร็จ" - }, - "404": { - "description": "ไม่พบของแฟ้ม" - }, - "500": { - "description": "เกิดข้อผิดพลาดกับระบบจัดการไฟล์" - } - }, - "tags": [ - "แฟ้มย่อย" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}": { - "put": { - "operationId": "EditFolder", - "responses": { - "204": { - "description": "สำเร็จ" - }, - "500": { - "description": "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้" - } - }, - "tags": [ - "แฟ้มย่อย" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "name": { - "type": "string", - "example": "แฟ้มใหม่" - } - }, - "required": [ - "name" - ], - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteFolder", - "responses": { - "204": { - "description": "สำเร็จ" - } - }, - "tags": [ - "แฟ้มย่อย" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}/size": { - "get": { - "operationId": "Calc", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "size": { - "type": "number", - "format": "double" - } - }, - "required": [ - "size" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "แฟ้มย่อย" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - } - ] - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}/file": { - "get": { - "operationId": "GetFile", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/StorageFile" - }, - "type": "array" - }, - "examples": { - "Example 1": { - "value": [ - { - "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/เอกสาร 1", - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/", - "title": "เอกสาร", - "description": "เอกสารการเงิน", - "category": [ - "บัญชี" - ], - "keyword": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ], - "upload": false, - "fileName": "เอกสาร 1", - "fileSize": 10240, - "fileType": "application/pdf", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin", - "updatedAt": "2021-07-20T12:33:13.018Z", - "updatedBy": "admin" - } - ] - } - } - } - } - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - } - ] - }, - "post": { - "operationId": "UploadFile", - "responses": { - "201": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array" - }, - "category": { - "items": { - "type": "string" - }, - "type": "array" - }, - "description": { - "type": "string" - }, - "title": { - "type": "string" - }, - "file": { - "type": "string" - }, - "upload": { - "type": "string" - }, - "updatedBy": { - "type": "string" - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "createdBy": { - "type": "string" - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - } - }, - "required": [ - "file", - "upload", - "updatedBy", - "updatedAt", - "createdBy", - "createdAt" - ], - "type": "object" - }, - "examples": { - "Example 1": { - "value": { - "pathname": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/เอกสาร 1", - "path": "ตู้เอกสาร 1/ลิ้นชัก 1/แฟ้ม 1/แฟ้มย่อย 1/", - "title": "เอกสาร", - "description": "เอกสารการเงิน", - "category": [ - "บัญชี" - ], - "keyword": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ], - "upload": false, - "fileName": "เอกสาร 1", - "fileSize": 10240, - "fileType": "application/pdf", - "createdAt": "2021-07-20T12:33:13.018Z", - "createdBy": "admin", - "updatedAt": "2021-07-20T12:33:13.018Z", - "updatedBy": "admin" - } - } - } - } - } - }, - "404": { - "description": "ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ] - }, - "category": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "บัญชี" - ] - }, - "description": { - "type": "string", - "example": "เอกสารการเงิน" - }, - "title": { - "type": "string", - "example": "เอกสาร" - }, - "file": { - "type": "string", - "example": "เอกสาร 1" - } - }, - "required": [ - "file" - ], - "type": "object" - } - } - } - } - } - }, - "/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}/file/{fileName}": { - "patch": { - "operationId": "UpdateFile", - "responses": { - "200": { - "description": "สำเร็จ", - "content": { - "application/json": { - "schema": { - "anyOf": [ - {}, - { - "properties": { - "upload": { - "type": "string" - } - }, - "required": [ - "upload" - ], - "type": "object" - } - ] - } - } - } - }, - "404": { - "description": "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสาร 1" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "properties": { - "keyword": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "เงิน", - "บัญชี", - "รายจ่าย", - "รายรับ" - ] - }, - "category": { - "items": { - "type": "string" - }, - "type": "array", - "example": [ - "บัญชี" - ] - }, - "description": { - "type": "string", - "example": "เอกสารการเงินฉบับใหม่" - }, - "title": { - "type": "string", - "example": "เอกสารการเงิน" - }, - "file": { - "type": "string", - "example": "เอกสารใหม่" - } - }, - "type": "object" - } - } - } - } - }, - "delete": { - "operationId": "DeleteFile", - "responses": { - "200": { - "description": "สำเร็จ" - } - }, - "tags": [ - "ไฟล์" - ], - "security": [ - { - "bearerAuth": [ - "admin", - "management-role" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้ม 1" - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - }, - "example": "แฟ้มย่อย 1" - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสาร 1" - } - ] - }, - "get": { - "operationId": "DownloadFile", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "properties": { - "createdBy": { - "type": "string" - }, - "createdAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "updatedBy": { - "type": "string" - }, - "updatedAt": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "date-time" - } - ] - }, - "hidden": { - "type": "boolean" - }, - "upload": { - "type": "boolean" - }, - "path": { - "type": "string" - }, - "keyword": { - "items": { - "type": "string" - }, - "type": "array" - }, - "category": { - "items": { - "type": "string" - }, - "type": "array" - }, - "description": { - "type": "string" - }, - "title": { - "type": "string" - }, - "fileType": { - "type": "string" - }, - "fileSize": { - "type": "number", - "format": "double" - }, - "fileName": { - "type": "string" - }, - "pathname": { - "type": "string" - }, - "download": { - "type": "string" - } - }, - "required": [ - "createdBy", - "createdAt", - "updatedBy", - "updatedAt", - "hidden", - "upload", - "path", - "keyword", - "category", - "description", - "title", - "fileType", - "fileSize", - "fileName", - "pathname", - "download" - ], - "type": "object" - } - } - } - } - }, - "tags": [ - "ดาวน์โหลด" - ], - "security": [ - { - "bearerAuth": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "cabinetName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ตู้เอกสาร 1" - }, - { - "in": "path", - "name": "drawerName", - "required": true, - "schema": { - "type": "string" - }, - "example": "ลิ้นชัก 1" - }, - { - "in": "path", - "name": "folderName", - "required": true, - "schema": { - "type": "string" - }, - "examples": { - "Example 1": { - "value": "แฟ้ม 1" - }, - "Example 2": { - "value": "แฟ้มย่อย 1" - } - } - }, - { - "in": "path", - "name": "subFolderName", - "required": true, - "schema": { - "type": "string" - } - }, - { - "in": "path", - "name": "fileName", - "required": true, - "schema": { - "type": "string" - }, - "example": "เอกสาร 1" - } - ] - } - }, "/version": { "get": { "operationId": "GetVersion", @@ -3641,28 +1261,5 @@ "url": "/api" } ], - "tags": [ - { - "name": "ตู้เอกสาร" - }, - { - "name": "ลิ้นชัก" - }, - { - "name": "แฟ้ม" - }, - { - "name": "แฟ้มย่อย" - }, - { - "name": "ไฟล์" - }, - { - "name": "ดาวน์โหลด" - }, - { - "name": "ค้นหา" - } - ], "basePath": "/api" } \ No newline at end of file diff --git a/Services/server/tsoa.json b/Services/server/tsoa.json index 24383ef..e88a36b 100644 --- a/Services/server/tsoa.json +++ b/Services/server/tsoa.json @@ -25,16 +25,7 @@ "description": "Keycloak Bearer Token", "in": "header" } - }, - "tags": [ - { "name": "ตู้เอกสาร" }, - { "name": "ลิ้นชัก" }, - { "name": "แฟ้ม" }, - { "name": "แฟ้มย่อย" }, - { "name": "ไฟล์" }, - { "name": "ดาวน์โหลด" }, - { "name": "ค้นหา" } - ] + } }, "routes": { "routesDir": "src",