Files
location-mqtt-tracker-app/middleware.ts
2025-11-24 16:30:37 +00:00

66 lines
2.1 KiB
TypeScript

import { auth } from "@/lib/auth";
import { NextResponse } from "next/server";
// Force Node.js runtime for SQLite compatibility
export const runtime = 'nodejs';
export default auth((req) => {
const { pathname } = req.nextUrl;
const session = req.auth;
// Check if accessing map route (requires authentication only)
if (pathname.startsWith('/map')) {
// Require authentication for map access
if (!session?.user) {
const loginUrl = new URL('/login', req.url);
loginUrl.searchParams.set('callbackUrl', pathname);
return NextResponse.redirect(loginUrl);
}
// All authenticated users can access the map
return NextResponse.next();
}
// Check if accessing admin routes
if (pathname.startsWith('/admin')) {
// Require authentication
if (!session?.user) {
const loginUrl = new URL('/login', req.url);
loginUrl.searchParams.set('callbackUrl', pathname);
return NextResponse.redirect(loginUrl);
}
const userRole = (session.user as any).role;
// Define VIEWER-accessible routes (read-only)
const viewerAllowedRoutes = [
'/admin', // Dashboard
'/admin/devices', // Devices list (read-only)
];
// Check if VIEWER is accessing allowed route
const isViewerAllowedRoute = viewerAllowedRoutes.some(route =>
pathname === route || pathname.startsWith(route + '/')
);
// VIEWER can only access dashboard and devices (read-only)
if (userRole === 'VIEWER' && !isViewerAllowedRoute) {
const unauthorizedUrl = new URL('/unauthorized', req.url);
unauthorizedUrl.searchParams.set('from', pathname);
return NextResponse.redirect(unauthorizedUrl);
}
// Non-ADMIN and non-VIEWER users are denied
if (userRole !== 'ADMIN' && userRole !== 'VIEWER') {
const unauthorizedUrl = new URL('/unauthorized', req.url);
unauthorizedUrl.searchParams.set('from', pathname);
return NextResponse.redirect(unauthorizedUrl);
}
}
return NextResponse.next();
});
export const config = {
matcher: ["/admin/:path*", "/map/:path*"],
};