import { NextRequest, NextResponse } from "next/server" import { PUBLIC_ROUTES, canAccessRoute, UserRole } from "./src/config/routes.config" /** * Middleware để kiểm tra authentication và authorization * Chạy TRƯỚC khi render page */ export async function middleware(request: NextRequest) { const { pathname } = request.nextUrl // 1. Kiểm tra nếu là public route if (PUBLIC_ROUTES.includes(pathname)) { // Nếu user đã login, không cho vào signin/signup const userDataCookie = request.cookies.get("userDataRedux") if (userDataCookie && (pathname === "/signin" || pathname === "/signup")) { return NextResponse.redirect(new URL("/", request.url)) } return NextResponse.next() } // 2. Kiểm tra user data cookie (prioritize này để tránh redirect loop) const userDataCookie = request.cookies.get("userDataRedux") if (userDataCookie) { try { const userData = JSON.parse(userDataCookie.value) const userRoles: UserRole[] = userData.roles?.map((r: any) => r.name) || [] // Kiểm tra user có quyền truy cập route này không if (!canAccessRoute(userRoles, pathname)) { // Redirect về 403 page return NextResponse.redirect(new URL("/error-403", request.url)) } // User có quyền, cho qua return NextResponse.next() } catch (error) { console.error("Error parsing user data in middleware:", error) // Xóa cookie lỗi const response = NextResponse.redirect(new URL("/signin", request.url)) response.cookies.delete("userDataRedux") return response } } // 3. Kiểm tra token từ backend (HTTP-only cookie) const token = request.cookies.get("token") || request.cookies.get("access_token") // 4. Nếu không có token và không có user data, redirect về signin if (!token) { const signinUrl = new URL("/signin", request.url) signinUrl.searchParams.set("from", pathname) return NextResponse.redirect(signinUrl) } return NextResponse.next() } /** * Cấu hình matcher - middleware chỉ chạy cho những routes này */ export const config = { matcher: [ /* * Chạy middleware cho tất cả paths ngoại trừ: * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) * - public folder */ "/((?!_next/static|_next/image|favicon.ico|public).*)", ], }