import { Injectable } from '@nestjs/common'; import { userLoginValidator } from '@/src/auth/login/dtoValidator'; import { RedisHandlers } from '@/src/utils/auth/redis_handlers'; import { PasswordHandlers } from '@/src/utils/auth/login_handler'; import { PrismaService } from '@/src/prisma.service'; import { AuthTokenSchema } from '@/src/types/auth/token'; @Injectable() export class LoginService { constructor( private readonly redis: RedisHandlers, private readonly passHandlers: PasswordHandlers, private readonly prisma: PrismaService, ) {} async run(dto: userLoginValidator) { const foundUser = await this.prisma.users.findFirstOrThrow({ where: { email: dto.accessKey }, }); if (foundUser.password_token) { throw new Error('Password need to be set first'); } const isPasswordValid = this.passHandlers.check_password( foundUser.uu_id, dto.password, foundUser.hash_password, ); if (!isPasswordValid) { throw new Error('Invalid password'); } const foundPerson = await this.prisma.people.findFirstOrThrow({ where: { id: foundUser.id }, }); const alreadyExists = await this.redis.callExistingLoginToken( foundUser.uu_id, ); if (alreadyExists) { return { token: alreadyExists, message: 'User already logged in', }; } else { let selectList: any[] = []; if (foundUser.user_type === 'occupant') { const livingSpaces = await this.prisma.build_living_space.findMany({ where: { people: { id: foundPerson.id } }, orderBy: { build_parts: { build: { id: 'asc', }, }, }, select: { uu_id: true, occupant_types: { select: { uu_id: true, occupant_code: true, occupant_type: true, function_retriever: true, }, }, build_parts: { select: { uu_id: true, part_code: true, part_no: true, part_level: true, human_livable: true, api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown: { select: { uu_id: true, enum_class: true, value: true, }, }, build: { select: { uu_id: true, build_name: true, }, }, }, }, }, }); selectList = livingSpaces; } else if (foundUser.user_type === 'employee') { const employees = await this.prisma.employees.findMany({ where: { people: { id: foundPerson.id } }, orderBy: { staff: { duties: { departments: { companies: { formal_name: 'asc', }, }, }, }, }, select: { uu_id: true, staff: { select: { uu_id: true, staff_code: true, function_retriever: true, duties: { select: { uu_id: true, departments: { select: { uu_id: true, department_code: true, department_name: true, companies: { select: { uu_id: true, formal_name: true, public_name: true, addresses: { select: { comment_address: true, }, }, }, }, }, }, }, }, }, }, }, }); selectList = employees; } const redisData = AuthTokenSchema.parse({ people: foundPerson, users: foundUser, credentials: { person_uu_id: foundPerson.uu_id, person_name: foundPerson.firstname, person_full_name: `${foundPerson.firstname} ${foundPerson.middle_name || ''} | ${foundPerson.birthname || ''} | ${foundPerson.surname}`, }, selectionList: { type: foundUser.user_type, list: selectList, }, }); const accessToken = await this.redis.setLoginToRedis( redisData, foundUser.uu_id, ); return { token: accessToken, message: 'Login successful', }; } } }