Barazo AppView backend barazo.forum
at main 65 lines 2.3 kB view raw
1import type { FastifyReply, FastifyRequest } from 'fastify' 2import { eq } from 'drizzle-orm' 3import type { AuthMiddleware } from './middleware.js' 4import type { Database } from '../db/index.js' 5import type { Logger } from '../lib/logger.js' 6import { users } from '../db/schema/users.js' 7 8/** 9 * Create a requireModerator preHandler hook for Fastify routes. 10 * 11 * This middleware: 12 * 1. Delegates to requireAuth to verify the user is authenticated 13 * 2. Looks up the user in the database by DID 14 * 3. Checks if the user has the "moderator" or "admin" role 15 * 4. Returns 403 if the user does not have sufficient privileges 16 * 5. Logs moderator access attempts for audit trail 17 * 18 * @param db - Database instance for user lookups 19 * @param authMiddleware - Auth middleware with requireAuth hook 20 * @param logger - Optional Pino logger for audit trail 21 * @returns A Fastify preHandler function 22 */ 23export function createRequireModerator( 24 db: Database, 25 authMiddleware: AuthMiddleware, 26 logger?: Logger 27): (request: FastifyRequest, reply: FastifyReply) => Promise<void> { 28 return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => { 29 // First, run requireAuth to verify authentication 30 await authMiddleware.requireAuth(request, reply) 31 32 // If requireAuth sent a response (e.g. 401), stop here 33 if (reply.sent) { 34 return 35 } 36 37 // At this point request.user should be set by requireAuth 38 if (!request.user) { 39 logger?.warn( 40 { url: request.url, method: request.method }, 41 'Moderator access denied: no user after auth' 42 ) 43 await reply.status(403).send({ error: 'Moderator access required' }) 44 return 45 } 46 47 // Look up user role in database 48 const rows = await db.select().from(users).where(eq(users.did, request.user.did)) 49 50 const userRow = rows[0] 51 if (!userRow || (userRow.role !== 'moderator' && userRow.role !== 'admin')) { 52 logger?.warn( 53 { did: request.user.did, role: userRow?.role, url: request.url, method: request.method }, 54 'Moderator access denied: insufficient role' 55 ) 56 await reply.status(403).send({ error: 'Moderator access required' }) 57 return 58 } 59 60 logger?.info( 61 { did: request.user.did, role: userRow.role, url: request.url, method: request.method }, 62 'Moderator access granted' 63 ) 64 } 65}