Initial commit: breakpilot-compliance - Compliance SDK Platform
Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* API Route: Privacy Policy Generator
|
||||
*
|
||||
* POST - Generiert eine Datenschutzerklaerung aus dem Datenpunktkatalog
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import {
|
||||
CompanyInfo,
|
||||
DataPoint,
|
||||
SupportedLanguage,
|
||||
ExportFormat,
|
||||
GeneratedPrivacyPolicy,
|
||||
} from '@/lib/sdk/einwilligungen/types'
|
||||
import {
|
||||
generatePrivacyPolicy,
|
||||
generatePrivacyPolicySections,
|
||||
} from '@/lib/sdk/einwilligungen/generator/privacy-policy'
|
||||
import {
|
||||
PREDEFINED_DATA_POINTS,
|
||||
getDataPointById,
|
||||
} from '@/lib/sdk/einwilligungen/catalog/loader'
|
||||
|
||||
// In-Memory Storage fuer generierte Policies
|
||||
const policyStorage = new Map<string, GeneratedPrivacyPolicy>()
|
||||
|
||||
/**
|
||||
* POST /api/sdk/v1/einwilligungen/privacy-policy/generate
|
||||
*
|
||||
* Generiert eine Datenschutzerklaerung
|
||||
*
|
||||
* Body:
|
||||
* - dataPointIds: string[] - IDs der zu inkludierenden Datenpunkte
|
||||
* - companyInfo: CompanyInfo - Firmeninformationen
|
||||
* - language: 'de' | 'en' - Sprache
|
||||
* - format: 'HTML' | 'MARKDOWN' | 'PDF' | 'DOCX' - Ausgabeformat
|
||||
* - customDataPoints?: DataPoint[] - Kundenspezifische Datenpunkte
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const tenantId = request.headers.get('X-Tenant-ID')
|
||||
|
||||
if (!tenantId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Tenant ID required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const {
|
||||
dataPointIds,
|
||||
companyInfo,
|
||||
language = 'de',
|
||||
format = 'HTML',
|
||||
customDataPoints = [],
|
||||
} = body
|
||||
|
||||
// Validierung
|
||||
if (!companyInfo || !companyInfo.name || !companyInfo.address || !companyInfo.email) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Company info (name, address, email) required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (!dataPointIds || !Array.isArray(dataPointIds) || dataPointIds.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'At least one data point ID required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Validiere Sprache
|
||||
const validLanguages: SupportedLanguage[] = ['de', 'en']
|
||||
if (!validLanguages.includes(language)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid language. Must be "de" or "en"' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Validiere Format
|
||||
const validFormats: ExportFormat[] = ['HTML', 'MARKDOWN', 'PDF', 'DOCX']
|
||||
if (!validFormats.includes(format)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid format. Must be HTML, MARKDOWN, PDF, or DOCX' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Sammle alle Datenpunkte
|
||||
const allDataPoints: DataPoint[] = [
|
||||
...PREDEFINED_DATA_POINTS,
|
||||
...customDataPoints,
|
||||
]
|
||||
|
||||
// Filtere nach ausgewaehlten IDs
|
||||
const selectedDataPoints = dataPointIds
|
||||
.map((id: string) => allDataPoints.find((dp) => dp.id === id))
|
||||
.filter((dp): dp is DataPoint => dp !== undefined)
|
||||
|
||||
if (selectedDataPoints.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'No valid data points found for the provided IDs' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Generiere die Privacy Policy
|
||||
const policy = generatePrivacyPolicy(
|
||||
tenantId,
|
||||
selectedDataPoints,
|
||||
companyInfo as CompanyInfo,
|
||||
language as SupportedLanguage,
|
||||
format as ExportFormat
|
||||
)
|
||||
|
||||
// Speichere fuer spaeteres Abrufen
|
||||
policyStorage.set(policy.id, policy)
|
||||
|
||||
// Fuer PDF/DOCX: Nur Metadaten zurueckgeben, Download separat
|
||||
if (format === 'PDF' || format === 'DOCX') {
|
||||
return NextResponse.json({
|
||||
id: policy.id,
|
||||
tenantId: policy.tenantId,
|
||||
language: policy.language,
|
||||
format: policy.format,
|
||||
generatedAt: policy.generatedAt,
|
||||
version: policy.version,
|
||||
sections: policy.sections.map((s) => ({
|
||||
id: s.id,
|
||||
title: s.title,
|
||||
order: s.order,
|
||||
})),
|
||||
downloadUrl: `/api/sdk/v1/einwilligungen/privacy-policy/${policy.id}/download`,
|
||||
})
|
||||
}
|
||||
|
||||
// Fuer HTML/Markdown: Vollstaendige Policy zurueckgeben
|
||||
return NextResponse.json(policy)
|
||||
} catch (error) {
|
||||
console.error('Error generating privacy policy:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to generate privacy policy' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/sdk/v1/einwilligungen/privacy-policy/generate
|
||||
*
|
||||
* Liefert eine Vorschau der Abschnitte ohne vollstaendige Generierung
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const language = (searchParams.get('language') as SupportedLanguage) || 'de'
|
||||
|
||||
// Liefere die Standard-Abschnittsstruktur
|
||||
const sections = [
|
||||
{ id: 'controller', order: 1, title: { de: '1. Verantwortlicher', en: '1. Data Controller' } },
|
||||
{ id: 'data-collection', order: 2, title: { de: '2. Erhobene personenbezogene Daten', en: '2. Personal Data We Collect' } },
|
||||
{ id: 'purposes', order: 3, title: { de: '3. Zwecke der Datenverarbeitung', en: '3. Purposes of Data Processing' } },
|
||||
{ id: 'legal-basis', order: 4, title: { de: '4. Rechtsgrundlagen der Verarbeitung', en: '4. Legal Basis for Processing' } },
|
||||
{ id: 'recipients', order: 5, title: { de: '5. Empfaenger und Datenweitergabe', en: '5. Recipients and Data Sharing' } },
|
||||
{ id: 'retention', order: 6, title: { de: '6. Speicherdauer', en: '6. Data Retention' } },
|
||||
{ id: 'rights', order: 7, title: { de: '7. Ihre Rechte als betroffene Person', en: '7. Your Rights as a Data Subject' } },
|
||||
{ id: 'cookies', order: 8, title: { de: '8. Cookies und aehnliche Technologien', en: '8. Cookies and Similar Technologies' } },
|
||||
{ id: 'changes', order: 9, title: { de: '9. Aenderungen dieser Datenschutzerklaerung', en: '9. Changes to this Privacy Policy' } },
|
||||
]
|
||||
|
||||
return NextResponse.json({
|
||||
sections,
|
||||
availableLanguages: ['de', 'en'],
|
||||
availableFormats: ['HTML', 'MARKDOWN', 'PDF', 'DOCX'],
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error fetching sections:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to fetch sections' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user