@ufdevsllc/auth-me
Version:
Comprehensive licensing, security monitoring, and data mirroring package with hardcoded vendor-controlled database connection
437 lines (383 loc) âĸ 13.2 kB
JavaScript
/**
* Configuration validation script for @ufdevsllc/auth-me package
* Validates package configuration and provides detailed error messages
*/
const fs = require('fs');
const path = require('path');
/**
* Configuration validation rules
*/
const VALIDATION_RULES = {
required: {
licenseKey: {
type: 'string',
minLength: 16,
pattern: /^[A-Za-z0-9\-_]+$/,
message: 'License key must be at least 16 characters and contain only alphanumeric characters, hyphens, and underscores'
},
vendorEndpoint: {
type: 'string',
pattern: /^https?:\/\/.+/,
message: 'Vendor endpoint must be a valid HTTP/HTTPS URL'
},
schemas: {
type: 'array',
minLength: 1,
message: 'At least one schema must be provided'
}
},
optional: {
'options.enableEnvironmentBinding': {
type: 'boolean',
message: 'enableEnvironmentBinding must be a boolean value'
},
'options.enableTamperDetection': {
type: 'boolean',
message: 'enableTamperDetection must be a boolean value'
},
'options.enableUsageTracking': {
type: 'boolean',
message: 'enableUsageTracking must be a boolean value'
},
'options.crashOnViolation': {
type: 'boolean',
message: 'crashOnViolation must be a boolean value'
},
'options.verboseLogging': {
type: 'boolean',
message: 'verboseLogging must be a boolean value'
}
}
};
/**
* Environment-specific validation rules
*/
const ENVIRONMENT_RULES = {
production: {
required: ['licenseKey', 'vendorEndpoint'],
warnings: [
{
condition: (config) => config.options?.verboseLogging === true,
message: 'Verbose logging is enabled in production mode - this may impact performance'
},
{
condition: (config) => config.options?.crashOnViolation === false,
message: 'crashOnViolation is disabled in production mode - security violations may not be properly handled'
}
],
errors: [
{
condition: (config) => !config.licenseKey,
message: 'License key is required in production mode'
},
{
condition: (config) => !config.vendorEndpoint,
message: 'Vendor endpoint is required in production mode'
}
]
},
development: {
required: [],
warnings: [
{
condition: (config) => config.options?.enableTamperDetection === true,
message: 'Tamper detection is enabled in development mode - this may cause issues during development'
},
{
condition: (config) => config.options?.enableEnvironmentBinding === true,
message: 'Environment binding is enabled in development mode - this may prevent testing on different machines'
}
],
errors: []
},
test: {
required: [],
warnings: [
{
condition: (config) => config.options?.enableUsageTracking === true,
message: 'Usage tracking is enabled in test mode - this may interfere with test isolation'
}
],
errors: []
}
};
/**
* Validate configuration object
* @param {Object} config - Configuration to validate
* @param {string} environment - Environment mode
* @returns {Object} Validation result
*/
function validateConfiguration(config, environment = 'production') {
const result = {
valid: true,
errors: [],
warnings: [],
info: []
};
// Basic type validation
if (!config || typeof config !== 'object') {
result.valid = false;
result.errors.push('Configuration must be an object');
return result;
}
// Validate required fields
for (const [field, rules] of Object.entries(VALIDATION_RULES.required)) {
const value = getNestedValue(config, field);
const validation = validateField(field, value, rules);
if (!validation.valid) {
result.valid = false;
result.errors.push(...validation.errors);
}
}
// Validate optional fields
for (const [field, rules] of Object.entries(VALIDATION_RULES.optional)) {
const value = getNestedValue(config, field);
if (value !== undefined) {
const validation = validateField(field, value, rules);
if (!validation.valid) {
result.valid = false;
result.errors.push(...validation.errors);
}
}
}
// Environment-specific validation
if (ENVIRONMENT_RULES[environment]) {
const envRules = ENVIRONMENT_RULES[environment];
// Check environment-specific required fields
for (const field of envRules.required) {
const value = getNestedValue(config, field);
if (!value) {
result.valid = false;
result.errors.push(`${field} is required in ${environment} mode`);
}
}
// Check environment-specific warnings
for (const warning of envRules.warnings) {
if (warning.condition(config)) {
result.warnings.push(warning.message);
}
}
// Check environment-specific errors
for (const error of envRules.errors) {
if (error.condition(config)) {
result.valid = false;
result.errors.push(error.message);
}
}
}
// Schema-specific validation
if (config.schemas && Array.isArray(config.schemas)) {
const schemaValidation = validateSchemas(config.schemas);
if (!schemaValidation.valid) {
result.valid = false;
result.errors.push(...schemaValidation.errors);
}
result.warnings.push(...schemaValidation.warnings);
}
// Add informational messages
result.info.push(`Configuration validated for ${environment} environment`);
result.info.push(`Found ${config.schemas ? config.schemas.length : 0} schemas to register`);
return result;
}
/**
* Validate individual field
* @param {string} fieldName - Name of the field
* @param {any} value - Value to validate
* @param {Object} rules - Validation rules
* @returns {Object} Validation result
*/
function validateField(fieldName, value, rules) {
const result = {
valid: true,
errors: []
};
// Type validation
if (rules.type) {
const actualType = Array.isArray(value) ? 'array' : typeof value;
if (actualType !== rules.type) {
result.valid = false;
result.errors.push(`${fieldName} must be of type ${rules.type}, got ${actualType}`);
return result;
}
}
// String validations
if (rules.type === 'string' && typeof value === 'string') {
if (rules.minLength && value.length < rules.minLength) {
result.valid = false;
result.errors.push(`${fieldName} must be at least ${rules.minLength} characters long`);
}
if (rules.maxLength && value.length > rules.maxLength) {
result.valid = false;
result.errors.push(`${fieldName} must be no more than ${rules.maxLength} characters long`);
}
if (rules.pattern && !rules.pattern.test(value)) {
result.valid = false;
result.errors.push(rules.message || `${fieldName} format is invalid`);
}
}
// Array validations
if (rules.type === 'array' && Array.isArray(value)) {
if (rules.minLength && value.length < rules.minLength) {
result.valid = false;
result.errors.push(`${fieldName} must contain at least ${rules.minLength} items`);
}
if (rules.maxLength && value.length > rules.maxLength) {
result.valid = false;
result.errors.push(`${fieldName} must contain no more than ${rules.maxLength} items`);
}
}
return result;
}
/**
* Validate schemas array
* @param {Array} schemas - Schemas to validate
* @returns {Object} Validation result
*/
function validateSchemas(schemas) {
const result = {
valid: true,
errors: [],
warnings: []
};
for (let i = 0; i < schemas.length; i++) {
const schema = schemas[i];
if (!schema || typeof schema !== 'object') {
result.valid = false;
result.errors.push(`Schema at index ${i} must be an object`);
continue;
}
// Check for required schema properties
if (!schema.name || typeof schema.name !== 'string') {
result.valid = false;
result.errors.push(`Schema at index ${i} must have a valid name property`);
}
if (!schema.schema) {
result.valid = false;
result.errors.push(`Schema at index ${i} must have a schema property`);
}
// Check for duplicate schema names
const duplicates = schemas.filter((s, idx) => idx !== i && s.name === schema.name);
if (duplicates.length > 0) {
result.valid = false;
result.errors.push(`Duplicate schema name found: ${schema.name}`);
}
// Warnings for schema best practices
if (schema.name && schema.name.length < 3) {
result.warnings.push(`Schema name '${schema.name}' is very short - consider using a more descriptive name`);
}
}
return result;
}
/**
* Get nested object value by dot notation
* @param {Object} obj - Object to search
* @param {string} path - Dot notation path
* @returns {any} Value at path
*/
function getNestedValue(obj, path) {
return path.split('.').reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : undefined;
}, obj);
}
/**
* Format validation results for display
* @param {Object} result - Validation result
* @returns {string} Formatted output
*/
function formatValidationResult(result) {
let output = '';
if (result.valid) {
output += 'â
Configuration validation passed\n\n';
} else {
output += 'â Configuration validation failed\n\n';
}
if (result.errors.length > 0) {
output += 'đ¨ Errors:\n';
result.errors.forEach(error => {
output += ` âĸ ${error}\n`;
});
output += '\n';
}
if (result.warnings.length > 0) {
output += 'â ī¸ Warnings:\n';
result.warnings.forEach(warning => {
output += ` âĸ ${warning}\n`;
});
output += '\n';
}
if (result.info.length > 0) {
output += 'âšī¸ Information:\n';
result.info.forEach(info => {
output += ` âĸ ${info}\n`;
});
output += '\n';
}
return output;
}
/**
* Load and validate configuration from file
* @param {string} configPath - Path to configuration file
* @returns {Object} Validation result
*/
function validateConfigFile(configPath) {
try {
if (!fs.existsSync(configPath)) {
return {
valid: false,
errors: [`Configuration file not found: ${configPath}`],
warnings: [],
info: []
};
}
const configContent = fs.readFileSync(configPath, 'utf8');
let config;
try {
config = JSON.parse(configContent);
} catch (parseError) {
return {
valid: false,
errors: [`Invalid JSON in configuration file: ${parseError.message}`],
warnings: [],
info: []
};
}
const environment = process.env.NODE_ENV || 'production';
return validateConfiguration(config, environment);
} catch (error) {
return {
valid: false,
errors: [`Error reading configuration file: ${error.message}`],
warnings: [],
info: []
};
}
}
/**
* Main validation function
*/
function main() {
console.log('đ @ufdevsllc/auth-me Configuration Validator\n');
const configPath = process.argv[2] || path.join(process.cwd(), 'secure-guard-config.json');
const environment = process.env.NODE_ENV || 'production';
console.log(`Environment: ${environment}`);
console.log(`Config file: ${configPath}\n`);
const result = validateConfigFile(configPath);
const output = formatValidationResult(result);
console.log(output);
// Exit with appropriate code
process.exit(result.valid ? 0 : 1);
}
// Export for use as module
module.exports = {
validateConfiguration,
validateField,
validateSchemas,
formatValidationResult,
VALIDATION_RULES,
ENVIRONMENT_RULES
};
// Run if called directly
if (require.main === module) {
main();
}