import { UserSession } from '../entity/user-session.entity'; import { ClockIDGenService } from '../../../utils/service/clockIDGenUtil.service'; import { BadRequestException, Injectable } from '@nestjs/common'; import { UserSessionRepository } from '../repository/userSession.repository'; import { JwtAuthService } from 'src/module/auth/services/jwt.service'; import { ConfigService } from '@nestjs/config'; import { UserRoleMappingService } from './user-role-mapping.service'; import { DataSource, Repository } from 'typeorm'; import { UserRoleMapping } from '../entity/user-role-mapping.entity'; import { UserData } from '../entity/user.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { ReflectionHelper } from '../../../utils/service/reflection-helper.service'; @Injectable() export class UserSessionService { constructor( private readonly userSessionRepository: UserSessionRepository, private readonly jwtAuthService: JwtAuthService, private readonly clockIDGenService: ClockIDGenService, private configService: ConfigService, @InjectRepository(UserData) private readonly userDataRepository: Repository, @InjectRepository(UserRoleMapping) private readonly userRoleMappingRepository: Repository, private readonly reflectionHelper: ReflectionHelper, ) {} async createSession(user, appcode?: string, accessInfo?: any) { const sessionToken = this.clockIDGenService.idGenerator('SES'); const userSession: any = new UserSession(); userSession.user_id = user.id; userSession.session_key = sessionToken; userSession.is_session_loggedout = 0; userSession.login_time = new Date(); const expiryTokenInHours = this.configService.get('TOKEN_EXPIRY') || 1; userSession.expiry_date = new Date( Date.now() + expiryTokenInHours * 60 * 60 * 1000, ); await this.userSessionRepository.saveSession(userSession); const payload: any = { id: user.id, sessionToken, appcode, email_id: user.email_id, organization_id: user.organization_id, enterprise_id: user.enterprise_id, }; // ✅ Add role access details if (accessInfo) { payload.level_type = accessInfo.level_type; payload.level_id = accessInfo.level_id; } const accessToken = this.jwtAuthService.generateJwt(payload); userSession.access_token = accessToken; await this.userSessionRepository.saveSession(userSession); return accessToken; } async findBySessionKey(sessionKey: string): Promise { return await this.userSessionRepository.findBySessionKey(sessionKey); } async updateSession(userSession: UserSession) { await this.userSessionRepository.saveSession(userSession); } async switchCurrentLevelService( currentUser: any, data: any, ): Promise<{ success: boolean; accessToken: string; appcode: string; level_type: string; level_id: string; }> { let payload; payload = { ...currentUser, level_id: data.level_id, level_type: data.level_type, appcode: data.appcode, }; let getUserDetails: UserData | null = null; if (currentUser) { // Check if user has any role mappings for the given appcode getUserDetails = await this.userDataRepository.findOne({ where: { id: currentUser.id, }, }); } if (getUserDetails?.organization_id == 1 && payload.level_type == 'ORG') { payload.organization_id = payload.level_id; payload.enterprise_id = payload.level_id; } await this.userDataRepository.update(currentUser.id, { last_app_access: data.appcode, last_level_type: data.level_type, last_level_id: data.level_id, }); return { success: true, accessToken: this.jwtAuthService.generateJwt(payload), appcode: data.appcode, level_type: data.level_type, level_id: data.level_id, }; } async checkIfUserHasMapping( userId: number, appcode: string, levelType: string, levelId: string, ): Promise { // Get repositories dynamically via reflectionHelper const userRoleMappingRepo = this.reflectionHelper.getRepoService('UserRoleMapping'); const appMasterRepo = this.reflectionHelper.getRepoService('AppMaster'); // Use QueryBuilder with proper aliases const count = await userRoleMappingRepo .createQueryBuilder('urm') .innerJoin( appMasterRepo.metadata.tableName, 'app', 'app.appcode = urm.appcode', ) .where('urm.user_id = :userId', { userId }) .andWhere('urm.appcode = :appcode', { appcode }) .andWhere('urm.level_type = :levelType', { levelType }) .andWhere('urm.level_id = :levelId', { levelId }) .andWhere('app.show_in_ui = true') .getCount(); return count > 0; } async getUserRoleMappingForApp(userId: number, appcode: string) { const userRoleMappingRepo = this.reflectionHelper.getRepoService('UserRoleMapping'); const appMasterRepo = this.reflectionHelper.getRepoService('AppMaster'); const mapping = await userRoleMappingRepo .createQueryBuilder('urm') .innerJoin( appMasterRepo.metadata.tableName, 'app', 'app.appcode = urm.appcode', ) .where('urm.user_id = :userId', { userId }) .andWhere('urm.appcode = :appcode', { appcode }) .andWhere('app.show_in_ui = true') .getOne(); if (!mapping) { throw new BadRequestException( `User does not have visible access to app ${appcode}`, ); } if (mapping.level_type !== 'BRN') { return mapping; } // Resolve SCH under brand const schoolRepo = this.reflectionHelper.getRepoService('SSOSchool'); const school = await schoolRepo.findOne({ where: { brand_id: mapping.level_id }, order: { id: 'ASC' }, }); if (!school) { throw new BadRequestException( `No schools found under brand ${mapping.level_id}`, ); } return { ...mapping, level_type: 'SCH', level_id: school.id, }; } }