From 9f426d9b0890bfd252c56a9e8a6aa46975cdc72a Mon Sep 17 00:00:00 2001 From: Methapon Metanipat Date: Wed, 4 Sep 2024 11:40:55 +0700 Subject: [PATCH] refactor: permission user --- src/controllers/user-controller.ts | 133 +++++++++++++---------------- 1 file changed, 59 insertions(+), 74 deletions(-) diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 2979da2..60c1b4e 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -34,6 +34,12 @@ if (!process.env.MINIO_BUCKET) { } const MINIO_BUCKET = process.env.MINIO_BUCKET; +const MANAGE_ROLES = ["system", "head_of_admin", "admin", "branch_manager"]; + +function globalAllow(user: RequestWithUser["user"]) { + const listAllowed = ["system", "head_of_admin"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; +} type UserCreate = { status?: Status; @@ -294,7 +300,7 @@ export class UserController extends Controller { } @Post() - @Security("keycloak", ["system", "head_of_admin", "admin", "branch_admin", "branch_manager"]) + @Security("keycloak", MANAGE_ROLES) async createUser(@Request() req: RequestWithUser, @Body() body: UserCreate) { const [province, district, subDistrict, branch, user] = await prisma.$transaction([ prisma.province.findFirst({ where: { id: body.provinceId ?? undefined } }), @@ -340,31 +346,25 @@ export class UserController extends Controller { throw new HttpError(HttpStatus.BAD_REQUEST, "User exists.", "userExists"); } - if (!["system", "head_of_admin", "admin"].some((v) => req.user.roles?.includes(v))) { - if (body.userRole in ["system", "head_of_admin", "admin"]) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); - } - if (!req.user.roles.includes("branch_admin") && body.userRole === "branch_admin") { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); - } + const roleSetIndex = MANAGE_ROLES.findIndex((v) => v === body.userRole); + + const THROW_PERM_MSG = "You do not have permission to perform this action."; + const THROW_PERM_CODE = "noPermission"; + + if (roleSetIndex !== -1 && roleSetIndex < 1) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); } - if ( - !["system", "head_of_admin", "admin"].some((v) => req.user.roles?.includes(v)) && - branch?.some((v) => !v.user.find((v) => v.userId === req.user.sub)) - ) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); + if (roleSetIndex !== -1 && roleSetIndex < 2 && !req.user.roles?.includes("head_of_admin")) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } + if (roleSetIndex !== -1 && roleSetIndex < 3 && !req.user.roles?.includes("admin")) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } + + if (!globalAllow(req.user)) { + if (branch.some((v) => !v.user.find((v) => v.userId === req.user.sub))) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } } const { branchId, provinceId, districtId, subDistrictId, username, ...rest } = body; @@ -416,27 +416,24 @@ export class UserController extends Controller { province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + branch: { + create: Array.isArray(branchId) + ? branchId.map((v) => ({ + branchId: v, + createdByUserId: req.user.sub, + udatedByUserId: req.user.sub, + })) + : { + branchId, + createdByUserId: req.user.sub, + updatedByUserId: req.user.sub, + }, + }, createdBy: { connect: { id: req.user.sub } }, updatedBy: { connect: { id: req.user.sub } }, }, }); - await prisma.branchUser.createMany({ - data: Array.isArray(branchId) - ? branchId.map((v) => ({ - branchId: v, - userId: record.id, - createdByUserId: req.user.sub, - updatedByUserId: req.user.sub, - })) - : { - branchId, - userId: record.id, - createdByUserId: req.user.sub, - updatedByUserId: req.user.sub, - }, - }); - const updated = await userBranchCodeGen(record, branch[0]); // only generate code by using first branch only record.code = updated.code; @@ -458,7 +455,7 @@ export class UserController extends Controller { } @Put("{userId}") - @Security("keycloak", ["system", "head_of_admin", "admin", "branch_admin", "branch_manager"]) + @Security("keycloak", MANAGE_ROLES) async editUser( @Request() req: RequestWithUser, @Body() body: UserUpdate, @@ -509,34 +506,25 @@ export class UserController extends Controller { "minimumBranchNotMet", ); } - if ( - body.userRole && - !["system", "head_of_admin", "admin"].some((v) => req.user.roles?.includes(v)) - ) { - if (body.userRole in ["system", "head_of_admin", "admin"]) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); - } - if (!req.user.roles.includes("branch_admin") && body.userRole === "branch_admin") { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); - } + const roleSetIndex = MANAGE_ROLES.findIndex((v) => v === body.userRole); + + const THROW_PERM_MSG = "You do not have permission to perform this action."; + const THROW_PERM_CODE = "noPermission"; + + if (roleSetIndex !== -1 && roleSetIndex < 1) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); } - if ( - !["system", "head_of_admin", "admin"].some((v) => req.user.roles?.includes(v)) && - branch?.some((v) => !v.user.find((v) => v.userId === req.user.sub)) - ) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "You do not have permission to perform this action.", - "noPermission", - ); + if (roleSetIndex !== -1 && roleSetIndex < 2 && !req.user.roles?.includes("head_of_admin")) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } + if (roleSetIndex !== -1 && roleSetIndex < 3 && !req.user.roles?.includes("admin")) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } + + if (!globalAllow(req.user)) { + if (branch.some((v) => !v.user.find((v) => v.userId === req.user.sub))) { + throw new HttpError(HttpStatus.FORBIDDEN, THROW_PERM_MSG, THROW_PERM_CODE); + } } let userRole: string | undefined; @@ -658,7 +646,7 @@ export class UserController extends Controller { } @Delete("{userId}") - @Security("keycloak", ["system", "head_of_admin", "admin", "branch_admin", "branch_manager"]) + @Security("keycloak", MANAGE_ROLES) async deleteUser(@Request() req: RequestWithUser, @Path() userId: string) { const record = await prisma.user.findFirst({ include: { @@ -676,10 +664,7 @@ export class UserController extends Controller { where: { id: userId }, }); - if ( - !["system", "head_of_admin", "admin"].some((v) => req.user.roles?.includes(v)) && - !record?.branch.some((v) => v.userId === req.user.sub) - ) { + if (!globalAllow(req.user) && !record?.branch.some((v) => v.userId === req.user.sub)) { throw new HttpError( HttpStatus.FORBIDDEN, "You do not have permission to perform this action.",