From 370c7099f5701fc13019dcd2b022194232775dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Tue, 4 Nov 2025 08:40:06 +0100 Subject: [PATCH] fixes --- static/js/logs.js | 69 +++++++++++-- templates/logs.html | 231 ++++++++++++-------------------------------- 2 files changed, 123 insertions(+), 177 deletions(-) diff --git a/static/js/logs.js b/static/js/logs.js index 4ccc8de..9b574c2 100644 --- a/static/js/logs.js +++ b/static/js/logs.js @@ -1,8 +1,12 @@ +/** + * HAProxy Logs Management + * Pagination and dynamic loading of logs + */ + document.addEventListener('DOMContentLoaded', function() { let currentPage = 1; let perPage = 50; let totalLogs = parseInt(document.getElementById('total_count').textContent); - let allLogs = []; const logsContainer = document.getElementById('logs_container'); const perPageSelect = document.getElementById('logs_per_page'); @@ -14,6 +18,7 @@ document.addEventListener('DOMContentLoaded', function() { const currentPageSpan = document.getElementById('current_page'); const totalPagesSpan = document.getElementById('total_pages'); + // Event Listeners perPageSelect.addEventListener('change', function(e) { perPage = parseInt(e.target.value); currentPage = 1; @@ -43,11 +48,18 @@ document.addEventListener('DOMContentLoaded', function() { loadAllBtn.addEventListener('click', function() { perPage = totalLogs; currentPage = 1; - perPageSelect.value = totalLogs; + if (perPageSelect.querySelector(`option[value="${totalLogs}"]`)) { + perPageSelect.value = totalLogs; + } loadLogs(); }); + /** + * Load logs from API with pagination + */ function loadLogs() { + console.log(`[Logs] Loading page ${currentPage} with ${perPage} per page`); + fetch('/api/logs', { method: 'POST', headers: { @@ -63,18 +75,23 @@ document.addEventListener('DOMContentLoaded', function() { if (data.success) { renderLogs(data.logs); updatePagination(data); - console.log(`[Logs] Załadowano page ${data.page}/${Math.ceil(data.total / data.per_page)}`); + console.log(`[Logs] Successfully loaded page ${data.page}/${Math.ceil(data.total / data.per_page)}`); + } else { + showError(data.error || 'Unknown error'); } }) .catch(error => { - console.error('Error loading logs:', error); - logsContainer.innerHTML = `Błąd załadowania logów`; + console.error('[Logs] Error loading logs:', error); + showError('Failed to load logs. Please try again.'); }); } + /** + * Render logs in the table + */ function renderLogs(logs) { if (!logs || logs.length === 0) { - logsContainer.innerHTML = ' Brak logów'; + logsContainer.innerHTML = ' No logs available'; return; } @@ -82,10 +99,10 @@ document.addEventListener('DOMContentLoaded', function() { - ${entry.timestamp || 'N/A'}
- ${entry.source || 'N/A'}
+ ${escapeHtml(entry.timestamp || 'N/A')}
+ ${escapeHtml(entry.source || 'N/A')}
- ${entry.message || 'N/A'} + ${escapeHtml(entry.message || 'N/A')}
@@ -93,15 +110,49 @@ document.addEventListener('DOMContentLoaded', function() { `).join(''); } + /** + * Update pagination controls + */ function updatePagination(data) { const totalPages = Math.ceil(data.total / data.per_page); loadedSpan.textContent = data.logs.length; currentPageSpan.textContent = data.page; totalPagesSpan.textContent = totalPages; + // Disable/enable navigation buttons prevBtn.disabled = data.page === 1; nextBtn.disabled = !data.has_more; } + /** + * Show error message + */ + function showError(message) { + logsContainer.innerHTML = ` + + +
+ ${escapeHtml(message)} +
+ + + `; + } + + /** + * Escape HTML to prevent XSS + */ + function escapeHtml(text) { + const map = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + return text.replace(/[&<>"']/g, m => map[m]); + } + + // Initial load loadLogs(); }); diff --git a/templates/logs.html b/templates/logs.html index 53c3f82..b2bb2f9 100644 --- a/templates/logs.html +++ b/templates/logs.html @@ -8,7 +8,7 @@ {% endblock %} @@ -17,192 +17,87 @@
-
HAProxy Access Logs
+
HAProxy Logs
+
- {% if error_message %} - +
+ {{ error_message }} +
{% endif %} - {% if logs and logs|length > 0 %} -
-
- -
-
- + + + +
-
- -
-
-
- - -
-
-
-
- - -
-
-
- +
+
-
-
-
-
-
Total
- {{ logs|length }} -
-
-
-
-
-
-
Threats
- 0 -
-
-
-
-
-
-
2xx
- 0 -
-
-
-
-
-
-
4xx
- 0 -
-
-
-
-
-
-
5xx
- 0 -
-
-
-
-
-
-
Unique IPs
- 0 -
-
-
+ +
+ + Loaded: {{ loaded_count|default(0) }} / + Total: {{ total_logs|default(0) }} logs
-
- -
- - + +
+
+ + {% if logs %} + {% for entry in logs %} + + + + {% endfor %} + {% else %} - - - - - - - - - - {% for entry in logs %} - - - - - - - - {% endfor %} + {% endif %}
+ + {{ entry.get('timestamp', 'N/A') }}
+ {{ entry.get('source', 'N/A') }}
+ + {{ entry.get('message', 'N/A') }} + +
+
TimestampIP AddressHTTP MethodRequested URLStatus CodeAlerts
{{ entry['timestamp'] }} - {{ entry['ip_address'] }} - - {{ entry['http_method'] }} - - {{ entry['requested_url'] }} - - - {{ entry['status_code'] }} - - - {% if entry['xss_alert'] %} - XSS - {% endif %} - {% if entry['sql_alert'] %} - SQL - {% endif %} - {% if entry['put_method'] %} - PUT - {% endif %} - {% if entry['webshell_alert'] %} - Webshell - {% endif %} - {% if entry['illegal_resource'] %} - 403 - {% endif %} + + No logs available
- - {% elif logs %} -
- No log entries match your filters. -
- {% else %} - - {% endif %} + +
+ + Page 1 of 1 + +
+ + + +
+