Files
online-energieausweis/src/pages/api/bild.ts
2025-02-22 12:37:54 +11:00

107 lines
2.5 KiB
TypeScript

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."
})
}
},
})