#!/usr/bin/env node /** * Test script to verify routes work correctly after SQL security fixes * Run this before deploying to production */ const request = require('supertest'); const app = require('../src/app'); const { db } = require('../src/database/db'); const jwt = require('jsonwebtoken'); // Generate admin token for testing const adminToken = jwt.sign( { id: 1, username: 'admin', role: 'admin' }, process.env.JWT_SECRET || 'test-secret' ); console.log('=== Testing Routes After SQL Security Fixes ===\n'); let passed = 0; let failed = 0; async function testRoute(description, testFn) { try { await testFn(); console.log(`āœ… ${description}`); passed++; } catch (error) { console.log(`āŒ ${description}`); console.error(` Error: ${error.message}`); failed++; } } async function runTests() { // Test Dashboard Stats (uses whereRaw fixes) await testRoute('Dashboard stats endpoint', async () => { const res = await request(app) .get('/api/admin/dashboard/stats') .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!res.body.hasOwnProperty('activeEvents')) { throw new Error('Missing activeEvents in response'); } }); // Test Analytics with days parameter (uses sanitizeDays) await testRoute('Analytics with valid days parameter', async () => { const res = await request(app) .get('/api/admin/dashboard/analytics?days=7') .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!res.body.chartData || res.body.chartData.length !== 7) { throw new Error('Invalid chart data'); } }); // Test Analytics with SQL injection attempt in days await testRoute('Analytics rejects SQL injection in days parameter', async () => { const res = await request(app) .get('/api/admin/dashboard/analytics?days=7; DROP TABLE events; --') .set('Authorization', `Bearer ${adminToken}`) .expect(200); // Should default to 7 days if (res.body.chartData.length !== 7) { throw new Error('Days parameter not properly sanitized'); } }); // Test Event search with normal text (uses escapeLikePattern) await testRoute('Event search with normal text', async () => { const res = await request(app) .get('/api/admin/events?search=test') .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!res.body.hasOwnProperty('events')) { throw new Error('Missing events in response'); } }); // Test Event search with special characters await testRoute('Event search with special characters', async () => { const res = await request(app) .get('/api/admin/events?search=50%_test') .set('Authorization', `Bearer ${adminToken}`) .expect(200); // Should handle special chars safely if (!res.body.hasOwnProperty('events')) { throw new Error('Failed to handle special characters'); } }); // Test Event search with SQL injection attempt await testRoute('Event search prevents SQL injection', async () => { const res = await request(app) .get("/api/admin/events?search=' OR 1=1 --") .set('Authorization', `Bearer ${adminToken}`) .expect(200); // Should return empty results, not all events if (!res.body.hasOwnProperty('events')) { throw new Error('SQL injection may not be prevented'); } }); // Test Photo search (if event exists) await testRoute('Photo search functionality', async () => { // First check if we have any events const event = await db('events').first(); if (event) { const res = await request(app) .get(`/api/admin/events/${event.id}/photos?search=test`) .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!res.body.hasOwnProperty('photos')) { throw new Error('Missing photos in response'); } } }); // Test Activity endpoint await testRoute('Activity log endpoint', async () => { const res = await request(app) .get('/api/admin/dashboard/activity?limit=10') .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!Array.isArray(res.body)) { throw new Error('Activity should return array'); } }); // Test Health endpoint await testRoute('Health check endpoint', async () => { const res = await request(app) .get('/api/admin/dashboard/health') .set('Authorization', `Bearer ${adminToken}`) .expect(200); if (!res.body.hasOwnProperty('overall')) { throw new Error('Missing overall health status'); } }); // Summary console.log('\n=== Test Summary ==='); console.log(`Total tests: ${passed + failed}`); console.log(`Passed: ${passed}`); console.log(`Failed: ${failed}`); if (failed === 0) { console.log('\nāœ… All route tests passed! Safe to deploy.'); process.exit(0); } else { console.log('\nāŒ Some tests failed. Review the fixes before deploying.'); process.exit(1); } } // Run tests runTests().catch(error => { console.error('Test runner error:', error); process.exit(1); });