securesharkinputs
Version:
Advanced enterprise validation library with multi-layer security protection for SecureShark
410 lines (346 loc) • 13.8 kB
JavaScript
/**
* Script de verificación de conexión real
* Verifica que los inputs específicos del proyecto están protegidos
*
* Nuevas características incluidas:
* - Detección de react-hook-form usage
* - Verificación de plantillas instaladas
* - Análisis de ValidationShark con nuevas props
*
* Uso: node node_modules/securesharkinputs/scripts/test-connection.js
*/
const fs = require('fs');
const path = require('path');
console.log('🦈 SecureSharkInputs - Verificación de Conexión Real v1.4.0');
console.log('===========================================================\n');
// Colores para la consola
const colors = {
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
bold: '\x1b[1m'
};
const log = {
success: (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`),
error: (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`),
warning: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
title: (msg) => console.log(`\n${colors.bold}${msg}${colors.reset}`)
};
// Función para buscar archivos React/JSX en el proyecto
function findReactFiles() {
const extensions = ['.jsx', '.tsx', '.js', '.ts'];
const reactFiles = [];
function scanDirectory(dir) {
try {
const items = fs.readdirSync(dir);
for (const item of items) {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
scanDirectory(fullPath);
} else if (stat.isFile()) {
const ext = path.extname(item);
if (extensions.includes(ext)) {
reactFiles.push(fullPath);
}
}
}
} catch (error) {
// Ignorar errores de permisos
}
}
scanDirectory(process.cwd());
return reactFiles;
}
// Función para analizar un archivo y buscar inputs
function analyzeFile(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
const findings = {
inputs: [],
validationSharks: [],
unprotectedInputs: [],
protectedInputs: [],
reactHookFormUsage: false,
templateUsage: false,
imports: []
};
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const lineNumber = i + 1;
// Buscar imports
if (line.includes('import') || line.includes('require')) {
if (line.includes('react-hook-form')) {
findings.reactHookFormUsage = true;
}
if (line.includes('securesharkinputs')) {
findings.imports.push({ line: lineNumber, content: line.trim() });
}
if (line.includes('SecureSharkForm')) {
findings.templateUsage = true;
}
}
// Buscar inputs
const inputMatches = line.match(/<input[^>]*>/gi);
const textareaMatches = line.match(/<textarea[^>]*>/gi);
if (inputMatches || textareaMatches) {
const inputs = [...(inputMatches || []), ...(textareaMatches || [])];
inputs.forEach(input => {
const idMatch = input.match(/id=["']([^"']+)["']/i);
const nameMatch = input.match(/name=["']([^"']+)["']/i);
const typeMatch = input.match(/type=["']([^"']+)["']/i);
findings.inputs.push({
line: lineNumber,
content: input.trim(),
id: idMatch ? idMatch[1] : null,
name: nameMatch ? nameMatch[1] : null,
type: typeMatch ? typeMatch[1] : 'text'
});
});
}
// Buscar ValidationShark components
const validationSharkMatches = line.match(/<ValidationShark[^>]*>/gi);
if (validationSharkMatches) {
validationSharkMatches.forEach(match => {
const inputIdMatch = match.match(/inputId=["']([^"']+)["']/i);
const blockFormMatch = match.match(/blockForm=["']([^"']+)["']/i);
const showMessagesMatch = match.match(/showMessages=["']([^"']+)["']/i);
findings.validationSharks.push({
line: lineNumber,
content: match.trim(),
inputId: inputIdMatch ? inputIdMatch[1] : null,
blockForm: blockFormMatch ? blockFormMatch[1] : 'true',
showMessages: showMessagesMatch ? showMessagesMatch[1] : 'true'
});
});
}
}
return findings;
} catch (error) {
log.error(`Error analizando archivo ${filePath}: ${error.message}`);
return null;
}
}
// Verificar conexión entre inputs y ValidationShark
function verifyConnection(findings, filePath) {
const results = {
file: filePath,
totalInputs: findings.inputs.length,
totalValidationSharks: findings.validationSharks.length,
protectedInputs: [],
unprotectedInputs: [],
reactHookFormDetected: findings.reactHookFormUsage,
templateDetected: findings.templateUsage,
recommendations: []
};
// Verificar cada input
findings.inputs.forEach(input => {
const isProtected = checkIfInputIsProtected(input, findings.validationSharks);
if (isProtected) {
results.protectedInputs.push(input);
} else {
results.unprotectedInputs.push(input);
}
});
// Generar recomendaciones
if (results.unprotectedInputs.length > 0) {
results.recommendations.push(`Agregar ValidationShark para ${results.unprotectedInputs.length} inputs no protegidos`);
}
if (findings.reactHookFormUsage && results.unprotectedInputs.length > 0) {
results.recommendations.push('Usar ValidationShark con react-hook-form para mejor integración');
}
if (!findings.templateUsage && results.unprotectedInputs.length > 0) {
results.recommendations.push('Considerar usar la plantilla SecureSharkForm como base');
}
return results;
}
// Verificar si un input está protegido
function checkIfInputIsProtected(input, validationSharks) {
// Si no hay ValidationShark components, no está protegido
if (validationSharks.length === 0) {
return false;
}
// Buscar ValidationShark que proteja este input específico
for (const shark of validationSharks) {
// Si tiene inputId específico, verificar que coincida
if (shark.inputId) {
if (input.id === shark.inputId) {
return true;
}
} else {
// Si no tiene inputId, asumir que protege el input más cercano
// (esto es una aproximación, en la práctica depende de la estructura DOM)
return true;
}
}
return false;
}
// Generar reporte
function generateReport(allResults) {
log.title('📊 REPORTE DE CONEXIÓN');
console.log('========================\n');
let totalFiles = allResults.length;
let filesWithImports = 0;
let filesWithReactHookForm = 0;
let filesWithTemplates = 0;
let totalInputs = 0;
let totalProtected = 0;
let totalUnprotected = 0;
allResults.forEach(result => {
if (result.imports && result.imports.length > 0) filesWithImports++;
if (result.reactHookFormDetected) filesWithReactHookForm++;
if (result.templateDetected) filesWithTemplates++;
totalInputs += result.totalInputs;
totalProtected += result.protectedInputs.length;
totalUnprotected += result.unprotectedInputs.length;
});
// Estadísticas generales
console.log(`${colors.bold}📈 ESTADÍSTICAS GENERALES:${colors.reset}`);
console.log(` Archivos analizados: ${totalFiles}`);
console.log(` Archivos con imports de SecureShark: ${filesWithImports}`);
console.log(` Archivos usando react-hook-form: ${filesWithReactHookForm}`);
console.log(` Archivos usando plantillas: ${filesWithTemplates}`);
console.log(` Total de inputs encontrados: ${totalInputs}`);
console.log(` Inputs protegidos: ${totalProtected}`);
console.log(` Inputs no protegidos: ${totalUnprotected}`);
// Porcentaje de protección
const protectionPercentage = totalInputs > 0 ? Math.round((totalProtected / totalInputs) * 100) : 0;
console.log(` Porcentaje de protección: ${protectionPercentage}%`);
console.log('\n' + '='.repeat(60));
// Detalles por archivo
allResults.forEach(result => {
if (result.totalInputs > 0) {
console.log(`\n${colors.bold}📁 ${path.basename(result.file)}:${colors.reset}`);
console.log(` Inputs: ${result.totalInputs} | Protegidos: ${result.protectedInputs.length} | No protegidos: ${result.unprotectedInputs.length}`);
if (result.unprotectedInputs.length > 0) {
console.log(` ${colors.red}❌ Inputs no protegidos:${colors.reset}`);
result.unprotectedInputs.forEach(input => {
console.log(` Línea ${input.line}: ${input.content.substring(0, 50)}...`);
});
}
if (result.recommendations.length > 0) {
console.log(` ${colors.yellow}💡 Recomendaciones:${colors.reset}`);
result.recommendations.forEach(rec => {
console.log(` • ${rec}`);
});
}
}
});
// Resumen final
console.log('\n' + '='.repeat(60));
console.log(`${colors.bold}🎯 RESUMEN FINAL:${colors.reset}`);
if (totalUnprotected === 0 && totalInputs > 0) {
log.success('¡Excelente! Todos los inputs están protegidos');
} else if (protectionPercentage >= 80) {
log.success(`Buen trabajo! ${protectionPercentage}% de los inputs están protegidos`);
} else if (protectionPercentage >= 50) {
log.warning(`Progreso moderado: ${protectionPercentage}% de los inputs están protegidos`);
} else {
log.error(`Necesitas mejorar la protección: solo ${protectionPercentage}% de los inputs están protegidos`);
}
if (totalUnprotected > 0) {
console.log(`\n${colors.yellow}🔧 PRÓXIMOS PASOS:${colors.reset}`);
console.log(' 1. Agrega <ValidationShark /> después de cada input no protegido');
console.log(' 2. Considera usar la plantilla SecureSharkForm como base');
console.log(' 3. Ejecuta: node node_modules/securesharkinputs/scripts/manual-install.js');
}
}
// Crear test de conexión simple
function createConnectionTest() {
const testContent = `
import React from 'react';
import { useForm } from 'react-hook-form';
import ValidationShark from 'securesharkinputs';
function TestForm() {
const { register, handleSubmit } = useForm();
const onSubmit = (data) => {
console.log('Form submitted:', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="input-field">
<label>Name</label>
<input
id="name"
type="text"
{...register('name')}
placeholder="Your name"
/>
<ValidationShark inputId="name" />
</div>
<div className="input-field">
<label>Email</label>
<input
id="email"
type="email"
{...register('email')}
placeholder="your@email.com"
/>
<ValidationShark inputId="email" />
</div>
<div className="input-field">
<label>Message</label>
<textarea
id="message"
{...register('message')}
placeholder="Your message"
/>
<ValidationShark inputId="message" />
</div>
<button type="submit">Submit</button>
</form>
);
}
export default TestForm;
`;
const testPath = path.join(process.cwd(), 'test-connection-example.tsx');
try {
fs.writeFileSync(testPath, testContent);
log.success(`Test de conexión creado: ${testPath}`);
log.info('Puedes usar este archivo como referencia para proteger tus inputs');
} catch (error) {
log.error(`Error creando test de conexión: ${error.message}`);
}
}
// Función principal
function runConnectionAnalysis() {
log.title('🔍 ANALIZANDO CONEXIONES EN EL PROYECTO');
console.log('=======================================\n');
// Buscar archivos React
const reactFiles = findReactFiles();
if (reactFiles.length === 0) {
log.warning('No se encontraron archivos React/JSX en el proyecto');
log.info('Asegúrate de estar en el directorio raíz de tu proyecto React');
return;
}
log.info(`Encontrados ${reactFiles.length} archivos React/JSX para analizar`);
// Analizar cada archivo
const allResults = [];
reactFiles.forEach(file => {
const findings = analyzeFile(file);
if (findings) {
const result = verifyConnection(findings, file);
allResults.push(result);
}
});
// Generar reporte
generateReport(allResults);
// Crear test de conexión si hay inputs no protegidos
const totalUnprotected = allResults.reduce((sum, result) => sum + result.unprotectedInputs.length, 0);
if (totalUnprotected > 0) {
console.log('\n' + '='.repeat(60));
log.info('Creando ejemplo de test de conexión...');
createConnectionTest();
}
console.log('\n📖 Para más información:');
console.log(' - README.md en el paquete');
console.log(' - SECURESHARK_SETUP.md (si está disponible)');
console.log(' - https://github.com/AzzADesigns/SecureSharkInputs');
}
// Ejecutar análisis
runConnectionAnalysis();