import { AccountService } from './account/account.service'; import { AppService } from './app.service'; import { env } from './config/env'; import { Controller, Get, HttpStatus, Req, Res } from '@nestjs/common'; import { ApiExcludeController } from '@nestjs/swagger'; import { FastifyReply, FastifyRequest } from 'fastify'; import { cookieOptions } from 'src/config/cookie'; @Controller() @ApiExcludeController() export class AppController { constructor( private readonly appService: AppService, private readonly accountService: AccountService ) {} @Get('auth') public async auth(@Req() req: FastifyRequest, @Res() reply: FastifyReply) { const token = req.cookies[env.COOKIE_TOKEN_NAME] || req.headers?.authorization?.split(' ')[1]; if (!token) return reply.status(HttpStatus.UNAUTHORIZED).send(); try { return this.handleDefaultCheck(req, reply, token); } catch (error) { const _err = error as Error; const isTokenExpired = _err.name?.toLocaleLowerCase().includes('expired'); const refreshToken = req.headers['refresh-token'] === '1'; if (isTokenExpired && refreshToken) return this.handleExpiredToken(req, reply, token); return this.handleError(req, reply); } } private handleDefaultCheck(req: FastifyRequest, reply: FastifyReply, token: string) { this.appService.checkToken(token); reply.header('Authorization', `Bearer ${token}`); return reply.send(); } private async handleExpiredToken(req: FastifyRequest, reply: FastifyReply, token: string) { const authMode = req.headers['auth-mode']; const newToken = authMode === 'account' ? await this.accountService.refreshToken(token) : this.appService.refreshToken(token); reply.header('Authorization', `Bearer ${newToken}`); return reply.setCookie(env.COOKIE_TOKEN_NAME, newToken, cookieOptions).send(); } private handleError(req: FastifyRequest, reply: FastifyReply) { return reply.status(HttpStatus.UNAUTHORIZED).send(); } }