Release 2.8.0
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m49s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 32s

This commit is contained in:
2026-08-16 17:15:31 +01:00
parent 1bdc122995
commit 203d0bfc01
105 changed files with 4185 additions and 677 deletions
+37 -3
View File
@@ -7,21 +7,55 @@ const PASSWORD_KEY_LENGTH = 32;
const PASSWORD_DIGEST = 'sha256';
const SESSION_BYTES = 32;
function validatePasswordStrength(password) {
function validatePasswordStrength(password, options) {
const value = String(password || '');
const requirements = options && options.policy
? getPasswordPolicyPreset(options.policy)
: {
minimumLength: Number(options && options.minimumLength) || 10,
minimumCategories: Number(options && options.minimumCategories) || 3,
requireLowercase: Boolean(options && options.requireLowercase),
requireUppercase: Boolean(options && options.requireUppercase),
requireNumber: Boolean(options && options.requireNumber),
requireSymbol: Boolean(options && options.requireSymbol)
};
const hasLowercase = /[a-z]/.test(value);
const hasUppercase = /[A-Z]/.test(value);
const hasNumber = /[0-9]/.test(value);
const hasSymbol = /[^A-Za-z0-9]/.test(value);
const categoryCount = [hasLowercase, hasUppercase, hasNumber, hasSymbol].filter(Boolean).length;
if (value.length < 10 || categoryCount < 3) {
return 'Password must be at least 10 characters and include 3 of: uppercase, lowercase, number, and symbol.';
const missingRequiredCategory = requirements.requireLowercase && !hasLowercase
|| requirements.requireUppercase && !hasUppercase
|| requirements.requireNumber && !hasNumber
|| requirements.requireSymbol && !hasSymbol;
if (value.length < requirements.minimumLength || categoryCount < requirements.minimumCategories || missingRequiredCategory) {
if (missingRequiredCategory) {
const requiredCategories = [];
if (requirements.requireLowercase) requiredCategories.push('lowercase');
if (requirements.requireUppercase) requiredCategories.push('uppercase');
if (requirements.requireNumber) requiredCategories.push('number');
if (requirements.requireSymbol) requiredCategories.push('symbol');
return `Password must be at least ${requirements.minimumLength} characters and include ${requiredCategories.join(', ')}.`;
}
if (requirements.minimumCategories === 4) {
return `Password must be at least ${requirements.minimumLength} characters and include uppercase, lowercase, number, and symbol.`;
}
return `Password must be at least ${requirements.minimumLength} characters and include ${requirements.minimumCategories} of: uppercase, lowercase, number, and symbol.`;
}
return '';
}
function getPasswordPolicyPreset(policy) {
const normalizedPolicy = String(policy || 'standard').trim().toLowerCase();
return normalizedPolicy === 'strict'
? { minimumLength: 14, minimumCategories: 4 }
: normalizedPolicy === 'strong'
? { minimumLength: 12, minimumCategories: 3 }
: { minimumLength: 10, minimumCategories: 3 };
}
function hashPassword(password, salt) {
const safePassword = String(password || '');
const safeSalt = salt || crypto.randomBytes(16).toString('hex');