f38014099e
Test and Lint / backend-test (push) Successful in 1m12s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m16s
Version and Release / version-bump (push) Successful in 35s
Version and Release / trigger-drone (push) Successful in 3s
146 lines
4.5 KiB
JavaScript
146 lines
4.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Test Authentication V2 Security Fixes
|
|
*/
|
|
|
|
console.log('=== Testing Authentication V2 Fixes ===\n');
|
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
function test(description, fn) {
|
|
try {
|
|
const result = fn();
|
|
if (result || result === undefined) {
|
|
console.log(`✅ ${description}`);
|
|
passed++;
|
|
} else {
|
|
console.log(`❌ ${description}`);
|
|
failed++;
|
|
}
|
|
} catch (error) {
|
|
console.log(`❌ ${description} - Error: ${error.message}`);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
async function runTests() {
|
|
// Test 1: Rate Limiting Security
|
|
console.log('1. Testing Rate Limiting Security:');
|
|
const { hasValidAdminToken } = require('../src/utils/rateLimitSecurity');
|
|
|
|
// Mock requests
|
|
const validAdminReq = {
|
|
path: '/api/admin/events',
|
|
headers: {
|
|
authorization: 'Bearer ' + jwt.sign({ id: 1, type: 'admin' }, process.env.JWT_SECRET || 'test')
|
|
},
|
|
ip: '127.0.0.1'
|
|
};
|
|
|
|
const invalidTokenReq = {
|
|
path: '/api/admin/events',
|
|
headers: {
|
|
authorization: 'Bearer invalid.token.here'
|
|
},
|
|
ip: '127.0.0.1'
|
|
};
|
|
|
|
const galleryTokenReq = {
|
|
path: '/api/admin/events',
|
|
headers: {
|
|
authorization: 'Bearer ' + jwt.sign({ id: 1, type: 'gallery' }, process.env.JWT_SECRET || 'test')
|
|
},
|
|
ip: '127.0.0.1'
|
|
};
|
|
|
|
test('Valid admin token skips rate limit', () => hasValidAdminToken(validAdminReq) === true);
|
|
test('Invalid token applies rate limit', () => hasValidAdminToken(invalidTokenReq) === false);
|
|
test('Gallery token cannot bypass admin rate limit', () => hasValidAdminToken(galleryTokenReq) === false);
|
|
|
|
// Test 2: Password Validation
|
|
console.log('\n2. Testing Password Validation:');
|
|
const { validatePassword, validatePasswordInContext } = require('../src/utils/passwordValidation');
|
|
|
|
const weakPassword = validatePassword('weak123');
|
|
test('Weak password is rejected', () => !weakPassword.valid);
|
|
test('Weak password has errors', () => weakPassword.errors.length > 0);
|
|
|
|
const strongPassword = validatePassword('Str0ng!P@ssw0rd123');
|
|
test('Strong password is accepted', () => strongPassword.valid);
|
|
test('Strong password has good score', () => strongPassword.score >= 3);
|
|
|
|
const shortPassword = validatePassword('Short!1');
|
|
test('Short password is rejected', () => !shortPassword.valid &&
|
|
shortPassword.errors.some(e => e.includes('12 characters')));
|
|
|
|
const noSpecialChar = validatePassword('NoSpecialChar123');
|
|
test('Password without special char is rejected', () => !noSpecialChar.valid &&
|
|
noSpecialChar.errors.some(e => e.includes('special character')));
|
|
|
|
// Context validation
|
|
const adminContext = validatePasswordInContext('Admin123!Pass', 'admin', { username: 'admin' });
|
|
test('Admin password with username is rejected', () => !adminContext.valid);
|
|
|
|
const galleryContext = validatePasswordInContext('Event123!Pass', 'gallery', { eventName: 'event' });
|
|
test('Gallery password with event name is rejected', () => !galleryContext.valid);
|
|
|
|
// Test 3: Token Revocation
|
|
console.log('\n3. Testing Token Revocation:');
|
|
const { isTokenRevoked } = require('../src/utils/tokenRevocation');
|
|
|
|
const testToken = {
|
|
jti: 'test-123',
|
|
id: 1,
|
|
type: 'admin',
|
|
iat: Math.floor(Date.now() / 1000)
|
|
};
|
|
|
|
// This would need database setup to fully test
|
|
test('Token revocation check runs', async () => {
|
|
try {
|
|
await isTokenRevoked(testToken);
|
|
return true;
|
|
} catch (e) {
|
|
// Expected if tables don't exist yet
|
|
return true;
|
|
}
|
|
});
|
|
|
|
// Test 4: Bcrypt Rounds
|
|
console.log('\n4. Testing Configurable Bcrypt:');
|
|
const { getBcryptRounds, PASSWORD_CONFIG } = require('../src/utils/passwordValidation');
|
|
|
|
test('Bcrypt rounds are configurable', () => {
|
|
const rounds = getBcryptRounds();
|
|
return rounds >= 10 && rounds <= 14;
|
|
});
|
|
|
|
test('Default bcrypt rounds is 12', () => {
|
|
return PASSWORD_CONFIG.bcryptRounds === 12 ||
|
|
PASSWORD_CONFIG.bcryptRounds === parseInt(process.env.BCRYPT_ROUNDS);
|
|
});
|
|
|
|
// 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 authentication V2 tests passed!');
|
|
process.exit(0);
|
|
} else {
|
|
console.log('\n❌ Some tests failed. Review the implementation.');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Run tests
|
|
runTests().catch(error => {
|
|
console.error('Test error:', error);
|
|
process.exit(1);
|
|
}); |