import { authorizationMiddleware, maybeAuthorizationMiddleware } from "#lib/middleware/authorization.js"; import { prisma } from "#lib/server/prisma.js"; import { defineApiRoute, APIError } from "astro-typesafe-api/server"; import { z } from "astro:content"; import { fileURLToPath } from "url"; import isBase64 from "is-base64"; import { writeFileSync } from "fs" import { UUidWithPrefix } from "#components/Ausweis/types.js"; import { BildSchema } from "src/generated/zod/bild.js"; import sharp from "sharp" import { PERSISTENT_DIR } from "#lib/server/constants.js"; export const PUT = defineApiRoute({ input: BildSchema.pick({ kategorie: true, }).merge(z.object({ data: z.string() })), output: z.object({ uid: z.string({ description: "Die UID des Bildes." }) }), async fetch(input) { const data = input.data; if (!isBase64(data, { mimeRequired: true })) { throw new APIError({ code: "BAD_REQUEST", message: "Das Bild ist nicht base64.", }); } const dataWithoutPrefix = data.replace( /^data:image\/\w+;base64,/, "" ); const buffer = Buffer.from(dataWithoutPrefix, "base64"); const bild = await prisma.bild.create({ data: { kategorie: input.kategorie }, select: { uid: true, }, }); const filePath = fileURLToPath(new URL(`${PERSISTENT_DIR}/images/${bild.uid}.jpg`, import.meta.url)); try { // Wir optimieren das Bild und konvertieren es in JPEG const optimizedBuffer = await sharp(buffer).jpeg({ quality: 80 }).toBuffer(); writeFileSync(filePath, optimizedBuffer) } catch(e) { // Bild wurde nicht gespeichert, wir löschen den Eintrag wieder await prisma.bild.delete({ where: { uid: bild.uid } }) // Und geben einen Fehler zurück throw new APIError({ code: "INTERNAL_SERVER_ERROR", message: "Bild konnte nicht gespeichert werden.", }); } return { uid: bild.uid }; }, }) export const DELETE = defineApiRoute({ input: z.object({ uid: UUidWithPrefix }), middleware: maybeAuthorizationMiddleware, async fetch(input, context, user) { try { if (user) { await prisma.bild.delete({ where: { uid: input.uid, aufnahme: { benutzer: { id: user.id } } } }) } else { await prisma.bild.delete({ where: { uid: input.uid, aufnahme_id: null } }) } } catch(e) { throw new APIError({ code: "INTERNAL_SERVER_ERROR", message: "Bild konnte nicht gelöscht werden." }) } }, })