48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getSession, UserSession } from './auth';
|
|
import { getPrisma } from './db';
|
|
|
|
type AuthenticatedHandler = (
|
|
req: NextRequest,
|
|
context: { session: UserSession; prisma: any; params?: any }
|
|
) => Promise<NextResponse> | NextResponse;
|
|
|
|
/**
|
|
* API Route guard that enforces authentication and RBAC role validation.
|
|
* Binds the authenticated session to the context-aware Prisma client.
|
|
*/
|
|
export function withAuth(
|
|
handler: AuthenticatedHandler,
|
|
allowedRoles?: string[]
|
|
) {
|
|
return async (req: NextRequest, { params }: { params?: any } = {}) => {
|
|
try {
|
|
const session = getSession(req);
|
|
|
|
if (!session) {
|
|
return NextResponse.json(
|
|
{ error: 'Unauthorized. Session expired or missing.' },
|
|
{ status: 401 }
|
|
);
|
|
}
|
|
|
|
if (allowedRoles && allowedRoles.length > 0 && !allowedRoles.includes(session.role)) {
|
|
return NextResponse.json(
|
|
{ error: 'Forbidden. Insufficient permissions.' },
|
|
{ status: 403 }
|
|
);
|
|
}
|
|
|
|
// Get context-aware Prisma client bound to active session
|
|
const prisma = getPrisma(session);
|
|
|
|
return await handler(req, { session, prisma, params });
|
|
} catch (err) {
|
|
console.error('API guard execution error:', err);
|
|
return NextResponse.json(
|
|
{ error: 'Internal server error' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
};
|
|
}
|