All files / src/features/auth auth.controller.ts

100% Statements 17/17
100% Branches 8/8
80% Functions 4/5
100% Lines 17/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                                      18x       4x 4x 2x   2x           5x       5x 2x   3x                         3x 3x 1x   2x   2x   3x 3x   3x              
import {
    Controller,
    Post,
    Body,
    UnauthorizedException,
    Get,
    UseGuards,
    Req,
    Res,
} from '@nestjs/common'
import { AuthService } from './auth.service'
import { LoginDto, StaffLoginDto } from '@fundraising/types'
import { GoogleAuthUser } from './providers/auth-provider.interface'
import { AuthGuard } from '@nestjs/passport'
import { Throttle } from '@nestjs/throttler'
import type { Request, Response } from 'express'
 
@Controller('auth')
export class AuthController {
    constructor(private authService: AuthService) {}
 
    @Post('login')
    async login(@Body() loginDto: LoginDto) {
        const user = await this.authService.validateUser(loginDto.email, loginDto.password)
        if (!user) {
            throw new UnauthorizedException('Invalid credentials')
        }
        return this.authService.login(user)
    }
 
    @Post('staff/login')
    @Throttle({ default: { limit: 10, ttl: 60000 } })
    async staffLogin(@Body() staffLoginDto: StaffLoginDto) {
        const staff = await this.authService.validateStaff(
            staffLoginDto.code,
            staffLoginDto.eventId,
        )
        if (!staff) {
            throw new UnauthorizedException('Invalid staff code')
        }
        return this.authService.loginStaff(staff)
    }
 
    @Get('google')
    @UseGuards(AuthGuard('google'))
    async googleAuth() {
        // The AuthGuard('google') intercepts the request and redirects to Google.
        // This function body is intentionally empty and will not be reached.
    }
 
    @Get('google/callback')
    @UseGuards(AuthGuard('google'))
    async googleAuthRedirect(@Req() req: AuthenticatedRequest, @Res() res: Response) {
        const user = await this.authService.validateGoogleUser(req.user)
        if (!user) {
            throw new UnauthorizedException('Unauthorized Google Account')
        }
        const { accessToken, user: loggedInUser } = this.authService.login(user)
 
        const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173'
 
        const token = encodeURIComponent(accessToken)
        const userData = encodeURIComponent(JSON.stringify(loggedInUser))
 
        return res.redirect(`${frontendUrl}/auth/success?token=${token}&user=${userData}`)
    }
}
 
interface AuthenticatedRequest extends Request {
    user: GoogleAuthUser
}