import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; import { ROLE } from '../../../common/utils/constants/common.constant'; import ApiError from '../../../common/utils/helper/ApiError'; function normalizeIdArray(values: unknown): number[] { if (!Array.isArray(values)) { return []; } return Array.from( new Set( values .map((item) => Number(item)) .filter((item) => Number.isInteger(item) && item > 0), ), ); } @Injectable() export class HostRolePermissionService { constructor(private prisma: PrismaClient) {} async saveRolePermissions(input: { hostUserXid: number; roleXid: number; permissionMasterXids: unknown; }) { const permissionMasterXids = normalizeIdArray(input.permissionMasterXids); if (!permissionMasterXids.length) { throw new ApiError(400, 'permissionMasterXids is required.'); } return this.prisma.$transaction(async (tx) => { const host = await tx.hostHeader.findFirst({ where: { userXid: input.hostUserXid, isActive: true, deletedAt: null, }, select: { id: true, companyName: true, userXid: true, }, }); if (!host) { throw new ApiError(404, 'Host company not found for the logged-in user.'); } const role = await tx.roles.findFirst({ where: { id: input.roleXid, isActive: true, deletedAt: null, }, select: { id: true, roleName: true, }, }); if (!role) { throw new ApiError(400, 'Invalid roleXid.'); } const selectedPermissions = await tx.hostPermissionMasters.findMany({ where: { id: { in: permissionMasterXids }, isActive: true, deletedAt: null, }, select: { id: true, permissionKey: true, permissionGroup: true, permissionSection: true, permissionAction: true, displayLabel: true, displayOrder: true, }, orderBy: { displayOrder: 'asc', }, }); if (selectedPermissions.length !== permissionMasterXids.length) { throw new ApiError(400, 'One or more permissionMasterXids are invalid.'); } const saved = await tx.hostRolePermissionMasters.upsert({ where: { hostXid_roleXid: { hostXid: host.id, roleXid: role.id, }, }, create: { hostXid: host.id, roleXid: role.id, permissionMasterXids, isActive: true, }, update: { permissionMasterXids, isActive: true, deletedAt: null, }, select: { id: true, hostXid: true, roleXid: true, permissionMasterXids: true, createdAt: true, updatedAt: true, }, }); return { host, role, saved, selectedPermissions, }; }); } async getMemberPermissions(input: { hostUserXid: number; memberUserXid: number; }) { return this.prisma.$transaction(async (tx) => { // Find the host const host = await tx.hostHeader.findFirst({ where: { userXid: input.hostUserXid, isActive: true, deletedAt: null, }, select: { id: true, companyName: true, userXid: true, }, }); if (!host) { throw new ApiError(404, 'Host company not found for the logged-in user.'); } // Find the host member const hostMember = await tx.hostMembers.findFirst({ where: { hostXid: host.id, userXid: input.memberUserXid, isActive: true, deletedAt: null, memberStatus: 'accepted', }, select: { id: true, userXid: true, roleXid: true, role: { select: { id: true, roleName: true, }, }, hostRolePermissionMasterXid: true, }, }); if (!hostMember) { throw new ApiError(404, 'Host member not found or not active.'); } // Check if role is operator or co-admin if (hostMember.roleXid !== ROLE.CO_ADMIN && hostMember.roleXid !== ROLE.OPERATOR) { throw new ApiError(400, 'Member is not an operator or co-admin.'); } if (!hostMember.hostRolePermissionMasterXid) { // Return empty permissions if no role permissions assigned return { host, member: { userXid: hostMember.userXid, role: hostMember.role, }, permissions: [], }; } // Get the role permissions const rolePermissions = await tx.hostRolePermissionMasters.findFirst({ where: { id: hostMember.hostRolePermissionMasterXid, isActive: true, deletedAt: null, }, select: { id: true, permissionMasterXids: true, }, }); if (!rolePermissions) { return { host, member: { userXid: hostMember.userXid, role: hostMember.role, }, permissions: [], }; } // Get the actual permissions const permissionIds = rolePermissions.permissionMasterXids as number[]; const permissions = await tx.hostPermissionMasters.findMany({ where: { id: { in: permissionIds }, isActive: true, deletedAt: null, }, select: { id: true, permissionKey: true, permissionGroup: true, permissionSection: true, permissionAction: true, displayLabel: true, displayOrder: true, }, orderBy: { displayOrder: 'asc', }, }); return { host, member: { userXid: hostMember.userXid, role: hostMember.role, }, permissions, }; }); } }