Files
PolyWeather/frontend/lib/ops-admin.ts
T

56 lines
1.4 KiB
TypeScript
Raw Normal View History

import { cookies } from "next/headers";
import { redirect } from "next/navigation";
2026-05-29 17:22:33 +08:00
import {
createSupabaseServerClient,
hasSupabaseServerEnv,
hasSupabaseSessionCookieValues,
} from "@/lib/supabase/server";
function parseAdminEmails() {
return String(process.env.POLYWEATHER_OPS_ADMIN_EMAILS || "")
.split(",")
.map((item) => item.trim().toLowerCase())
.filter(Boolean);
}
export async function requireOpsAdmin(nextPath = "/ops") {
const allowedEmails = parseAdminEmails();
if (!allowedEmails.length || !hasSupabaseServerEnv()) {
redirect("/");
}
const cookieStore = await cookies();
2026-05-29 17:22:33 +08:00
const supabaseCookies = cookieStore.getAll().map((item) => ({
name: item.name,
value: item.value,
}));
if (!hasSupabaseSessionCookieValues(supabaseCookies)) {
redirect(`/auth/login?next=${encodeURIComponent(nextPath)}`);
}
const supabase = createSupabaseServerClient({
getAll() {
2026-05-29 17:22:33 +08:00
return supabaseCookies;
},
setAll() {
// Server components cannot persist refreshed cookies. Route handlers keep
// the session fresh; here we only need read access for page gating.
},
});
const {
2026-05-29 17:22:33 +08:00
data,
error,
} = await supabase.auth.getClaims();
2026-05-29 17:22:33 +08:00
const email = error ? "" : String(data?.claims?.email || "").trim().toLowerCase();
if (!email) {
redirect(`/auth/login?next=${encodeURIComponent(nextPath)}`);
}
if (!allowedEmails.includes(email)) {
redirect("/");
}
return { email };
}