upskill-event-manager/test-security-authentication.js
Ben c3e7fe9140 feat: comprehensive HVAC plugin development framework and modernization
## Major Enhancements

### 🏗️ Architecture & Infrastructure
- Implement comprehensive Docker testing infrastructure with hermetic environment
- Add Forgejo Actions CI/CD pipeline for automated deployments
- Create Page Object Model (POM) testing architecture reducing test duplication by 90%
- Establish security-first development patterns with input validation and output escaping

### 🧪 Testing Framework Modernization
- Migrate 146+ tests from 80 duplicate files to centralized architecture
- Add comprehensive E2E test suites for all user roles and workflows
- Implement WordPress error detection with automatic site health monitoring
- Create robust browser lifecycle management with proper cleanup

### 📚 Documentation & Guides
- Add comprehensive development best practices guide
- Create detailed administrator setup documentation
- Establish user guides for trainers and master trainers
- Document security incident reports and migration guides

### 🔧 Core Plugin Features
- Enhance trainer profile management with certification system
- Improve find trainer functionality with advanced filtering
- Strengthen master trainer area with content management
- Add comprehensive venue and organizer management

### 🛡️ Security & Reliability
- Implement security-first patterns throughout codebase
- Add comprehensive input validation and output escaping
- Create secure credential management system
- Establish proper WordPress role-based access control

### 🎯 WordPress Integration
- Strengthen singleton pattern implementation across all classes
- Enhance template hierarchy with proper WordPress integration
- Improve page manager with hierarchical URL structure
- Add comprehensive shortcode and menu system

### 🔍 Developer Experience
- Add extensive debugging and troubleshooting tools
- Create comprehensive test data seeding scripts
- Implement proper error handling and logging
- Establish consistent code patterns and standards

### 📊 Performance & Optimization
- Optimize database queries and caching strategies
- Improve asset loading and script management
- Enhance template rendering performance
- Streamline user experience across all interfaces

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 11:26:10 -03:00

259 lines
No EOL
9.4 KiB
JavaScript

#!/usr/bin/env node
/**
* SECURITY & AUTHENTICATION VALIDATION TEST
*
* Tests that claimed pages properly redirect for authentication
* and that security fixes are working correctly.
*/
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
const BASE_URL = 'https://upskill-staging.measurequick.com';
const SCREENSHOTS_DIR = path.join(__dirname, 'security-test-evidence');
// URLs to test for proper authentication redirects
const PROTECTED_URLS = [
'/trainer/venue/list/',
'/trainer/venue/manage/',
'/trainer/organizer/manage/',
'/trainer/profile/training-leads/',
'/master-trainer/google-sheets/',
'/master-trainer/announcements/',
'/master-trainer/pending-approvals/',
'/master-trainer/trainers/'
];
class SecurityValidator {
constructor() {
this.browser = null;
this.page = null;
this.results = {
authenticationTests: [],
securityTests: [],
overall: { passed: 0, failed: 0 }
};
}
async init() {
if (!fs.existsSync(SCREENSHOTS_DIR)) {
fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
}
this.browser = await chromium.launch({
headless: true,
args: ['--no-sandbox', '--disable-dev-shm-usage']
});
this.page = await this.browser.newPage();
await this.page.setViewportSize({ width: 1920, height: 1080 });
}
async takeScreenshot(name) {
const filename = `${name}-${Date.now()}.png`;
const filepath = path.join(SCREENSHOTS_DIR, filename);
await this.page.screenshot({ path: filepath, fullPage: true });
console.log(`📸 Screenshot: ${filename}`);
return filename;
}
async testAuthenticationRedirect(url) {
console.log(`\n🔐 Testing Authentication for: ${url}`);
const result = {
url,
redirectsToLogin: false,
properRedirectUrl: null,
errors: [],
screenshot: null
};
try {
const response = await this.page.goto(`${BASE_URL}${url}`, {
waitUntil: 'networkidle',
timeout: 15000
});
const finalUrl = this.page.url();
result.screenshot = await this.takeScreenshot(`auth-test-${url.replace(/[^a-z0-9]/gi, '-')}`);
// Check if redirected to login page
if (finalUrl.includes('training-login') || finalUrl.includes('wp-login')) {
result.redirectsToLogin = true;
result.properRedirectUrl = finalUrl;
console.log(` ✅ PASS: Properly redirects to login`);
console.log(` 📍 Redirect URL: ${finalUrl}`);
this.results.overall.passed++;
} else if (response.status() === 200 && !finalUrl.includes('login')) {
// This would be a security issue - page accessible without auth
result.redirectsToLogin = false;
result.errors.push('Page accessible without authentication - SECURITY ISSUE');
console.log(` ❌ FAIL: Page accessible without login - SECURITY RISK`);
this.results.overall.failed++;
} else {
result.errors.push(`Unexpected response: ${response.status()}`);
console.log(` ⚠️ Unexpected response: ${response.status()}`);
this.results.overall.failed++;
}
} catch (error) {
result.errors.push(`Test error: ${error.message}`);
console.log(` 💥 ERROR: ${error.message}`);
this.results.overall.failed++;
}
return result;
}
async testAjaxSecurity() {
console.log(`\n🔒 Testing AJAX Endpoint Security`);
const ajaxEndpoints = [
'/wp-admin/admin-ajax.php?action=hvac_get_trainer_stats',
'/wp-admin/admin-ajax.php?action=hvac_manage_announcement',
'/wp-admin/admin-ajax.php?action=hvac_approve_trainer'
];
const securityResults = [];
for (const endpoint of ajaxEndpoints) {
console.log(` 🧪 Testing: ${endpoint}`);
const result = {
endpoint,
secure: false,
statusCode: null,
response: null,
errors: []
};
try {
const response = await this.page.goto(`${BASE_URL}${endpoint}`, {
waitUntil: 'networkidle',
timeout: 10000
});
result.statusCode = response.status();
const responseText = await this.page.textContent('body');
result.response = responseText ? responseText.substring(0, 200) : 'No response';
// AJAX endpoints should return proper error codes or auth required
if (response.status() === 403) {
result.secure = true;
console.log(` ✅ Returns 403 Forbidden - Properly secured`);
} else if (response.status() === 401) {
result.secure = true;
console.log(` ✅ Returns 401 Unauthorized - Properly secured`);
} else if (response.status() === 400 && responseText.includes('Bad Request')) {
result.secure = true; // Bad request is fine - at least not accessible
console.log(` ✅ Returns 400 Bad Request - Endpoint protected`);
} else if (responseText && (responseText.includes('-1') || responseText.trim() === '0')) {
result.secure = true; // WordPress AJAX returns -1 or 0 for unauthorized
console.log(` ✅ Returns ${responseText.trim()} (WordPress auth failure) - Secured`);
} else {
result.secure = false;
result.errors.push(`Potentially insecure: ${response.status()} - ${responseText.substring(0, 100)}`);
console.log(` ❌ May not be properly secured: ${response.status()}`);
}
} catch (error) {
result.errors.push(`AJAX test error: ${error.message}`);
console.log(` 💥 Error testing endpoint: ${error.message}`);
}
securityResults.push(result);
}
return securityResults;
}
async runSecurityTests() {
console.log('🔒 SECURITY & AUTHENTICATION VALIDATION');
console.log('=' * 45);
// Test authentication redirects
console.log('\n📋 TESTING AUTHENTICATION REDIRECTS');
console.log('-' * 35);
for (const url of PROTECTED_URLS) {
const result = await this.testAuthenticationRedirect(url);
this.results.authenticationTests.push(result);
}
// Test AJAX security
console.log('\n🔒 TESTING AJAX ENDPOINT SECURITY');
console.log('-' * 32);
this.results.securityTests = await this.testAjaxSecurity();
await this.generateSecurityReport();
}
async generateSecurityReport() {
console.log('\n📊 SECURITY VALIDATION REPORT');
console.log('=' * 30);
const totalTests = this.results.authenticationTests.length + this.results.securityTests.length;
const successRate = totalTests > 0 ? ((this.results.overall.passed / totalTests) * 100).toFixed(1) : 0;
console.log(`\n🎯 SUMMARY`);
console.log(`Total Tests: ${totalTests}`);
console.log(`Passed: ${this.results.overall.passed}`);
console.log(`Failed: ${this.results.overall.failed}`);
console.log(`Success Rate: ${successRate}%`);
console.log(`\n🔐 AUTHENTICATION RESULTS:`);
this.results.authenticationTests.forEach(test => {
const status = test.redirectsToLogin ? '✅ SECURED' : '❌ VULNERABLE';
console.log(` ${status} ${test.url}`);
if (test.errors.length > 0) {
test.errors.forEach(error => console.log(` ⚠️ ${error}`));
}
});
console.log(`\n🔒 AJAX SECURITY RESULTS:`);
this.results.securityTests.forEach(test => {
const status = test.secure ? '✅ SECURE' : '❌ INSECURE';
console.log(` ${status} ${test.endpoint} (${test.statusCode})`);
if (test.errors.length > 0) {
test.errors.forEach(error => console.log(` ⚠️ ${error}`));
}
});
// Save detailed report
const reportPath = path.join(__dirname, 'security-validation-report.json');
fs.writeFileSync(reportPath, JSON.stringify(this.results, null, 2));
console.log(`\n📄 Detailed report: ${reportPath}`);
console.log(`📸 Evidence: ${SCREENSHOTS_DIR}`);
return this.results;
}
async cleanup() {
if (this.browser) {
await this.browser.close();
}
}
}
async function main() {
const validator = new SecurityValidator();
try {
await validator.init();
await validator.runSecurityTests();
} catch (error) {
console.error('💥 Security test failed:', error);
process.exit(1);
} finally {
await validator.cleanup();
}
}
if (require.main === module) {
main().catch(console.error);
}
module.exports = { SecurityValidator };