attempts to have better validation during deploy from template

This commit is contained in:
Raven Scott
2025-11-24 18:26:13 -05:00
parent 4fb97242e8
commit 6c8ad3e9a0
4 changed files with 761 additions and 35 deletions
+112 -1
View File
@@ -219,6 +219,111 @@ function validateNumber(value, min = -Infinity, max = Infinity) {
return num;
}
/**
* Validates URL format
* @param {string} url - URL string
* @returns {boolean} - True if valid URL
*/
function isValidUrl(url) {
if (!url || typeof url !== 'string') return false;
try {
const urlObj = new URL(url);
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
} catch {
return false;
}
}
/**
* Validates email format
* @param {string} email - Email string
* @returns {boolean} - True if valid email
*/
function isValidEmail(email) {
if (!email || typeof email !== 'string') return false;
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailPattern.test(email);
}
/**
* Validates IP address (IPv4 or IPv6)
* @param {string} ip - IP address string
* @returns {boolean} - True if valid IP
*/
function isValidIpAddress(ip) {
if (!ip || typeof ip !== 'string') return false;
// IPv4
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
if (ipv4Pattern.test(ip)) {
const parts = ip.split('.');
return parts.every(part => {
const num = parseInt(part, 10);
return num >= 0 && num <= 255;
});
}
// IPv6 (simplified)
const ipv6Pattern = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
return ipv6Pattern.test(ip);
}
/**
* Validates that a value is in a list of allowed options
* @param {any} value - Value to validate
* @param {Array} options - Array of allowed options
* @returns {boolean} - True if value is in options
*/
function isValidSelectOption(value, options) {
if (!options || !Array.isArray(options)) return true; // If no options specified, allow any value
// Handle both simple arrays and object arrays with value property
const optionValues = options.map(opt => {
if (typeof opt === 'object' && opt.value !== undefined) {
return String(opt.value);
}
return String(opt);
});
return optionValues.includes(String(value));
}
/**
* Validates that preset values haven't been modified
* @param {Object} envVar - Environment variable object with name, value, and preset flag
* @param {Object} templateEnv - Template environment variable definition
* @returns {boolean} - True if preset value is unchanged or not preset
*/
function isValidPresetValue(envVar, templateEnv) {
if (!templateEnv || templateEnv.preset !== true) return true; // Not a preset, allow changes
if (!envVar.preset) return false; // Preset value was marked as non-preset
const expectedValue = templateEnv.default || templateEnv.set || '';
return String(envVar.value) === String(expectedValue);
}
/**
* Validates numeric range
* @param {any} value - Value to validate
* @param {number} min - Minimum value (optional)
* @param {number} max - Maximum value (optional)
* @returns {boolean} - True if value is within range
*/
function isValidNumericRange(value, min, max) {
if (value === null || value === undefined || value === '') return true; // Empty is valid (handled by required check)
const num = typeof value === 'number' ? value : parseFloat(value);
if (isNaN(num)) return false;
if (min !== undefined && num < min) return false;
if (max !== undefined && num > max) return false;
return true;
}
export {
isValidImageName,
isValidContainerName,
@@ -231,7 +336,13 @@ export {
isValidHostname,
isValidDnsServer,
sanitizeString,
validateNumber
validateNumber,
isValidUrl,
isValidEmail,
isValidIpAddress,
isValidSelectOption,
isValidPresetValue,
isValidNumericRange
};