-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.ts
More file actions
135 lines (114 loc) · 4.03 KB
/
proxy.ts
File metadata and controls
135 lines (114 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { NextResponse, type NextRequest } from "next/server";
import { buildClearedApiBaseUrlCookieOptions } from "@/lib/auth";
import { MAINTENANCE_SNAPSHOT_COOKIE } from "@/lib/maintenance";
const AUTH_TOKEN_COOKIE = "noderax_token";
const API_BASE_URL_COOKIE = "noderax_api_url";
const PUBLIC_AUTH_ROUTES = ["/login", "/forgot-password"] as const;
const PUBLIC_AUTH_ROUTE_PREFIXES = ["/reset-password/", "/invite/"] as const;
const isPublicAuthRoute = (pathname: string) =>
PUBLIC_AUTH_ROUTES.includes(pathname as (typeof PUBLIC_AUTH_ROUTES)[number]) ||
PUBLIC_AUTH_ROUTE_PREFIXES.some((prefix) => pathname.startsWith(prefix));
const readSetupStatus = async () => {
const baseUrl =
process.env.NODERAX_API_URL || process.env.NEXT_PUBLIC_NODERAX_API_URL;
if (!baseUrl) {
return null;
}
const url = new URL(baseUrl);
const normalizedBasePath =
url.pathname && url.pathname !== "/"
? `/${url.pathname.replace(/^\/+|\/+$/g, "")}`
: "/api/v1";
if (normalizedBasePath === "/" || normalizedBasePath === "/v1") {
url.pathname = "/api/v1/setup/status";
} else if (normalizedBasePath === "/api/v1") {
url.pathname = "/api/v1/setup/status";
} else {
url.pathname = `${normalizedBasePath}/setup/status`;
}
const response = await fetch(url, {
cache: "no-store",
});
if (!response.ok) {
return null;
}
return (await response.json()) as {
mode: "setup" | "promoting" | "installed" | "legacy";
};
};
export async function proxy(request: NextRequest) {
const token = request.cookies.get(AUTH_TOKEN_COOKIE)?.value;
const apiUrlOverride = request.cookies.get(API_BASE_URL_COOKIE)?.value;
const pathname = request.nextUrl.pathname;
const isLoginRoute = pathname === "/login";
const isPublicRoute = isPublicAuthRoute(pathname);
const isSetupRoute = pathname === "/setup" || pathname.startsWith("/setup/");
const isMaintenanceRoute =
pathname === "/maintenance/recovering" ||
pathname.startsWith("/maintenance/");
const maintenanceSnapshot = request.cookies.get(MAINTENANCE_SNAPSHOT_COOKIE)?.value;
const shouldClearApiOverride = Boolean(apiUrlOverride);
let clearCookieForInstalledSystem = false;
const finalizeResponse = (response: NextResponse, clearCookie = false) => {
if (clearCookie && shouldClearApiOverride) {
response.cookies.set(
API_BASE_URL_COOKIE,
"",
buildClearedApiBaseUrlCookieOptions(),
);
}
return response;
};
if (maintenanceSnapshot && !isPublicRoute && !isSetupRoute && !isMaintenanceRoute) {
return finalizeResponse(
NextResponse.rewrite(new URL("/maintenance/recovering", request.url)),
clearCookieForInstalledSystem,
);
}
try {
const status = await readSetupStatus();
if (status) {
clearCookieForInstalledSystem =
status.mode === "installed" || status.mode === "legacy";
if (
(status.mode === "setup" || status.mode === "promoting") &&
!isSetupRoute
) {
return finalizeResponse(
NextResponse.redirect(new URL("/setup", request.url)),
);
}
if (
(status.mode === "installed" || status.mode === "legacy") &&
isSetupRoute
) {
return finalizeResponse(
NextResponse.redirect(new URL(token ? "/" : "/login", request.url)),
clearCookieForInstalledSystem,
);
}
}
} catch {
return NextResponse.next();
}
if (!token && !isPublicRoute && !isSetupRoute) {
const loginUrl = new URL("/login", request.url);
loginUrl.searchParams.set("next", pathname);
return finalizeResponse(
NextResponse.redirect(loginUrl),
clearCookieForInstalledSystem,
);
}
if (token && (isLoginRoute || isSetupRoute)) {
return finalizeResponse(
NextResponse.redirect(new URL("/", request.url)),
clearCookieForInstalledSystem,
);
}
return finalizeResponse(NextResponse.next(), clearCookieForInstalledSystem);
}
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)",
],
};