/** * Test script to verify admin can perform actions during maintenance mode * * This script tests: * 1. Admin can authenticate during maintenance * 2. Admin can access admin endpoints during maintenance * 3. Admin can perform CRUD operations during maintenance * 4. Non-admin users are still blocked during maintenance * * Usage: node test-admin-maintenance.js */ import fetch from 'node-fetch'; import dotenv from 'dotenv'; dotenv.config(); const API_URL = process.env.VITE_API_URL || 'http://localhost:3000'; const BASE_URL = `${API_URL}/api`; // Colors for console output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', }; function log(message, color = 'reset') { console.log(`${colors[color]}${message}${colors.reset}`); } function logTest(name) { console.log(`\n${colors.bright}${colors.blue}đŸ§Ē Testing: ${name}${colors.reset}`); } function logSuccess(message) { log(`✅ ${message}`, 'green'); } function logError(message) { log(`❌ ${message}`, 'red'); } function logWarning(message) { log(`âš ī¸ ${message}`, 'yellow'); } function logInfo(message) { log(`â„šī¸ ${message}`, 'blue'); } // Helper to make authenticated requests async function makeRequest(endpoint, options = {}) { const url = endpoint.startsWith('http') ? endpoint : `${BASE_URL}${endpoint}`; try { const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, }, }); const data = await response.json(); return { status: response.status, ok: response.ok, data, }; } catch (error) { return { status: 0, ok: false, error: error.message, }; } } // Test 1: Check if maintenance mode is enabled async function testMaintenanceStatus() { logTest('Checking maintenance status'); const result = await makeRequest('/config/status'); if (result.ok) { const { maintenance } = result.data; if (maintenance) { logSuccess('Maintenance mode is ENABLED'); return true; } else { logWarning('Maintenance mode is DISABLED - enable it to test properly'); return false; } } else { logError(`Failed to check maintenance status: ${result.status}`); return false; } } // Test 2: Check public config endpoint (should work during maintenance) async function testPublicConfig() { logTest('Testing public config endpoint (should work during maintenance)'); const result = await makeRequest('/config/public'); if (result.ok) { logSuccess('Public config endpoint accessible'); return true; } else { logError(`Public config endpoint failed: ${result.status}`); return false; } } // Test 3: Test unauthenticated admin request (should be blocked) async function testUnauthenticatedAdminRequest() { logTest('Testing unauthenticated admin request (should be blocked)'); const result = await makeRequest('/admin/config'); if (result.status === 503) { logSuccess('Unauthenticated request correctly blocked (503)'); logInfo(`Message: ${result.data.message}`); return true; } else if (result.status === 401) { logSuccess('Unauthenticated request blocked by auth (401)'); return true; } else { logError(`Unexpected status: ${result.status}`); return false; } } // Test 4: Test admin authentication (manual test - requires actual admin cookies) async function testAdminAuthentication(cookies) { logTest('Testing admin authentication with provided cookies'); if (!cookies) { logWarning('No cookies provided - skipping authenticated tests'); logInfo('To test with authentication, run: node test-admin-maintenance.js "accessToken=your_token"'); return null; } const result = await makeRequest('/auth/me', { headers: { Cookie: cookies, }, }); if (result.ok && result.data.user) { const { user } = result.data; logSuccess(`Authenticated as: ${user.username}`); logInfo(`Staff Level: ${user.staffLevel}`); if (user.staffLevel >= 3) { logSuccess('User is an admin (staffLevel >= 3)'); return cookies; } else { logWarning('User is NOT an admin (staffLevel < 3)'); return null; } } else { logError('Authentication failed'); return null; } } // Test 5: Test admin endpoints with authentication async function testAdminEndpoints(cookies) { if (!cookies) { logWarning('Skipping admin endpoint tests - no valid admin cookies'); return false; } logTest('Testing admin endpoints during maintenance'); // Test 5a: Get admin config const configResult = await makeRequest('/admin/config', { headers: { Cookie: cookies, }, }); if (configResult.ok) { logSuccess('GET /admin/config - Success'); } else { logError(`GET /admin/config - Failed (${configResult.status})`); if (configResult.data) { logError(`Message: ${configResult.data.message || JSON.stringify(configResult.data)}`); } return false; } // Test 5b: Get users list const usersResult = await makeRequest('/admin/users?page=1&limit=10', { headers: { Cookie: cookies, }, }); if (usersResult.ok) { logSuccess('GET /admin/users - Success'); logInfo(`Found ${usersResult.data.users?.length || 0} users`); } else { logError(`GET /admin/users - Failed (${usersResult.status})`); if (usersResult.data) { logError(`Message: ${usersResult.data.message || JSON.stringify(usersResult.data)}`); } } // Test 5c: Get announcements const announcementsResult = await makeRequest('/admin/announcements', { headers: { Cookie: cookies, }, }); if (announcementsResult.ok) { logSuccess('GET /admin/announcements - Success'); logInfo(`Found ${announcementsResult.data.announcements?.length || 0} announcements`); } else { logError(`GET /admin/announcements - Failed (${announcementsResult.status})`); } return true; } // Test 6: Test maintenance toggle (the actual action that was failing) async function testMaintenanceToggle(cookies) { if (!cookies) { logWarning('Skipping maintenance toggle test - no valid admin cookies'); return false; } logTest('Testing maintenance mode toggle (the critical test)'); // First, get current config const getCurrentConfig = await makeRequest('/admin/config', { headers: { Cookie: cookies, }, }); if (!getCurrentConfig.ok) { logError('Failed to get current config'); return false; } const currentMaintenanceState = getCurrentConfig.data.config.maintenance.enabled; logInfo(`Current maintenance state: ${currentMaintenanceState}`); // Try to toggle maintenance (just toggle and toggle back) const newState = !currentMaintenanceState; const updateResult = await makeRequest('/admin/config/maintenance', { method: 'PUT', headers: { Cookie: cookies, }, body: JSON.stringify({ enabled: newState, message: "Test toggle during maintenance", }), }); if (updateResult.ok) { logSuccess(`Successfully toggled maintenance to: ${newState}`); // Toggle back to original state const restoreResult = await makeRequest('/admin/config/maintenance', { method: 'PUT', headers: { Cookie: cookies, }, body: JSON.stringify({ enabled: currentMaintenanceState, message: getCurrentConfig.data.config.maintenance.message, }), }); if (restoreResult.ok) { logSuccess(`Restored maintenance to original state: ${currentMaintenanceState}`); } else { logWarning(`Failed to restore original state - maintenance is now ${newState}`); } return true; } else { logError(`Failed to toggle maintenance (${updateResult.status})`); if (updateResult.data) { logError(`Message: ${updateResult.data.message || JSON.stringify(updateResult.data)}`); } return false; } } // Main test runner async function runTests() { log('\n' + '='.repeat(60), 'bright'); log('🔧 Admin Maintenance Mode Test Suite', 'bright'); log('='.repeat(60) + '\n', 'bright'); // Get cookies from command line if provided const cookies = process.argv[2] || null; if (!cookies) { logWarning('No authentication cookies provided'); logInfo('To test with authentication:'); logInfo('1. Login to the site as admin'); logInfo('2. Open browser DevTools > Application > Cookies'); logInfo('3. Copy your accessToken cookie value'); logInfo('4. Run: node test-admin-maintenance.js "accessToken=YOUR_TOKEN_HERE"'); console.log(); } let allPassed = true; // Run tests const maintenanceEnabled = await testMaintenanceStatus(); if (!maintenanceEnabled) { logWarning('\nâš ī¸ Please enable maintenance mode in admin panel first!'); process.exit(1); } allPassed = await testPublicConfig() && allPassed; allPassed = await testUnauthenticatedAdminRequest() && allPassed; const validCookies = await testAdminAuthentication(cookies); if (validCookies) { allPassed = await testAdminEndpoints(validCookies) && allPassed; allPassed = await testMaintenanceToggle(validCookies) && allPassed; } // Summary log('\n' + '='.repeat(60), 'bright'); if (allPassed && validCookies) { log('✅ All tests passed!', 'green'); } else if (!validCookies) { log('âš ī¸ Basic tests passed, but admin tests were skipped', 'yellow'); log('Provide admin cookies to run full test suite', 'yellow'); } else { log('❌ Some tests failed', 'red'); } log('='.repeat(60) + '\n', 'bright'); } // Run the tests runTests().catch((error) => { logError(`Test suite failed with error: ${error.message}`); console.error(error); process.exit(1); });