Add setup and restore flow
This commit is contained in:
1 parent
19e4621aeb
commit
72229cf14c
15 files changed
+511
-94
No files matched your search
+32
-37
@@ -1,42 +1,25 @@
|
||||
import { query } from "./db.js";
|
||||
import { hashPassword } from "./auth.js";
|
||||
|
||||
async function ensureMigrationAdmin() {
|
||||
const username = process.env.ADMIN_USERNAME?.trim() || "admin";
|
||||
const password = process.env.ADMIN_PASSWORD ?? "admin";
|
||||
const displayName = process.env.ADMIN_DISPLAY_NAME?.trim() || "Admin";
|
||||
|
||||
const existingUsers = await query<{ count: string }>("SELECT COUNT(*) AS count FROM users;");
|
||||
|
||||
if (Number(existingUsers.rows[0]?.count ?? 0) === 0) {
|
||||
await query(
|
||||
`
|
||||
INSERT INTO users (username, display_name, password_hash, role)
|
||||
VALUES ($1, $2, $3, 'admin');
|
||||
`,
|
||||
[username, displayName, await hashPassword(password)]
|
||||
);
|
||||
|
||||
if (!process.env.ADMIN_PASSWORD) {
|
||||
console.warn("Initialer Admin wurde mit admin/admin angelegt. Bitte Passwort über ADMIN_PASSWORD setzen oder im Adminbereich ändern.");
|
||||
}
|
||||
}
|
||||
|
||||
async function findMigrationAdmin() {
|
||||
const adminResult = await query<{ id: string }>("SELECT id FROM users WHERE role = 'admin' ORDER BY id ASC LIMIT 1;");
|
||||
|
||||
if (adminResult.rows.length === 0) {
|
||||
throw new Error("At least one admin user is required");
|
||||
}
|
||||
|
||||
return adminResult.rows[0].id;
|
||||
return adminResult.rows[0]?.id ?? null;
|
||||
}
|
||||
|
||||
async function ensureClosureOwnership(table: string, column: string, primaryKeyColumns: string[], adminId: string) {
|
||||
async function ensureClosureOwnership(table: string, column: string, primaryKeyColumns: string[], adminId: string | null) {
|
||||
await query(`ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS user_id BIGINT REFERENCES users(id);`);
|
||||
await query(`UPDATE ${table} SET user_id = $1 WHERE user_id IS NULL;`, [adminId]);
|
||||
await query(`ALTER TABLE ${table} ALTER COLUMN user_id SET NOT NULL;`);
|
||||
await query(`ALTER TABLE ${table} DROP CONSTRAINT IF EXISTS ${table}_pkey;`);
|
||||
await query(`ALTER TABLE ${table} ADD CONSTRAINT ${table}_pkey PRIMARY KEY (${primaryKeyColumns.join(", ")}, user_id);`);
|
||||
if (adminId) {
|
||||
await query(`UPDATE ${table} SET user_id = $1 WHERE user_id IS NULL;`, [adminId]);
|
||||
}
|
||||
await query(`
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM ${table} WHERE user_id IS NULL) THEN
|
||||
ALTER TABLE ${table} ALTER COLUMN user_id SET NOT NULL;
|
||||
ALTER TABLE ${table} DROP CONSTRAINT IF EXISTS ${table}_pkey;
|
||||
ALTER TABLE ${table} ADD CONSTRAINT ${table}_pkey PRIMARY KEY (${primaryKeyColumns.join(", ")}, user_id);
|
||||
END IF;
|
||||
END $$;
|
||||
`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_${table}_${column}_user ON ${table}(${column}, user_id);`);
|
||||
}
|
||||
|
||||
@@ -74,9 +57,12 @@ export async function migrate() {
|
||||
await query("CREATE INDEX IF NOT EXISTS idx_auth_sessions_user ON auth_sessions(user_id);");
|
||||
await query("CREATE INDEX IF NOT EXISTS idx_auth_sessions_expires ON auth_sessions(expires_at);");
|
||||
|
||||
const adminId = await ensureMigrationAdmin();
|
||||
const adminId = await findMigrationAdmin();
|
||||
|
||||
if (adminId) {
|
||||
await query("UPDATE users SET role = 'user', updated_at = now() WHERE role = 'admin' AND id <> $1;", [adminId]);
|
||||
}
|
||||
|
||||
await query("UPDATE users SET role = 'user', updated_at = now() WHERE role = 'admin' AND id <> $1;", [adminId]);
|
||||
await query("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_single_admin ON users ((role)) WHERE role = 'admin';");
|
||||
|
||||
await query(`
|
||||
@@ -170,8 +156,17 @@ export async function migrate() {
|
||||
await query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS recurring_billing_slot_id BIGINT;");
|
||||
await query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS recurring_occurrence_date DATE;");
|
||||
await query("ALTER TABLE sessions ADD COLUMN IF NOT EXISTS recurring_occurrence_key TEXT;");
|
||||
await query("UPDATE sessions SET user_id = $1 WHERE user_id IS NULL;", [adminId]);
|
||||
await query("ALTER TABLE sessions ALTER COLUMN user_id SET NOT NULL;");
|
||||
if (adminId) {
|
||||
await query("UPDATE sessions SET user_id = $1 WHERE user_id IS NULL;", [adminId]);
|
||||
}
|
||||
await query(`
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM sessions WHERE user_id IS NULL) THEN
|
||||
ALTER TABLE sessions ALTER COLUMN user_id SET NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
`);
|
||||
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS recurring_billings (
|
||||
|
||||
Reference in new issue
Block a user