feat: subfolder

This commit is contained in:
Methapon2001 2023-11-17 15:17:12 +07:00
parent c3c7a0ad27
commit 083e984c89
No known key found for this signature in database
GPG key ID: 849924FEF46BD132
3 changed files with 488 additions and 0 deletions

View file

@ -0,0 +1,146 @@
import {
Body,
Controller,
Delete,
Get,
Path,
Post,
Put,
Query,
Route,
SuccessResponse,
Tags,
} from "tsoa";
import * as Minio from "minio";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { listFolder, pathExist } from "../utils/minio";
import { EhrFolder } from "../interfaces/ehr-fs";
import minioClient from "../storage";
@Route("/cabinet")
export class SubFolderController extends Controller {
@Get("/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder")
@Tags("SubFolder")
@SuccessResponse(HttpStatusCode.OK)
public async listFolder(
@Path() cabinetName: string,
@Path() drawerName: string,
@Path() folderName: string,
): Promise<EhrFolder[]> {
const fullpath = [cabinetName, drawerName, folderName].join("/") + "/";
if (!(await pathExist(fullpath))) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "Provided path does not exist.");
}
return listFolder(fullpath);
}
@Post("/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder")
@Tags("SubFolder")
@SuccessResponse(HttpStatusCode.CREATED)
public async createFolder(
@Body() body: { name: string },
@Path() cabinetName: string,
@Path() drawerName: string,
@Path() folderName: string,
) {
if (!(await pathExist(`${cabinetName}/${drawerName}/${folderName}`))) {
throw new HttpError(
HttpStatusCode.PRECONDITION_FAILED,
"Cabinet, drawer or folder cannot be found.",
);
}
const uploaded = await minioClient
.putObject("ehr", `${cabinetName}/${drawerName}/${folderName}/${body.name}/.keep`, "", 0, {
createdAt: new Date().toISOString(),
createdBy: "SomeUser",
})
.catch((e) => console.error(e));
if (!uploaded) {
throw new Error("Object storage error occured.");
}
return this.setStatus(HttpStatusCode.CREATED);
}
@Put("/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}")
@Tags("SubFolder")
@SuccessResponse(HttpStatusCode.NO_CONTENT)
public async editFolder(
@Body() body: { name: string },
@Query() cabinetName: string,
@Query() drawerName: string,
@Query() folderName: string,
@Query() subFolderName: string,
) {
const fullpath = [cabinetName, drawerName, folderName, subFolderName].join("/") + "/";
if (!(await pathExist(fullpath))) {
throw new HttpError(
HttpStatusCode.PRECONDITION_FAILED,
"Provided resource location does not exist.",
);
}
return new Promise((resolve, reject) => {
const stream = minioClient.listObjectsV2("ehr", fullpath, true);
stream.on("data", (v) => {
if (!(v && v.name)) return;
const destination = `${cabinetName}/${drawerName}/${folderName}/${body.name}/${v.name.slice(
fullpath.length,
)}`;
const source = `/ehr/${v.name}`;
const cond = new Minio.CopyConditions();
minioClient.copyObject("ehr", destination, source, cond, (e) => {
if (e) {
return reject(new Error("Failed to move."));
}
return minioClient.removeObject("ehr", v.name);
});
});
stream.on("end", () => {
resolve(this.setStatus(HttpStatusCode.NO_CONTENT));
});
stream.on("error", () => reject(new Error("Object storage error occured.")));
});
}
@Delete("/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder/{subFolderName}")
@Tags("SubFolder")
@SuccessResponse(HttpStatusCode.NO_CONTENT)
public async deleteFolder(
@Path() cabinetName: string,
@Path() drawerName: string,
@Path() folderName: string,
@Path() subFolderName: string,
) {
return new Promise((resolve, reject) => {
const objects: string[] = [];
const stream = minioClient.listObjectsV2(
"ehr",
`${cabinetName}/${drawerName}/${folderName}/${subFolderName}`,
true,
);
stream.on("data", (v) => {
if (!(v && v.name)) return;
objects.push(v.name);
});
stream.on("close", () => minioClient.removeObjects("ehr", objects));
stream.on("error", () => reject(new Error("Object storage error occured.")));
resolve(this.setStatus(HttpStatusCode.NO_CONTENT));
});
}
}

View file

@ -10,6 +10,8 @@ import { DrawerController } from './controllers/drawerController';
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 { SubFolderController } from './controllers/subFolderController';
import { expressAuthentication } from './utils/auth';
// @ts-ignore - no great way to install types from subpackage
const promiseAny = require('promise.any');
@ -376,6 +378,118 @@ export function RegisterRoutes(app: Router) {
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/subfolder',
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(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',
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(SubFolderController.prototype.createFolder)),
function SubFolderController_createFolder(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 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',
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(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":"query","name":"cabinetName","required":true,"dataType":"string"},
drawerName: {"in":"query","name":"drawerName","required":true,"dataType":"string"},
folderName: {"in":"query","name":"folderName","required":true,"dataType":"string"},
subFolderName: {"in":"query","name":"subFolderName","required":true,"dataType":"string"},
};
// 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',
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(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) {

View file

@ -607,6 +607,234 @@
}
}
}
},
"/cabinet/{cabinetName}/drawer/{drawerName}/folder/{folderName}/subfolder": {
"get": {
"operationId": "ListFolder",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/EhrFolder"
},
"type": "array"
}
}
}
}
},
"tags": [
"SubFolder"
],
"security": [],
"parameters": [
{
"in": "path",
"name": "cabinetName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "drawerName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "folderName",
"required": true,
"schema": {
"type": "string"
}
}
]
},
"post": {
"operationId": "CreateFolder",
"responses": {
"201": {
"description": ""
}
},
"tags": [
"SubFolder"
],
"security": [],
"parameters": [
{
"in": "path",
"name": "cabinetName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "drawerName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "folderName",
"required": true,
"schema": {
"type": "string"
}
}
],
"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": "",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"tags": [
"SubFolder"
],
"security": [],
"parameters": [
{
"in": "query",
"name": "cabinetName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "drawerName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "folderName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "subFolderName",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
}
}
}
}
},
"delete": {
"operationId": "DeleteFolder",
"responses": {
"204": {
"description": "",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"tags": [
"SubFolder"
],
"security": [],
"parameters": [
{
"in": "path",
"name": "cabinetName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "drawerName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "folderName",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "subFolderName",
"required": true,
"schema": {
"type": "string"
}
}
]
}
}
},
"servers": [