import { TokenDictType, OccupantTokenObject, EmployeeTokenObject, UserType, } from '@/src/types/auth/token'; import { CacheService } from '@/src/cache.service'; import { users } from '@prisma/client'; import { PasswordHandlers } from './login_handler'; import { Injectable } from '@nestjs/common'; @Injectable() export class RedisHandlers { AUTH_TOKEN = 'AUTH_TOKEN'; constructor( private readonly cacheService: CacheService, private readonly passwordService: PasswordHandlers, ) { this.cacheService = cacheService; this.passwordService = passwordService; } async process_redis_object(redis_object: any): Promise { if (!redis_object) { throw new Error('Invalid Redis object: Object is null or undefined'); } if (redis_object.user_type === UserType.employee) { const validateEmployeeToken = (obj: any): obj is EmployeeTokenObject => { return ( typeof obj === 'object' && obj !== null && typeof obj.user_type === 'number' && typeof obj.user_uu_id === 'string' && typeof obj.user_id === 'number' && typeof obj.person_id === 'number' && typeof obj.person_uu_id === 'string' && Array.isArray(obj.companies_id_list) && Array.isArray(obj.companies_uu_id_list) && Array.isArray(obj.duty_id_list) && Array.isArray(obj.duty_uu_id_list) ); }; const empToken: EmployeeTokenObject = { ...redis_object, is_employee: true, is_occupant: false, user_type: UserType.employee, credential_token: redis_object.credential_token || '', }; if (!validateEmployeeToken(empToken)) { throw new Error( 'Invalid Redis object: Does not match EmployeeTokenObject interface', ); } return empToken; } if (redis_object.user_type === UserType.occupant) { const validateOccupantToken = (obj: any): obj is OccupantTokenObject => { return ( typeof obj === 'object' && obj !== null && typeof obj.user_type === 'number' && typeof obj.user_uu_id === 'string' && typeof obj.user_id === 'number' && typeof obj.person_id === 'number' && typeof obj.person_uu_id === 'string' ); }; const occToken: OccupantTokenObject = { ...redis_object, is_employee: false, is_occupant: true, user_type: UserType.occupant, credential_token: redis_object.credential_token || '', available_occupants: redis_object.available_occupants || null, }; if (!validateOccupantToken(occToken)) { throw new Error( 'Invalid Redis object: Does not match OccupantTokenObject interface', ); } return occToken; } throw new Error(`Invalid user_type: ${redis_object.user_type}`); } async get_object_from_redis(access_token: string): Promise { const token = await this.cacheService.get(access_token); return this.process_redis_object(token); } async set_login_to_redis(user: users, token: TokenDictType): Promise { const generated_token = this.passwordService.generateAccessToken(); const listKeys = [this.AUTH_TOKEN, generated_token, user.uu_id]; await this.cacheService.set_with_ttl( this.cacheService.createRegexPattern(listKeys), token, 60 * 60 * 24, ); return generated_token; } async update_token_via_token(token: string, additional: any): Promise { const listKeys = [this.AUTH_TOKEN, token, '*']; const accessObject = await this.cacheService.get_with_keys(listKeys); if (!accessObject) throw new Error('Token not found'); const processedObject: TokenDictType = await this.process_redis_object(accessObject); if (processedObject.is_employee) { processedObject.selected = additional; } if (processedObject.is_occupant) { processedObject.selected = additional; } const listKeysNew = [this.AUTH_TOKEN, token, processedObject.user_uu_id]; await this.cacheService.set_with_ttl( this.cacheService.createRegexPattern(listKeysNew), processedObject, 60 * 60 * 24, ); return token; } }