74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import { NextResponse, type NextRequest } from "next/server";
|
|
import { SESSION_COOKIE_NAME, getAuthRuntimeConfig, safeNextPath } from "@/lib/auth/config";
|
|
import { hasAdminSessionAccess, hasSuperAdminAccess } from "@/lib/auth/permissions";
|
|
import { parseSessionCookieValue, readChunkedCookieValue } from "@/lib/auth/session";
|
|
|
|
export async function middleware(request: NextRequest) {
|
|
const config = getAuthRuntimeConfig();
|
|
if (!config.required) return NextResponse.next();
|
|
|
|
const pathname = request.nextUrl.pathname;
|
|
if (config.configured && config.sessionSecret) {
|
|
const session = await parseSessionCookieValue(
|
|
readChunkedCookieValue(SESSION_COOKIE_NAME, (name) => request.cookies.get(name)?.value),
|
|
config.sessionSecret
|
|
);
|
|
if (session) {
|
|
const access = requiredAccess(pathname);
|
|
const allowed = access === "super"
|
|
? hasSuperAdminAccess(session.user)
|
|
: access === "admin"
|
|
? hasAdminSessionAccess(session)
|
|
: true;
|
|
if (!allowed) {
|
|
if (pathname.startsWith("/api/")) {
|
|
return NextResponse.json({ error: access === "super" ? "需要超级管理员权限。" : "需要管理员权限。" }, { status: 403 });
|
|
}
|
|
return NextResponse.redirect(new URL(access === "super" ? "/create" : "/create", request.url));
|
|
}
|
|
return NextResponse.next();
|
|
}
|
|
}
|
|
|
|
if (pathname.startsWith("/api/")) {
|
|
return NextResponse.json({
|
|
error: config.configured ? "请先登录。" : "认证配置不完整。"
|
|
}, { status: config.configured ? 401 : 503 });
|
|
}
|
|
|
|
const loginUrl = new URL("/auth/login", request.url);
|
|
loginUrl.searchParams.set("next", safeNextPath(`${pathname}${request.nextUrl.search}`));
|
|
if (!config.configured) loginUrl.searchParams.set("error", "auth_not_configured");
|
|
return NextResponse.redirect(loginUrl);
|
|
}
|
|
|
|
export const config = {
|
|
matcher: [
|
|
"/",
|
|
"/create/:path*",
|
|
"/assets/:path*",
|
|
"/logs/:path*",
|
|
"/settings/:path*",
|
|
"/accounts/:path*",
|
|
"/usage/:path*",
|
|
"/billing/:path*",
|
|
"/image-edit/:path*",
|
|
"/uploads/:path*",
|
|
"/generated-results/:path*",
|
|
"/api/assets/:path*",
|
|
"/api/generations/:path*",
|
|
"/api/usage/:path*",
|
|
"/api/billing/:path*",
|
|
"/api/logs/:path*",
|
|
"/api/prompt/:path*",
|
|
"/api/settings/:path*",
|
|
"/api/admin/:path*"
|
|
]
|
|
};
|
|
|
|
function requiredAccess(pathname: string): "super" | "admin" | null {
|
|
if (pathname.startsWith("/logs") || pathname.startsWith("/api/logs") || pathname.startsWith("/api/settings")) return "super";
|
|
if (pathname.startsWith("/usage") || pathname.startsWith("/api/admin")) return "admin";
|
|
return null;
|
|
}
|