mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-17 05:53:15 +02:00
Chages that enables testing logpaths before saving and making multiple attempts to create correct patterns
This commit is contained in:
@@ -861,6 +861,7 @@ func equalStringSlices(a, b []string) bool {
|
|||||||
|
|
||||||
// TestLogpathHandler tests a logpath and returns matching files
|
// TestLogpathHandler tests a logpath and returns matching files
|
||||||
// Resolves Fail2Ban variables before testing
|
// Resolves Fail2Ban variables before testing
|
||||||
|
// Accepts optional logpath in request body, otherwise reads from saved jail config
|
||||||
func TestLogpathHandler(c *gin.Context) {
|
func TestLogpathHandler(c *gin.Context) {
|
||||||
config.DebugLog("----------------------------")
|
config.DebugLog("----------------------------")
|
||||||
config.DebugLog("TestLogpathHandler called (handlers.go)") // entry point
|
config.DebugLog("TestLogpathHandler called (handlers.go)") // entry point
|
||||||
@@ -871,22 +872,40 @@ func TestLogpathHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get jail config to extract logpath
|
var originalLogpath string
|
||||||
jailCfg, err := conn.GetJailConfig(c.Request.Context(), jail)
|
|
||||||
if err != nil {
|
// Check if logpath is provided in request body
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load jail config: " + err.Error()})
|
var reqBody struct {
|
||||||
return
|
Logpath string `json:"logpath"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&reqBody); err == nil && reqBody.Logpath != "" {
|
||||||
|
// Use logpath from request body (from textarea)
|
||||||
|
originalLogpath = strings.TrimSpace(reqBody.Logpath)
|
||||||
|
config.DebugLog("Using logpath from request body: %s", originalLogpath)
|
||||||
|
} else {
|
||||||
|
// Fall back to reading from saved jail config
|
||||||
|
jailCfg, err := conn.GetJailConfig(c.Request.Context(), jail)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load jail config: " + err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract logpath from jail config
|
||||||
|
originalLogpath = fail2ban.ExtractLogpathFromJailConfig(jailCfg)
|
||||||
|
if originalLogpath == "" {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"original_logpath": "",
|
||||||
|
"resolved_logpath": "",
|
||||||
|
"files": []string{},
|
||||||
|
"message": "No logpath configured for this jail",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.DebugLog("Using logpath from saved jail config: %s", originalLogpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract logpath from jail config
|
|
||||||
originalLogpath := fail2ban.ExtractLogpathFromJailConfig(jailCfg)
|
|
||||||
if originalLogpath == "" {
|
if originalLogpath == "" {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{"error": "No logpath provided"})
|
||||||
"original_logpath": "",
|
|
||||||
"resolved_logpath": "",
|
|
||||||
"files": []string{},
|
|
||||||
"message": "No logpath configured for this jail",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,9 +132,35 @@ function saveJailConfig() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract logpath from jail config text
|
||||||
|
function extractLogpathFromConfig(configText) {
|
||||||
|
if (!configText) return '';
|
||||||
|
|
||||||
|
// Match logpath = value (handles various formats)
|
||||||
|
var logpathMatch = configText.match(/^logpath\s*=\s*(.+)$/im);
|
||||||
|
if (logpathMatch && logpathMatch[1]) {
|
||||||
|
// Trim whitespace and remove quotes if present
|
||||||
|
var logpath = logpathMatch[1].trim();
|
||||||
|
// Remove surrounding quotes
|
||||||
|
logpath = logpath.replace(/^["']|["']$/g, '');
|
||||||
|
return logpath;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
function testLogpath() {
|
function testLogpath() {
|
||||||
if (!currentJailForConfig) return;
|
if (!currentJailForConfig) return;
|
||||||
|
|
||||||
|
// Extract logpath from the textarea
|
||||||
|
var jailTextArea = document.getElementById('jailConfigTextarea');
|
||||||
|
var jailConfig = jailTextArea ? jailTextArea.value : '';
|
||||||
|
var logpath = extractLogpathFromConfig(jailConfig);
|
||||||
|
|
||||||
|
if (!logpath) {
|
||||||
|
showToast('No logpath found in jail configuration. Please add a logpath line (e.g., logpath = /var/log/example.log)', 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var resultsDiv = document.getElementById('logpathResults');
|
var resultsDiv = document.getElementById('logpathResults');
|
||||||
resultsDiv.textContent = 'Testing logpath...';
|
resultsDiv.textContent = 'Testing logpath...';
|
||||||
resultsDiv.classList.remove('hidden');
|
resultsDiv.classList.remove('hidden');
|
||||||
@@ -145,6 +171,7 @@ function testLogpath() {
|
|||||||
fetch(withServerParam(url), {
|
fetch(withServerParam(url), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: serverHeaders({ 'Content-Type': 'application/json' }),
|
headers: serverHeaders({ 'Content-Type': 'application/json' }),
|
||||||
|
body: JSON.stringify({ logpath: logpath })
|
||||||
})
|
})
|
||||||
.then(function(res) { return res.json(); })
|
.then(function(res) { return res.json(); })
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
@@ -163,28 +190,35 @@ function testLogpath() {
|
|||||||
var resolvedLogpath = data.resolved_logpath || '';
|
var resolvedLogpath = data.resolved_logpath || '';
|
||||||
var files = data.files || [];
|
var files = data.files || [];
|
||||||
|
|
||||||
// Build output message
|
// Build output message with better formatting
|
||||||
var output = '';
|
var output = '';
|
||||||
|
|
||||||
|
// Show original logpath
|
||||||
|
if (originalLogpath) {
|
||||||
|
output += 'Logpath:\n ' + originalLogpath + '\n\n';
|
||||||
|
}
|
||||||
|
|
||||||
// Show resolved logpath if different from original
|
// Show resolved logpath if different from original
|
||||||
if (resolvedLogpath && resolvedLogpath !== originalLogpath) {
|
if (resolvedLogpath && resolvedLogpath !== originalLogpath) {
|
||||||
output += 'Resolved logpath: ' + resolvedLogpath + '\n\n';
|
output += 'Resolved logpath:\n ' + resolvedLogpath + '\n\n';
|
||||||
} else if (resolvedLogpath) {
|
} else if (resolvedLogpath) {
|
||||||
output += 'Logpath: ' + resolvedLogpath + '\n\n';
|
//output += 'Logpath:\n ' + resolvedLogpath + '\n\n';
|
||||||
} else if (originalLogpath) {
|
|
||||||
output += 'Logpath: ' + originalLogpath + '\n\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show files found
|
// Show files found with better formatting
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
output += 'No files found matching the logpath pattern.';
|
output += 'No files found matching the logpath pattern.';
|
||||||
resultsDiv.classList.remove('text-red-600');
|
resultsDiv.classList.remove('text-red-600');
|
||||||
resultsDiv.classList.add('text-yellow-600');
|
resultsDiv.classList.add('text-yellow-600');
|
||||||
} else {
|
} else {
|
||||||
output += 'Found ' + files.length + ' file(s):\n' + files.join('\n');
|
output += 'Found ' + files.length + ' file(s):\n\n';
|
||||||
|
files.forEach(function(file, index) {
|
||||||
|
output += ' ' + (index + 1) + '. ' + file + '\n';
|
||||||
|
});
|
||||||
resultsDiv.classList.remove('text-red-600', 'text-yellow-600');
|
resultsDiv.classList.remove('text-red-600', 'text-yellow-600');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use textContent for plain text, but we could also use innerHTML for better formatting
|
||||||
resultsDiv.textContent = output;
|
resultsDiv.textContent = output;
|
||||||
|
|
||||||
// Auto-scroll to results
|
// Auto-scroll to results
|
||||||
|
|||||||
@@ -805,7 +805,7 @@
|
|||||||
class="inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
class="inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-sm font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||||
onclick="testLogpath()"
|
onclick="testLogpath()"
|
||||||
data-i18n="modal.test_logpath">Test Logpath</button>
|
data-i18n="modal.test_logpath">Test Logpath</button>
|
||||||
<div id="logpathResults" class="mt-2 p-3 bg-gray-100 rounded-md text-sm font-mono max-h-32 overflow-y-auto hidden"></div>
|
<pre id="logpathResults" class="mt-2 p-3 bg-gray-100 rounded-md text-sm font-mono max-h-32 overflow-y-auto hidden"></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user