import { UserRepository } from "../repositories/UserRepository.js"; import { encrypt } from "../utils/encryptionUtils.js"; import { ValidationError, UnauthorizedError } from "../errors/httpErrors.js"; import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js"; import { LoginResponseDto } from "../dtos/LoginResponseDto.js"; import { LoginRequestDto } from "../dtos/LoginRequestDto.js"; /** * Controller responsible for authentication, e.g., login or issueing a token with extended * lifetime */ export class AuthController { constructor( private userRepository: UserRepository, private mapper: UserDtoEntityMapper ) {} /** * Login: Check user and password and generate token * @param loginRequest LoginRequestDto containing userName and password for login * @returns LoginResponse containing token and user data for the user who just logged in */ async login(loginRequest : LoginRequestDto): Promise { const userName :string|undefined = loginRequest.userName; const password :string|undefined = loginRequest.password; console.log("user", userName, " is trying to log in") if (!userName || !password) { throw new ValidationError("Username and password are required"); } // Find user by userName const user = await this.userRepository.findByUserName(userName); // check user before trying to access password! if(!user){ throw new UnauthorizedError("Invalid username or password"); } // ensure user has an id - required to generate token const userId = user.id; if(user.id == undefined){ throw new UnauthorizedError("Invalid username or password"); } // Compare password const passwordMatches = encrypt.comparepassword(password, user.password); if (!passwordMatches) { throw new UnauthorizedError("Invalid username or password"); } // Create JWT const tokenInfo = encrypt.generateToken({ id: userId!, // ! to indicate that we've definitely checked for userId being defined }); const responseDto = new LoginResponseDto(); responseDto.userData = this.mapper.toDto(user); responseDto.token = tokenInfo.token; responseDto.expiryDate = tokenInfo.expiryDate; return responseDto; } }