import { NextApiRequest, NextApiResponse } from 'next'; import { ApiHandlerOptions } from './types'; import { AuthUser } from '../types'; // Clean API route protection export function apiHandler(options: ApiHandlerOptions) { return async (req: NextApiRequest, res: NextApiResponse) => { try { // Get auth token const token = req.cookies['auth-token'] || req.headers.authorization?.replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: 'Unauthorized' }); } // Verify token and get user const user = await verifyApiToken(token); if (!user) { return res.status(401).json({ error: 'Invalid token' }); } // Check authorization const isAuthorized = await checkApiAuthorization(user, options); if (!isAuthorized) { return res.status(403).json({ error: 'Forbidden' }); } // Call the handler with user await options.handler(req, res, user); } catch (error: any) { console.error('[API Handler] Error:', error); res.status(500).json({ error: 'Internal server error' }); } }; } // Convenience functions for common patterns export const protectedApi = ( handler: (req: NextApiRequest, res: NextApiResponse, user: AuthUser) => Promise | void ) => apiHandler({ handler }); export const adminApi = ( handler: (req: NextApiRequest, res: NextApiResponse, user: AuthUser) => Promise | void ) => apiHandler({ isAdmin: true, handler }); export const roleApi = ( role: string | string[], handler: (req: NextApiRequest, res: NextApiResponse, user: AuthUser) => Promise | void ) => apiHandler({ role, handler }); export const departmentApi = ( department: string | string[], handler: (req: NextApiRequest, res: NextApiResponse, user: AuthUser) => Promise | void ) => apiHandler({ department, handler }); export const permissionApi = ( permission: string | string[], handler: (req: NextApiRequest, res: NextApiResponse, user: AuthUser) => Promise | void ) => apiHandler({ permission, handler }); // Helper functions async function verifyApiToken(token: string): Promise { // This would use Firebase Admin SDK or your backend // Mock implementation for now return { uid: 'user123', email: 'user@example.com', emailVerified: true, role: 'editor', department: 'marketing', permissions: ['edit:content'], } as AuthUser; } async function checkApiAuthorization(user: AuthUser, options: ApiHandlerOptions): Promise { // Admin checks if (options.isSuperAdmin && !user.isSuperAdmin) return false; if (options.isAdmin && !user.isAdmin && !user.isSuperAdmin) return false; // Role checks const requiredRoles = options.roles || options.role; if (requiredRoles) { const roles = Array.isArray(requiredRoles) ? requiredRoles : [requiredRoles]; const userRoles = [...(user.roles || []), ...(user.role ? [user.role] : [])]; const hasRole = options.requireAll ? roles.every(r => userRoles.includes(r)) : roles.some(r => userRoles.includes(r)); if (!hasRole) return false; } // Department checks const requiredDepts = options.departments || options.department; if (requiredDepts) { const depts = Array.isArray(requiredDepts) ? requiredDepts : [requiredDepts]; const userDepts = [...(user.departments || []), ...(user.department ? [user.department] : [])]; const hasDept = options.requireAll ? depts.every(d => userDepts.includes(d)) : depts.some(d => userDepts.includes(d)); if (!hasDept) return false; } // Permission checks const requiredPerms = options.permissions || options.permission; if (requiredPerms) { const perms = Array.isArray(requiredPerms) ? requiredPerms : [requiredPerms]; const userPerms = user.permissions || []; const hasPerm = options.requireAll ? perms.every(p => userPerms.includes(p)) : perms.some(p => userPerms.includes(p)); if (!hasPerm) return false; } return true; }