einbau von rollen, neue Admin Ansicht
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import { Body, Controller, HttpException, HttpStatus, Inject, Post } from '@nestjs/common';
|
||||
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) {
|
||||
@@ -33,5 +39,91 @@ export class AuthController {
|
||||
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<UsersResponse> {
|
||||
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}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { FirebaseAdminModule } from 'src/firebase-admin/firebase-admin.module';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule.forRoot({ envFilePath: '.env' }),FirebaseAdminModule],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService],
|
||||
exports: [],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
113
bizmatch-server/src/auth/auth.service.ts
Normal file
113
bizmatch-server/src/auth/auth.service.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import * as admin from 'firebase-admin';
|
||||
import { FirebaseUserInfo, UserRole } from 'src/models/main.model';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(@Inject('FIREBASE_ADMIN') private firebaseAdmin: admin.app.App) {}
|
||||
|
||||
/**
|
||||
* Set a user's role via Firebase custom claims
|
||||
*/
|
||||
async setUserRole(uid: string, role: UserRole): Promise<void> {
|
||||
try {
|
||||
// Get the current custom claims
|
||||
const user = await this.firebaseAdmin.auth().getUser(uid);
|
||||
const currentClaims = user.customClaims || {};
|
||||
|
||||
// Set the new role
|
||||
await this.firebaseAdmin.auth().setCustomUserClaims(uid, {
|
||||
...currentClaims,
|
||||
role: role,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error setting user role:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user's current role
|
||||
*/
|
||||
async getUserRole(uid: string): Promise<UserRole | null> {
|
||||
try {
|
||||
const user = await this.firebaseAdmin.auth().getUser(uid);
|
||||
const claims = user.customClaims || {};
|
||||
return (claims.role as UserRole) || null;
|
||||
} catch (error) {
|
||||
console.error('Error getting user role:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users with a specific role
|
||||
*/
|
||||
async getUsersByRole(role: UserRole): Promise<admin.auth.UserRecord[]> {
|
||||
// Note: Firebase Admin doesn't provide a direct way to query users by custom claims
|
||||
// For a production app, you might want to store role information in Firestore as well
|
||||
// This is a simple implementation that lists all users and filters them
|
||||
try {
|
||||
const listUsersResult = await this.firebaseAdmin.auth().listUsers();
|
||||
return listUsersResult.users.filter(user => user.customClaims && user.customClaims.role === role);
|
||||
} catch (error) {
|
||||
console.error('Error getting users by role:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Firebase users with their roles
|
||||
* @param maxResults Maximum number of users to return (optional, default 1000)
|
||||
* @param pageToken Token for pagination (optional)
|
||||
*/
|
||||
async getAllUsers(maxResults: number = 1000, pageToken?: string): Promise<{ users: FirebaseUserInfo[]; pageToken?: string }> {
|
||||
try {
|
||||
const listUsersResult = await this.firebaseAdmin.auth().listUsers(maxResults, pageToken);
|
||||
|
||||
const users = listUsersResult.users.map(user => this.mapUserRecord(user));
|
||||
|
||||
return {
|
||||
users,
|
||||
pageToken: listUsersResult.pageToken,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error getting all users:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Maps a Firebase UserRecord to our FirebaseUserInfo interface
|
||||
*/
|
||||
private mapUserRecord(user: admin.auth.UserRecord): FirebaseUserInfo {
|
||||
return {
|
||||
uid: user.uid,
|
||||
email: user.email || null,
|
||||
displayName: user.displayName || null,
|
||||
photoURL: user.photoURL || null,
|
||||
phoneNumber: user.phoneNumber || null,
|
||||
disabled: user.disabled,
|
||||
emailVerified: user.emailVerified,
|
||||
role: user.customClaims?.role || null,
|
||||
creationTime: user.metadata.creationTime,
|
||||
lastSignInTime: user.metadata.lastSignInTime,
|
||||
// Optionally include other customClaims if needed
|
||||
customClaims: user.customClaims,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default role for a new user
|
||||
*/
|
||||
async setDefaultRole(uid: string): Promise<void> {
|
||||
return this.setUserRole(uid, 'guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if a user has a specific role
|
||||
*/
|
||||
async hasRole(uid: string, role: UserRole): Promise<boolean> {
|
||||
const userRole = await this.getUserRole(uid);
|
||||
return userRole === role;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user