107 lines
2.5 KiB
TypeScript
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."
|
|
})
|
|
}
|
|
},
|
|
}) |