All files / src/lib/api/middleware withAdmin.ts

100% Statements 65/65
95.23% Branches 20/21
100% Functions 1/1
100% Lines 65/65

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 661x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 20x 20x 20x 20x 163x 163x 163x 163x 163x 163x 163x 21x 21x 142x 142x 142x 142x 163x 163x 163x 163x 163x 163x 142x 163x 2x 2x 140x 163x 17x 17x 123x 123x 20x 20x  
/**
 * Admin Middleware
 *
 * Ensures the request is from an authenticated admin user.
 */
 
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { unauthorizedResponse, forbiddenResponse, notFoundResponse, type ApiErrorResponse } from '../responses';
import type {
  RouteContext,
  AuthenticatedUserHandler,
  AuthenticatedUser } from './types';
 
/**
 * Admin middleware
 *
 * Wraps a handler to require authentication AND admin role.
 * Returns 401 if not authenticated, 403 if not admin.
 *
 * @example
 * ```ts
 * export const GET = withAdmin(async (request, context, session, user) => {
 *   // user is guaranteed to be an admin
 *   const allUsers = await prisma.user.findMany();
 *   return successResponse(allUsers);
 * });
 * ```
 */
export function withAdmin<T>(
  handler: AuthenticatedUserHandler<T>
) {
  return async (
    request: Request,
    context?: RouteContext
  ): Promise<NextResponse<T | ApiErrorResponse>> => {
    const session = await getServerSession();
 
    // Check for valid session with user id (numeric) or email
    if (!session?.user?.id && !session?.user?.email) {
      return unauthorizedResponse();
    }
 
    const user = await prisma.user.findUnique({
      where: session.user.email
        ? { email: session.user.email }
        : { id: session.user.id },
      select: {
        id: true,
        email: true,
        name: true,
        role: true } });
 
    if (!user) {
      return notFoundResponse('User');
    }
 
    if (user.role !== 'ADMIN') {
      return forbiddenResponse('Admin access required');
    }
 
    return handler(request as NextRequest, context, session, user as AuthenticatedUser);
  };
}