Files
anouma/collections/Media.ts
T
maro 82c4261a81 Fix security and correctness issues found in full-codebase audit
- Restrict meetingPassword field so it isn't leaked via the public REST/GraphQL API
- Fix booking slot computation to use Europe/Berlin time instead of the server's UTC clock
- Reset email verification when a customer changes their email address
- Fix ICS calendar injection via unescaped carriage returns in event descriptions
- Bind WebRTC meeting kicks to a persistent client id so they survive a rejoin
- Move the meeting signaling token out of the WebSocket query string into the first message
- Prevent duplicate signaling connections from leaking when the same participant reconnects
- Use the rightmost X-Forwarded-For entry for rate limiting (single trusted reverse proxy)
- Use constant-time comparison for the cron endpoint's bearer token
- Remove SVG from allowed Media upload types (stored-XSS risk, unused anyway)
- Add baseline security headers and a CSP to next.config.ts
- Fix CI/CD script injection via unsanitized git ref names in release.yml
2026-09-06 21:59:39 +02:00

59 lines
1.7 KiB
TypeScript

import path from "path";
import { fileURLToPath } from "url";
import type { CollectionConfig } from "payload";
import { isAdmin } from "@/access";
const dirname = path.dirname(fileURLToPath(import.meta.url));
export const Media: CollectionConfig = {
slug: "media",
labels: {
singular: "Bild",
plural: "Bilder",
},
admin: {
useAsTitle: "alt",
description: "Bilder für die Website — Alt-Text ist für Barrierefreiheit und SEO Pflicht.",
},
access: {
// Images are public so the website can display them without a login.
read: () => true,
create: isAdmin,
update: isAdmin,
delete: isAdmin,
},
upload: {
staticDir: path.resolve(dirname, "..", "media"),
// SVG deliberately excluded: it can carry inline <script>/event-handler
// payloads that execute if the raw file is ever opened directly (not via
// <img>) — not currently needed by any part of the site.
mimeTypes: ["image/jpeg", "image/png", "image/webp"],
imageSizes: [
{ name: "thumbnail", width: 400, position: "centre" },
{ name: "card", width: 800, position: "centre" },
{ name: "hero", width: 1600, position: "centre" },
],
adminThumbnail: "thumbnail",
formatOptions: { format: "webp", options: { quality: 82 } },
},
fields: [
{
name: "alt",
type: "text",
label: "Alt-Text",
required: true,
admin: {
description: "Kurze Beschreibung des Bildes für Screenreader und Suchmaschinen.",
},
},
{
name: "caption",
type: "textarea",
label: "Bildbeschreibung",
admin: {
description: "Optionale, längere Beschreibung (z. B. für eine Bildunterschrift).",
},
},
],
};