Next.js 15 App Router mit öffentlicher Übersicht und geschütztem Admin-Bereich zur Pflege von Datenschutzerklärungen nach Art. 12ff. DSGVO. - Oberfläche auf Basis von shadcn/ui, Inter lokal eingebunden - Prisma/SQLite, Auth.js mit Credentials-Provider und Rollen - Massenimport der Merkblätter des Amtes Leezen aus PDF - Docker-Image (standalone) und Gitea-Workflow zur Veröffentlichung Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
102 lines
3.7 KiB
TypeScript
102 lines
3.7 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { PrismaClient } from '@prisma/client'
|
|
import { requireAdmin } from '@/lib/require-admin'
|
|
|
|
// Prisma client instance
|
|
const prisma = new PrismaClient()
|
|
|
|
// Validation function for privacy policy data
|
|
function validatePrivacyPolicyData(data: any) {
|
|
const errors: string[] = []
|
|
|
|
// Required fields validation
|
|
if (!data.title?.trim()) errors.push('Title ist erforderlich')
|
|
if (!data.responsible?.trim()) errors.push('Verantwortlicher ist erforderlich')
|
|
if (!data.contactDPO?.trim()) errors.push('Kontaktdaten des Datenschutzbeauftragten sind erforderlich')
|
|
if (!data.dataSubjectsRights?.trim()) errors.push('Betroffenen-Rechte sind erforderlich')
|
|
if (!data.complaintRight?.trim()) errors.push('Beschwerderecht ist erforderlich')
|
|
if (!data.withdrawalRight?.trim()) errors.push('Widerrufsrecht ist erforderlich')
|
|
if (!data.processingDescription?.trim()) errors.push('Verarbeitungstätigkeit ist erforderlich')
|
|
if (!data.recipients?.trim()) errors.push('Empfänger sind erforderlich')
|
|
|
|
// Optional boolean validation
|
|
if (data.isPublic !== undefined && typeof data.isPublic !== 'boolean') {
|
|
errors.push('isPublic muss ein Boolean-Wert sein')
|
|
}
|
|
|
|
return errors
|
|
}
|
|
|
|
// GET /api/privacy-policies - returns privacy policies based on admin parameter
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(request.url)
|
|
const isAdmin = searchParams.get('admin') === 'true'
|
|
|
|
// Get policies based on admin flag
|
|
const policies = await prisma.privacyPolicy.findMany({
|
|
where: isAdmin ? {} : {
|
|
isPublic: true
|
|
},
|
|
orderBy: {
|
|
createdAt: 'desc'
|
|
}
|
|
})
|
|
|
|
return NextResponse.json(policies)
|
|
} catch (error) {
|
|
console.error('Error fetching privacy policies:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Fehler beim Abrufen der Datenschutzerklärungen' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|
|
// POST /api/privacy-policies - creates a new privacy policy (Admin)
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const denied = await requireAdmin()
|
|
if (denied) return denied
|
|
|
|
const data = await request.json()
|
|
|
|
// Validate required fields
|
|
const validationErrors = validatePrivacyPolicyData(data)
|
|
if (validationErrors.length > 0) {
|
|
return NextResponse.json(
|
|
{ error: 'Validierungsfehler', details: validationErrors },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Create new privacy policy
|
|
const newPolicy = await prisma.privacyPolicy.create({
|
|
data: {
|
|
title: data.title.trim(),
|
|
responsible: data.responsible.trim(),
|
|
contactDPO: data.contactDPO.trim(),
|
|
dataSubjectsRights: data.dataSubjectsRights.trim(),
|
|
complaintRight: data.complaintRight.trim(),
|
|
withdrawalRight: data.withdrawalRight.trim(),
|
|
processingDescription: data.processingDescription.trim(),
|
|
processingPurposes: data.processingPurposes?.trim() || null,
|
|
legalBasis: data.legalBasis?.trim() || null,
|
|
recipients: data.recipients.trim(),
|
|
storageDuration: data.storageDuration?.trim() || null,
|
|
dataSource: data.dataSource?.trim() || null,
|
|
provisionObligation: data.provisionObligation?.trim() || null,
|
|
provisionConsequences: data.provisionConsequences?.trim() || null,
|
|
isPublic: data.isPublic !== undefined ? data.isPublic : true
|
|
}
|
|
})
|
|
|
|
return NextResponse.json(newPolicy, { status: 201 })
|
|
} catch (error) {
|
|
console.error('Error creating privacy policy:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Fehler beim Erstellen der Datenschutzerklärung' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
} |