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 { 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 { 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 { // 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 { return this.setUserRole(uid, 'guest'); } /** * Verify if a user has a specific role */ async hasRole(uid: string, role: UserRole): Promise { const userRole = await this.getUserRole(uid); return userRole === role; } }