feat: add initial database schema migration
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
120
scripts/migrations/001_initial_schema.sql
Normal file
120
scripts/migrations/001_initial_schema.sql
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
-- Устанавливаем таймзону для сессии, чтобы все 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 -- Пинг от бэкенда до игрового сервера в мс
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Таблица модпаков (сборок)
|
||||||
|
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.'
|
||||||
Reference in New Issue
Block a user