Complete backend verification: fix syntax errors, create __init__.py files, add setup_db.py, update docker-compose for two PostgreSQL containers
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
"""
|
||||
Database initialization script for MTG Online backend.
|
||||
|
||||
Creates all necessary tables matching the SQLAlchemy ORM models
|
||||
for both databases.
|
||||
"""
|
||||
import asyncio
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy import text
|
||||
from app.core.settings import get_settings
|
||||
|
||||
|
||||
async def setup_mtg_online_database():
|
||||
"""Create tables for the mtgonline database."""
|
||||
settings = get_settings()
|
||||
engine = create_async_engine(settings.MTGO_DATABASE_URL)
|
||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
async with async_session() as session:
|
||||
# Create tables
|
||||
tables = [
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(128) NOT NULL,
|
||||
salt VARCHAR(128) NOT NULL,
|
||||
email VARCHAR(255),
|
||||
country VARCHAR(2),
|
||||
real_name VARCHAR(128),
|
||||
avatar_bmp TEXT,
|
||||
privlevel VARCHAR(50) DEFAULT 'User',
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
is_banned BOOLEAN DEFAULT FALSE,
|
||||
ban_reason TEXT,
|
||||
ban_ends TIMESTAMP,
|
||||
vip_status INTEGER DEFAULT 0,
|
||||
vip_expiry TIMESTAMP,
|
||||
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
last_login TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_decklist_folders (
|
||||
id SERIAL PRIMARY KEY,
|
||||
owner_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
parent_id INTEGER REFERENCES mtgonline_decklist_folders(id) ON DELETE CASCADE,
|
||||
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_decklist_files (
|
||||
id SERIAL PRIMARY KEY,
|
||||
folder_id INTEGER REFERENCES mtgonline_decklist_folders(id) ON DELETE CASCADE,
|
||||
owner_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
format VARCHAR(50) DEFAULT 'native',
|
||||
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_rooms (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
is_password_protected BOOLEAN DEFAULT FALSE,
|
||||
password_hash VARCHAR(128),
|
||||
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_rooms_gametypes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
room_id INTEGER REFERENCES mtgonline_rooms(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_bans (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
|
||||
server_id INTEGER,
|
||||
reason TEXT NOT NULL,
|
||||
moderators VARCHAR(255),
|
||||
ip_address VARCHAR(45),
|
||||
expiration_time TIMESTAMP,
|
||||
active BOOLEAN DEFAULT TRUE,
|
||||
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
room_id INTEGER REFERENCES mtgonline_rooms(id) ON DELETE CASCADE,
|
||||
player_id INTEGER REFERENCES mtgonline_users(id) ON DELETE CASCADE,
|
||||
message TEXT NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtgonline_audit (
|
||||
id SERIAL PRIMARY KEY,
|
||||
admin_id INTEGER REFERENCES mtgonline_users(id) ON DELETE SET NULL,
|
||||
action_type VARCHAR(50) NOT NULL,
|
||||
target_user_id INTEGER REFERENCES mtgonline_users(id) ON DELETE SET NULL,
|
||||
details TEXT,
|
||||
ip_address VARCHAR(45),
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
]
|
||||
|
||||
for table_sql in tables:
|
||||
await session.execute(text(table_sql))
|
||||
|
||||
# Create indexes
|
||||
indexes = [
|
||||
"CREATE INDEX IF NOT EXISTS idx_decks_owner ON mtgonline_decklist_files(owner_id);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_decks_folder ON mtgonline_decklist_files(folder_id);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_bans_active ON mtgonline_bans(active);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_log_timestamp ON mtgonline_log(timestamp);",
|
||||
]
|
||||
|
||||
for idx_sql in indexes:
|
||||
await session.execute(text(idx_sql))
|
||||
|
||||
print("✓ All mtgonline tables created")
|
||||
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
async def setup_mtg_data_database():
|
||||
"""Create tables for the mtgdata database."""
|
||||
settings = get_settings()
|
||||
engine = create_async_engine(settings.MTG_DATABASE_URL)
|
||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
async with async_session() as session:
|
||||
# Create tables
|
||||
tables = [
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtg_sets (
|
||||
id SERIAL PRIMARY KEY,
|
||||
code VARCHAR(10) UNIQUE NOT NULL,
|
||||
name VARCHAR(255),
|
||||
type VARCHAR(100),
|
||||
release_date DATE,
|
||||
base_set_size INTEGER,
|
||||
total_size INTEGER,
|
||||
is_foil_only BOOLEAN,
|
||||
is_non_foil_only BOOLEAN,
|
||||
digital BOOLEAN,
|
||||
icon_svg_url TEXT,
|
||||
parent_code VARCHAR(10),
|
||||
mtgo_code VARCHAR(10),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS mtg_cards (
|
||||
id SERIAL PRIMARY KEY,
|
||||
set_id INTEGER REFERENCES mtg_sets(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255),
|
||||
mana_cost VARCHAR(255),
|
||||
type_line VARCHAR(255),
|
||||
oracle_text TEXT,
|
||||
power VARCHAR(50),
|
||||
toughness VARCHAR(50),
|
||||
rarity VARCHAR(50),
|
||||
layout VARCHAR(50),
|
||||
artist VARCHAR(255),
|
||||
flavor_text TEXT,
|
||||
numbers VARCHAR(100),
|
||||
identifiers TEXT,
|
||||
images TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""",
|
||||
]
|
||||
|
||||
for table_sql in tables:
|
||||
await session.execute(text(table_sql))
|
||||
|
||||
# Create indexes
|
||||
indexes = [
|
||||
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_name ON mtg_cards(name);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_type ON mtg_cards(type_line);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_rarity ON mtg_cards(rarity);",
|
||||
"CREATE INDEX IF NOT EXISTS idx_mtg_cards_set_id ON mtg_cards(set_id);",
|
||||
]
|
||||
|
||||
for idx_sql in indexes:
|
||||
await session.execute(text(idx_sql))
|
||||
|
||||
print("✓ All mtgdata tables created")
|
||||
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main initialization function."""
|
||||
print("MTG Online Database Initialization")
|
||||
print("=" * 50)
|
||||
|
||||
# Setup mtgonline database
|
||||
print("\nSetting up mtgonline database...")
|
||||
await setup_mtg_online_database()
|
||||
|
||||
# Setup mtgdata database
|
||||
print("\nSetting up mtgdata database...")
|
||||
await setup_mtg_data_database()
|
||||
|
||||
print("\n✓ Database initialization complete!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user