Merge branch 'development' of https://github.com/Frappet/EDM into oat

This commit is contained in:
oat 2023-12-04 16:43:17 +07:00
commit 65abeb27cd
13 changed files with 153 additions and 79 deletions

View file

@ -20,6 +20,7 @@
"@tsconfig/node18": "^18.2.2",
"axios": "^1.6.2",
"keycloak-js": "^23.0.0",
"nanoid": "^5.0.4",
"pinia": "^2.1.7",
"quasar": "^2.14.0",
"vite-plugin-pwa": "^0.17.2",

View file

@ -19,9 +19,8 @@ const props = withDefaults(
)
const DEPT_NAME = ['ตู้เอกสาร', 'ลิ้นชัก', 'แฟ้ม', 'แฟ้มย่อย'] as const
const { getFileInfo } = useFileInfoStore()
const { currentFolder, currentFile, currentDept, currentPath } = storeToRefs(
useTreeDataStore()
)
const { currentFolder, currentFile, currentDept, currentPath } =
storeToRefs(useTreeDataStore())
const {
createFolder,
editFolder,
@ -38,8 +37,8 @@ const currentIcon = computed(() =>
currentDept.value === 0
? 'mdi-file-cabinet'
: currentDept.value === 1
? 'inbox'
: 'o_folder_open',
? 'inbox'
: 'o_folder_open',
)
const dialogDeleteState = ref<boolean>(false)
@ -184,7 +183,10 @@ async function submitFileForm(
{{ DEPT_NAME[currentDept] }}
</div>
<div class="grid q-mt-md">
<div v-for="(value, index) in currentFolder" key="value.name">
<div
v-for="(value, index) in currentFolder"
:data-pathname="value.pathname"
>
<div
:style="{
position: 'relative',
@ -200,7 +202,6 @@ async function submitFileForm(
;(folderFormState = false), getFolder(value.pathname)
}
"
:id="`getFolderFileItem${index}`"
>
<div class="q-px-md flex items-center justify-center">
<q-icon
@ -217,6 +218,7 @@ async function submitFileForm(
v-if="props.action"
>
<file-item-action
:nameId="value.pathname"
@delete="() => triggerFolderDelete(value.pathname)"
@edit="() => triggerFolderEdit(value.name, value.pathname)"
/>
@ -289,7 +291,7 @@ async function submitFileForm(
เอกสาร
</div>
<div class="grid q-mt-md">
<div v-for="(value, index) in currentFile">
<div v-for="(value, index) in currentFile" :data-pathname="value.pathname">
<div
:style="{
position: 'relative',
@ -316,6 +318,7 @@ async function submitFileForm(
v-if="props.action"
>
<file-item-action
:nameId="value.pathname"
@edit="
() =>
triggerFileEdit(

View file

@ -1,9 +1,17 @@
<script lang="ts" setup>
defineEmits(['edit', 'delete'])
const props =
defineProps<{
nameId: string
}>()
</script>
<template>
<q-btn @click.stop icon="more_vert" color="grey" flat dense>
<q-btn @click.stop icon="more_vert" color="grey" flat dense :id="props.nameId">
<q-menu auto-close>
<q-list dense>
<q-item clickable @click="() => $emit('edit')" id="FileltemActionEdit">

View file

@ -35,4 +35,4 @@ app.listen(PORT, "0.0.0.0", () =>
console.log(`[APP] Application is running on http://localhost:${PORT}`),
);
rabbitmq.init(amqHandler).catch((e) => console.error(e));
// rabbitmq.init(amqHandler).catch((e) => console.error(e));

View file

@ -64,7 +64,7 @@ export class CabinetController extends Controller {
@Post("/")
@Tags("ตู้เอกสาร")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์")
@SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ")
public async createCabinet(
@ -94,7 +94,7 @@ export class CabinetController extends Controller {
*/
@Put("/{cabinetName}")
@Tags("ตู้เอกสาร")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้")
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async editCabinet(
@ -163,7 +163,7 @@ export class CabinetController extends Controller {
*/
@Delete("/{cabinetName}")
@Tags("ตู้เอกสาร")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาด ไม่สามารถลบไฟล์ได้")
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async deleteCabinet(@Path() cabinetName: string) {

View file

@ -71,7 +71,7 @@ export class DrawerController extends Controller {
*/
@Post("/")
@Tags("ลิ้นชัก")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.NOT_FOUND, "ไม่พบลิ้นชัก")
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์")
@SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ")
@ -110,7 +110,7 @@ export class DrawerController extends Controller {
*/
@Put("/{drawerName}")
@Tags("ลิ้นชัก")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้")
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async editDrawer(
@ -181,7 +181,7 @@ export class DrawerController extends Controller {
*/
@Delete("/{drawerName}")
@Tags("ลิ้นชัก")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async deleteDrawer(@Path() cabinetName: string, @Path() drawerName: string) {
await new Promise<void>((resolve, reject) => {

View file

@ -93,7 +93,7 @@ export class FileController extends Controller {
*/
@Post("/")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(
HttpStatusCode.NOT_FOUND,
"ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ",
@ -180,7 +180,7 @@ export class FileController extends Controller {
const metadata: Partial<StorageFile> = {
pathname,
path: basePath,
fileName: replaceIllegalChars( body.file ),
fileName: replaceIllegalChars(body.file),
fileSize: 0,
fileType: "",
title: body.title ?? "",
@ -218,7 +218,7 @@ export class FileController extends Controller {
*/
@Patch("/{fileName}")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม")
@Response(HttpStatusCode.NO_CONTENT, "สำเร็จ")
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
@ -270,9 +270,11 @@ export class FileController extends Controller {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์");
}
const { file, ...metadata } = body;
// assume user will probably replace file by re-upload but maybe just rename
if (body.file) {
const destination = `${basePath}${replaceIllegalChars(body.file)}`;
if (file) {
const destination = `${basePath}${replaceIllegalChars(file)}`;
const source = `/${DEFAULT_BUCKET}/${basePath}${fileName}`;
const copy = await minioClient.copyObject(DEFAULT_BUCKET!, destination, source, copyCond);
@ -291,9 +293,10 @@ export class FileController extends Controller {
index,
id,
doc: {
...metadata,
pathname: destination,
path: basePath,
fileName: replaceIllegalChars(body.file),
fileName: replaceIllegalChars(file),
updatedAt: new Date().toISOString(),
updatedBy: request.user.preferred_username ?? "n/a",
},
@ -318,7 +321,7 @@ export class FileController extends Controller {
index,
id,
doc: {
...body,
...metadata,
updatedAt: new Date().toISOString(),
updatedBy: request.user.preferred_username ?? "n/a",
},
@ -345,7 +348,7 @@ export class FileController extends Controller {
*/
@Delete("/{fileName}")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
public async deleteFile(
@Path() cabinetName: string,

View file

@ -75,7 +75,7 @@ export class FolderController extends Controller {
*/
@Post("/")
@Tags("แฟ้ม")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม")
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์")
@SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ")
@ -116,7 +116,7 @@ export class FolderController extends Controller {
*/
@Put("/{folderName}")
@Tags("แฟ้ม")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้")
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async editFolder(
@ -189,7 +189,7 @@ export class FolderController extends Controller {
*/
@Delete("/{folderName}")
@Tags("แฟ้ม")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async deleteFolder(
@Path() cabinetName: string,

View file

@ -79,7 +79,7 @@ export class SubFolderController extends Controller {
*/
@Post("/")
@Tags("แฟ้มย่อย")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.NOT_FOUND, "ไม่พบของแฟ้ม")
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดกับระบบจัดการไฟล์")
@SuccessResponse(HttpStatusCode.CREATED, "สำเร็จ")
@ -116,7 +116,7 @@ export class SubFolderController extends Controller {
*/
@Put("/{subFolderName}")
@Tags("แฟ้มย่อย")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดไม่สามารถย้ายไฟล์ได้")
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async editFolder(
@ -193,7 +193,7 @@ export class SubFolderController extends Controller {
*/
@Delete("/{subFolderName}")
@Tags("แฟ้มย่อย")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@SuccessResponse(HttpStatusCode.NO_CONTENT, "สำเร็จ")
public async deleteFolder(
@Path() cabinetName: string,

View file

@ -98,7 +98,7 @@ export class SubFolderFileController extends Controller {
*/
@Post("/")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(
HttpStatusCode.NOT_FOUND,
"ตำแหน่งที่ระบุไม่พบ กรุณาเตรียมตำแหน่งที่ต้องการก่อนดำเนินการ",
@ -225,7 +225,7 @@ export class SubFolderFileController extends Controller {
*/
@Patch("/{fileName}")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@Response(HttpStatusCode.NOT_FOUND, "ไม่พบตำแหน่งที่ต้องการสร้างแฟ้ม")
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
public async updateFile(
@ -277,9 +277,11 @@ export class SubFolderFileController extends Controller {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบไฟล์");
}
const { file, ...metadata } = body;
// assume user will probably replace file by re-upload but maybe just rename
if (body.file) {
const destination = `${basePath}${replaceIllegalChars(body.file)}`;
if (file) {
const destination = `${basePath}${replaceIllegalChars(file)}`;
const source = `/${DEFAULT_BUCKET}/${basePath}${fileName}`;
const copy = await minioClient.copyObject(DEFAULT_BUCKET!, destination, source, copyCond);
@ -298,8 +300,10 @@ export class SubFolderFileController extends Controller {
index,
id,
doc: {
...metadata,
pathname: destination,
fileName: replaceIllegalChars(body.file),
path: basePath,
fileName: replaceIllegalChars(file),
updatedAt: new Date().toISOString(),
updatedBy: request.user.preferred_username ?? "n/a",
},
@ -324,7 +328,7 @@ export class SubFolderFileController extends Controller {
index,
id,
doc: {
...body,
...metadata,
updatedAt: new Date().toISOString(),
updatedBy: request.user.preferred_username ?? "n/a",
},
@ -352,7 +356,7 @@ export class SubFolderFileController extends Controller {
*/
@Delete("/{fileName}")
@Tags("ไฟล์")
@Security("bearerAuth", ["admin"])
@Security("bearerAuth", ["admin", "management-role"])
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
public async deleteFile(
@Path() cabinetName: string,

View file

@ -101,7 +101,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(CabinetController)),
...(fetchMiddlewares<RequestHandler>(CabinetController.prototype.createCabinet)),
@ -128,7 +128,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(CabinetController)),
...(fetchMiddlewares<RequestHandler>(CabinetController.prototype.editCabinet)),
@ -155,7 +155,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(CabinetController)),
...(fetchMiddlewares<RequestHandler>(CabinetController.prototype.deleteCabinet)),
@ -207,7 +207,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(DrawerController)),
...(fetchMiddlewares<RequestHandler>(DrawerController.prototype.createDrawer)),
@ -235,7 +235,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(DrawerController)),
...(fetchMiddlewares<RequestHandler>(DrawerController.prototype.editDrawer)),
@ -263,7 +263,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(DrawerController)),
...(fetchMiddlewares<RequestHandler>(DrawerController.prototype.deleteDrawer)),
@ -318,7 +318,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FileController)),
...(fetchMiddlewares<RequestHandler>(FileController.prototype.uploadFile)),
@ -348,7 +348,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FileController)),
...(fetchMiddlewares<RequestHandler>(FileController.prototype.updateFile)),
@ -379,7 +379,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FileController)),
...(fetchMiddlewares<RequestHandler>(FileController.prototype.deleteFile)),
@ -464,7 +464,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FolderController)),
...(fetchMiddlewares<RequestHandler>(FolderController.prototype.createFolder)),
@ -493,7 +493,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FolderController)),
...(fetchMiddlewares<RequestHandler>(FolderController.prototype.editFolder)),
@ -522,7 +522,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(FolderController)),
...(fetchMiddlewares<RequestHandler>(FolderController.prototype.deleteFolder)),
@ -604,7 +604,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(SubFolderController.prototype.createFolder)),
@ -634,7 +634,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(SubFolderController.prototype.editFolder)),
@ -664,7 +664,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderController)),
...(fetchMiddlewares<RequestHandler>(SubFolderController.prototype.deleteFolder)),
@ -722,7 +722,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController)),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController.prototype.uploadFile)),
@ -753,7 +753,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController)),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController.prototype.updateFile)),
@ -785,7 +785,7 @@ export function RegisterRoutes(app: Router) {
});
// 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"]}]),
authenticateMiddleware([{"bearerAuth":["admin","management-role"]}]),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController)),
...(fetchMiddlewares<RequestHandler>(SubFolderFileController.prototype.deleteFile)),

View file

@ -261,7 +261,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -304,7 +305,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -355,7 +357,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -450,7 +453,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -503,7 +507,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -560,7 +565,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -783,7 +789,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -906,7 +913,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1007,7 +1015,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1286,7 +1295,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1348,7 +1358,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1414,7 +1425,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1584,7 +1596,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1654,7 +1667,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1729,7 +1743,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -1979,7 +1994,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -2108,7 +2124,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],
@ -2218,7 +2235,8 @@
"security": [
{
"bearerAuth": [
"admin"
"admin",
"management-role"
]
}
],

View file

@ -1,12 +1,19 @@
import * as express from "express";
import { createVerifier } from "fast-jwt";
import { createDecoder, createVerifier } from "fast-jwt";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { JwtPayload } from "jsonwebtoken";
if (!process.env.PUBLIC_KEY && !process.env.REALM_URL) {
if (!(process.env.PUBLIC_KEY && process.env.REALM_URL)) {
throw new Error("Require public key or realm url.");
}
if (process.env.PUBLIC_KEY && process.env.REALM_URL && !process.env.PREFERRED_AUTH) {
throw new Error("Preferred auth type must be specified if public key and realm url is provided.");
}
if (!process.env.MANAGEMENT_ROLE) {
throw new Error("Management role env is required.");
}
const jwtVerify = createVerifier({
key: async () => {
@ -14,6 +21,8 @@ const jwtVerify = createVerifier({
},
});
const jwtDecode = createDecoder();
export async function expressAuthentication(
request: express.Request,
securityName: string,
@ -29,19 +38,47 @@ export async function expressAuthentication(
if (!token) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "No token provided.");
const payload = await jwtVerify(token).catch((_) => null);
let payload: JwtPayload = {};
if (!payload) {
throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
switch (process.env.PREFERRED_AUTH) {
case "online":
payload = await verifyOnline(token);
break;
case "offline":
payload = await verifyOffline(token);
break;
default:
if (process.env.REALM_URL) payload = await verifyOnline(token);
if (process.env.PUBLIC_KEY) payload = await verifyOffline(token);
break;
}
if (
scopes &&
scopes.length > 0 &&
scopes.some((v) => !payload.resource_access[payload.azp].roles.includes(v))
scopes
.map((v) => (v === "management-role" ? process.env.MANAGEMENT_ROLE : v))
.every((v) => !payload.resource_access[payload.azp].roles.includes(v))
) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "You are not allowed to perform this action.");
}
return payload;
}
async function verifyOffline(token: string) {
const payload = await jwtVerify(token).catch((_) => null);
if (!payload) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
return payload;
}
async function verifyOnline(token: string) {
const res = await fetch(`${process.env.REALM_URL}/protocol/openid-connect/userinfo`, {
headers: { authorization: `Bearer ${token}` },
}).catch((e) => console.error(e));
if (!res) throw new Error("Cannot connect to auth service.");
if (!res.ok) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
return await jwtDecode(token);
}