/** * Utilitaires d'authentification et d'autorisation */ const admin = require('firebase-admin'); const logger = require('firebase-functions/logger'); /** * Vérifie le token Firebase et retourne l'utilisateur */ async function authenticateUser(req) { if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) { throw new Error('Unauthorized: No token provided'); } const idToken = req.headers.authorization.split('Bearer ')[1]; try { const decodedToken = await admin.auth().verifyIdToken(idToken); return decodedToken; } catch (e) { logger.error("Error verifying Firebase ID token:", e); throw new Error('Unauthorized: Invalid token'); } } /** * Récupère les données utilisateur depuis Firestore */ async function getUserData(uid) { const userDoc = await admin.firestore().collection('users').doc(uid).get(); if (!userDoc.exists) { return null; } return { uid, ...userDoc.data() }; } /** * Récupère les permissions d'un rôle */ async function getRolePermissions(roleRef) { if (!roleRef) return []; let roleId; if (typeof roleRef === 'string') { roleId = roleRef; } else if (roleRef.id) { roleId = roleRef.id; } else { return []; } const roleDoc = await admin.firestore().collection('roles').doc(roleId).get(); if (!roleDoc.exists) return []; return roleDoc.data().permissions || []; } /** * Vérifie si l'utilisateur a une permission spécifique */ async function hasPermission(uid, requiredPermission) { const userData = await getUserData(uid); if (!userData) return false; const permissions = await getRolePermissions(userData.role); return permissions.includes(requiredPermission); } /** * Vérifie si l'utilisateur est admin */ async function isAdmin(uid) { const userData = await getUserData(uid); if (!userData) return false; let roleId; const roleField = userData.role; if (typeof roleField === 'string') { roleId = roleField; } else if (roleField && roleField.id) { roleId = roleField.id; } else { return false; } return roleId === 'ADMIN'; } /** * Vérifie si l'utilisateur est assigné à un événement */ async function isAssignedToEvent(uid, eventId) { const eventDoc = await admin.firestore().collection('events').doc(eventId).get(); if (!eventDoc.exists) return false; const eventData = eventDoc.data(); const workforce = eventData.workforce || []; // workforce contient des références DocumentReference return workforce.some(ref => { if (typeof ref === 'string') return ref === uid; if (ref && ref.id) return ref.id === uid; return false; }); } /** * Middleware d'authentification pour les Cloud Functions HTTP */ async function authMiddleware(req, res, next) { try { const decodedToken = await authenticateUser(req); req.user = decodedToken; req.uid = decodedToken.uid; next(); } catch (error) { res.status(401).json({ error: error.message }); } } /** * Middleware de vérification de permission */ function requirePermission(permission) { return async (req, res, next) => { try { const hasAccess = await hasPermission(req.uid, permission); if (!hasAccess) { res.status(403).json({ error: `Forbidden: Requires permission '${permission}'` }); return; } next(); } catch (error) { res.status(403).json({ error: error.message }); } }; } /** * Middleware admin uniquement */ async function requireAdmin(req, res, next) { try { const adminAccess = await isAdmin(req.uid); if (!adminAccess) { res.status(403).json({ error: 'Forbidden: Admin access required' }); return; } next(); } catch (error) { res.status(403).json({ error: error.message }); } } module.exports = { authenticateUser, getUserData, getRolePermissions, hasPermission, isAdmin, isAssignedToEvent, authMiddleware, requirePermission, requireAdmin, };