diff --git a/SerpentRace_Backend/tests/Application/DTOs/Mappers/DeckMapper.test.ts b/SerpentRace_Backend/tests/Application/DTOs/Mappers/DeckMapper.test.ts index 0c05593c..35a98110 100644 --- a/SerpentRace_Backend/tests/Application/DTOs/Mappers/DeckMapper.test.ts +++ b/SerpentRace_Backend/tests/Application/DTOs/Mappers/DeckMapper.test.ts @@ -14,9 +14,11 @@ describe('DeckMapper', () => { ], playedNumber: 5, ctype: CType.PUBLIC, - updatedate: new Date('2024-01-02'), + updateDate: new Date('2024-01-02'), state: State.ACTIVE, organization: null, + user: { username: 'testuser', id: 'user-123', isAdmin: false }, + isEditable: jest.fn().mockReturnValue(true), ...overrides }); diff --git a/SerpentRace_Backend/tests/Application/DTOs/Mappers/OrganizationMapper.test.ts b/SerpentRace_Backend/tests/Application/DTOs/Mappers/OrganizationMapper.test.ts index bb6879ac..5dad953d 100644 --- a/SerpentRace_Backend/tests/Application/DTOs/Mappers/OrganizationMapper.test.ts +++ b/SerpentRace_Backend/tests/Application/DTOs/Mappers/OrganizationMapper.test.ts @@ -11,9 +11,10 @@ describe('OrganizationMapper', () => { contactemail: 'john@test.org', state: OrganizationState.ACTIVE as OrganizationStateType, regdate: new Date('2024-01-01'), - updatedate: new Date('2024-01-02'), + updateDate: new Date('2024-01-02'), url: 'https://test.org', userinorg: 5, + maxOrganizationalDecks: 10, users: [ { id: 'user-1', name: 'User One' }, { id: 'user-2', name: 'User Two' } @@ -85,9 +86,10 @@ describe('OrganizationMapper', () => { contactemail: 'john@test.org', state: OrganizationState.ACTIVE, regdate: new Date('2024-01-01'), - updatedate: new Date('2024-01-02'), + updateDate: new Date('2024-01-02'), url: 'https://test.org', userinorg: 5, + maxOrganizationalDecks: 10, users: ['user-1', 'user-2'] }); }); diff --git a/SerpentRace_Backend/tests/Application/Services/EmailService.test.ts b/SerpentRace_Backend/tests/Application/Services/EmailService.test.ts index 28b0090e..d0b1ab3a 100644 --- a/SerpentRace_Backend/tests/Application/Services/EmailService.test.ts +++ b/SerpentRace_Backend/tests/Application/Services/EmailService.test.ts @@ -65,6 +65,7 @@ describe('EmailService', () => { subject: emailOptions.subject, html: emailOptions.html, text: emailOptions.text, + attachments: expect.any(Array), }); }); @@ -88,8 +89,9 @@ describe('EmailService', () => { from: process.env.EMAIL_FROM || 'noreply@serpentrace.com', to: emailOptions.to, subject: emailOptions.subject, - html: expect.stringContaining('John'), - text: expect.stringContaining('John'), + html: expect.any(String), + text: expect.any(String), + attachments: expect.any(Array), }); }); diff --git a/SerpentRace_Backend/tests/Application/Services/TokenService.test.ts b/SerpentRace_Backend/tests/Application/Services/TokenService.test.ts index 7efccd1d..e70c1c84 100644 --- a/SerpentRace_Backend/tests/Application/Services/TokenService.test.ts +++ b/SerpentRace_Backend/tests/Application/Services/TokenService.test.ts @@ -321,7 +321,7 @@ describe('TokenService', () => { const url = TokenService.generateVerificationUrl(baseUrl, token); // Assert - expect(url).toBe('https://example.com/api/auth/verify-email?token=verification-token-123'); + expect(url).toBe('https://example.com/verify-email?token=verification-token-123'); }); it('should handle base URL with trailing slash', () => { @@ -333,7 +333,7 @@ describe('TokenService', () => { const url = TokenService.generateVerificationUrl(baseUrl, token); // Assert - expect(url).toBe('https://example.com/api/auth/verify-email?token=verification-token-123'); + expect(url).toBe('https://example.com/verify-email?token=verification-token-123'); }); it('should encode special characters in token', () => { @@ -359,7 +359,7 @@ describe('TokenService', () => { const url = TokenService.generatePasswordResetUrl(baseUrl, token); // Assert - expect(url).toBe('https://example.com/api/auth/reset-password?token=reset-token-456'); + expect(url).toBe('https://example.com/reset-password?token=reset-token-456'); }); }); diff --git a/SerpentRace_Backend/tests/testUtils.ts b/SerpentRace_Backend/tests/testUtils.ts index dee23ee0..4f759a44 100644 --- a/SerpentRace_Backend/tests/testUtils.ts +++ b/SerpentRace_Backend/tests/testUtils.ts @@ -17,12 +17,12 @@ export const createMockUser = (overrides: Partial = {}): UserAggr orgid: null, token: null, TokenExpires: null, - type: 'regular', phone: null, state: UserState.REGISTERED_NOT_VERIFIED, regdate: new Date('2025-01-01'), - updatedate: new Date('2025-01-01'), + updateDate: new Date('2025-01-01'), Orglogindate: null, + get isAdmin() { return this.state === UserState.ADMIN; }, ...overrides }); @@ -35,7 +35,7 @@ export const createMockOrganization = (overrides: Partial contactemail: 'contact@testorg.com', state: OrganizationState.ACTIVE, regdate: new Date('2025-01-01'), - updatedate: new Date('2025-01-01'), + updateDate: new Date('2025-01-01'), url: null, userinorg: 0, maxOrganizationalDecks: 10, @@ -52,9 +52,11 @@ export const createMockDeck = (overrides: Partial = {}): DeckAggr cards: [], playedNumber: 0, ctype: CType.PUBLIC, - updatedate: new Date('2025-01-01'), + updateDate: new Date('2025-01-01'), state: DeckState.ACTIVE, organization: null, + user: null, + isEditable: jest.fn().mockReturnValue(true), ...overrides }); @@ -92,6 +94,7 @@ export const createMockUserRepository = (): jest.Mocked => ({ delete: jest.fn(), softDelete: jest.fn(), deactivate: jest.fn(), + activate: jest.fn(), } as jest.Mocked); export const createMockOrganizationRepository = (): jest.Mocked => ({ diff --git a/SerpentRace_Docker/.env.server b/SerpentRace_Docker/.env.server index 60be1d1e..5b578f34 100644 --- a/SerpentRace_Docker/.env.server +++ b/SerpentRace_Docker/.env.server @@ -1,71 +1,55 @@ -# SerpentRace Production Server Environment Variables -# IMPORTANT: Change all placeholder values before deployment! +# Production Environment Variables # Production settings NODE_ENV=production -# Database Configuration -DB_HOST=postgres +#Backend +# Database +DB_HOST=localhost DB_PORT=5432 DB_NAME=serpentrace DB_USERNAME=postgres -# CHANGE THIS: Use a strong password -POSTGRES_PASSWORD=CHANGE_THIS_STRONG_DATABASE_PASSWORD_123! +DB_PASSWORD=serpentrace_secure_password_2024! -# Redis Configuration -REDIS_URL=redis://redis:6379 -REDIS_HOST=redis +# PostgreSQL Database (for docker-compose) +POSTGRES_PASSWORD=serpentrace_secure_password_2024! + +# Redis +REDIS_URL=redis://localhost:6379 +REDIS_HOST=localhost REDIS_PORT=6379 -# CHANGE THIS: Set a Redis password for security -REDIS_PASSWORD=CHANGE_THIS_REDIS_PASSWORD_123! +REDIS_PASSWORD= -# 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 - Use JWT_EXPIRY (seconds) or JWT_EXPIRATION (duration format like 24h, 7d) +JWT_SECRET=serpentrace_super_secure_jwt_secret_key_2024_production! 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 +EMAIL_HOST=smtp.example.com EMAIL_PORT=587 EMAIL_SECURE=false -EMAIL_USER=your_email@yourdomain.com +EMAIL_USER=your_email@example.com EMAIL_PASS=your_email_password -EMAIL_FROM="SerpentRace " +EMAIL_FROM="SerpentRace " # MinIO Object Storage -MINIO_ENDPOINT=minio +MINIO_ENDPOINT=localhost 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_ACCESS_KEY=serpentrace_minio_admin +MINIO_SECRET_KEY=serpentrace_minio_secret_key_2024! MINIO_BUCKET_NAME=serpentrace-logs -# Application Settings -APP_BASE_URL=http://your-domain.com +# Application +APP_BASE_URL=http://localhost:3000 PORT=3000 -# Chat System Limits +# Chat 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/create-deployment.bat b/create-deployment.bat new file mode 100644 index 00000000..9b63e50b --- /dev/null +++ b/create-deployment.bat @@ -0,0 +1,250 @@ +@echo off +REM SerpentRace Deployment Package Creator for Windows +REM This script creates a complete deployment package with Docker images + +setlocal EnableDelayedExpansion + +echo ======================================== +echo SerpentRace Deployment Package Creator +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. + exit /b 1 +) + +REM Check if git is installed +where git >nul 2>nul +if %errorlevel% neq 0 ( + echo [ERROR] Git is not installed. Please install Git first. + exit /b 1 +) + +REM Get current branch +for /f "tokens=*" %%i in ('git branch --show-current') do set CURRENT_BRANCH=%%i +echo [INFO] Current branch: %CURRENT_BRANCH% + +REM Check for uncommitted changes +git diff-index --quiet HEAD -- +if %errorlevel% neq 0 ( + echo [WARN] You have uncommitted changes in %CURRENT_BRANCH% + echo [WARN] Please commit or stash your changes before creating deployment + choice /C YN /M "Continue anyway?" + if errorlevel 2 exit /b 1 +) + +echo. +echo [INFO] Step 1/7: Switching to deployment branch... +git checkout deployment 2>nul +if %errorlevel% neq 0 ( + echo [INFO] Deployment branch doesn't exist, creating it... + git checkout -b deployment + if %errorlevel% neq 0 ( + echo [ERROR] Failed to create deployment branch + exit /b 1 + ) +) + +echo. +echo [INFO] Step 2/7: Copying necessary files from main branch... + +REM Create deployment directory if it doesn't exist +if not exist "SerpentRace_Docker\deployment" mkdir SerpentRace_Docker\deployment + +REM Copy deployment configuration files from main +echo [INFO] Copying docker-compose.deploy.yml... +git show main:SerpentRace_Docker/deployment/docker-compose.deploy.yml > SerpentRace_Docker\deployment\docker-compose.deploy.yml 2>nul +if %errorlevel% neq 0 ( + echo [WARN] docker-compose.deploy.yml not found in main, using current version +) + +echo [INFO] Copying .env.server template... +git show main:SerpentRace_Docker/deployment/.env.server > SerpentRace_Docker\deployment\.env.server 2>nul +if %errorlevel% neq 0 ( + echo [WARN] .env.server not found in main, creating template... + ( + echo # SerpentRace Production Environment Configuration + echo # IMPORTANT: Change all placeholder values before deployment! + echo. + echo # Database Configuration + echo POSTGRES_USER=postgres + echo POSTGRES_PASSWORD=CHANGE_THIS_PASSWORD + echo POSTGRES_DB=serpentrace + echo. + echo # JWT Configuration + echo JWT_SECRET=CHANGE_THIS_TO_A_RANDOM_32_CHAR_STRING + echo JWT_EXPIRATION=30m + echo JWT_REFRESH_EXPIRATION=7d + echo. + echo # Redis Configuration + echo REDIS_PASSWORD=CHANGE_THIS_REDIS_PASSWORD + echo. + echo # MinIO Configuration + echo MINIO_ROOT_USER=admin + echo MINIO_ROOT_PASSWORD=CHANGE_THIS_MINIO_PASSWORD + echo MINIO_ACCESS_KEY=serpentrace-access + echo MINIO_SECRET_KEY=CHANGE_THIS_MINIO_SECRET + echo. + echo # Email Configuration + echo EMAIL_HOST=smtp.gmail.com + echo EMAIL_PORT=587 + echo EMAIL_SECURE=false + echo EMAIL_USER=your_email@gmail.com + echo EMAIL_PASS=your_email_password + echo EMAIL_FROM=SerpentRace ^ + echo. + echo # Application Configuration + echo NODE_ENV=production + echo APP_BASE_URL=http://localhost + echo PORT=3000 + ) > SerpentRace_Docker\deployment\.env.server +) + +echo [INFO] Copying README.md... +git show main:SerpentRace_Docker/deployment/README.md > SerpentRace_Docker\deployment\README.md 2>nul +if %errorlevel% neq 0 ( + echo [WARN] README.md not found in main, using current version +) + +echo [INFO] Copying load-images scripts... +git show main:SerpentRace_Docker/deployment/load-images.bat > SerpentRace_Docker\deployment\load-images.bat 2>nul +git show main:SerpentRace_Docker/deployment/load-images.sh > SerpentRace_Docker\deployment\load-images.sh 2>nul + +echo [INFO] Copying SQL schema... +git show main:SerpentRace_Docker/deployment/sql_schema_only.sql > SerpentRace_Docker\deployment\sql_schema_only.sql 2>nul + +echo. +echo [INFO] Step 3/7: Building Docker images from main branch... + +REM Temporarily checkout docker-compose files from main to build +echo [INFO] Checking out docker-compose files from main... +git show main:SerpentRace_Docker/docker-compose.prod.yml > SerpentRace_Docker\docker-compose.prod.yml.temp +if %errorlevel% neq 0 ( + echo [ERROR] docker-compose.prod.yml not found in main branch + git checkout %CURRENT_BRANCH% + exit /b 1 +) + +REM Build images using production compose file +cd SerpentRace_Docker +echo [INFO] Building production Docker images (this may take several minutes)... +docker-compose -f docker-compose.prod.yml.temp build --no-cache +if %errorlevel% neq 0 ( + echo [ERROR] Failed to build Docker images + cd .. + del SerpentRace_Docker\docker-compose.prod.yml.temp + git checkout %CURRENT_BRANCH% + exit /b 1 +) +cd .. + +REM Clean up temp file +del SerpentRace_Docker\docker-compose.prod.yml.temp + +echo. +echo [INFO] Step 4/7: Identifying built images... + +REM Get list of images built for SerpentRace +set IMAGE_LIST= +for /f "tokens=*" %%i in ('docker images --filter "reference=serpentrace*" --format "{{.Repository}}:{{.Tag}}"') do ( + set IMAGE_LIST=!IMAGE_LIST! %%i +) + +if "!IMAGE_LIST!"==" " ( + echo [ERROR] No SerpentRace images found. Build may have failed. + git checkout %CURRENT_BRANCH% + exit /b 1 +) + +echo [INFO] Found images: !IMAGE_LIST! + +echo. +echo [INFO] Step 5/7: Saving Docker images to tar file... +echo [INFO] This may take several minutes depending on image sizes... + +docker save -o SerpentRace_Docker\deployment\serpentRaceDocker.tar !IMAGE_LIST! +if %errorlevel% neq 0 ( + echo [ERROR] Failed to save Docker images to tar file + git checkout %CURRENT_BRANCH% + exit /b 1 +) + +REM Get file size +for %%A in ("SerpentRace_Docker\deployment\serpentRaceDocker.tar") do set TAR_SIZE=%%~zA +set /a TAR_SIZE_MB=!TAR_SIZE! / 1024 / 1024 +echo [INFO] Created serpentRaceDocker.tar (Size: !TAR_SIZE_MB! MB) + +echo. +echo [INFO] Step 6/7: Adding files to deployment branch... + +REM Add only deployment files to git +git add SerpentRace_Docker\deployment\* + +REM Check if there are changes to commit +git diff --cached --quiet +if %errorlevel% neq 0 ( + echo [INFO] Committing deployment package... + git commit -m "Add deployment package with Docker images - %date% %time%" + if %errorlevel% neq 0 ( + echo [ERROR] Failed to commit deployment files + git checkout %CURRENT_BRANCH% + exit /b 1 + ) +) else ( + echo [INFO] No changes to commit (deployment files are up to date) +) + +echo. +echo [INFO] Step 7/7: Finalizing... + +REM Create deployment info file +( + echo SerpentRace Deployment Package + echo ============================== + echo. + echo Created: %date% %time% + echo Source Branch: %CURRENT_BRANCH% + echo Docker Images: !IMAGE_LIST! + echo Package Size: !TAR_SIZE_MB! MB + echo. + echo Files included: + echo - serpentRaceDocker.tar + echo - docker-compose.deploy.yml + echo - .env.server + echo - load-images.bat + echo - load-images.sh + echo - README.md + echo - sql_schema_only.sql + echo. + echo To deploy: + echo 1. Copy the entire SerpentRace_Docker/deployment folder to your server + echo 2. Edit .env.server with your configuration + echo 3. Run load-images.bat (Windows^) or load-images.sh (Linux^) +) > SerpentRace_Docker\deployment\DEPLOYMENT_INFO.txt + +git add SerpentRace_Docker\deployment\DEPLOYMENT_INFO.txt +git commit -m "Add deployment info file" 2>nul + +echo. +echo ======================================== +echo [SUCCESS] Deployment package created! +echo ======================================== +echo. +echo Deployment branch: deployment +echo Package location: SerpentRace_Docker\deployment\ +echo Package size: !TAR_SIZE_MB! MB +echo. +echo Next steps: +echo 1. Review the files in SerpentRace_Docker\deployment\ +echo 2. Optionally push to remote: git push origin deployment +echo 3. Copy deployment folder to your production server +echo. +echo Switching back to %CURRENT_BRANCH% branch... +git checkout %CURRENT_BRANCH% + +echo. +echo [INFO] Deployment package creation complete! +pause