41 lines
1.4 KiB
TypeScript
41 lines
1.4 KiB
TypeScript
import 'server-only';
|
|
import { NextResponse } from 'next/server';
|
|
import { getCurrentUser, type SessionUser } from './auth';
|
|
import { canDelete, canImport, canWrite, isCrmRole } from '@/lib/rbac';
|
|
|
|
export type Guarded = { user: SessionUser; error?: undefined } | { user?: undefined; error: NextResponse };
|
|
|
|
const forbidden = () => NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
|
|
|
/** API guard: a signed-in CRM user (admin | editor | viewer). */
|
|
export async function apiStaff(): Promise<Guarded> {
|
|
const user = await getCurrentUser();
|
|
if (!user) return { error: NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) };
|
|
if (!isCrmRole(user.role)) return { error: forbidden() };
|
|
return { user };
|
|
}
|
|
|
|
/** API guard for mutations a writer/editor may perform. */
|
|
export async function apiWrite(): Promise<Guarded> {
|
|
const g = await apiStaff();
|
|
if (g.error) return g;
|
|
if (!canWrite(g.user.role)) return { error: forbidden() };
|
|
return g;
|
|
}
|
|
|
|
/** API guard for destructive actions (admin only). */
|
|
export async function apiDelete(): Promise<Guarded> {
|
|
const g = await apiStaff();
|
|
if (g.error) return g;
|
|
if (!canDelete(g.user.role)) return { error: forbidden() };
|
|
return g;
|
|
}
|
|
|
|
/** API guard for CSV import (admin or editor). */
|
|
export async function apiImport(): Promise<Guarded> {
|
|
const g = await apiStaff();
|
|
if (g.error) return g;
|
|
if (!canImport(g.user.role)) return { error: forbidden() };
|
|
return g;
|
|
}
|