import { Request } from 'express' ; import { getRepository , getCustomRepository } from 'typeorm' ; import { badRequest , notFound } from '@hapi/boom' ; import * as Jwt from 'jwt-simple' ; import { ACCESS_TOKEN } from '@config/environment.config' ; import { IResponse , IUserRequest , ITokenOptions } from '@interfaces' ; import { User } from '@models/user.model' ; import { RefreshToken } from '@models/refresh-token.model' ; import { UserRepository } from '@repositories/user.repository' ; import { AuthService } from '@services/auth.service' ; import { Safe } from '@decorators/safe.decorator' ; import { ROLE , STATUS } from '@enums' ; import { EmailEmitter } from '@events' ; /**
 * Manage incoming requests from api/{version}/auth
 */ class AuthController { description private static instance : AuthController ; private constructor ( ) { } description static get ( ) { if ( ! AuthController . instance ) { AuthController . instance = new AuthController ( ) ; } return AuthController . instance ; } description param req param res @ Safe ( ) async register ( req , res ) { const repository = getRepository ( User ) ; const user = new User ( req . body as Record < string , unknown > ) ; const count = await repository . count ( ) ; if ( count === 0 ) { user . role = ROLE . admin ; } await repository . insert ( user ) ; const token = await AuthService . generateTokenResponse ( user , user . token ( ) ) ; res . locals . data = { token , user } ; } description param req param res @ Safe ( ) async login ( req , res ) { const repository = getCustomRepository ( UserRepository ) ; const { user , accessToken } = await repository . findAndGenerateToken ( req . body as ITokenOptions ) ; const token = await AuthService . generateTokenResponse ( user , accessToken ) ; res . locals . data = { token , user } ; } description param req param res @ Safe ( ) async logout ( req , res ) { await AuthService . revokeRefreshToken ( req . user as User ) ; res . locals . data = null ; } description param req param res @ Safe ( ) async oAuth ( req , res ) { const user = req . user as User ; const accessToken = user . token ( ) ; const token = await AuthService . generateTokenResponse ( user , accessToken ) ; res . locals . data = { token , user } ; } description param req param res @ Safe ( ) async refresh ( req , res , next ) { const refreshTokenRepository = getRepository ( RefreshToken ) ; const userRepository = getCustomRepository ( UserRepository ) ; const { token } = req . body as { token : { refreshToken ? : string ; } ; } ; const refreshToken = await refreshTokenRepository . findOne ( { where : { token : token . refreshToken } } ) ; if ( typeof ( refreshToken ) === 'undefined' ) { return next ( notFound ( 'RefreshToken not found' ) ) ; } await refreshTokenRepository . remove ( refreshToken ) ; const { user , accessToken } = await userRepository . findAndGenerateToken ( { email : refreshToken . user . email , refreshToken } ) ; const response = await AuthService . generateTokenResponse ( user , accessToken ) ; res . locals . data = { token : response } ; } description param req param res fixme @ Safe ( ) async confirm ( req , res ) { const repository = getRepository ( User ) ; const decoded = Jwt . decode ( req . body . token , ACCESS_TOKEN . SECRET ) as { sub ; } ; if ( ! decoded ) { throw badRequest ( 'User token cannot be read' ) ; } const user = await repository . findOneOrFail ( decoded . sub as string ) ; if ( user . status !== STATUS . REGISTERED && user . status !== STATUS . REVIEWED ) { throw badRequest ( 'User status cannot be confirmed' ) ; } user . status = STATUS . CONFIRMED ; await repository . save ( user ) ; const token = await AuthService . generateTokenResponse ( user , user . token ( ) ) ; res . locals . data = { token , user } ; } description param req param res @ Safe ( ) async requestPassword ( req , res ) { const repository = getRepository ( User ) ; const user = await repository . findOne ( { email : req . query . email } ) ; if ( user && user . status === STATUS . CONFIRMED ) { void AuthService . revokeRefreshToken ( user ) ; EmailEmitter . emit ( 'password.request' , user ) ; } res . locals . data = { } ; } } const authController = AuthController . get ( ) ; export { authController as AuthController } ;