mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-18 00:24:10 +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>
457 lines
11 KiB
Markdown
457 lines
11 KiB
Markdown
# 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`:
|
|
|
|
```typescript
|
|
// 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`:
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```typescript
|
|
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
|
|
}
|
|
}
|
|
```
|