syncova-policies/scripts/import-policy.js
Weapie 328f042307 Syncova Policies: Portal für DSGVO-Datenschutzerklärungen
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>
2026-09-07 16:23:51 +02:00

102 lines
2.9 KiB
JavaScript

/**
* Importiert eine Datenschutzerklärung aus einer JSON-Datei in die Datenbank.
*
* npm run import-policy -- data/policies/bauantrag.json
* npm run import-policy -- data/policies/bauantrag.json --update
*
* Ohne --update wird ein vorhandener Datensatz mit gleichem Titel nicht
* überschrieben, sondern der Import abgebrochen. Schlüssel mit führendem
* Unterstrich (z. B. "_quelle") sind Kommentare und werden ignoriert.
*/
const fs = require("fs")
const path = require("path")
const { PrismaClient } = require("@prisma/client")
const prisma = new PrismaClient()
const requiredFields = [
"title",
"responsible",
"contactDPO",
"dataSubjectsRights",
"complaintRight",
"withdrawalRight",
"processingDescription",
"processingPurposes",
"legalBasis",
"recipients",
]
const optionalFields = ["storageDuration", "dataSource"]
async function importPolicy() {
const file = process.argv.find((arg) => arg.endsWith(".json"))
const allowUpdate = process.argv.includes("--update")
if (!file) {
console.error("Bitte eine JSON-Datei angeben, z. B.:")
console.error(" npm run import-policy -- data/policies/bauantrag.json")
process.exitCode = 1
return
}
const filePath = path.resolve(process.cwd(), file)
if (!fs.existsSync(filePath)) {
console.error(`Datei nicht gefunden: ${filePath}`)
process.exitCode = 1
return
}
const raw = JSON.parse(fs.readFileSync(filePath, "utf8"))
const missing = requiredFields.filter((field) => !String(raw[field] ?? "").trim())
if (missing.length > 0) {
console.error(`Pflichtfelder fehlen oder sind leer: ${missing.join(", ")}`)
process.exitCode = 1
return
}
const data = {}
for (const field of requiredFields) {
data[field] = String(raw[field]).trim()
}
for (const field of optionalFields) {
const value = String(raw[field] ?? "").trim()
data[field] = value || null
}
data.isPublic = raw.isPublic !== undefined ? Boolean(raw.isPublic) : true
const existing = await prisma.privacyPolicy.findFirst({
where: { title: data.title },
})
if (existing && !allowUpdate) {
console.error(
`Es existiert bereits eine Erklärung mit dem Titel „${data.title}“ (ID ${existing.id}).`
)
console.error("Zum Überschreiben erneut mit --update aufrufen.")
process.exitCode = 1
return
}
const policy = existing
? await prisma.privacyPolicy.update({ where: { id: existing.id }, data })
: await prisma.privacyPolicy.create({ data })
console.log(
`${existing ? "Aktualisiert" : "Importiert"}: „${policy.title}“ (ID ${policy.id}, ${
policy.isPublic ? "öffentlich" : "privat"
})`
)
if (raw._quelle) console.log(`Quelle: ${raw._quelle}`)
}
importPolicy()
.catch((error) => {
console.error("Fehler beim Import:", error)
process.exitCode = 1
})
.finally(async () => {
await prisma.$disconnect()
})