Files
picpeak/backend/src/utils/passwordGenerator.js
T
paulandClaude 1773ed5f95
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m28s
Version and Release / version-bump (push) Successful in 32s
Version and Release / trigger-drone (push) Has been skipped
Initial commit - Project start (July 17, 2025)
Original: feat: enhance security logging and ensure rate limit blocks are properly tracked

- Add comprehensive logging for rate limit blocks with full request details
  - IP address (with proper proxy detection), user agent, headers, timestamps
  - Rate limit info (current count, limit, remaining, reset time)
  - Separate tracking for auth vs general endpoints

- Enhance authentication failure logging
  - JWT validation failures with detailed error info
  - Admin auth attempts without token
  - Failed token validation with user context
  - All events include IP, path, method, user agent

- Improve Winston logger configuration for production
  - Add automatic log rotation (10MB errors, 50MB combined)
  - Create separate security.log for auth/rate limit events
  - Ensure logs directory exists automatically
  - Add structured JSON format for log aggregation
  - Support container logging with LOG_TO_CONSOLE env var

- Create comprehensive documentation
  - Security logging guide with examples
  - Monitoring recommendations
  - Configuration reference

- Add test script to verify logging functionality

All rate limit settings remain configurable via admin panel:
- Window duration, max requests, auth limits
- Skip authenticated requests option
- Public endpoints only option

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

Co-Authored-By: Claude <[email protected]>
2025-07-24 16:57:07 +02:00

122 lines
3.4 KiB
JavaScript

const crypto = require('crypto');
/**
* Generate a secure random password
* @param {number} length - Password length (default: 16)
* @returns {string} Generated password
*/
function generateSecurePassword(length = 16) {
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
let password = '';
// Ensure at least one of each required character type
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
const special = '!@#$%^&*()_+-=[]{}|;:,.<>?';
// Add one of each required type
password += lowercase[crypto.randomInt(lowercase.length)];
password += uppercase[crypto.randomInt(uppercase.length)];
password += numbers[crypto.randomInt(numbers.length)];
password += special[crypto.randomInt(special.length)];
// Fill the rest randomly
for (let i = password.length; i < length; i++) {
password += charset[crypto.randomInt(charset.length)];
}
// Shuffle the password
return password.split('').sort(() => crypto.randomInt(3) - 1).join('');
}
/**
* Generate a human-readable password using words and numbers
* @returns {string} Generated password
*/
function generateReadablePassword() {
const adjectives = [
'Swift', 'Bright', 'Strong', 'Happy', 'Clever',
'Brave', 'Noble', 'Quick', 'Sharp', 'Bold'
];
const nouns = [
'Eagle', 'Mountain', 'River', 'Thunder', 'Forest',
'Ocean', 'Falcon', 'Dragon', 'Phoenix', 'Tiger'
];
const adjective = adjectives[crypto.randomInt(adjectives.length)];
const noun = nouns[crypto.randomInt(nouns.length)];
const number = crypto.randomInt(1000, 9999);
const special = '!@#$%'[crypto.randomInt(5)];
return `${adjective}${noun}${number}${special}`;
}
/**
* Validate password strength
* @param {string} password - Password to validate
* @returns {object} Validation result with score and messages
*/
function validatePasswordStrength(password) {
const result = {
score: 0,
messages: [],
isValid: false
};
// Length check
if (password.length < 8) {
result.messages.push('Password must be at least 8 characters long');
} else if (password.length < 12) {
result.score += 1;
} else {
result.score += 2;
}
// Character type checks
if (!/[a-z]/.test(password)) {
result.messages.push('Password must contain lowercase letters');
} else {
result.score += 1;
}
if (!/[A-Z]/.test(password)) {
result.messages.push('Password must contain uppercase letters');
} else {
result.score += 1;
}
if (!/[0-9]/.test(password)) {
result.messages.push('Password must contain numbers');
} else {
result.score += 1;
}
if (!/[!@#$%^&*()_+\-=\[\]{}|;:,.<>?]/.test(password)) {
result.messages.push('Password must contain special characters');
} else {
result.score += 1;
}
// Common password check
const commonPasswords = [
'password', 'admin123', '12345678', 'qwerty', 'abc123',
'password123', 'admin', 'letmein', 'welcome', 'monkey'
];
if (commonPasswords.includes(password.toLowerCase())) {
result.score = 0;
result.messages.push('Password is too common');
}
result.isValid = result.score >= 4 && result.messages.length === 0;
return result;
}
module.exports = {
generateSecurePassword,
generateReadablePassword,
validatePasswordStrength
};