mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import type { Env } from "../types";
|
|
|
|
const SESSION_COOKIE = "wh_admin_session";
|
|
const SESSION_TTL = 7 * 24 * 3600;
|
|
|
|
export interface AdminSession {
|
|
userId: string;
|
|
login: string;
|
|
}
|
|
|
|
export function isAdminUser(env: Env, userId: string, login: string): boolean {
|
|
const ids = (env.ADMIN_USER_IDS ?? "")
|
|
.split(",")
|
|
.map((s) => s.trim())
|
|
.filter(Boolean);
|
|
if (ids.length === 0) return false;
|
|
return ids.includes(userId) || ids.some((id) => id.toLowerCase() === login.toLowerCase());
|
|
}
|
|
|
|
function generateSessionId(): string {
|
|
const bytes = new Uint8Array(32);
|
|
crypto.getRandomValues(bytes);
|
|
return Array.from(bytes)
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
.join("");
|
|
}
|
|
|
|
export async function createAdminSession(
|
|
kv: KVNamespace,
|
|
userId: string,
|
|
login: string,
|
|
): Promise<string> {
|
|
const sessionId = generateSessionId();
|
|
const session: AdminSession = { userId, login };
|
|
await kv.put(`session:${sessionId}`, JSON.stringify(session), {
|
|
expirationTtl: SESSION_TTL,
|
|
});
|
|
return sessionId;
|
|
}
|
|
|
|
export function adminCookie(sessionId: string): string {
|
|
return `${SESSION_COOKIE}=${sessionId}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${SESSION_TTL}`;
|
|
}
|
|
|
|
export function clearAdminCookie(): string {
|
|
return `${SESSION_COOKIE}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`;
|
|
}
|
|
|
|
function parseCookies(header: string | undefined): Record<string, string> {
|
|
const out: Record<string, string> = {};
|
|
if (!header) return out;
|
|
for (const part of header.split(";")) {
|
|
const idx = part.indexOf("=");
|
|
if (idx === -1) continue;
|
|
out[part.slice(0, idx).trim()] = part.slice(idx + 1).trim();
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export async function getAdminSession(
|
|
kv: KVNamespace,
|
|
cookieHeader: string | undefined,
|
|
): Promise<AdminSession | null> {
|
|
const sessionId = parseCookies(cookieHeader)[SESSION_COOKIE];
|
|
if (!sessionId) return null;
|
|
const raw = await kv.get<AdminSession>(`session:${sessionId}`, "json");
|
|
if (!raw) return null;
|
|
return raw;
|
|
}
|
|
|
|
export async function destroyAdminSession(
|
|
kv: KVNamespace,
|
|
cookieHeader: string | undefined,
|
|
): Promise<void> {
|
|
const sessionId = parseCookies(cookieHeader)[SESSION_COOKIE];
|
|
if (sessionId) await kv.delete(`session:${sessionId}`);
|
|
}
|