diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index e067951..da1008d 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -24,7 +24,28 @@ if (!process.env.MINIO_BUCKET) { } const MINIO_BUCKET = process.env.MINIO_BUCKET; -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "branch_manager", "head_of_sale", "sale"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "branch_manager", + "head_of_sale", + "sale", + "head_of_account", + "account", +]; + +function globalAllow(user: RequestWithUser["user"]) { + const allowList = [ + "system", + "head_of_admin", + "admin", + "branch_manager", + "head_of_sale", + "head_of_account", + ]; + return allowList.some((v) => user.roles?.includes(v)); +} export type CustomerCreate = { registeredBranchId?: string; @@ -167,8 +188,20 @@ export class CustomerController extends Controller { @Post() @Security("keycloak", MANAGE_ROLES) async create(@Request() req: RequestWithUser, @Body() body: CustomerCreate) { + // NOTE: handle empty string + if (!body.registeredBranchId) { + body.registeredBranchId = undefined; + } + const [branch] = await prisma.$transaction([ - prisma.branch.findFirst({ where: { id: body.registeredBranchId } }), + prisma.branch.findFirst({ + where: { id: body.registeredBranchId }, + include: { + user: { + where: { userId: req.user.sub }, + }, + }, + }), ]); if (!!body.registeredBranchId && !branch) { @@ -179,8 +212,14 @@ export class CustomerController extends Controller { ); } - if (!body.registeredBranchId) { - body.registeredBranchId = undefined; + if (body.registeredBranchId !== undefined && !globalAllow(req.user)) { + if (body.registeredBranchId === null || (branch && branch.user.length === 0)) { + throw new HttpError( + HttpStatus.FORBIDDEN, + "You do not have permission to perform this action.", + "noPermission", + ); + } } const record = await prisma.$transaction( @@ -230,6 +269,10 @@ export class CustomerController extends Controller { @Request() req: RequestWithUser, @Body() body: CustomerUpdate, ) { + if (body.registeredBranchId === "") { + body.registeredBranchId = undefined; + } + const customer = await prisma.customer.findUnique({ where: { id: customerId } }); if (!customer) { @@ -237,8 +280,14 @@ export class CustomerController extends Controller { } const [branch] = await prisma.$transaction([ - prisma.customer.findUnique({ where: { id: customerId } }), - prisma.branch.findFirst({ where: { id: body.registeredBranchId } }), + prisma.branch.findFirst({ + where: { id: body.registeredBranchId }, + include: { + user: { + where: { userId: req.user.sub }, + }, + }, + }), ]); if (!!body.registeredBranchId && !branch) { @@ -249,8 +298,14 @@ export class CustomerController extends Controller { ); } - if (!body.registeredBranchId) { - body.registeredBranchId = undefined; + if (body.registeredBranchId !== undefined && !globalAllow(req.user)) { + if (body.registeredBranchId === null || (branch && branch.user.length === 0)) { + throw new HttpError( + HttpStatus.FORBIDDEN, + "You do not have permission to perform this action.", + "noPermission", + ); + } } const record = await prisma.$transaction(async (tx) => { @@ -280,13 +335,31 @@ export class CustomerController extends Controller { @Delete("{customerId}") @Security("keycloak", MANAGE_ROLES) - async deleteById(@Path() customerId: string) { - const record = await prisma.customer.findFirst({ where: { id: customerId } }); + async deleteById(@Path() customerId: string, @Request() req: RequestWithUser) { + const record = await prisma.customer.findFirst({ + where: { id: customerId }, + include: { + registeredBranch: { + include: { user: { where: { userId: req.user.sub } } }, + }, + }, + }); if (!record) { throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); } + if ( + !globalAllow(req.user) && + (!record.registeredBranch || record.registeredBranch.user.length === 0) + ) { + throw new HttpError( + HttpStatus.FORBIDDEN, + "You do not have permission to perform this action.", + "noPermission", + ); + } + if (record.status !== Status.CREATED) { throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "customerInUsed"); } @@ -313,9 +386,7 @@ export class CustomerController extends Controller { @Security("keycloak", MANAGE_ROLES) async setCustomerImageById(@Request() req: RequestWithUser, @Path() customerId: string) { const record = await prisma.customer.findFirst({ - where: { - id: customerId, - }, + where: { id: customerId }, }); if (!record) {