import { Body, Controller, Get, HttpException, HttpStatus, Inject, Param, Post, Query, Req, UseGuards } from '@nestjs/common'; import * as admin from 'firebase-admin'; import { AdminGuard } from 'src/jwt-auth/admin-auth.guard'; import { AuthGuard } from 'src/jwt-auth/auth.guard'; import { LocalhostGuard } from 'src/jwt-auth/localhost.guard'; import { UserRole, UsersResponse } from 'src/models/main.model'; import { AuthService } from './auth.service'; @Controller('auth') export class AuthController { constructor( @Inject('FIREBASE_ADMIN') private readonly firebaseAdmin: typeof admin, private readonly authService: AuthService, ) {} @Post('verify-email') async verifyEmail(@Body('oobCode') oobCode: string, @Body('email') email: string) { if (!oobCode || !email) { throw new HttpException('oobCode and email are required', HttpStatus.BAD_REQUEST); } try { // Step 1: Get the user by email address const userRecord = await this.firebaseAdmin.auth().getUserByEmail(email); if (userRecord.emailVerified) { // Even if already verified, we'll still return a valid token const customToken = await this.firebaseAdmin.auth().createCustomToken(userRecord.uid); return { message: 'Email is already verified', token: customToken, }; } // Step 2: Update the user status to set emailVerified to true await this.firebaseAdmin.auth().updateUser(userRecord.uid, { emailVerified: true, }); // Step 3: Generate a custom Firebase token for the user // This token can be used on the client side to authenticate with Firebase const customToken = await this.firebaseAdmin.auth().createCustomToken(userRecord.uid); return { message: 'Email successfully verified', token: customToken, }; } catch (error) { throw new HttpException(error.message || 'Failed to verify email', HttpStatus.BAD_REQUEST); } } @Post(':uid/role') @UseGuards(AuthGuard, AdminGuard) // Only admins can change roles async setUserRole(@Param('uid') uid: string, @Body('role') role: UserRole): Promise<{ success: boolean }> { await this.authService.setUserRole(uid, role); return { success: true }; } @Get('me/role') @UseGuards(AuthGuard) async getMyRole(@Req() req: any): Promise<{ role: UserRole | null }> { console.log('->', req.user); console.log('-->', req.user.uid); const uid = req.user.uid; // From FirebaseAuthGuard const role = await this.authService.getUserRole(uid); return { role }; } @Get(':uid/role') @UseGuards(AuthGuard) async getUserRole(@Param('uid') uid: string): Promise<{ role: UserRole | null }> { const role = await this.authService.getUserRole(uid); return { role }; } @Get('role/:role') @UseGuards(AuthGuard, AdminGuard) // Only admins can list users by role async getUsersByRole(@Param('role') role: UserRole): Promise<{ users: any[] }> { const users = await this.authService.getUsersByRole(role); // Map to simpler objects to avoid circular references const simplifiedUsers = users.map(user => ({ uid: user.uid, email: user.email, displayName: user.displayName, })); return { users: simplifiedUsers }; } /** * Ruft alle Firebase-Benutzer mit ihren Rollen ab * @param maxResults Maximale Anzahl an zurückzugebenden Benutzern (optional, Standard: 1000) * @param pageToken Token für die Paginierung (optional) * @returns Eine Liste von Benutzern mit ihren Rollen und Metadaten */ @Get() @UseGuards(AuthGuard, AdminGuard) // Only admins can list all users async getAllUsers(@Query('maxResults') maxResults?: number, @Query('pageToken') pageToken?: string): Promise { const result = await this.authService.getAllUsers(maxResults ? parseInt(maxResults.toString(), 10) : undefined, pageToken); return { users: result.users, totalCount: result.users.length, ...(result.pageToken && { pageToken: result.pageToken }), }; } /** * Endpoint zum direkten Einstellen einer Rolle für Debug-Zwecke * WARNUNG: Dieser Endpoint sollte in der Produktion entfernt oder stark gesichert werden */ @Post('set-role') @UseGuards(AuthGuard, LocalhostGuard) async setUserRoleOnLocalhost(@Req() req: any, @Body('role') role: UserRole): Promise<{ success: boolean; message: string }> { try { const uid = req.user.uid; // Aktuelle Rolle protokollieren const currentUser = await this.authService.getUserRole(uid); console.log(`Changing role for user ${uid} from ${currentUser} to ${role}`); // Neue Rolle setzen await this.authService.setUserRole(uid, role); // Rolle erneut prüfen, um zu bestätigen const newRole = await this.authService.getUserRole(uid); return { success: true, message: `Rolle für Benutzer ${uid} von ${currentUser} zu ${newRole} geändert`, }; } catch (error) { console.error('Fehler beim Setzen der Rolle:', error); return { success: false, message: `Fehler: ${error.message}`, }; } } }