import { NextRequestWithAuth, withAuth } from "next-auth/middleware"; import { ability, authOptions } from "@/config/authConfig"; import { NextFetchEvent, NextResponse } from "next/server"; import { getToken } from "next-auth/jwt"; // user groups export const [ SUPER_ADMIN, TOP_MANAGEMENT, TEAM_LEAD, NORMAL_STAFF, SUPPORTING_STAFF ] = [ "Super Admin", "Top Management", "Team Leader", "Normal Staff", "Supporting Staff" ] // abilities export const [ VIEW_USER, MAINTAIN_USER, MAINTAIN_TIMESHEET, VIEW_TASK_TEMPLATE, VIEW_GROUP, VIEW_MASTERDATA, MAINTAIN_MASTERDATA, VIEW_DASHBOARD_SELF, VIEW_DASHBOARD_ALL, IMPORT_INVOICE, MAINTAIN_GROUP, GENERATE_REPORTS, VIEW_STAFF_PROFILE, IMPORT_RECEIPT, MAINTAIN_TASK_TEMPLATE, MAINTAIN_TIMESHEET_7DAYS, VIEW_PROJECT, MAINTAIN_PROJECT, DELETE_PROJECT, ] = [ 'VIEW_USER', 'MAINTAIN_USER', 'MAINTAIN_TIMESHEET', 'VIEW_TASK_TEMPLATE', 'VIEW_GROUP', 'VIEW_MASTERDATA', 'MAINTAIN_MASTERDATA', 'VIEW_DASHBOARD_SELF', 'VIEW_DASHBOARD_ALL', 'IMPORT_INVOICE', 'MAINTAIN_GROUP', 'GENERATE_REPORTS', 'VIEW_STAFF_PROFILE', 'IMPORT_RECEIPT', 'MAINTAIN_TASK_TEMPLATE', 'MAINTAIN_TIMESHEET_7DAYS', 'VIEW_PROJECT', 'MAINTAIN_PROJECT', 'DELETE_PROJECT' ] const PRIVATE_ROUTES = [ "/analytics", "/dashboard", "/home", "/invoice", "/projects", "/tasks", "/settings", "/staffReimbursement", ]; const LANG_QUERY_PARAM = "lang"; export default async function middleware( req: NextRequestWithAuth, event: NextFetchEvent, ) { const langPref = req.nextUrl.searchParams.get(LANG_QUERY_PARAM); // const token = await getToken({ req: req, secret: process.env.SECRET }); if (langPref) { // Redirect to same url without the lang query param + set cookies const newUrl = new URL(req.nextUrl); newUrl.searchParams.delete(LANG_QUERY_PARAM); const response = NextResponse.redirect(newUrl); response.cookies.set("i18next", langPref); return response; } const authMiddleware = withAuth({ pages: authOptions.pages, callbacks: { authorized: ({req, token}) => { let isAuth = Boolean(token); if (!Boolean(token)) { return Boolean(token) } const abilities = (token!.abilities as ability[]).map((item: ability) => item.actionSubjectCombo); if (req.nextUrl.pathname.startsWith('/projects')) { isAuth = [MAINTAIN_PROJECT].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/tasks')) { isAuth = [MAINTAIN_TASK_TEMPLATE].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/settings')) { isAuth = [VIEW_MASTERDATA, MAINTAIN_MASTERDATA].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/settings/user')) { isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/settings/staff/user')) { isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/analytics')) { isAuth = [GENERATE_REPORTS].some((ability) => abilities.includes(ability)); } if (req.nextUrl.pathname.startsWith('/settings/staff/edit')) { isAuth = [VIEW_STAFF_PROFILE].some((ability) => abilities.includes(ability)); } return isAuth } } }); // Matcher for using the auth middleware return PRIVATE_ROUTES.some((route) => req.nextUrl.pathname.startsWith(route)) ? await authMiddleware(req, event) // Let auth middleware handle response : NextResponse.next(); // Return normal response }