Complete admin panel for content management: - SQLite database with better-sqlite3, seed script from content.ts - Simple password auth with HMAC-signed cookies (Edge + Node compatible) - 9 section editors: meta, hero, about, team, classes, schedule, pricing, FAQ, contact - Team CRUD with image upload and drag reorder - Schedule editor with Google Calendar-style visual timeline (colored blocks, overlap detection, click-to-add) - All public components refactored to accept data props from DB (with fallback to static content) - Middleware protecting /admin/* and /api/admin/* routes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
29 lines
841 B
TypeScript
29 lines
841 B
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { verifyToken, COOKIE_NAME } from "@/lib/auth-edge";
|
|
|
|
export async function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// Allow login page and login API
|
|
if (pathname === "/admin/login" || pathname === "/api/auth/login") {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// Protect /admin/* and /api/admin/*
|
|
const token = request.cookies.get(COOKIE_NAME)?.value;
|
|
const valid = token ? await verifyToken(token) : false;
|
|
|
|
if (!valid) {
|
|
if (pathname.startsWith("/api/")) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
return NextResponse.redirect(new URL("/admin/login", request.url));
|
|
}
|
|
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ["/admin/:path*", "/api/admin/:path*"],
|
|
};
|