improve login and add migration script

This commit is contained in:
Anika Raemer 2025-09-21 20:01:33 +02:00
parent 1fce467571
commit 099ffb74a1
5 changed files with 106 additions and 9 deletions

View file

@ -1,8 +1,9 @@
import { UserRepository } from "../repositories/UserRepository"; import { UserRepository } from "../repositories/UserRepository";
import { encrypt } from "../utils/encryptionUtils"; import { encrypt } from "../utils/encryptionUtils";
import { ValidationError, UnauthorizedError } from "../errors/httpErrors"; import { ValidationError, UnauthorizedError } from "../errors/httpErrors";
import { UserDto } from "../dtos/UserDto";
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper"; import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper";
import { LoginResponseDto } from "../dtos/LoginResponseDto";
import { LoginRequestDto } from "../dtos/LoginRequestDto";
export class AuthController { export class AuthController {
constructor( constructor(
@ -10,7 +11,9 @@ export class AuthController {
private mapper: UserDtoEntityMapper private mapper: UserDtoEntityMapper
) {} ) {}
async login(userName: string, password: string): Promise<{ token: string; user: UserDto }> { async login(loginRequest : LoginRequestDto): Promise<LoginResponseDto> {
const userName :string = loginRequest.userName;
const password :string = loginRequest.password;
if (!userName || !password) { if (!userName || !password) {
throw new ValidationError("Username and password are required"); throw new ValidationError("Username and password are required");
} }
@ -30,9 +33,9 @@ export class AuthController {
role: user.role, role: user.role,
}); });
return { const responseDto = new LoginResponseDto();
token, responseDto.userData = this.mapper.toDto(user);
user: this.mapper.toDto(user), responseDto.token = token;
}; return responseDto;
} }
} }

View file

@ -0,0 +1,7 @@
/**
* Defines a login request
*/
export class LoginRequestDto {
userName: string;
password: string;
}

View file

@ -0,0 +1,9 @@
import { UserDto } from "./UserDto";
/**
* Response to a successful login
*/
export class LoginResponseDto {
userData: UserDto;
token: string;
}

View file

@ -7,6 +7,7 @@ import {
UnauthorizedError, UnauthorizedError,
InternalServerError, InternalServerError,
} from "../errors/httpErrors"; } from "../errors/httpErrors";
import { LoginRequestDto } from "../dtos/LoginRequestDto";
const router = Router(); const router = Router();
@ -16,9 +17,9 @@ const authController = new AuthController(userRepository, mapper);
router.post("/login", async (req, res) => { router.post("/login", async (req, res) => {
try { try {
const { userName, password } = req.body; const requestDto: LoginRequestDto = req.body;
const result = await authController.login(userName, password); const responseDto = await authController.login(requestDto));
res.json(result); res.json(responseDto);
} catch (err: any) { } catch (err: any) {
if (err instanceof ValidationError || err instanceof UnauthorizedError) { if (err instanceof ValidationError || err instanceof UnauthorizedError) {
res.status(err.statusCode).json({ error: err.message }); res.status(err.statusCode).json({ error: err.message });

View file

@ -0,0 +1,77 @@
import { MigrationInterface, QueryRunner, Table, TableUnique } from "typeorm";
export class CreateUserTable1661234567890 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: "user",
columns: [
{
name: "id",
type: "uuid",
isPrimary: true,
isGenerated: true,
generationStrategy: "uuid",
},
{
name: "userName",
type: "varchar",
isNullable: false,
},
{
name: "email",
type: "varchar",
isNullable: false,
},
{
name: "password",
type: "varchar",
isNullable: false,
},
{
name: "firstName",
type: "varchar",
isNullable: true,
},
{
name: "lastName",
type: "varchar",
isNullable: true,
},
{
name: "role",
type: "varchar",
default: "'user'",
},
{
name: "createdAt",
type: "timestamp",
default: "now()",
},
{
name: "updatedAt",
type: "timestamp",
default: "now()",
},
],
}),
true
);
// Add a unique constraint on userName
await queryRunner.createUniqueConstraint(
"user",
new TableUnique({
columnNames: ["userName"],
name: "UQ_user_userName",
})
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
// Drop the unique constraint first
await queryRunner.dropUniqueConstraint("user", "UQ_user_userName");
// Drop the table
await queryRunner.dropTable("user");
}
}