/api/health meldet Status, Version, Instanz und Erreichbarkeit der Datenbank – ohne Anmeldung, deshalb ohne Zählstände, Namen oder Adressen. update.sh wird sich später darauf stützen. Der Seed legt die vier Bereiche an und ein erstes Verwaltungskonto aus ADMIN_EMAIL und ADMIN_PASSWORT. Er läuft mehrfach ohne Schaden; ohne ADMIN_PASSWORT entsteht ein Konto, das sich nur über OIDC oder Passkey anmelden kann. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
157 lines
3.8 KiB
TypeScript
157 lines
3.8 KiB
TypeScript
/**
|
||
* Grundausstattung für eine frische Datenbank.
|
||
*
|
||
* Läuft mehrfach ohne Schaden: alles wird per upsert angelegt, vorhandene
|
||
* Einträge bleiben unangetastet. Es entstehen keine erfundenen Aufgaben oder
|
||
* Termine – dafür gibt es prisma/demo-seed.ts.
|
||
*/
|
||
import 'dotenv/config'
|
||
import { PrismaPg } from '@prisma/adapter-pg'
|
||
import bcrypt from 'bcryptjs'
|
||
import { PrismaClient } from '../src/generated/prisma/client.js'
|
||
|
||
const verbindung = process.env.DATABASE_URL
|
||
if (!verbindung) {
|
||
throw new Error('DATABASE_URL ist nicht gesetzt.')
|
||
}
|
||
|
||
const db = new PrismaClient({ adapter: new PrismaPg({ connectionString: verbindung }) })
|
||
|
||
const BEREICHE = [
|
||
{
|
||
name: 'Firma',
|
||
farbe: '#2563eb',
|
||
reihenfolge: 1,
|
||
arbeitsfensterVon: 7 * 60 + 30,
|
||
arbeitsfensterBis: 16 * 60 + 30,
|
||
kapazitaetMo: 360,
|
||
kapazitaetDi: 360,
|
||
kapazitaetMi: 360,
|
||
kapazitaetDo: 360,
|
||
kapazitaetFr: 240,
|
||
kapazitaetSa: 0,
|
||
kapazitaetSo: 0,
|
||
},
|
||
{
|
||
name: 'Gewerbe',
|
||
farbe: '#7c3aed',
|
||
reihenfolge: 2,
|
||
arbeitsfensterVon: 17 * 60,
|
||
arbeitsfensterBis: 21 * 60,
|
||
kapazitaetMo: 90,
|
||
kapazitaetDi: 90,
|
||
kapazitaetMi: 90,
|
||
kapazitaetDo: 90,
|
||
kapazitaetFr: 60,
|
||
kapazitaetSa: 180,
|
||
kapazitaetSo: 0,
|
||
},
|
||
{
|
||
name: 'Privat',
|
||
farbe: '#16a34a',
|
||
reihenfolge: 3,
|
||
arbeitsfensterVon: 17 * 60,
|
||
arbeitsfensterBis: 22 * 60,
|
||
kapazitaetMo: 60,
|
||
kapazitaetDi: 60,
|
||
kapazitaetMi: 60,
|
||
kapazitaetDo: 60,
|
||
kapazitaetFr: 120,
|
||
kapazitaetSa: 240,
|
||
kapazitaetSo: 240,
|
||
},
|
||
{
|
||
name: 'Homelab',
|
||
farbe: '#ea580c',
|
||
reihenfolge: 4,
|
||
arbeitsfensterVon: 19 * 60,
|
||
arbeitsfensterBis: 23 * 60,
|
||
kapazitaetMo: 0,
|
||
kapazitaetDi: 60,
|
||
kapazitaetMi: 0,
|
||
kapazitaetDo: 60,
|
||
kapazitaetFr: 0,
|
||
kapazitaetSa: 120,
|
||
kapazitaetSo: 60,
|
||
},
|
||
]
|
||
|
||
async function bereicheAnlegen(): Promise<void> {
|
||
for (const bereich of BEREICHE) {
|
||
await db.bereich.upsert({
|
||
where: { name: bereich.name },
|
||
update: {},
|
||
create: bereich,
|
||
})
|
||
}
|
||
console.log(`Bereiche geprüft: ${BEREICHE.map((b) => b.name).join(', ')}`)
|
||
}
|
||
|
||
async function verwaltungAnlegen(): Promise<void> {
|
||
const email = process.env.ADMIN_EMAIL?.trim().toLowerCase()
|
||
const passwort = process.env.ADMIN_PASSWORT
|
||
|
||
if (!email) {
|
||
console.log(
|
||
'ADMIN_EMAIL ist nicht gesetzt – kein Verwaltungskonto angelegt. ' +
|
||
'Bei reiner OIDC-Anmeldung ist das richtig: die erste Person, die sich ' +
|
||
'anmeldet, muss danach von Hand hochgestuft werden.',
|
||
)
|
||
return
|
||
}
|
||
|
||
const vorhanden = await db.benutzer.findUnique({
|
||
where: { email },
|
||
select: { id: true, rolle: true },
|
||
})
|
||
|
||
if (vorhanden) {
|
||
if (vorhanden.rolle !== 'ADMIN') {
|
||
await db.benutzer.update({ where: { id: vorhanden.id }, data: { rolle: 'ADMIN' } })
|
||
console.log(`${email} zur Verwaltung hochgestuft.`)
|
||
} else {
|
||
console.log(`${email} ist bereits Verwaltung.`)
|
||
}
|
||
return
|
||
}
|
||
|
||
if (!passwort) {
|
||
await db.benutzer.create({
|
||
data: { email, rolle: 'ADMIN', name: null },
|
||
})
|
||
console.log(
|
||
`${email} als Verwaltung angelegt, ohne Passwort. ` +
|
||
'Anmeldung ist damit nur über OIDC oder einen Passkey möglich.',
|
||
)
|
||
return
|
||
}
|
||
|
||
if (passwort.length < 12) {
|
||
throw new Error('ADMIN_PASSWORT ist zu kurz, mindestens 12 Zeichen.')
|
||
}
|
||
|
||
await db.benutzer.create({
|
||
data: {
|
||
email,
|
||
rolle: 'ADMIN',
|
||
passwortHash: await bcrypt.hash(passwort, 12),
|
||
},
|
||
})
|
||
console.log(`${email} als Verwaltung mit Passwort angelegt.`)
|
||
}
|
||
|
||
async function main(): Promise<void> {
|
||
await bereicheAnlegen()
|
||
await verwaltungAnlegen()
|
||
}
|
||
|
||
main()
|
||
.then(async () => {
|
||
await db.$disconnect()
|
||
})
|
||
.catch(async (fehler: unknown) => {
|
||
console.error(fehler)
|
||
await db.$disconnect()
|
||
process.exit(1)
|
||
})
|