import { decodeToken } from "#lib/auth/token.js"; import { hashPassword } from "#lib/password.js"; import { prisma } from "#lib/server/prisma.js"; import { APIError, TypesafeAPIContextWithRequest } from "astro-typesafe-api/server"; import { z } from "zod"; export async function checkAuthorizationHeaderNoThrow(authorization: string): Promise | null> { try { return await checkAuthorizationHeader(authorization) } catch(e) { return null } } export async function checkAuthorizationHeader(authorization: string) { if (!authorization) { throw new APIError({ code: "BAD_REQUEST", message: "Request is missing an 'Authorization' header." }) } if (authorization.startsWith("Basic")) { const payload = btoa(authorization.split(" ")[1]).split(":"); if (payload.length !== 2) { throw new APIError({ code: "BAD_REQUEST", message: "Malformed 'Authorization' header." }) } const [email, password] = payload; const user = await prisma.benutzer.findUnique({ where: { email } }) if (!user || user.passwort !== hashPassword(password)) { throw new APIError({ code: "UNAUTHORIZED", message: "Unknown combination of email and password." }) } return user; } else if (authorization.startsWith("Bearer")) { const token = authorization.split(" ")[1] if (!token) { throw new APIError({ code: "BAD_REQUEST", message: "Malformed 'Authorization' header." }) } const payload = decodeToken(token) if ((payload.exp || 0) < Date.now()) { throw new APIError({ code: "UNAUTHORIZED", message: "Access Token has expired." }) } const user = await prisma.benutzer.findUnique({ where: { id: payload.id } }) if (!user) { throw new APIError({ code: "UNAUTHORIZED", message: "Invalid Bearer Token." }) } return user; } throw new APIError({ code: "BAD_REQUEST", message: "Invalid authorization method in 'Authorization' header." }) } export async function authorizationMiddleware(input: any, ctx: TypesafeAPIContextWithRequest) { return await checkAuthorizationHeader(ctx.request.headers.get("Authorization")); } export async function maybeAuthorizationMiddleware(input: any, ctx: TypesafeAPIContextWithRequest) { let user = null; try { user = await authorizationMiddleware(input, ctx) } catch(e) { console.log(e); } return user; } export const authorizationHeaders = { Authorization: z.string() } export async function adminMiddleware(input: any, ctx: TypesafeAPIContextWithRequest) { try { const user = await authorizationMiddleware(input, ctx) if (user.rolle === "ADMIN") { return user } } catch(e) { } throw new APIError({ code: "FORBIDDEN", "message": "Diese Route ist für Admins vorbehalten." }) }