-- Устанавливаем таймзону для сессии, чтобы все timestamp были в UTC SET TIMEZONE = 'UTC'; -- Таблица пользователей. Основная сущность, хранящая данные для входа. CREATE TABLE users ( id SERIAL PRIMARY KEY, uuid UUID NOT NULL UNIQUE, username VARCHAR(16) NOT NULL UNIQUE, email VARCHAR(255) NOT NULL UNIQUE, password_hash VARCHAR(60) NOT NULL, -- bcrypt хеши имеют длину 60 символов role VARCHAR(20) NOT NULL DEFAULT 'user', -- 'user' или 'admin' created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Индекс для быстрого поиска по имени пользователя (хотя UNIQUE уже создает индекс) CREATE INDEX idx_users_username ON users(username); -- Таблица профилей. Связана с пользователями и хранит игровые данные (скины, плащи). CREATE TABLE profiles ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL UNIQUE, skin_hash VARCHAR(40), -- SHA1 хеш скина (40 символов) cape_hash VARCHAR(40), -- SHA1 хеш плаща (40 символов) created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT fk_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE -- Если пользователь удален, его профиль тоже удаляется ); -- Таблица для хранения активных access-токенов (Yggdrasil) CREATE TABLE access_tokens ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, access_token VARCHAR(36) NOT NULL UNIQUE, -- UUIDv4 client_token VARCHAR(255) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT fk_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE ); -- Таблица игровых серверов, которые отображаются в мониторинге CREATE TABLE game_servers ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, address VARCHAR(255) NOT NULL UNIQUE, -- Например, "mc.example.com:25565" is_enabled BOOLEAN NOT NULL DEFAULT TRUE, -- Данные, получаемые поллером status_json TEXT, -- Полный JSON-ответ от сервера Minecraft last_polled_at TIMESTAMPTZ, -- Данные, которые мы будем извлекать из JSON для удобства motd TEXT, player_count INTEGER, max_players INTEGER, version_name VARCHAR(100), ping_backend_server INTEGER -- Пинг от бэкенда до игрового сервера в мс ); INSERT INTO game_servers (name, address) VALUES ('Vanilla', 'vanilla.mc.mrixs.me'); -- Таблица модпаков (сборок) CREATE TABLE modpacks ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE, -- Уникальное имя, например, "TechnoMagic" display_name VARCHAR(255) NOT NULL, -- Человекочитаемое имя, "TechnoMagic SkyBlock" minecraft_version VARCHAR(50) NOT NULL, is_active BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Таблица файлов, принадлежащих модпакам. -- Хранит метаданные о каждом файле в модпаке. CREATE TABLE modpack_files ( id BIGSERIAL PRIMARY KEY, modpack_id INTEGER NOT NULL, -- Относительный путь файла в клиенте, например, "mods/industrial-craft.jar" relative_path TEXT NOT NULL, file_hash VARCHAR(40) NOT NULL, -- SHA1 хеш файла file_size BIGINT NOT NULL, -- URL для скачивания (если файл импортирован с CurseForge/Modrinth) download_url TEXT, CONSTRAINT fk_modpack FOREIGN KEY(modpack_id) REFERENCES modpacks(id) ON DELETE CASCADE, -- Уникальный ключ, чтобы в одном модпаке не было двух файлов с одинаковым путем UNIQUE (modpack_id, relative_path) ); -- Индекс для быстрого поиска файлов по хешу CREATE INDEX idx_modpack_files_hash ON modpack_files(file_hash); -- Функция для автоматического обновления поля updated_at CREATE OR REPLACE FUNCTION trigger_set_timestamp() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Триггеры для таблиц users и profiles CREATE TRIGGER set_timestamp BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamp(); CREATE TRIGGER set_timestamp BEFORE UPDATE ON profiles FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamp(); -- Сообщение об успешном завершении миграции \echo 'Initial schema migration applied successfully.'