From 0bf7e9f7409230b90bab8716a902d46715af564b Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:11:44 +0700 Subject: [PATCH] feat: branch permission for task order --- prisma/schema.prisma | 6 +-- src/controllers/07-task-controller.ts | 77 ++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b842e47..5610974 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -312,6 +312,7 @@ model Branch { productGroup ProductGroup[] quotation Quotation[] workflowTemplate WorkflowTemplate[] + taskOrder TaskOrder[] } model BranchBank { @@ -481,7 +482,6 @@ model User { notificationReceive Notification[] @relation("NotificationReceiver") notificationRead Notification[] taskOrderCreated TaskOrder[] @relation("TaskOrderCreatedByUser") - taskOrderAccepted TaskOrder[] requestWorkStepStatus RequestWorkStepStatus[] } @@ -1494,8 +1494,8 @@ model TaskOrder { institution Institution @relation(fields: [institutionId], references: [id]) institutionId String - acceptedBy User? @relation(fields: [acceptedByUserId], references: [id]) - acceptedByUserId String? + registeredBranch Branch @relation(fields: [registeredBranchId], references: [id]) + registeredBranchId String createdAt DateTime @default(now()) createdBy User @relation(name: "TaskOrderCreatedByUser", fields: [createdByUserId], references: [id]) diff --git a/src/controllers/07-task-controller.ts b/src/controllers/07-task-controller.ts index f6e89e2..ef5e9c8 100644 --- a/src/controllers/07-task-controller.ts +++ b/src/controllers/07-task-controller.ts @@ -14,8 +14,27 @@ import { } from "tsoa"; import prisma from "../db"; import { notFoundError } from "../utils/error"; -import { TaskStatus } from "@prisma/client"; +import { RequestWorkStatus, TaskStatus } from "@prisma/client"; import { RequestWithUser } from "../interfaces/user"; +import { + branchRelationPermInclude, + createPermCheck, + createPermCondition, +} from "../services/permission"; +import HttpError from "../interfaces/http-error"; +import HttpStatus from "../interfaces/http-status"; + +const MANAGE_ROLES = ["system", "head_of_admin", "admin", "document_checker"]; + +function globalAllow(user: RequestWithUser["user"]) { + const allowList = ["system", "head_of_admin"]; + return allowList.some((v) => user.roles?.includes(v)); +} + +const permissionCondCompany = createPermCondition((_) => true); + +const permissionCheck = createPermCheck(globalAllow); +const permissionCheckCompany = createPermCheck((_) => true); @Route("/api/v1/task") @Tags("Task Order") @@ -40,6 +59,7 @@ export class TaskController extends Controller { @Get() @Security("keycloak") async getTaskOrderList( + @Request() req: RequestWithUser, @Query() query: string = "", @Query() page = 1, @Query() pageSize = 30, @@ -49,6 +69,7 @@ export class TaskController extends Controller { prisma.taskOrder.findMany({ where: { taskStatus, + registeredBranch: { OR: permissionCondCompany(req.user) }, OR: [ { code: { contains: query, mode: "insensitive" } }, { taskName: { contains: query } }, @@ -58,7 +79,6 @@ export class TaskController extends Controller { }, include: { institution: true, - acceptedBy: true, createdBy: true, }, }), @@ -70,9 +90,9 @@ export class TaskController extends Controller { @Get("{taskId}") @Security("keycloak") - async getTaskOrder(@Path() taskId: string) { + async getTaskOrder(@Request() req: RequestWithUser, @Path() taskId: string) { const record = await prisma.taskOrder.findFirst({ - where: { id: taskId }, + where: { id: taskId, registeredBranch: { OR: permissionCondCompany(req.user) } }, include: { taskList: { include: { @@ -84,7 +104,6 @@ export class TaskController extends Controller { }, }, institution: true, - acceptedBy: true, createdBy: true, }, }); @@ -95,7 +114,7 @@ export class TaskController extends Controller { } @Post() - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async createTaskOrderList( @Request() req: RequestWithUser, @Body() @@ -106,6 +125,7 @@ export class TaskController extends Controller { contactTel: string; institutionId: string; + registeredBranchId?: string; requestWork: { requestWorkId: string; step: number }[]; }, @@ -131,6 +151,23 @@ export class TaskController extends Controller { const { requestWork, ...rest } = body; + const userAffiliatedBranch = await tx.branch.findFirst({ + include: branchRelationPermInclude(req.user), + where: body.registeredBranchId + ? { id: body.registeredBranchId } + : { + user: { some: { userId: req.user.sub } }, + }, + }); + if (!userAffiliatedBranch) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "You must be affilated with at least one branch or specify branch to be registered (System permission required).", + "reqMinAffilatedBranch", + ); + } + await permissionCheckCompany(req.user, userAffiliatedBranch); + await tx.taskOrder.create({ include: { taskList: { @@ -139,12 +176,12 @@ export class TaskController extends Controller { }, }, institution: true, - acceptedBy: true, createdBy: true, }, data: { ...rest, code, + registeredBranchId: userAffiliatedBranch.id, createdByUserId: req.user.sub, taskList: { connect: requestWork.map((v) => ({ step_requestWorkId: v })), @@ -156,6 +193,7 @@ export class TaskController extends Controller { @Put("{taskId}") async editTaskById( + @Request() req: RequestWithUser, @Path() taskId: string, @Body() body: { @@ -173,15 +211,19 @@ export class TaskController extends Controller { const record = await prisma.taskOrder.findFirst({ where: { id: taskId }, include: { + registeredBranch: { include: branchRelationPermInclude(req.user) }, taskList: { include: { requestWork: true }, }, institution: true, - acceptedBy: true, createdBy: true, }, }); + if (!record) throw notFoundError("Task Order"); + + await permissionCheckCompany(req.user, record.registeredBranch); + await prisma.taskOrder.update({ where: { id: taskId }, include: { @@ -191,7 +233,7 @@ export class TaskController extends Controller { }, }, institution: true, - acceptedBy: true, + registeredBranch: true, createdBy: true, }, data: { @@ -217,11 +259,21 @@ export class TaskController extends Controller { } @Delete("{taskId}") - async deleteTask(@Path() taskId: string) { + @Security("keycloak", MANAGE_ROLES) + async deleteTask(@Request() req: RequestWithUser, @Path() taskId: string) { await prisma.$transaction(async (tx) => { - let record = await tx.taskOrder.deleteMany({ where: { id: taskId } }); + let record = await tx.taskOrder.findFirst({ + where: { id: taskId }, + include: { + registeredBranch: { + include: branchRelationPermInclude(req.user), + }, + }, + }); - if (record.count <= 0) throw notFoundError("Task Order"); + if (!record) throw notFoundError("Task Order"); + + await permissionCheck(req.user, record.registeredBranch); }); } } @@ -247,7 +299,6 @@ export class TaskActionController extends Controller { where: { id: taskId }, data: { taskStatus: "InProgress", - acceptedByUserId: req.user.sub, }, }); await tx.requestWorkStepStatus.updateMany({