Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
4.9 kB ยท 135 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136import { asc, db, eq } from "@openstatus/db";import { user, usersToWorkspaces, workspace } from "@openstatus/db/src/schema";import { getCurrency } from "@openstatus/db/src/schema/plan/utils";import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";import { SSO_ORG_COOKIE } from "@/lib/sso-cookie";import { WORKSPACE_SLUG_COOKIE } from "@/lib/workspace-cookie";
export default auth(async (req) => { const url = req.nextUrl.clone(); const response = NextResponse.next();
const continent = req.headers.get("x-vercel-ip-continent") || "NA"; const country = req.headers.get("x-vercel-ip-country") || "US"; const currency = getCurrency({ continent, country });
// NOTE: used in the pricing table to display the currency based on user's location response.cookies.set("x-currency", currency);
if (url.pathname.includes("api/trpc")) { return response; }
if (!req.auth && url.pathname !== "/login") { if (process.env.NODE_ENV === "development") { console.log("User not authenticated, redirecting to login"); } const newURL = new URL("/login", req.url); // Only worth preserving a non-root destination; tryRedirectToCallback // rejects "/" anyway, so storing it would be a no-op redirect. const encodedSearchParams = url.pathname === "/" ? null : `${url.pathname}${url.search}`;
if (encodedSearchParams) { newURL.searchParams.append("redirectTo", encodedSearchParams); }
const response = NextResponse.redirect(newURL); // Store the redirect URL in a cookie for new users who go through onboarding. // Auth.js may not reliably pass callbackUrl to pages.newUser, so we use a // cookie as a fallback to ensure invite links work correctly. if (encodedSearchParams) { response.cookies.set("auth-redirect", encodedSearchParams, { path: "/", httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", maxAge: 60 * 10, // 10 minutes }); } return response; }
if (req.auth && url.pathname === "/login") { const redirectTo = url.searchParams.get("redirectTo"); if (redirectTo) { // Same-origin only: rebuild from path/search/hash so an absolute // redirectTo (e.g. https://evil.com) can't become an open redirect. const target = new URL(redirectTo, req.nextUrl.origin); if ( (target.protocol === "http:" || target.protocol === "https:") && !target.pathname.startsWith("//") ) { const safe = new URL( `${target.pathname}${target.search}${target.hash}`, req.nextUrl.origin, ); if (process.env.NODE_ENV === "development") { console.log("User authenticated, redirecting to", safe); } const res = NextResponse.redirect(safe); res.cookies.delete("auth-redirect"); return res; } } }
const hasWorkspaceSlug = req.cookies.has(WORKSPACE_SLUG_COOKIE); const ssoOrg = req.cookies.get(SSO_ORG_COOKIE)?.value;
if (req.auth?.user?.id && (!hasWorkspaceSlug || ssoOrg)) { const rows = await db .select() .from(usersToWorkspaces) .innerJoin(user, eq(user.id, usersToWorkspaces.userId)) .innerJoin(workspace, eq(workspace.id, usersToWorkspaces.workspaceId)) .where(eq(user.id, Number.parseInt(req.auth.user.id))) .orderBy(asc(usersToWorkspaces.createdAt)) .all();
// The cookie only *selects* among workspaces the user already belongs to โ // it can never grant access, so a forged value is inert. const target = ssoOrg ? rows.find((row) => row.workspace.workosOrganizationId === ssoOrg) : undefined; const query = target ?? rows[0];
if (!query) { console.error(">> Should not happen, no workspace found for user"); } else if (target || !hasWorkspaceSlug) { response.cookies.set(WORKSPACE_SLUG_COOKIE, query.workspace.slug); } }
if (ssoOrg) { response.cookies.delete(SSO_ORG_COOKIE); }
if (!req.auth && hasWorkspaceSlug) { response.cookies.delete(WORKSPACE_SLUG_COOKIE); }
// auth-redirect is single-use and consumed by the /onboarding Server // Component. Middleware response-cookie writes are reflected into the same // request's cookies(), so deleting it on the /onboarding request itself // would race (and lose) that read. Clear it on the next authenticated // request instead: by then onboarding has redirected to the target, the // cookie's job is done, and the stale back-button re-redirect is killed. if ( req.auth && url.pathname !== "/onboarding" && req.cookies.has("auth-redirect") ) { response.cookies.delete("auth-redirect"); }
return response;});
export const config = { matcher: [ "/((?!api|assets|_next/static|_next/image|favicon.ico|icon.svg|sitemap.xml|robots.txt).*)", ],};