commit 5b7c3ba4b2dbac15c2796fad25f207aebccaa854 Author: DonĂ¡t Date: Sat Sep 20 11:22:44 2025 +0200 Initial deployment-only branch with production deployment files diff --git a/SerpentRace_Docker/deployment/.env.server b/SerpentRace_Docker/deployment/.env.server new file mode 100644 index 00000000..60be1d1e --- /dev/null +++ b/SerpentRace_Docker/deployment/.env.server @@ -0,0 +1,71 @@ +# SerpentRace Production Server Environment Variables +# IMPORTANT: Change all placeholder values before deployment! + +# Production settings +NODE_ENV=production + +# Database Configuration +DB_HOST=postgres +DB_PORT=5432 +DB_NAME=serpentrace +DB_USERNAME=postgres +# CHANGE THIS: Use a strong password +POSTGRES_PASSWORD=CHANGE_THIS_STRONG_DATABASE_PASSWORD_123! + +# Redis Configuration +REDIS_URL=redis://redis:6379 +REDIS_HOST=redis +REDIS_PORT=6379 +# CHANGE THIS: Set a Redis password for security +REDIS_PASSWORD=CHANGE_THIS_REDIS_PASSWORD_123! + +# JWT Configuration +# CHANGE THIS: Use a strong secret key (minimum 32 characters) +JWT_SECRET=CHANGE_THIS_JWT_SECRET_KEY_MINIMUM_32_CHARACTERS_FOR_PRODUCTION_SECURITY +JWT_EXPIRY=86400 +JWT_EXPIRATION=24h +JWT_REFRESH_EXPIRATION=7d + +# Email Configuration (SMTP) +# CHANGE THESE: Configure your email provider +EMAIL_HOST=smtp.yourmailprovider.com +EMAIL_PORT=587 +EMAIL_SECURE=false +EMAIL_USER=your_email@yourdomain.com +EMAIL_PASS=your_email_password +EMAIL_FROM="SerpentRace " + +# MinIO Object Storage +MINIO_ENDPOINT=minio +MINIO_PORT=9000 +MINIO_USE_SSL=false +# CHANGE THESE: Use strong credentials +MINIO_ACCESS_KEY=serpentrace_admin +MINIO_SECRET_KEY=CHANGE_THIS_MINIO_SECRET_KEY_123! +MINIO_BUCKET_NAME=serpentrace-logs + +# Application Settings +APP_BASE_URL=http://your-domain.com +PORT=3000 + +# Chat System Limits +CHAT_INACTIVITY_TIMEOUT_MINUTES=30 +CHAT_MAX_MESSAGES_PER_USER=100 +CHAT_MESSAGE_CLEANUP_WEEKS=4 + +# Logging +MAX_LOGS_PER_FILE=10000 + +# SSL/TLS Configuration (if using HTTPS) +# Uncomment and configure if you have SSL certificates +# SSL_CERT_PATH=/path/to/certificate.crt +# SSL_KEY_PATH=/path/to/private.key +# SSL_CA_PATH=/path/to/ca-bundle.crt + +# Security Headers (already configured in nginx) +# These are handled by the nginx configuration + +# Backup Configuration (optional) +# BACKUP_ENABLED=true +# BACKUP_SCHEDULE=0 2 * * * +# BACKUP_RETENTION_DAYS=30 \ No newline at end of file diff --git a/SerpentRace_Docker/deployment/README.md b/SerpentRace_Docker/deployment/README.md new file mode 100644 index 00000000..97a0a4bc --- /dev/null +++ b/SerpentRace_Docker/deployment/README.md @@ -0,0 +1,203 @@ +# SerpentRace Production Deployment Guide + +## Overview +This package contains everything needed to deploy SerpentRace in a production environment using pre-built Docker images. + +## Package Contents +- `serpentRaceDocker.tar` - All Docker images packed for deployment +- `docker-compose.deploy.yml` - Production Docker Compose configuration +- `.env.server` - Environment variables template for production +- `load-images.bat` - Automated deployment script for Windows servers +- `README.md` - This deployment guide + +## System Requirements +- Windows Server 2016+ or Windows 10/11 +- Docker Desktop or Docker Engine +- Docker Compose +- Minimum 4GB RAM, 20GB free disk space +- Network ports: 80, 443, 3000, 5432, 6379, 9000, 9001 + +## Pre-Deployment Configuration + +### 1. Environment Variables +Edit `.env.server` and update the following **REQUIRED** settings: + +```bash +# Database - Use a strong password +POSTGRES_PASSWORD=your_strong_database_password + +# JWT Security - Use a random 32+ character string +JWT_SECRET=your_super_secret_jwt_key_32_chars_minimum + +# Redis Security +REDIS_PASSWORD=your_redis_password + +# MinIO Storage +MINIO_ACCESS_KEY=your_minio_admin_user +MINIO_SECRET_KEY=your_minio_secret_key + +# Email Configuration (for notifications) +EMAIL_HOST=smtp.yourmailprovider.com +EMAIL_USER=your_email@yourdomain.com +EMAIL_PASS=your_email_password +EMAIL_FROM="SerpentRace " + +# Application URL +APP_BASE_URL=http://your-domain.com +``` + +### 2. Security Checklist +- [ ] Changed all default passwords +- [ ] Generated strong JWT secret (32+ characters) +- [ ] Configured email settings +- [ ] Updated domain name in APP_BASE_URL +- [ ] Configured firewall rules +- [ ] Planned SSL certificate setup + +## Deployment Steps + +### Automatic Deployment (Recommended) +1. Extract all files to your server directory +2. Edit `.env.server` with your configuration +3. Run `load-images.bat` +4. Follow the prompts + +### Manual Deployment +1. Load Docker images: + ```cmd + docker load -i serpentRaceDocker.tar + ``` + +2. Start services: + ```cmd + docker-compose -f docker-compose.deploy.yml --env-file .env.server up -d + ``` + +## Post-Deployment + +### Verify Services +Check that all services are running: +```cmd +docker-compose -f docker-compose.deploy.yml ps +``` + +### Access Points +- **Frontend Application**: http://localhost (or your domain) +- **Backend API**: http://localhost:3000 +- **MinIO Console**: http://localhost:9001 +- **Database**: localhost:5432 (internal access only) + +### Initial Setup +1. Access the frontend and verify it loads +2. Test user registration and login +3. Check backend API health: http://localhost:3000/health +4. Access MinIO console to verify storage + +### Security Hardening + +#### Firewall Configuration +Open only necessary ports: +- Port 80 (HTTP) - Public +- Port 443 (HTTPS) - Public (when SSL configured) +- Ports 3000, 5432, 6379, 9000, 9001 - Internal/VPN only + +#### SSL/TLS Setup +1. Obtain SSL certificates (Let's Encrypt, commercial CA) +2. Configure nginx for HTTPS in the frontend container +3. Update APP_BASE_URL to use https:// + +#### Regular Maintenance +- Monitor logs: `docker-compose -f docker-compose.deploy.yml logs -f` +- Update images periodically +- Backup database and MinIO data +- Monitor disk space and performance + +## Management Commands + +### View Logs +```cmd +# All services +docker-compose -f docker-compose.deploy.yml logs -f + +# Specific service +docker-compose -f docker-compose.deploy.yml logs -f backend +``` + +### Restart Services +```cmd +# Restart all +docker-compose -f docker-compose.deploy.yml restart + +# Restart specific service +docker-compose -f docker-compose.deploy.yml restart backend +``` + +### Stop Services +```cmd +docker-compose -f docker-compose.deploy.yml down +``` + +### Update Deployment +1. Stop current services +2. Load new images +3. Start services with new configuration + +## Backup Strategy + +### Database Backup +```cmd +docker exec serpentrace-postgres pg_dump -U postgres serpentrace > backup_$(date +%Y%m%d).sql +``` + +### Complete Backup +```cmd +# Stop services +docker-compose -f docker-compose.deploy.yml down + +# Backup volumes +docker run --rm -v postgres_data:/data -v %cd%:/backup ubuntu tar czf /backup/postgres_backup.tar.gz -C /data . +docker run --rm -v minio_data:/data -v %cd%:/backup ubuntu tar czf /backup/minio_backup.tar.gz -C /data . + +# Restart services +docker-compose -f docker-compose.deploy.yml up -d +``` + +## Troubleshooting + +### Common Issues + +#### Services Not Starting +1. Check Docker is running +2. Verify port availability +3. Check environment variables +4. Review logs for specific errors + +#### Database Connection Issues +1. Verify POSTGRES_PASSWORD matches in .env.server +2. Check database container is healthy +3. Ensure network connectivity + +#### Frontend Not Loading +1. Check nginx container status +2. Verify backend API is responding +3. Check browser console for errors + +#### Performance Issues +1. Monitor resource usage: `docker stats` +2. Check available disk space +3. Review application logs +4. Consider scaling if needed + +### Getting Help +- Check application logs for specific error messages +- Verify all environment variables are set correctly +- Ensure all required ports are available +- Contact support with log files and configuration details + +## Version Information +- SerpentRace Backend: Latest +- Frontend: Latest +- PostgreSQL: 15-alpine +- Redis: 7-alpine +- MinIO: Latest +- Nginx: Alpine \ No newline at end of file diff --git a/SerpentRace_Docker/deployment/docker-compose.deploy.yml b/SerpentRace_Docker/deployment/docker-compose.deploy.yml new file mode 100644 index 00000000..7a5d8e2f --- /dev/null +++ b/SerpentRace_Docker/deployment/docker-compose.deploy.yml @@ -0,0 +1,147 @@ +version: '3.8' + +services: + # Backend service using pre-built image + backend: + image: serpentrace-backend:latest + container_name: serpentrace-backend + restart: unless-stopped + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + - DB_HOST=postgres + - DB_PORT=5432 + - DB_NAME=serpentrace + - DB_USERNAME=postgres + - DB_PASSWORD=${POSTGRES_PASSWORD} + - REDIS_URL=redis://redis:6379 + - REDIS_HOST=redis + - REDIS_PORT=6379 + - JWT_SECRET=${JWT_SECRET} + - JWT_EXPIRATION=${JWT_EXPIRATION:-24h} + - JWT_REFRESH_EXPIRATION=${JWT_REFRESH_EXPIRATION:-7d} + - MINIO_ENDPOINT=minio + - MINIO_PORT=9000 + - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} + - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} + - MINIO_USE_SSL=false + - EMAIL_HOST=${EMAIL_HOST} + - EMAIL_PORT=${EMAIL_PORT} + - EMAIL_SECURE=${EMAIL_SECURE} + - EMAIL_USER=${EMAIL_USER} + - EMAIL_PASS=${EMAIL_PASS} + - EMAIL_FROM=${EMAIL_FROM} + volumes: + - backend_logs:/app/logs + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + minio: + condition: service_healthy + networks: + - serpentrace-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Frontend service using pre-built image + frontend: + image: serpentrace-frontend:latest + container_name: serpentrace-frontend + restart: unless-stopped + ports: + - "80:80" + - "443:443" + depends_on: + - backend + networks: + - serpentrace-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/health"] + interval: 30s + timeout: 10s + retries: 3 + + # PostgreSQL Database + postgres: + image: postgres:15-alpine + container_name: serpentrace-postgres + restart: unless-stopped + ports: + - "5432:5432" + environment: + POSTGRES_DB: serpentrace + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_INITDB_ARGS: "--encoding=UTF-8" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./sql_schema_only.sql:/docker-entrypoint-initdb.d/init.sql + networks: + - serpentrace-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + # Redis Cache + redis: + image: redis:7-alpine + container_name: serpentrace-redis + restart: unless-stopped + ports: + - "6379:6379" + volumes: + - redis_data:/data + command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD} + networks: + - serpentrace-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # MinIO Object Storage + minio: + image: minio/minio:latest + container_name: serpentrace-minio + restart: unless-stopped + ports: + - "9000:9000" + - "9001:9001" + environment: + MINIO_ROOT_USER: ${MINIO_ACCESS_KEY} + MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY} + volumes: + - minio_data:/data + command: server /data --console-address ":9001" + networks: + - serpentrace-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: + driver: local + redis_data: + driver: local + minio_data: + driver: local + backend_logs: + driver: local + +networks: + serpentrace-network: + driver: bridge \ No newline at end of file diff --git a/SerpentRace_Docker/deployment/load-images.bat b/SerpentRace_Docker/deployment/load-images.bat new file mode 100644 index 00000000..583eea00 --- /dev/null +++ b/SerpentRace_Docker/deployment/load-images.bat @@ -0,0 +1,103 @@ +@echo off +REM SerpentRace Production Deployment Script +REM This script loads Docker images and starts the production environment + +setlocal EnableDelayedExpansion + +echo =============================================== +echo SerpentRace Production Deployment +echo =============================================== +echo. + +REM Check if Docker is installed +where docker >nul 2>nul +if %errorlevel% neq 0 ( + echo [ERROR] Docker is not installed. Please install Docker first. + pause + exit /b 1 +) + +where docker-compose >nul 2>nul +if %errorlevel% neq 0 ( + echo [ERROR] Docker Compose is not installed. Please install Docker Compose first. + pause + exit /b 1 +) + +REM Check if serpentRaceDocker.tar exists +if not exist "serpentRaceDocker.tar" ( + echo [ERROR] serpentRaceDocker.tar not found! + echo Please ensure the tar file is in the same directory as this script. + pause + exit /b 1 +) + +REM Check if environment file exists +if not exist ".env.server" ( + echo [ERROR] .env.server file not found! + echo Please ensure the environment file is configured. + pause + exit /b 1 +) + +echo [INFO] Loading Docker images from serpentRaceDocker.tar... +docker load -i serpentRaceDocker.tar +if %errorlevel% neq 0 ( + echo [ERROR] Failed to load Docker images! + pause + exit /b 1 +) + +echo [INFO] Images loaded successfully! +echo. + +REM Show loaded images +echo [INFO] Loaded images: +docker images | findstr serpentrace +docker images | findstr postgres +docker images | findstr redis +docker images | findstr minio +echo. + +echo [WARNING] Before starting the services, please review and update .env.server: +echo - Change all placeholder passwords +echo - Configure email settings +echo - Update domain names +echo - Set strong JWT secret +echo. +echo Press any key to continue with deployment or Ctrl+C to exit... +pause >nul + +echo [INFO] Starting production services... +docker-compose -f docker-compose.deploy.yml --env-file .env.server up -d + +if %errorlevel% neq 0 ( + echo [ERROR] Failed to start services! + pause + exit /b 1 +) + +echo. +echo =============================================== +echo Deployment Complete! +echo =============================================== +echo. +echo Services are starting up. Please wait a few moments for all services to be ready. +echo. +echo Available services: +echo - Frontend: http://localhost (or your domain) +echo - Backend API: http://localhost:3000 +echo - MinIO Console: http://localhost:9001 +echo. +echo To check service status: docker-compose -f docker-compose.deploy.yml ps +echo To view logs: docker-compose -f docker-compose.deploy.yml logs -f [service_name] +echo To stop services: docker-compose -f docker-compose.deploy.yml down +echo. +echo IMPORTANT SECURITY NOTES: +echo 1. Change all default passwords in .env.server +echo 2. Configure firewall rules for your server +echo 3. Set up SSL/TLS certificates for HTTPS +echo 4. Configure regular backups +echo 5. Monitor logs and system resources +echo. +pause \ No newline at end of file diff --git a/SerpentRace_Docker/deployment/load-images.sh b/SerpentRace_Docker/deployment/load-images.sh new file mode 100644 index 00000000..481949ee --- /dev/null +++ b/SerpentRace_Docker/deployment/load-images.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# SerpentRace Production Deployment Script for Linux +# This script loads Docker images and starts the production environment + +set -e + +echo "===============================================" +echo "SerpentRace Production Deployment" +echo "===============================================" +echo + +# Check if Docker is installed +if ! command -v docker &> /dev/null; then + echo "[ERROR] Docker is not installed. Please install Docker first." + exit 1 +fi + +if ! command -v docker-compose &> /dev/null; then + echo "[ERROR] Docker Compose is not installed. Please install Docker Compose first." + exit 1 +fi + +# Check if serpentRaceDocker.tar exists +if [ ! -f "serpentRaceDocker.tar" ]; then + echo "[ERROR] serpentRaceDocker.tar not found!" + echo "Please ensure the tar file is in the same directory as this script." + exit 1 +fi + +# Check if environment file exists +if [ ! -f ".env.server" ]; then + echo "[ERROR] .env.server file not found!" + echo "Please ensure the environment file is configured." + exit 1 +fi + +echo "[INFO] Loading Docker images from serpentRaceDocker.tar..." +docker load -i serpentRaceDocker.tar + +echo "[INFO] Images loaded successfully!" +echo + +# Show loaded images +echo "[INFO] Loaded images:" +docker images | grep -E "(serpentrace|postgres|redis|minio)" +echo + +echo "[WARNING] Before starting the services, please review and update .env.server:" +echo " - Change all placeholder passwords" +echo " - Configure email settings" +echo " - Update domain names" +echo " - Set strong JWT secret" +echo +read -p "Press Enter to continue with deployment or Ctrl+C to exit..." + +echo "[INFO] Starting production services..." +docker-compose -f docker-compose.deploy.yml --env-file .env.server up -d + +echo +echo "===============================================" +echo "Deployment Complete!" +echo "===============================================" +echo +echo "Services are starting up. Please wait a few moments for all services to be ready." +echo +echo "Available services:" +echo " - Frontend: http://localhost (or your domain)" +echo " - Backend API: http://localhost:3000" +echo " - MinIO Console: http://localhost:9001" +echo +echo "To check service status: docker-compose -f docker-compose.deploy.yml ps" +echo "To view logs: docker-compose -f docker-compose.deploy.yml logs -f [service_name]" +echo "To stop services: docker-compose -f docker-compose.deploy.yml down" +echo +echo "IMPORTANT SECURITY NOTES:" +echo "1. Change all default passwords in .env.server" +echo "2. Configure firewall rules for your server" +echo "3. Set up SSL/TLS certificates for HTTPS" +echo "4. Configure regular backups" +echo "5. Monitor logs and system resources" +echo \ No newline at end of file diff --git a/SerpentRace_Docker/deployment/serpentRaceDocker.tar b/SerpentRace_Docker/deployment/serpentRaceDocker.tar new file mode 100644 index 00000000..a4a84819 Binary files /dev/null and b/SerpentRace_Docker/deployment/serpentRaceDocker.tar differ diff --git a/SerpentRace_Docker/deployment/sql_schema_only.sql b/SerpentRace_Docker/deployment/sql_schema_only.sql new file mode 100644 index 00000000..e36d9e25 --- /dev/null +++ b/SerpentRace_Docker/deployment/sql_schema_only.sql @@ -0,0 +1,236 @@ +-- SerpentRace Database Schema +-- Generated from TypeORM Entity Aggregates +-- This file creates the complete database schema without initial data + +-- Enable UUID extension +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- Create Users table +CREATE TABLE "Users" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "orgid" UUID NULL, + "username" VARCHAR(100) UNIQUE NOT NULL, + "password" VARCHAR(255) NOT NULL, + "email" VARCHAR(255) UNIQUE NOT NULL, + "fname" VARCHAR(100) NOT NULL, + "lname" VARCHAR(100) NOT NULL, + "token" VARCHAR(255) NULL, + "TokenExpires" TIMESTAMP NULL, + "phone" VARCHAR(20) NULL, + "state" INTEGER NOT NULL DEFAULT 0, + "regdate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "Orglogindate" TIMESTAMP NULL +); + +-- Create Organizations table +CREATE TABLE "Organizations" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "name" VARCHAR(255) NOT NULL, + "contactfname" VARCHAR(100) NOT NULL, + "contactlname" VARCHAR(100) NOT NULL, + "contactphone" VARCHAR(20) NOT NULL, + "contactemail" VARCHAR(255) NOT NULL, + "state" INTEGER NOT NULL DEFAULT 0, + "regdate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "url" VARCHAR(500) NULL, + "userinorg" INTEGER NOT NULL DEFAULT 0, + "maxOrganizationalDecks" INTEGER NULL +); + +-- Create Decks table +CREATE TABLE "Decks" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "name" VARCHAR(255) NOT NULL, + "type" INTEGER NOT NULL, + "user_id" UUID NOT NULL, + "creation_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "cards" JSONB NOT NULL DEFAULT '[]', + "played_number" INTEGER NOT NULL DEFAULT 0, + "ctype" INTEGER NOT NULL DEFAULT 0, + "update_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "state" INTEGER NOT NULL DEFAULT 0, + "organization_id" UUID NULL +); + +-- Create Chats table +CREATE TABLE "Chats" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "type" VARCHAR(50) NOT NULL DEFAULT 'direct', + "name" VARCHAR(255) NULL, + "gameId" UUID NULL, + "createdBy" UUID NULL, + "users" UUID[] NOT NULL, + "messages" JSONB NOT NULL DEFAULT '[]', + "lastActivity" TIMESTAMP NULL, + "createDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "state" INTEGER NOT NULL DEFAULT 0, + "archiveDate" TIMESTAMP NULL +); + +-- Create Contacts table +CREATE TABLE "Contacts" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "name" VARCHAR(255) NOT NULL, + "email" VARCHAR(255) NOT NULL, + "userid" UUID NULL, + "type" INTEGER NOT NULL, + "txt" TEXT NOT NULL, + "state" INTEGER NOT NULL DEFAULT 0, + "createDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "adminResponse" TEXT NULL, + "responseDate" TIMESTAMP NULL, + "respondedBy" UUID NULL +); + +-- Create Games table +CREATE TABLE "Games" ( + "id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + "gamecode" VARCHAR(10) UNIQUE NOT NULL, + "maxplayers" INTEGER NOT NULL, + "logintype" INTEGER NOT NULL DEFAULT 0, + "state" INTEGER NOT NULL DEFAULT 0, + "playerids" UUID[] NOT NULL DEFAULT '{}', + "decks" JSONB NOT NULL DEFAULT '[]', + "boardsize" INTEGER NOT NULL DEFAULT 50, + "createDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateDate" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + "finishDate" TIMESTAMP NULL, + "winnerid" UUID NULL, + "createdBy" UUID NOT NULL, + "organizationid" UUID NULL +); + +-- Add Foreign Key Constraints +ALTER TABLE "Users" +ADD CONSTRAINT "FK_Users_Organizations" +FOREIGN KEY ("orgid") REFERENCES "Organizations"("id") ON DELETE SET NULL; + +ALTER TABLE "Decks" +ADD CONSTRAINT "FK_Decks_Users" +FOREIGN KEY ("user_id") REFERENCES "Users"("id") ON DELETE CASCADE; + +ALTER TABLE "Decks" +ADD CONSTRAINT "FK_Decks_Organizations" +FOREIGN KEY ("organization_id") REFERENCES "Organizations"("id") ON DELETE SET NULL; + +ALTER TABLE "Contacts" +ADD CONSTRAINT "FK_Contacts_Users" +FOREIGN KEY ("userid") REFERENCES "Users"("id") ON DELETE SET NULL; + +ALTER TABLE "Contacts" +ADD CONSTRAINT "FK_Contacts_RespondedBy" +FOREIGN KEY ("respondedBy") REFERENCES "Users"("id") ON DELETE SET NULL; + +ALTER TABLE "Chats" +ADD CONSTRAINT "FK_Chats_CreatedBy" +FOREIGN KEY ("createdBy") REFERENCES "Users"("id") ON DELETE SET NULL; + +ALTER TABLE "Chats" +ADD CONSTRAINT "FK_Chats_Games" +FOREIGN KEY ("gameId") REFERENCES "Games"("id") ON DELETE SET NULL; + +ALTER TABLE "Games" +ADD CONSTRAINT "FK_Games_CreatedBy" +FOREIGN KEY ("createdBy") REFERENCES "Users"("id") ON DELETE CASCADE; + +ALTER TABLE "Games" +ADD CONSTRAINT "FK_Games_Organizations" +FOREIGN KEY ("organizationid") REFERENCES "Organizations"("id") ON DELETE SET NULL; + +ALTER TABLE "Games" +ADD CONSTRAINT "FK_Games_Winner" +FOREIGN KEY ("winnerid") REFERENCES "Users"("id") ON DELETE SET NULL; + +-- Create Indexes for Performance +CREATE INDEX "IDX_Users_Username" ON "Users" ("username"); +CREATE INDEX "IDX_Users_Email" ON "Users" ("email"); +CREATE INDEX "IDX_Users_OrgId" ON "Users" ("orgid"); +CREATE INDEX "IDX_Users_State" ON "Users" ("state"); + +CREATE INDEX "IDX_Organizations_Name" ON "Organizations" ("name"); +CREATE INDEX "IDX_Organizations_State" ON "Organizations" ("state"); + +CREATE INDEX "IDX_Decks_UserId" ON "Decks" ("user_id"); +CREATE INDEX "IDX_Decks_Type" ON "Decks" ("type"); +CREATE INDEX "IDX_Decks_CType" ON "Decks" ("ctype"); +CREATE INDEX "IDX_Decks_State" ON "Decks" ("state"); +CREATE INDEX "IDX_Decks_OrganizationId" ON "Decks" ("organization_id"); + +CREATE INDEX "IDX_Chats_Type" ON "Chats" ("type"); +CREATE INDEX "IDX_Chats_State" ON "Chats" ("state"); +CREATE INDEX "IDX_Chats_GameId" ON "Chats" ("gameId"); +CREATE INDEX "IDX_Chats_CreatedBy" ON "Chats" ("createdBy"); + +CREATE INDEX "IDX_Contacts_Type" ON "Contacts" ("type"); +CREATE INDEX "IDX_Contacts_State" ON "Contacts" ("state"); +CREATE INDEX "IDX_Contacts_UserId" ON "Contacts" ("userid"); + +CREATE INDEX "IDX_Games_GameCode" ON "Games" ("gamecode"); +CREATE INDEX "IDX_Games_State" ON "Games" ("state"); +CREATE INDEX "IDX_Games_CreatedBy" ON "Games" ("createdBy"); +CREATE INDEX "IDX_Games_OrganizationId" ON "Games" ("organizationid"); + +-- Create update trigger for updatedate columns +CREATE OR REPLACE FUNCTION update_updatedate_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updatedate = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +-- Apply update triggers +CREATE TRIGGER update_users_updatedate + BEFORE UPDATE ON "Users" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +CREATE TRIGGER update_organizations_updatedate + BEFORE UPDATE ON "Organizations" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +CREATE TRIGGER update_decks_updatedate + BEFORE UPDATE ON "Decks" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +CREATE TRIGGER update_chats_updatedate + BEFORE UPDATE ON "Chats" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +CREATE TRIGGER update_contacts_updatedate + BEFORE UPDATE ON "Contacts" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +CREATE TRIGGER update_games_updatedate + BEFORE UPDATE ON "Games" + FOR EACH ROW EXECUTE FUNCTION update_updatedate_column(); + +-- Comments for documentation +COMMENT ON TABLE "Users" IS 'User accounts with authentication and profile information'; +COMMENT ON TABLE "Organizations" IS 'Organizations that can have multiple users and premium features'; +COMMENT ON TABLE "Decks" IS 'Card decks for the game, can be public, private, or organizational'; +COMMENT ON TABLE "Chats" IS 'Chat system supporting direct messages, groups, and game chats'; +COMMENT ON TABLE "Contacts" IS 'Contact form submissions and support tickets'; +COMMENT ON TABLE "Games" IS 'Game sessions with players, decks, and game state'; + +-- Enum value comments +COMMENT ON COLUMN "Users"."state" IS '0=REGISTERED_NOT_VERIFIED, 1=VERIFIED_REGULAR, 2=VERIFIED_PREMIUM, 3=SOFT_DELETE, 4=DEACTIVATED, 5=ADMIN'; +COMMENT ON COLUMN "Organizations"."state" IS '0=REGISTERED, 1=ACTIVE, 2=SOFT_DELETE'; +COMMENT ON COLUMN "Decks"."type" IS '0=LUCK, 1=JOKER, 2=QUESTION'; +COMMENT ON COLUMN "Decks"."ctype" IS '0=PUBLIC, 1=PRIVATE, 2=ORGANIZATION'; +COMMENT ON COLUMN "Decks"."state" IS '0=ACTIVE, 1=SOFT_DELETE'; +COMMENT ON COLUMN "Chats"."type" IS 'direct, group, game'; +COMMENT ON COLUMN "Chats"."state" IS '0=ACTIVE, 1=ARCHIVE, 2=SOFT_DELETE'; +COMMENT ON COLUMN "Contacts"."type" IS '0=BUG, 1=PROBLEM, 2=QUESTION, 3=SALES, 4=OTHER'; +COMMENT ON COLUMN "Contacts"."state" IS '0=ACTIVE, 1=RESOLVED, 2=SOFT_DELETE'; +COMMENT ON COLUMN "Games"."state" IS '0=WAITING, 1=ACTIVE, 2=FINISHED, 3=CANCELLED'; +COMMENT ON COLUMN "Games"."logintype" IS '0=PUBLIC, 1=PRIVATE, 2=ORGANIZATION'; + +-- Grant permissions for application user +-- Note: Replace 'serpentrace_app' with your actual application database user +-- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO serpentrace_app; +-- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO serpentrace_app; +-- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO serpentrace_app; \ No newline at end of file