0
Fork 0
mirror of https://github.com/stonith404/pingvin-share.git synced 2025-01-15 01:14:27 -05:00
pingvin-share/frontend/src/middleware.ts

112 lines
3 KiB
TypeScript
Raw Normal View History

import jwtDecode from "jwt-decode";
import { NextRequest, NextResponse } from "next/server";
import configService from "./services/config.service";
// This middleware redirects based on different conditions:
// - Authentication state
// - Setup status
// - Admin privileges
export const config = {
matcher: "/((?!api|static|.*\\..*|_next).*)",
};
export async function middleware(request: NextRequest) {
// Get config from backend
const config = await (
await fetch("http://localhost:8080/api/configs")
).json();
const getConfig = (key: string) => {
return configService.get(key, config);
};
const containsRoute = (routes: string[], url: string) => {
for (const route of routes) {
if (new RegExp("^" + route.replace(/\*/g, ".*") + "$").test(url))
return true;
}
return false;
};
const route = request.nextUrl.pathname;
let user: { isAdmin: boolean } | null = null;
const accessToken = request.cookies.get("access_token")?.value;
try {
const claims = jwtDecode<{ exp: number; isAdmin: boolean }>(
accessToken as string
);
if (claims.exp * 1000 > Date.now()) {
user = claims;
}
} catch {
user = null;
}
const unauthenticatedRoutes = ["/auth/signIn", "/"];
let publicRoutes = ["/share/*", "/upload/*"];
const setupStatusRegisteredRoutes = ["/auth/*", "/admin/setup"];
const adminRoutes = ["/admin/*"];
const accountRoutes = ["/account/*"];
if (getConfig("ALLOW_REGISTRATION")) {
unauthenticatedRoutes.push("/auth/signUp");
}
if (getConfig("ALLOW_UNAUTHENTICATED_SHARES")) {
publicRoutes = ["*"];
}
const isPublicRoute = containsRoute(publicRoutes, route);
const isUnauthenticatedRoute = containsRoute(unauthenticatedRoutes, route);
const isAdminRoute = containsRoute(adminRoutes, route);
const isAccountRoute = containsRoute(accountRoutes, route);
const isSetupStatusRegisteredRoute = containsRoute(
setupStatusRegisteredRoutes,
route
);
// prettier-ignore
const rules = [
// Setup status
{
condition: getConfig("SETUP_STATUS") == "STARTED" && route != "/auth/signUp",
path: "/auth/signUp",
},
{
condition: getConfig("SETUP_STATUS") == "REGISTERED" && !isSetupStatusRegisteredRoute,
path: user ? "/admin/setup" : "/auth/signIn",
},
// Authenticated state
{
condition: user && isUnauthenticatedRoute,
path: "/upload",
},
// Unauthenticated state
{
condition: !user && !isPublicRoute && !isUnauthenticatedRoute,
path: "/auth/signIn",
},
{
condition: !user && isAccountRoute,
path: "/upload",
},
// Admin privileges
{
condition: isAdminRoute && !user?.isAdmin,
path: "/upload",
},
// Home page
{
condition: (!getConfig("SHOW_HOME_PAGE") || user) && route == "/",
path: "/upload",
},
];
for (const rule of rules) {
if (rule.condition)
return NextResponse.redirect(new URL(rule.path, request.url));
}
}