-
Notifications
You must be signed in to change notification settings - Fork 3
/
middleware.ts
82 lines (69 loc) · 2.57 KB
/
middleware.ts
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
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
// In maintenance mode, rewrite all requests to /$maintenance
if (process.env.MAINTENANCE_MODE === "true") {
return NextResponse.rewrite(new URL("/$maintenance.html", request.url));
}
// Match subdomains and rewrite to the project preview route
// For example, `https://0123456789.preview.leopardjs.com/example.html` will be rewritten to
// `https://leopardjs.com/$preview/0123456789/example.html`
const host = request.headers.get("host");
if (host !== null) {
const subdomains = getSubdomains(host);
if (subdomains.length === 2 && subdomains[1] === "preview") {
return NextResponse.rewrite(
new URL(
`/$preview/${subdomains[0]}${request.nextUrl.pathname}`,
request.url,
),
);
}
}
// Block URLs begining with $. We will use that as our convention for paths
// which should not be accessible directly and should only ever be reached
// via rewrite rules. (Such as /$preview/...)
if (
request.nextUrl.pathname.startsWith("$") || // I have no idea if the non-/ version is needed here but I'm including it to be on the safe side
request.nextUrl.pathname.startsWith("/$")
) {
// Exception: If unsafe same-domain previews are enabled, allow
// $preview paths to be loaded directly
if (process.env.NEXT_PUBLIC_UNSAFE_SAME_DOMAIN_PREVIEWS === "true") {
if (
request.nextUrl.pathname.startsWith("$preview") ||
request.nextUrl.pathname.startsWith("/$preview")
) {
return NextResponse.next();
}
}
// Return a 404 for any requests to these paths
return NextResponse.error();
}
if (request.nextUrl.pathname.startsWith("/admin")) {
const user = await getUserFromAPI(request);
if (!user || user.role !== "ADMIN") {
return NextResponse.redirect(new URL("/", request.url));
}
}
if (request.nextUrl.pathname.startsWith("/api/admin")) {
const user = await getUserFromAPI(request);
if (!user || user.role !== "ADMIN") {
return NextResponse.error();
}
}
return NextResponse.next();
}
async function getUserFromAPI(request: NextRequest) {
const { user } = await fetch(process.env.NEXT_PUBLIC_BASE_URL + "/api/me", {
headers: {
cookie: request.headers.get("cookie") ?? "",
},
}).then((res) => res.json());
return user;
}
function getSubdomains(host: string) {
// Remove port if it exists
host = host.split(":")[0];
return host.split(".").slice(0, -2);
}