47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
import { type NextRequest, NextResponse } from "next/server"
|
|
|
|
import {
|
|
canAccessRoute,
|
|
getRequiredPermission,
|
|
isPublicRoute,
|
|
resolveRoleFromRequest,
|
|
} from "@/lib/access"
|
|
|
|
export function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl
|
|
|
|
if (isPublicRoute(pathname)) {
|
|
return NextResponse.next()
|
|
}
|
|
|
|
const role = resolveRoleFromRequest(request)
|
|
|
|
if (!role) {
|
|
const loginUrl = request.nextUrl.clone()
|
|
loginUrl.pathname = "/login"
|
|
loginUrl.searchParams.set("next", pathname)
|
|
|
|
return NextResponse.redirect(loginUrl)
|
|
}
|
|
|
|
if (!canAccessRoute(role, pathname)) {
|
|
const unauthorizedUrl = request.nextUrl.clone()
|
|
unauthorizedUrl.pathname = "/unauthorized"
|
|
|
|
const required = getRequiredPermission(pathname)
|
|
unauthorizedUrl.searchParams.set("required", required.permission)
|
|
unauthorizedUrl.searchParams.set("scope", required.scope)
|
|
|
|
return NextResponse.redirect(unauthorizedUrl)
|
|
}
|
|
|
|
const response = NextResponse.next()
|
|
response.headers.set("x-cms-role", role)
|
|
|
|
return response
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
|
|
}
|