mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 18:34:13 +00:00
Tests: - Update frontend.e2e.spec.ts with locale testing - Add search.e2e.spec.ts for search functionality - Add i18n.int.spec.ts for localization tests - Add search.int.spec.ts for search integration - Update playwright.config.ts Documentation: - Add CLAUDE.md with project instructions - Add docs/ directory with detailed documentation - Add scripts/ for utility scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
11 KiB
11 KiB
PROMPT: Datenschutzerklärung Integration - Payload Backend
Kontext
Du arbeitest auf dem Server sv-payload (10.10.181.100) im Verzeichnis /home/payload/payload-cms.
Die Datenschutzerklärungen werden extern vom Datenschutzbeauftragten über Alfright gepflegt und sollen per iframe eingebunden werden. Die Konfiguration (Tenant-Key, Styling) wird pro Mandant in Payload CMS verwaltet.
Aufgabe
Erweitere das System um eine PrivacyPolicySettings Collection für die Verwaltung der externen Datenschutzerklärung pro Tenant.
Schritt 1: Collection erstellen
Erstelle src/collections/PrivacyPolicySettings.ts:
// src/collections/PrivacyPolicySettings.ts
import type { CollectionConfig } from 'payload'
import { tenantScopedPublicRead, authenticatedOnly } from '../lib/tenantAccess'
/**
* PrivacyPolicySettings Collection
*
* Konfiguration für externe Datenschutzerklärung (Alfright) pro Tenant.
* Öffentlich lesbar (für Frontend), aber tenant-isoliert.
*/
export const PrivacyPolicySettings: CollectionConfig = {
slug: 'privacy-policy-settings',
admin: {
useAsTitle: 'title',
group: 'Consent Management',
description: 'Externe Datenschutzerklärung Konfiguration (Alfright)',
},
access: {
read: tenantScopedPublicRead,
create: authenticatedOnly,
update: authenticatedOnly,
delete: authenticatedOnly,
},
fields: [
{
name: 'tenant',
type: 'relationship',
relationTo: 'tenants',
required: true,
unique: true,
admin: {
description: 'Jeder Tenant kann nur eine Konfiguration haben',
},
},
{
name: 'title',
type: 'text',
required: true,
defaultValue: 'Datenschutzerklärung',
admin: {
description: 'Interner Titel zur Identifikation',
},
},
{
name: 'provider',
type: 'select',
required: true,
defaultValue: 'alfright',
options: [
{ label: 'Alfright (extern via iframe)', value: 'alfright' },
{ label: 'Eigener Text (nicht implementiert)', value: 'internal' },
],
admin: {
description: 'Quelle der Datenschutzerklärung',
},
},
// Alfright Konfiguration
{
name: 'alfright',
type: 'group',
label: 'Alfright Konfiguration',
admin: {
condition: (data) => data?.provider === 'alfright',
description: 'Einstellungen für die Alfright Integration',
},
fields: [
{
name: 'tenantId',
type: 'text',
required: true,
defaultValue: 'alfright_schutzteam',
admin: {
description: 'Alfright Tenant-ID (aus dem iframe-Code)',
},
},
{
name: 'apiKey',
type: 'text',
required: true,
admin: {
description: 'Alfright API-Key / Dokument-ID (aus dem iframe-Code, z.B. "9f315103c43245bcb0806dd56c2be757")',
},
},
{
name: 'language',
type: 'select',
required: true,
defaultValue: 'de-de',
options: [
{ label: 'Deutsch (Deutschland)', value: 'de-de' },
{ label: 'Deutsch (Österreich)', value: 'de-at' },
{ label: 'Deutsch (Schweiz)', value: 'de-ch' },
{ label: 'Englisch (UK)', value: 'en-gb' },
{ label: 'Englisch (US)', value: 'en-us' },
],
admin: {
description: 'Sprache der Datenschutzerklärung',
},
},
{
name: 'iframeHeight',
type: 'number',
required: true,
defaultValue: 4000,
min: 500,
max: 10000,
admin: {
description: 'Höhe des iframes in Pixeln (empfohlen: 3000-5000)',
},
},
],
},
// Styling (passend zum Website-Theme)
{
name: 'styling',
type: 'group',
label: 'Styling',
admin: {
condition: (data) => data?.provider === 'alfright',
description: 'Farben und Schriften an das Website-Design anpassen',
},
fields: [
{
name: 'headerColor',
type: 'text',
required: true,
defaultValue: '#ca8a04',
admin: {
description: 'Farbe der Überschriften (Hex-Code, z.B. #ca8a04 für Gold)',
},
},
{
name: 'headerFont',
type: 'text',
required: true,
defaultValue: 'Inter, sans-serif',
admin: {
description: 'Schriftart der Überschriften',
},
},
{
name: 'headerSize',
type: 'text',
required: true,
defaultValue: '24px',
admin: {
description: 'Schriftgröße der Hauptüberschriften',
},
},
{
name: 'subheaderSize',
type: 'text',
required: true,
defaultValue: '18px',
admin: {
description: 'Schriftgröße der Unterüberschriften',
},
},
{
name: 'fontColor',
type: 'text',
required: true,
defaultValue: '#f3f4f6',
admin: {
description: 'Textfarbe (Hex-Code, z.B. #f3f4f6 für hellen Text)',
},
},
{
name: 'textFont',
type: 'text',
required: true,
defaultValue: 'Inter, sans-serif',
admin: {
description: 'Schriftart für Fließtext',
},
},
{
name: 'textSize',
type: 'text',
required: true,
defaultValue: '16px',
admin: {
description: 'Schriftgröße für Fließtext',
},
},
{
name: 'linkColor',
type: 'text',
required: true,
defaultValue: '#ca8a04',
admin: {
description: 'Linkfarbe (Hex-Code)',
},
},
{
name: 'backgroundColor',
type: 'text',
required: true,
defaultValue: '#111827',
admin: {
description: 'Hintergrundfarbe (Hex-Code, z.B. #111827 für Dark Theme)',
},
},
],
},
// Cookie-Tabelle Option
{
name: 'showCookieTable',
type: 'checkbox',
defaultValue: true,
admin: {
description: 'Cookie-Tabelle aus CookieInventory unterhalb der Datenschutzerklärung anzeigen',
},
},
{
name: 'cookieTableTitle',
type: 'text',
defaultValue: 'Übersicht der verwendeten Cookies',
admin: {
condition: (data) => data?.showCookieTable,
description: 'Überschrift für die Cookie-Tabelle',
},
},
{
name: 'cookieTableDescription',
type: 'textarea',
defaultValue: 'Ergänzend zur Datenschutzerklärung finden Sie hier eine detaillierte Übersicht aller auf dieser Website eingesetzten Cookies. Sie können Ihre Cookie-Einstellungen jederzeit über den Link "Cookie-Einstellungen" im Footer anpassen.',
admin: {
condition: (data) => data?.showCookieTable,
description: 'Einleitungstext für die Cookie-Tabelle',
},
},
// SEO
{
name: 'seo',
type: 'group',
label: 'SEO',
fields: [
{
name: 'metaTitle',
type: 'text',
defaultValue: 'Datenschutzerklärung',
admin: {
description: 'Meta-Titel für die Seite',
},
},
{
name: 'metaDescription',
type: 'textarea',
defaultValue: 'Informationen zum Datenschutz und zur Verarbeitung Ihrer personenbezogenen Daten.',
admin: {
description: 'Meta-Beschreibung für Suchmaschinen',
},
},
],
},
],
}
Schritt 2: Collection in Payload Config registrieren
Aktualisiere src/payload.config.ts:
// Import hinzufügen (bei den anderen Collection-Imports)
import { PrivacyPolicySettings } from './collections/PrivacyPolicySettings'
// In collections Array hinzufügen
collections: [
Users,
Media,
Tenants,
Pages,
Posts,
Categories,
SocialLinks,
CookieConfigurations,
CookieInventory,
ConsentLogs,
PrivacyPolicySettings, // NEU
],
// In multiTenantPlugin collections hinzufügen
plugins: [
multiTenantPlugin({
tenantsSlug: 'tenants',
collections: {
// ... bestehende Collections ...
'privacy-policy-settings': {}, // NEU
},
}),
],
Schritt 3: Build und Migration
cd /home/payload/payload-cms
# TypeScript Types generieren
pnpm payload generate:types
# Migration erstellen
pnpm payload migrate:create
# Migration ausführen
pnpm payload migrate
# Build
pnpm build
# PM2 neu starten
pm2 restart payload
Schritt 4: Initiale Daten anlegen
Im Admin Panel unter Consent Management → Privacy Policy Settings → Create:
Für porwoll.de (Tenant 1):
| Feld | Wert |
|---|---|
| Tenant | porwoll.de |
| Title | Datenschutzerklärung porwoll.de |
| Provider | Alfright (extern via iframe) |
Alfright Konfiguration:
| Feld | Wert |
|---|---|
| Tenant ID | alfright_schutzteam |
| API Key | 9f315103c43245bcb0806dd56c2be757 |
| Language | Deutsch (Deutschland) |
| iframe Height | 4000 |
Styling (Dark Theme):
| Feld | Wert |
|---|---|
| Header Color | #ca8a04 |
| Header Font | Inter, sans-serif |
| Header Size | 24px |
| Subheader Size | 18px |
| Font Color | #f3f4f6 |
| Text Font | Inter, sans-serif |
| Text Size | 16px |
| Link Color | #ca8a04 |
| Background Color | #111827 |
Cookie-Tabelle:
| Feld | Wert |
|---|---|
| Show Cookie Table | ✅ Aktiviert |
| Cookie Table Title | Übersicht der verwendeten Cookies |
SEO:
| Feld | Wert |
|---|---|
| Meta Title | Datenschutzerklärung | porwoll.de |
| Meta Description | Informationen zum Datenschutz und zur Verarbeitung Ihrer personenbezogenen Daten auf porwoll.de |
Schritt 5: API-Test
# Privacy Policy Settings abrufen (mit Host-Header)
curl -s -H "Host: porwoll.de" "http://localhost:3000/api/privacy-policy-settings" | jq
# Ohne Host-Header (sollte verweigert werden)
curl -s "http://localhost:3000/api/privacy-policy-settings" | jq
Zusammenfassung
| Datei | Aktion |
|---|---|
src/collections/PrivacyPolicySettings.ts |
NEU erstellt |
src/payload.config.ts |
Collection registriert |
src/payload-types.ts |
Automatisch generiert |
API-Endpoint
| Endpoint | Methode | Auth | Beschreibung |
|---|---|---|---|
/api/privacy-policy-settings |
GET | Public (tenant-scoped) | Datenschutz-Konfiguration |
Datenmodell
interface PrivacyPolicySettings {
id: number
tenant: Tenant
title: string
provider: 'alfright' | 'internal'
alfright: {
tenantId: string
apiKey: string
language: string
iframeHeight: number
}
styling: {
headerColor: string
headerFont: string
headerSize: string
subheaderSize: string
fontColor: string
textFont: string
textSize: string
linkColor: string
backgroundColor: string
}
showCookieTable: boolean
cookieTableTitle: string
cookieTableDescription: string
seo: {
metaTitle: string
metaDescription: string
}
}