fix ops admin frontend fallback
This commit is contained in:
@@ -43,6 +43,19 @@ export function runTests() {
|
|||||||
"ops server page gate must honor localhost ops access before Supabase/admin-email redirects",
|
"ops server page gate must honor localhost ops access before Supabase/admin-email redirects",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
opsAdminSource.includes("verifyOpsAdminWithBackend") &&
|
||||||
|
opsAdminSource.includes("POLYWEATHER_API_BASE_URL") &&
|
||||||
|
opsAdminSource.includes("/api/ops/online-users") &&
|
||||||
|
opsAdminSource.includes("Authorization") &&
|
||||||
|
opsAdminSource.includes("BACKEND_ENTITLEMENT_HEADER") &&
|
||||||
|
opsAdminSource.includes("await supabase.auth.getSession()") &&
|
||||||
|
opsAdminSource.includes("if (allowedEmails.includes(email))") &&
|
||||||
|
opsAdminSource.includes("if (await verifyOpsAdminWithBackend(accessToken))") &&
|
||||||
|
!opsAdminSource.includes("if (!allowedEmails.length || !hasSupabaseServerEnv())"),
|
||||||
|
"ops admin page gate must fall back to the backend ops admin check when the frontend admin email env is missing or stale",
|
||||||
|
);
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
opsProxyAuthSource.includes("isLocalOpsAccessHost") &&
|
opsProxyAuthSource.includes("isLocalOpsAccessHost") &&
|
||||||
opsProxyAuthSource.includes("x-forwarded-host") &&
|
opsProxyAuthSource.includes("x-forwarded-host") &&
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { cookies, headers } from "next/headers";
|
import { cookies, headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
import { BACKEND_ENTITLEMENT_HEADER } from "@/lib/backend-auth";
|
||||||
import { isLocalOpsAccessHost } from "@/lib/ops-local-access";
|
import { isLocalOpsAccessHost } from "@/lib/ops-local-access";
|
||||||
import {
|
import {
|
||||||
createSupabaseServerClient,
|
createSupabaseServerClient,
|
||||||
@@ -7,6 +8,7 @@ import {
|
|||||||
hasSupabaseSessionCookieValues,
|
hasSupabaseSessionCookieValues,
|
||||||
} from "@/lib/supabase/server";
|
} from "@/lib/supabase/server";
|
||||||
|
|
||||||
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
const LOCAL_DEV_OPS_EMAIL = "local-dev@polyweather.local";
|
const LOCAL_DEV_OPS_EMAIL = "local-dev@polyweather.local";
|
||||||
|
|
||||||
function parseAdminEmails() {
|
function parseAdminEmails() {
|
||||||
@@ -16,6 +18,30 @@ function parseAdminEmails() {
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function verifyOpsAdminWithBackend(accessToken: string) {
|
||||||
|
const token = String(accessToken || "").trim();
|
||||||
|
if (!API_BASE || !token) return false;
|
||||||
|
|
||||||
|
const headers = new Headers({
|
||||||
|
Accept: "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
});
|
||||||
|
const backendToken = process.env.POLYWEATHER_BACKEND_ENTITLEMENT_TOKEN?.trim();
|
||||||
|
if (backendToken) {
|
||||||
|
headers.set(BACKEND_ENTITLEMENT_HEADER, backendToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE.replace(/\/+$/, "")}/api/ops/online-users`, {
|
||||||
|
cache: "no-store",
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
return response.ok;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function requireOpsAdmin(nextPath = "/ops") {
|
export async function requireOpsAdmin(nextPath = "/ops") {
|
||||||
const headerStore = await headers();
|
const headerStore = await headers();
|
||||||
const requestHost =
|
const requestHost =
|
||||||
@@ -25,7 +51,7 @@ export async function requireOpsAdmin(nextPath = "/ops") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const allowedEmails = parseAdminEmails();
|
const allowedEmails = parseAdminEmails();
|
||||||
if (!allowedEmails.length || !hasSupabaseServerEnv()) {
|
if (!hasSupabaseServerEnv()) {
|
||||||
redirect("/");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,9 +83,18 @@ export async function requireOpsAdmin(nextPath = "/ops") {
|
|||||||
if (!email) {
|
if (!email) {
|
||||||
redirect(`/auth/login?next=${encodeURIComponent(nextPath)}`);
|
redirect(`/auth/login?next=${encodeURIComponent(nextPath)}`);
|
||||||
}
|
}
|
||||||
if (!allowedEmails.includes(email)) {
|
|
||||||
redirect("/");
|
if (allowedEmails.includes(email)) {
|
||||||
|
return { email };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { email };
|
const {
|
||||||
|
data: { session },
|
||||||
|
} = await supabase.auth.getSession();
|
||||||
|
const accessToken = session?.access_token || "";
|
||||||
|
if (await verifyOpsAdminWithBackend(accessToken)) {
|
||||||
|
return { email };
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user