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

100% Statements 45/45
100% Branches 17/17
100% Functions 1/1
100% Lines 45/45

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 461x 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 25x 25x 25x 25x 235x 235x 235x 235x 235x 235x 235x 36x 36x 199x 199x 25x 25x  
/**
 * Authentication Middleware
 *
 * Ensures the request has a valid session before executing the handler.
 */
 
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from '@/lib/auth';
import { unauthorizedResponse, type ApiErrorResponse } from '../responses';
import type {
  RouteContext,
  AuthenticatedHandler } from './types';
 
/**
 * Authentication middleware
 *
 * Wraps a handler to require authentication. If the user is not authenticated,
 * returns a 401 Unauthorized response.
 *
 * @example
 * ```ts
 * export const GET = withAuth(async (request, context, session) => {
 *   // session is guaranteed to be valid here
 *   const userId = session.user.id;
 *   return successResponse({ userId });
 * });
 * ```
 */
export function withAuth<T>(
  handler: AuthenticatedHandler<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();
    }
 
    return handler(request as NextRequest, context, session);
  };
}