186 lines
7.7 KiB
JavaScript
186 lines
7.7 KiB
JavaScript
import pool from '../db.js';
|
|
|
|
// ==============================================================================
|
|
// Void-Genesis - Datenbank Initialisierungs-Skript
|
|
// Führt alle nötigen CREATE TABLE Befehle aus, falls die Tabellen nicht existieren.
|
|
// ==============================================================================
|
|
|
|
const createTablesQuery = `
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- DROP TABLES
|
|
-- WICHTIG: Die Reihenfolge beim Löschen ist entscheidend!
|
|
-- Tabellen mit Fremdschlüsseln (Foreign Keys) müssen zuerst gelöscht werden.
|
|
-- ------------------------------------------------------------------------------
|
|
DROP TABLE IF EXISTS refresh_tokens;
|
|
DROP TABLE IF EXISTS auth_otps;
|
|
DROP TABLE IF EXISTS lobby_accounts_sectors; -- Zuerst die Brückentabelle löschen
|
|
DROP TABLE IF EXISTS sectors; -- Dann die Sektoren-Tabelle
|
|
DROP TABLE IF EXISTS lobby_accounts; -- Zuletzt die Haupt-Nutzer-Tabelle
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TABLE: lobby_accounts
|
|
-- Basis-Nutzerdaten für das gesamte Void-Genesis Universum.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS lobby_accounts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
username VARCHAR(50) UNIQUE NOT NULL,
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
is_email_verified BOOLEAN DEFAULT false,
|
|
res_premium INT DEFAULT 0,
|
|
is_admin BOOLEAN DEFAULT false,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TABLE: sectors
|
|
-- Beinhaltet die globalen Metadaten zu allen verfügbaren Spiel-Sektoren.
|
|
-- Hier definieren wir, welche Server existieren und welche Eigenschaften sie haben.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS sectors (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(50) UNIQUE NOT NULL,
|
|
status VARCHAR(20) DEFAULT 'offline',
|
|
speed_fleet INT DEFAULT 1,
|
|
speed_economy INT DEFAULT 1,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TABLE: lobby_accounts_sectors (Brückentabelle)
|
|
-- Verknüpft einen Lobby-Account mit einem Sektor.
|
|
-- Existiert hier ein Eintrag, bedeutet das: Der Nutzer hat in diesem Sektor einen Spielstand.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS lobby_accounts_sectors (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
lobby_account_id UUID REFERENCES lobby_accounts(id) ON DELETE CASCADE,
|
|
sector_id UUID REFERENCES sectors(id) ON DELETE CASCADE,
|
|
local_username VARCHAR(50) NOT NULL,
|
|
gender VARCHAR(20) NOT NULL,
|
|
res_premium INT DEFAULT 0,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE(lobby_account_id, sector_id),
|
|
UNIQUE(sector_id, local_username)
|
|
);
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TABLE: auth_otps
|
|
-- Speichert temporäre 6-stellige Codes für Registrierung oder Passwort-Reset.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS auth_otps (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID REFERENCES lobby_accounts(id) ON DELETE CASCADE,
|
|
otp_code VARCHAR(6) NOT NULL,
|
|
type VARCHAR(20) NOT NULL,
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TABLE: refresh_tokens
|
|
-- Speichert langlebige Tokens für die "Angemeldet bleiben"-Funktion.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id UUID REFERENCES lobby_accounts(id) ON DELETE CASCADE,
|
|
token VARCHAR(500) UNIQUE NOT NULL,
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- ------------------------------------------------------------------------------
|
|
-- TRIGGER: Auto-update 'updated_at' timestamp
|
|
-- Diese Funktion setzt das 'updated_at' Feld bei jeder Änderung auf die aktuelle Zeit.
|
|
-- ------------------------------------------------------------------------------
|
|
CREATE OR REPLACE FUNCTION update_modified_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
-- Wir wenden den Trigger nur an, wenn er noch nicht existiert.
|
|
DO $$
|
|
BEGIN
|
|
-- Trigger für lobby_accounts
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_lobby_accounts_modtime') THEN
|
|
CREATE TRIGGER update_lobby_accounts_modtime
|
|
BEFORE UPDATE ON lobby_accounts
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_modified_column();
|
|
END IF;
|
|
|
|
-- Trigger für sectors
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_sectors_modtime') THEN
|
|
CREATE TRIGGER update_sectors_modtime
|
|
BEFORE UPDATE ON sectors
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_modified_column();
|
|
END IF;
|
|
|
|
-- Trigger für lobby_accounts_sectors (WICHTIG für unsere "Zuletzt gespielt" Funktion)
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_lobby_accounts_sectors_modtime') THEN
|
|
CREATE TRIGGER update_lobby_accounts_sectors_modtime
|
|
BEFORE UPDATE ON lobby_accounts_sectors
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_modified_column();
|
|
END IF;
|
|
END $$;
|
|
`;
|
|
|
|
// ==============================================================================
|
|
// Ausführungs-Logik
|
|
// ==============================================================================
|
|
async function initDatabase() {
|
|
console.log('⏳ Starte Datenbank-Initialisierung...');
|
|
|
|
// Wir holen uns eine Verbindung aus dem Pool
|
|
const client = await pool.connect();
|
|
|
|
try {
|
|
// Wir senden den kompletten SQL-String an die Datenbank
|
|
await client.query(createTablesQuery);
|
|
console.log('✅ Tabellen wurden erfolgreich erstellt (oder existierten bereits).');
|
|
|
|
const sectorCheck = await client.query('SELECT count(*) FROM sectors');
|
|
if (parseInt(sectorCheck.rows[0].count) === 0) {
|
|
console.log('🌱 Füge 24 Test-Sektoren ein...');
|
|
|
|
const greekAlphabet = [
|
|
'Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta',
|
|
'Eta', 'Theta', 'Iota', 'Kappa', 'Lambda', 'Mu',
|
|
'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma',
|
|
'Tau', 'Upsilon', 'Phi', 'Chi', 'Psi', 'Omega'
|
|
];
|
|
|
|
// Wir generieren für jeden Namen ein dynamisches INSERT
|
|
const insertPromises = greekAlphabet.map((name, index) => {
|
|
// Wir variieren die Geschwindigkeiten leicht für optische Vielfalt
|
|
const speed = (index % 4) + 1;
|
|
return client.query(`
|
|
INSERT INTO sectors (name, status, speed_fleet, speed_economy)
|
|
VALUES ($1, 'online', $2, $2)
|
|
`, [name, speed]);
|
|
});
|
|
|
|
await Promise.all(insertPromises);
|
|
console.log('✅ 24 Test-Sektoren erfolgreich eingefügt.');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Fehler beim Erstellen der Tabellen:', error);
|
|
} finally {
|
|
// Ganz wichtig: Verbindung wieder freigeben
|
|
client.release();
|
|
// Den Node-Prozess beenden, damit das Skript nicht in der Konsole hängen bleibt
|
|
process.exit();
|
|
}
|
|
}
|
|
|
|
// Skript direkt aufrufen
|
|
initDatabase(); |