diff --git a/serverless/functions/host.yml b/serverless/functions/host.yml index 685bcd7..b05dce0 100644 --- a/serverless/functions/host.yml +++ b/serverless/functions/host.yml @@ -388,6 +388,22 @@ getHostMemberRoles: path: /settings/member-roles method: get +getMemberPermissions: + handler: src/modules/host/handlers/settings/getMemberPermissions.handler + memorySize: 384 + package: + patterns: + - 'src/modules/host/handlers/settings/**' + - 'src/modules/host/services/**' + - ${file(./serverless/patterns/base.yml):pattern1} + - ${file(./serverless/patterns/base.yml):pattern2} + - ${file(./serverless/patterns/base.yml):pattern3} + - ${file(./serverless/patterns/base.yml):pattern4} + events: + - httpApi: + path: /settings/member-permissions/{memberUserXid} + method: get + # Functions with S3/AWS SDK dependencies submitCompanyDetails: handler: src/modules/host/handlers/Host_Admin/onboarding/submitCompanyDetails.handler diff --git a/src/modules/host/handlers/settings/getMemberPermissions.ts b/src/modules/host/handlers/settings/getMemberPermissions.ts new file mode 100644 index 0000000..b43bbb2 --- /dev/null +++ b/src/modules/host/handlers/settings/getMemberPermissions.ts @@ -0,0 +1,58 @@ +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; + +import { prismaClient } from '../../../../common/database/prisma.lambda.service'; +import { verifyHostToken } from '../../../../common/middlewares/jwt/authForHost'; +import { safeHandler } from '../../../../common/utils/handlers/safeHandler'; +import ApiError from '../../../../common/utils/helper/ApiError'; +import { HostRolePermissionService } from '../../services/hostRolePermission.service'; + +const hostRolePermissionService = new HostRolePermissionService(prismaClient); + +export const handler = safeHandler(async ( + event: APIGatewayProxyEvent, + context?: Context, +): Promise => { + const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']; + + if (!token) { + throw new ApiError( + 400, + 'This is a protected route. Please provide a valid token.', + ); + } + + const userInfo = await verifyHostToken(token); + + const memberUserXid = event.pathParameters?.memberUserXid; + + if (!memberUserXid) { + throw new ApiError(400, 'memberUserXid is required.'); + } + + const memberUserId = parseInt(memberUserXid, 10); + if (isNaN(memberUserId)) { + throw new ApiError(400, 'Invalid memberUserXid. Must be a number.'); + } + + const result = await hostRolePermissionService.getMemberPermissions({ + hostUserXid: userInfo.id, + memberUserXid: memberUserId, + }); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Member permissions retrieved successfully', + data: result, + }), + }; +}); \ No newline at end of file diff --git a/src/modules/host/services/hostRolePermission.service.ts b/src/modules/host/services/hostRolePermission.service.ts index 668e938..8acd4af 100644 --- a/src/modules/host/services/hostRolePermission.service.ts +++ b/src/modules/host/services/hostRolePermission.service.ts @@ -1,5 +1,6 @@ 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'; @@ -126,4 +127,128 @@ export class HostRolePermissionService { }; }); } + + 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, + }; + }); + } } diff --git a/src/modules/user/services/itinerary.service.ts b/src/modules/user/services/itinerary.service.ts index f55d661..849168e 100644 --- a/src/modules/user/services/itinerary.service.ts +++ b/src/modules/user/services/itinerary.service.ts @@ -4938,7 +4938,6 @@ export class ItineraryService { trainerOrGuide: activitySelection?.isTrainerOpted ? 'Yes' : 'No', }, ticketCard: { - qrCodeValue: itineraryDetail?.offlineCode ?? null, checkInCode: itineraryDetail?.offlineCode ?? null, activityTitle: itineraryActivity.activity?.activityTitle ?? null, date: bookingDate,