first commit
This commit is contained in:
57
src/middleware.ts
Normal file
57
src/middleware.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { MiddlewareHandler } from "astro";
|
||||
import { options } from "./runtime.js";
|
||||
import { verifyAndDecode } from "./lib/sign.js";
|
||||
|
||||
function parseCookies(cookieHeader: string | null): Record<string, string> {
|
||||
const out: Record<string, string> = {};
|
||||
if (!cookieHeader) return out;
|
||||
const parts = cookieHeader.split(/;\s*/);
|
||||
for (const part of parts) {
|
||||
const idx = part.indexOf("=");
|
||||
if (idx === -1) continue;
|
||||
const name = decodeURIComponent(part.slice(0, idx));
|
||||
const val = decodeURIComponent(part.slice(idx + 1));
|
||||
out[name] = val;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function escapeRegex(str: string): string {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
function globToRegExp(pattern: string): RegExp {
|
||||
const escaped = pattern.split("*").map(escapeRegex).join(".*");
|
||||
return new RegExp(`^${escaped}$`);
|
||||
}
|
||||
|
||||
function isProtected(pathname: string, patterns: string[]): boolean {
|
||||
return patterns.some((p) => globToRegExp(p).test(pathname));
|
||||
}
|
||||
|
||||
export const onRequest: MiddlewareHandler = async (context, next) => {
|
||||
const { request, locals, url } = context;
|
||||
const cookieName = options.cookie.name;
|
||||
const cookies = parseCookies(request.headers.get("cookie"));
|
||||
const token = cookies[cookieName];
|
||||
|
||||
locals.user = null;
|
||||
if (token) {
|
||||
const res = await verifyAndDecode<{ sub: string; email?: string }>(
|
||||
token,
|
||||
options.cookie.signingSecret,
|
||||
);
|
||||
if (res.valid && res.payload && typeof res.payload.sub === "string") {
|
||||
locals.user = { sub: res.payload.sub, email: res.payload.email };
|
||||
}
|
||||
}
|
||||
|
||||
if (isProtected(url.pathname, options.protected) && !locals.user) {
|
||||
const returnTo = url.pathname + (url.search || "");
|
||||
const loginUrl = new URL(options.routes.login, url);
|
||||
loginUrl.searchParams.set("return_to", returnTo);
|
||||
return Response.redirect(loginUrl, 302);
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
Reference in New Issue
Block a user