import { Body, Controller, Get, Headers, Post, Query, Req, Res, } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { Throttle } from "@nestjs/throttler"; import type { Request, Response } from "express"; import { getIronSession } from "iron-session"; import { AuthService } from "./auth.service"; import { BootstrapService } from "./bootstrap.service"; import { LoginDto } from "./dto/login.dto"; import { RegisterDto } from "./dto/register.dto"; import { Verify2faDto } from "./dto/verify-2fa.dto"; import { getSessionOptions, SessionData } from "./session.config"; @Controller("auth") export class AuthController { constructor( private readonly authService: AuthService, private readonly bootstrapService: BootstrapService, private readonly configService: ConfigService, ) {} @Post("register") @Throttle({ default: { limit: 5, ttl: 60000 } }) register(@Body() registerDto: RegisterDto) { return this.authService.register(registerDto); } @Post("login") @Throttle({ default: { limit: 5, ttl: 60000 } }) async login( @Body() loginDto: LoginDto, @Headers("user-agent") userAgent: string, @Req() req: Request, @Res() res: Response, ) { const ip = req.ip; const result = await this.authService.login(loginDto, userAgent, ip); if (result.access_token) { const session = await getIronSession( req, res, getSessionOptions(this.configService.get("SESSION_PASSWORD") as string), ); session.accessToken = result.access_token; session.refreshToken = result.refresh_token; session.userId = result.userId; await session.save(); // On ne renvoie pas les tokens dans le body pour plus de sécurité return res.json({ message: result.message, userId: result.userId, }); } return res.json(result); } @Post("verify-2fa") @Throttle({ default: { limit: 5, ttl: 60000 } }) async verifyTwoFactor( @Body() verify2faDto: Verify2faDto, @Headers("user-agent") userAgent: string, @Req() req: Request, @Res() res: Response, ) { const ip = req.ip; const result = await this.authService.verifyTwoFactorLogin( verify2faDto.userId, verify2faDto.token, userAgent, ip, ); if (result.access_token) { const session = await getIronSession( req, res, getSessionOptions(this.configService.get("SESSION_PASSWORD") as string), ); session.accessToken = result.access_token; session.refreshToken = result.refresh_token; session.userId = verify2faDto.userId; await session.save(); return res.json({ message: result.message, }); } return res.json(result); } @Post("refresh") async refresh(@Req() req: Request, @Res() res: Response) { const session = await getIronSession( req, res, getSessionOptions(this.configService.get("SESSION_PASSWORD") as string), ); if (!session.refreshToken) { return res.status(401).json({ message: "No refresh token" }); } const result = await this.authService.refresh(session.refreshToken); session.accessToken = result.access_token; session.refreshToken = result.refresh_token; await session.save(); return res.json({ message: "Token refreshed" }); } @Post("logout") async logout(@Req() req: Request, @Res() res: Response) { const session = await getIronSession( req, res, getSessionOptions(this.configService.get("SESSION_PASSWORD") as string), ); session.destroy(); return res.json({ message: "User logged out" }); } @Get("bootstrap-admin") async bootstrapAdmin( @Query("token") token: string, @Query("username") username: string, ) { return this.bootstrapService.consumeToken(token, username); } }