#!/usr/bin/env node /** * Fix CSP violations in admin JS files * - Replace inline styles with classes and data attributes * - Replace inline event handlers with event delegation */ const fs = require('fs'); const path = require('path'); // Fix auth-check.js inline styles function fixAuthCheck() { const filePath = path.join(__dirname, '../public/js/admin/auth-check.js'); let content = fs.readFileSync(filePath, 'utf8'); const oldHTML = `

Authentication Required

\${reason}

Redirecting to login...

`; const newHTML = `

Authentication Required

\${reason}

Redirecting to login...

`; if (content.includes(oldHTML)) { content = content.replace(oldHTML, newHTML); fs.writeFileSync(filePath, content); return 6; // 6 inline styles fixed } return 0; } // Fix progress bar widths by using data attributes function fixProgressBars() { const files = [ 'public/js/admin/audit-analytics.js', 'public/js/admin/rule-editor.js', 'public/js/admin/rule-manager.js' ]; let totalFixed = 0; files.forEach(file => { const filePath = path.join(__dirname, '..', file); let content = fs.readFileSync(filePath, 'utf8'); let fileFixed = 0; // Pattern 1:
const pattern1 = /(]*class="[^"]*(?:bg-blue-600|bg-green-500|bg-blue-500|bg-yellow-500)[^"]*"[^>]*)\s+style="width:\s*\$\{([^}]+)\}%"/g; content = content.replace(pattern1, (match, before, variable) => { fileFixed++; return `${before} data-width="\${${variable}}"`; }); // Pattern 2:
or style="width: 100%"> const pattern2 = /(]*(?:id="[^"]*-bar")[^>]*)\s+style="width:\s*(0|100)%"/g; content = content.replace(pattern2, (match, before, value) => { fileFixed++; return `${before} data-width="${value}"`; }); // Pattern 3: style="height: ${barHeight}%" const pattern3 = /style="height:\s*\$\{([^}]+)\}%"/g; content = content.replace(pattern3, (match, variable) => { fileFixed++; return `data-height="\${${variable}}"`; }); if (fileFixed > 0) { fs.writeFileSync(filePath, content); console.log(`✓ ${file}: Fixed ${fileFixed} inline style(s)`); totalFixed += fileFixed; } }); return totalFixed; } // Add width-setting helper after DOM insertion function addProgressBarHelper() { const files = [ { file: 'public/js/admin/audit-analytics.js', hasProgressBars: true }, { file: 'public/js/admin/rule-editor.js', hasProgressBars: true }, { file: 'public/js/admin/rule-manager.js', hasProgressBars: true } ]; const helper = ` // Set widths from data attributes (CSP compliance) function setProgressBarWidths(container) { const elements = container.querySelectorAll('[data-width], [data-height]'); elements.forEach(el => { if (el.dataset.width) { el.style.width = el.dataset.width + '%'; } if (el.dataset.height) { el.style.height = el.dataset.height + '%'; } }); }`; files.forEach(({ file, hasProgressBars }) => { if (!hasProgressBars) return; const filePath = path.join(__dirname, '..', file); let content = fs.readFileSync(filePath, 'utf8'); // Check if helper already exists if (content.includes('setProgressBarWidths')) { return; } // Add helper function before the last closing brace/parenthesis of the file // Find a good insertion point - typically after other helper functions const insertionPoint = content.lastIndexOf('})()'); if (insertionPoint > 0) { content = content.slice(0, insertionPoint) + helper + '\n\n' + content.slice(insertionPoint); fs.writeFileSync(filePath, content); console.log(`✓ ${file}: Added setProgressBarWidths helper`); } }); } // Main execution console.log('\n🔧 Fixing admin CSP violations...\n'); let totalFixed = 0; console.log('1. Fixing auth-check.js inline styles...'); totalFixed += fixAuthCheck(); console.log('\n2. Converting progress bar widths to data attributes...'); totalFixed += fixProgressBars(); console.log('\n3. Adding progress bar width helpers...'); addProgressBarHelper(); console.log(`\n✅ Total inline styles fixed: ${totalFixed}`); console.log('\n⚠️ Note: Inline event handlers require manual refactoring'); console.log(' Run scripts/fix-admin-event-handlers.js for those.\n');