mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-11 13:47:05 +02:00
Add bootstrap tooltips and refactor some code formatings
This commit is contained in:
@@ -16,7 +16,7 @@ func main() {
|
||||
// Register our routes (IndexHandler, /api/summary, /api/jails/:jail/unban/:ip)
|
||||
web.RegisterRoutes(r)
|
||||
|
||||
log.Println("Starting Fail2ban UI on :8080. Run with 'sudo' if fail2ban-client requires it.")
|
||||
log.Println("Starting Fail2ban-UI server on :8080.")
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
log.Fatalf("Server crashed: %v", err)
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@ package fail2ban
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type JailInfo struct {
|
||||
JailName string `json:"jailName"`
|
||||
TotalBanned int `json:"totalBanned"`
|
||||
NewInLastHour int `json:"newInLastHour"`
|
||||
BannedIPs []string `json:"bannedIPs"`
|
||||
JailName string `json:"jailName"`
|
||||
TotalBanned int `json:"totalBanned"`
|
||||
NewInLastHour int `json:"newInLastHour"`
|
||||
BannedIPs []string `json:"bannedIPs"`
|
||||
}
|
||||
|
||||
// GetJails returns all configured jails using "fail2ban-client status".
|
||||
@@ -128,29 +128,29 @@ func BuildJailInfos(logPath string) ([]JailInfo, error) {
|
||||
// Example: we assume each jail config is at /etc/fail2ban/filter.d/<jail>.conf
|
||||
// Adapt this to your environment.
|
||||
func GetJailConfig(jail string) (string, error) {
|
||||
configPath := filepath.Join("/etc/fail2ban/filter.d", jail+".conf")
|
||||
content, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read config for jail %s: %v", jail, err)
|
||||
}
|
||||
return string(content), nil
|
||||
configPath := filepath.Join("/etc/fail2ban/filter.d", jail+".conf")
|
||||
content, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read config for jail %s: %v", jail, err)
|
||||
}
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
// SetJailConfig overwrites the config file for a given jail with new content.
|
||||
func SetJailConfig(jail, newContent string) error {
|
||||
configPath := filepath.Join("/etc/fail2ban/filter.d", jail+".conf")
|
||||
if err := ioutil.WriteFile(configPath, []byte(newContent), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write config for jail %s: %v", jail, err)
|
||||
}
|
||||
return nil
|
||||
configPath := filepath.Join("/etc/fail2ban/filter.d", jail+".conf")
|
||||
if err := os.WriteFile(configPath, []byte(newContent), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write config for jail %s: %v", jail, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReloadFail2ban runs "fail2ban-client reload"
|
||||
func ReloadFail2ban() error {
|
||||
cmd := exec.Command("fail2ban-client", "reload")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail2ban reload error: %v\nOutput: %s", err, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
cmd := exec.Command("fail2ban-client", "reload")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail2ban reload error: %v\nOutput: %s", err, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
//"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -69,31 +68,3 @@ func ParseBanLog(logPath string) (map[string][]BanEvent, error) {
|
||||
}
|
||||
return eventsByJail, nil
|
||||
}
|
||||
|
||||
// GetLastFiveBans crawls the parse results to find the last 5 ban events overall.
|
||||
func GetLastFiveBans(eventsByJail map[string][]BanEvent) []BanEvent {
|
||||
var allEvents []BanEvent
|
||||
for _, events := range eventsByJail {
|
||||
allEvents = append(allEvents, events...)
|
||||
}
|
||||
|
||||
// Sort by time descending
|
||||
// (We want the latest 5 ban events)
|
||||
sortByTimeDesc(allEvents)
|
||||
|
||||
if len(allEvents) > 5 {
|
||||
return allEvents[:5]
|
||||
}
|
||||
return allEvents
|
||||
}
|
||||
|
||||
// A simple in-file sorting utility
|
||||
func sortByTimeDesc(events []BanEvent) {
|
||||
for i := 0; i < len(events); i++ {
|
||||
for j := i + 1; j < len(events); j++ {
|
||||
if events[j].Time.After(events[i].Time) {
|
||||
events[i], events[j] = events[j], events[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,9 +256,18 @@ window.addEventListener('DOMContentLoaded', function() {
|
||||
checkReloadNeeded();
|
||||
fetchSummary().then(function() {
|
||||
showLoading(false);
|
||||
initializeTooltips(); // Initialize tooltips after fetching and rendering
|
||||
});
|
||||
});
|
||||
|
||||
// Function to initialize Bootstrap tooltips
|
||||
function initializeTooltips() {
|
||||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.forEach(function (tooltipTriggerEl) {
|
||||
new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle the loading overlay (with !important)
|
||||
function showLoading(show) {
|
||||
var overlay = document.getElementById('loading-overlay');
|
||||
@@ -342,7 +351,7 @@ function renderDashboard(data) {
|
||||
html += '<p>No jails found.</p>';
|
||||
} else {
|
||||
html += ''
|
||||
+ '<h2>Overview</h2>'
|
||||
+ '<h2><span data-bs-toggle="tooltip" data-bs-placement="top" title="The Overview displays the currently enabled jails that you have added to your jail.local configuration.">Overview</span></h2>'
|
||||
+ '<table class="table table-striped" id="jailsTable">'
|
||||
+ ' <thead>'
|
||||
+ ' <tr>'
|
||||
|
||||
Reference in New Issue
Block a user