Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
49 lines
2.2 KiB
TypeScript
49 lines
2.2 KiB
TypeScript
import "dotenv/config";
|
|
import { readFile, readdir } from "node:fs/promises";
|
|
import { randomBytes } from "node:crypto";
|
|
import { db } from "../src/lib/db";
|
|
import { hashPassword } from "../src/lib/password";
|
|
|
|
async function setup() {
|
|
if (!process.env.DATABASE_URL) throw new Error("Zuerst npm run configure ausfuehren.");
|
|
await db.query(await readFile(new URL("./schema.sql", import.meta.url), "utf8"));
|
|
const client = await db.connect();
|
|
try {
|
|
await client.query("BEGIN");
|
|
await client.query("SELECT pg_advisory_xact_lock(724139002)");
|
|
await client.query("CREATE TABLE IF NOT EXISTS schema_migrations(name text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now())");
|
|
const directory = new URL("./migrations/", import.meta.url);
|
|
for (const name of (await readdir(directory)).filter((file) => file.endsWith(".sql")).sort()) {
|
|
const applied = await client.query("SELECT name FROM schema_migrations WHERE name = $1", [name]);
|
|
if (applied.rowCount) continue;
|
|
await client.query(await readFile(new URL(name, directory), "utf8"));
|
|
await client.query("INSERT INTO schema_migrations(name) VALUES ($1)", [name]);
|
|
console.log(`Migration angewendet: ${name}`);
|
|
}
|
|
await client.query("COMMIT");
|
|
} catch (error) {
|
|
await client.query("ROLLBACK");
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
const email = (process.env.BOOTSTRAP_EMAIL ?? "admin@kibu.local").trim().toLowerCase();
|
|
const existing = await db.query("SELECT id FROM staff WHERE email = $1", [email]);
|
|
if (existing.rowCount) {
|
|
console.log("Schema bereit. Bestehender Zugang bleibt unveraendert.");
|
|
return;
|
|
}
|
|
const password = process.env.BOOTSTRAP_PASSWORD ?? randomBytes(18).toString("base64url");
|
|
if (password.length < 12) throw new Error("BOOTSTRAP_PASSWORD muss mindestens 12 Zeichen haben.");
|
|
await db.query(
|
|
"INSERT INTO staff(email, name, password_hash) VALUES ($1, $2, $3)",
|
|
[email, "Betreuung", await hashPassword(password)],
|
|
);
|
|
console.log(`Erster Zugang erstellt.\nE-Mail: ${email}\nPasswort: ${password}\nBitte sicher aufbewahren.`);
|
|
}
|
|
|
|
setup().catch((error: unknown) => {
|
|
console.error("Datenbank-Einrichtung fehlgeschlagen:", error);
|
|
process.exitCode = 1;
|
|
}).finally(() => db.end());
|