Reorganize console.js file

This commit is contained in:
2026-02-15 23:57:01 +01:00
parent a98095581a
commit d1a13da8b0

View File

@@ -1,11 +1,20 @@
// Console Output Handler for Fail2ban UI // Console output handler (websocket log stream and rendering).
"use strict"; "use strict";
// =========================================================================
// Global Variables
// =========================================================================
let consoleOutputContainer = null; let consoleOutputContainer = null;
let consoleOutputElement = null; let consoleOutputElement = null;
let maxConsoleLines = 1000; // Maximum number of lines to keep in console let maxConsoleLines = 1000;
let wasConsoleEnabledOnLoad = false; // Track if console was enabled when page loaded let wasConsoleEnabledOnLoad = false;
// =========================================================================
// Initialization
// =========================================================================
// Initialize the console output container and connect to the websocket
function initConsoleOutput() { function initConsoleOutput() {
consoleOutputContainer = document.getElementById('consoleOutputContainer'); consoleOutputContainer = document.getElementById('consoleOutputContainer');
consoleOutputElement = document.getElementById('consoleOutputWindow'); consoleOutputElement = document.getElementById('consoleOutputWindow');
@@ -13,14 +22,12 @@ function initConsoleOutput() {
if (!consoleOutputContainer || !consoleOutputElement) { if (!consoleOutputContainer || !consoleOutputElement) {
return; return;
} }
// Register WebSocket callback for console logs
if (typeof wsManager !== 'undefined' && wsManager) { if (typeof wsManager !== 'undefined' && wsManager) {
wsManager.onConsoleLog(function(message, timestamp) { wsManager.onConsoleLog(function(message, timestamp) {
appendConsoleLog(message, timestamp); appendConsoleLog(message, timestamp);
}); });
} else { } else {
// Wait for WebSocket manager to be available // Wait for websocket manager to be available
const wsCheckInterval = setInterval(function() { const wsCheckInterval = setInterval(function() {
if (typeof wsManager !== 'undefined' && wsManager) { if (typeof wsManager !== 'undefined' && wsManager) {
wsManager.onConsoleLog(function(message, timestamp) { wsManager.onConsoleLog(function(message, timestamp) {
@@ -29,14 +36,14 @@ function initConsoleOutput() {
clearInterval(wsCheckInterval); clearInterval(wsCheckInterval);
} }
}, 100); }, 100);
// Timeout after 5 seconds if websocket manager is not available
// Stop checking after 5 seconds
setTimeout(function() { setTimeout(function() {
clearInterval(wsCheckInterval); clearInterval(wsCheckInterval);
}, 5000); }, 5000);
} }
} }
// Toggle the console output container
function toggleConsoleOutput(userClicked) { function toggleConsoleOutput(userClicked) {
const checkbox = document.getElementById('consoleOutput'); const checkbox = document.getElementById('consoleOutput');
const container = document.getElementById('consoleOutputContainer'); const container = document.getElementById('consoleOutputContainer');
@@ -46,18 +53,15 @@ function toggleConsoleOutput(userClicked) {
} }
if (checkbox.checked) { if (checkbox.checked) {
// Show the console output container
container.classList.remove('hidden'); container.classList.remove('hidden');
// Initialize console if not already done
if (!consoleOutputElement) { if (!consoleOutputElement) {
initConsoleOutput(); initConsoleOutput();
} else { } else {
// Re-register WebSocket callback in case it wasn't registered before
if (typeof wsManager !== 'undefined' && wsManager) { if (typeof wsManager !== 'undefined' && wsManager) {
// Remove any existing callbacks and re-register
if (!wsManager.consoleLogCallbacks) { if (!wsManager.consoleLogCallbacks) {
wsManager.consoleLogCallbacks = []; wsManager.consoleLogCallbacks = [];
} }
// Check if callback already exists
let callbackExists = false; let callbackExists = false;
for (let i = 0; i < wsManager.consoleLogCallbacks.length; i++) { for (let i = 0; i < wsManager.consoleLogCallbacks.length; i++) {
if (wsManager.consoleLogCallbacks[i].toString().includes('appendConsoleLog')) { if (wsManager.consoleLogCallbacks[i].toString().includes('appendConsoleLog')) {
@@ -73,16 +77,13 @@ function toggleConsoleOutput(userClicked) {
} }
} }
// Show save hint only if user just clicked to enable (not on page load)
const consoleEl = document.getElementById('consoleOutputWindow'); const consoleEl = document.getElementById('consoleOutputWindow');
// Show save hint only if user just clicked to enable (not on page load)
if (consoleEl && userClicked && !wasConsoleEnabledOnLoad) { if (consoleEl && userClicked && !wasConsoleEnabledOnLoad) {
// Clear initial placeholder message
const placeholder = consoleEl.querySelector('.text-gray-500'); const placeholder = consoleEl.querySelector('.text-gray-500');
if (placeholder && placeholder.textContent === 'Console output will appear here...') { if (placeholder && placeholder.textContent === 'Console output will appear here...') {
placeholder.remove(); placeholder.remove();
} }
// Show save hint message
const hintDiv = document.createElement('div'); const hintDiv = document.createElement('div');
hintDiv.className = 'text-yellow-400 italic text-center py-4'; hintDiv.className = 'text-yellow-400 italic text-center py-4';
hintDiv.id = 'consoleSaveHint'; hintDiv.id = 'consoleSaveHint';
@@ -90,59 +91,76 @@ function toggleConsoleOutput(userClicked) {
hintDiv.textContent = hintText; hintDiv.textContent = hintText;
consoleEl.appendChild(hintDiv); consoleEl.appendChild(hintDiv);
} else if (consoleEl) { } else if (consoleEl) {
// Just clear initial placeholder if it exists
const placeholder = consoleEl.querySelector('.text-gray-500'); const placeholder = consoleEl.querySelector('.text-gray-500');
// Remove placeholder if it exists
if (placeholder && placeholder.textContent === 'Console output will appear here...') { if (placeholder && placeholder.textContent === 'Console output will appear here...') {
placeholder.remove(); placeholder.remove();
} }
} }
} else { } else {
// Hide the console output container
container.classList.add('hidden'); container.classList.add('hidden');
} }
} }
// Auto-start console if enabled on load
if (typeof window !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
const checkbox = document.getElementById('consoleOutput');
if (checkbox && checkbox.checked) {
wasConsoleEnabledOnLoad = true;
toggleConsoleOutput(false);
}
initConsoleOutput();
});
} else {
const checkbox = document.getElementById('consoleOutput');
if (checkbox && checkbox.checked) {
wasConsoleEnabledOnLoad = true;
toggleConsoleOutput(false);
}
initConsoleOutput();
}
}
// =========================================================================
// Log Rendering / Core Functionality
// =========================================================================
function appendConsoleLog(message, timestamp) { function appendConsoleLog(message, timestamp) {
if (!consoleOutputElement) { if (!consoleOutputElement) {
consoleOutputElement = document.getElementById('consoleOutputWindow'); consoleOutputElement = document.getElementById('consoleOutputWindow');
} }
if (!consoleOutputElement) { if (!consoleOutputElement) {
return; return;
} }
// Remove placeholder if it exists
// Remove initial placeholder message
const placeholder = consoleOutputElement.querySelector('.text-gray-500'); const placeholder = consoleOutputElement.querySelector('.text-gray-500');
if (placeholder && placeholder.textContent === 'Console output will appear here...') { if (placeholder && placeholder.textContent === 'Console output will appear here...') {
placeholder.remove(); placeholder.remove();
} }
// Remove save hint if it exists
// Remove save hint when first log arrives
const saveHint = document.getElementById('consoleSaveHint'); const saveHint = document.getElementById('consoleSaveHint');
if (saveHint) { if (saveHint) {
saveHint.remove(); saveHint.remove();
} }
// Create new log line element with timestamp
// Create log line
const logLine = document.createElement('div'); const logLine = document.createElement('div');
logLine.className = 'text-green-400 leading-relaxed'; logLine.className = 'text-green-400 leading-relaxed';
// Format timestamp if provided
let timeStr = ''; let timeStr = '';
if (timestamp) { if (timestamp) {
try { try {
const date = new Date(timestamp); const date = new Date(timestamp);
timeStr = '<span class="text-gray-500">[' + date.toLocaleTimeString() + ']</span> '; timeStr = '<span class="text-gray-500">[' + date.toLocaleTimeString() + ']</span> ';
} catch (e) { } catch (e) {}
// Ignore timestamp parsing errors
}
} }
// Escape HTML to prevent XSS (but preserve timestamp HTML) // Escape message to prevent XSS
let escapedMessage = message; let escapedMessage = message;
if (typeof escapeHtml === 'function') { if (typeof escapeHtml === 'function') {
escapedMessage = escapeHtml(escapedMessage); escapedMessage = escapeHtml(escapedMessage);
} else { } else {
// Fallback HTML escaping
escapedMessage = escapedMessage escapedMessage = escapedMessage
.replace(/&/g, '&amp;') .replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
@@ -151,10 +169,8 @@ function appendConsoleLog(message, timestamp) {
.replace(/'/g, '&#039;'); .replace(/'/g, '&#039;');
} }
// Color code different log levels using precise patterns to avoid // Set different colors for different log levels using patterns below.
// false positives from SSH flags (e.g. "-o LogLevel=ERROR") or // Default is green.
// substrings like "stderr".
// Skip coloring for SSH command output that dumps config file content
let logClass = 'text-green-400'; let logClass = 'text-green-400';
var isConfigDump = /SSH command output\b/.test(message) && /Fail2Ban-UI Managed Configuration|jail\.local|action_mwlg/.test(message); var isConfigDump = /SSH command output\b/.test(message) && /Fail2Ban-UI Managed Configuration|jail\.local|action_mwlg/.test(message);
if (!isConfigDump) { if (!isConfigDump) {
@@ -166,53 +182,26 @@ function appendConsoleLog(message, timestamp) {
logClass = 'text-blue-400'; logClass = 'text-blue-400';
} }
} }
logLine.className = logClass + ' leading-relaxed'; logLine.className = logClass + ' leading-relaxed';
logLine.innerHTML = timeStr + escapedMessage;
// Add to console // Build complete log line with timestamp and message
logLine.innerHTML = timeStr + escapedMessage;
// Add log line to console
consoleOutputElement.appendChild(logLine); consoleOutputElement.appendChild(logLine);
// Limit number of lines
const lines = consoleOutputElement.children; const lines = consoleOutputElement.children;
if (lines.length > maxConsoleLines) { if (lines.length > maxConsoleLines) {
consoleOutputElement.removeChild(lines[0]); consoleOutputElement.removeChild(lines[0]);
} }
// Auto-scroll to bottom
consoleOutputElement.scrollTop = consoleOutputElement.scrollHeight; consoleOutputElement.scrollTop = consoleOutputElement.scrollHeight;
} }
// Clear the console
function clearConsole() { function clearConsole() {
if (!consoleOutputElement) { if (!consoleOutputElement) {
consoleOutputElement = document.getElementById('consoleOutputWindow'); consoleOutputElement = document.getElementById('consoleOutputWindow');
} }
if (consoleOutputElement) { if (consoleOutputElement) {
consoleOutputElement.textContent = ''; consoleOutputElement.textContent = '';
// Note: wasConsoleEnabledOnLoad remains true, so hint won't show again after clear
}
}
// Initialize on page load
if (typeof window !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
// Check if console output is already enabled on page load
const checkbox = document.getElementById('consoleOutput');
if (checkbox && checkbox.checked) {
wasConsoleEnabledOnLoad = true; // Mark that it was enabled on load
toggleConsoleOutput(false); // false = not a user click
}
initConsoleOutput();
});
} else {
// Check if console output is already enabled on page load
const checkbox = document.getElementById('consoleOutput');
if (checkbox && checkbox.checked) {
wasConsoleEnabledOnLoad = true; // Mark that it was enabled on load
toggleConsoleOutput(false); // false = not a user click
}
initConsoleOutput();
} }
} }