-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathmiddleware.ts
More file actions
99 lines (83 loc) · 3 KB
/
Copy pathmiddleware.ts
File metadata and controls
99 lines (83 loc) · 3 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
import { defineMiddleware } from "astro:middleware";
import { env } from "cloudflare:workers";
import { createAuth } from "./lib/auth";
import { createDb } from "./lib/db";
/** Routes that require authentication infrastructure */
const PROTECTED_PREFIXES = ["/dashboard", "/api/auth"];
function isProtectedRoute(pathname: string): boolean {
return PROTECTED_PREFIXES.some((prefix) => pathname.startsWith(prefix));
}
export const onRequest = defineMiddleware(async (context, next) => {
// Skip for prerendered pages
if (context.isPrerendered) return next();
const url = new URL(context.request.url);
// Get D1 binding from Cloudflare Workers env (Astro v6 pattern)
const d1 = (env as any).DB;
// B1 fix: Block protected routes when D1 is unavailable
if (!d1) {
if (isProtectedRoute(url.pathname)) {
return new Response("Service unavailable — auth database not configured", {
status: 503,
});
}
context.locals.user = null;
context.locals.session = null;
return next();
}
// B2 fix: Validate required auth env vars before creating auth instance
const cfEnv = env as Record<string, string>;
const requiredVars = ["BETTER_AUTH_SECRET", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"] as const;
const missingVars = requiredVars.filter((key) => !cfEnv[key]);
if (missingVars.length > 0) {
if (isProtectedRoute(url.pathname)) {
console.error(`Auth misconfigured — missing env vars: ${missingVars.join(", ")}`);
return new Response("Service unavailable — auth not configured", {
status: 503,
});
}
context.locals.user = null;
context.locals.session = null;
return next();
}
const db = createDb(d1);
const auth = createAuth(db, cfEnv);
// Store auth instance for API routes
context.locals.auth = auth;
// Check session on every request
try {
const isAuthed = await auth.api.getSession({
headers: context.request.headers,
});
if (isAuthed) {
context.locals.user = isAuthed.user;
context.locals.session = isAuthed.session;
} else {
context.locals.user = null;
context.locals.session = null;
}
} catch {
context.locals.user = null;
context.locals.session = null;
}
// Protect dashboard routes — redirect unauthenticated users
if (url.pathname.startsWith("/dashboard") && !context.locals.session) {
return context.redirect("/login");
}
const response = await next();
// Prevent caching when in Sanity draft/preview mode so iframe refresh always shows current content
const cookieHeader = context.request.headers.get("Cookie") ?? "";
if (cookieHeader.includes("__sanity_preview=")) {
const headers = new Headers(response.headers);
headers.set(
"Cache-Control",
"no-store, no-cache, must-revalidate, max-age=0, proxy-revalidate",
);
headers.set("Pragma", "no-cache");
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
});
}
return response;
});