60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { UserRepository } from "../repositories/UserRepository.js";
|
|
import { encrypt } from "../utils/encryptionUtils.js";
|
|
import { ValidationError, UnauthorizedError } from "../api/errors/httpErrors.js";
|
|
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
|
import { LoginResponse } from "../api/dtos/LoginResponse.js";
|
|
import { LoginRequest } from "../api/dtos/LoginRequest.js";
|
|
|
|
/**
|
|
* Controller responsible for authentication, e.g., login or issueing a token with extended
|
|
* lifetime
|
|
*/
|
|
export class AuthHandler {
|
|
constructor(
|
|
private userRepository: UserRepository,
|
|
private mapper: UserDtoEntityMapper
|
|
) {}
|
|
|
|
/**
|
|
* Login: Check user and password and generate token
|
|
* @param loginRequest LoginRequest containing userName and password for login
|
|
* @returns LoginResponse containing token and user data for the user who just logged in
|
|
*/
|
|
async login(loginRequest : LoginRequest): Promise<LoginResponse> {
|
|
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
|
|
role: user.role
|
|
});
|
|
|
|
const responseDto = new LoginResponse();
|
|
responseDto.userData = this.mapper.toDto(user);
|
|
responseDto.token = tokenInfo.token;
|
|
responseDto.expiryDate = tokenInfo.expiryDate;
|
|
return responseDto;
|
|
}
|
|
}
|