redactor
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// edit.js — drobne UX dla edytora
|
||||
(() => {
|
||||
'use strict';
|
||||
const ta = document.getElementById('haproxy_config');
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// index.js — logika formularza FE/BE (bez jQuery)
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// logs.js — na razie brak dodatkowej logiki (przykładowe miejsce na filtrowanie)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// stats.js — (miejsce na przyszłe wykresy)
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<span>© 2025 HAProxy Configurator</span>
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
<i class="bi bi-code-slash"></i>
|
||||
<span>Made for ops • Dark UX</span>
|
||||
<span>Based on: <a href="https://github.com/alonz22/haproxy-dashboard">This project</a> | by @linuxiarz.pl </span>
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
{% block content %}
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h4 class="mb-3 text-muted">Edytuj konfigurację HAProxy</h4>
|
||||
<h4 class="mb-3 text-muted">Edit HAProxy configuration</h4>
|
||||
<form method="POST" novalidate>
|
||||
<div class="mb-3">
|
||||
<label for="haproxy_config" class="form-label">Konfiguracja</label>
|
||||
<label for="haproxy_config" class="form-label">Config</label>
|
||||
<textarea class="form-control" name="haproxy_config" id="haproxy_config" rows="20">{{ config_content }}</textarea>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-warning" id="save_check" name="save_check">
|
||||
<i class="bi bi-search me-1"></i> Zapisz & Sprawdź
|
||||
<i class="bi bi-search me-1"></i> Check & Save
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" name="save_reload">
|
||||
<i class="bi bi-arrow-repeat me-1"></i> Zapisz & Restart
|
||||
<i class="bi bi-arrow-repeat me-1"></i> Check & Restart
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% block content %}
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h4 class="mb-3">Witaj! Szybkie podsumowanie</h4>
|
||||
<h4 class="mb-3">Summary</h4>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="p-3 rounded border d-flex align-items-center justify-content-between">
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<a href="{{ url_for('main.index') }}" class="btn btn-primary"><i class="fas fa-plus me-2"></i>Dodaj Frontend/Backend</a>
|
||||
<a href="{{ url_for('main.index') }}" class="btn btn-primary"><i class="fas fa-plus me-2"></i>Add Frontend/Backend</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<form method="post" action="/" id="fe-be-form" novalidate>
|
||||
<h5 class="mb-3"><i class="fas fa-globe me-2"></i>Nowy frontend</h5>
|
||||
<h5 class="mb-3"><i class="fas fa-globe me-2"></i>New frontend</h5>
|
||||
{% if message %}
|
||||
<div class="alert {% if 'already exists' in message %}alert-danger{% else %}alert-success{% endif %} alert-dismissible" role="alert">
|
||||
{{ message }}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="frontend_name">Nazwa</label>
|
||||
<label class="form-label" for="frontend_name">Name</label>
|
||||
<input type="text" class="form-control" name="frontend_name" id="frontend_name" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<div class="row g-3 mt-1 d-none" id="ssl_fields">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="ssl_cert_path">Ścieżka certyfikatu</label>
|
||||
<label class="form-label" for="ssl_cert_path">Certificate path (put in /ssl/)</label>
|
||||
<input type="text" id="ssl_cert_path" class="form-control" name="ssl_cert_path">
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-end">
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="protocol">Tryb</label>
|
||||
<select class="form-select" name="protocol" id="protocol" required>
|
||||
<option value="" disabled selected>--Wybierz--</option>
|
||||
<option value="" disabled selected>--Select--</option>
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="http">HTTP</option>
|
||||
</select>
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
<div class="form-check mt-3">
|
||||
<input type="checkbox" class="form-check-input" name="add_acl" id="add_acl">
|
||||
<label class="form-check-label" for="add_acl"><i class="fas fa-user-lock me-2"></i>ACL dla frontendu</label>
|
||||
<label class="form-check-label" for="add_acl"><i class="fas fa-user-lock me-2"></i>ACL for frontend</label>
|
||||
</div>
|
||||
<div class="row g-3 mt-1 d-none" id="acl_fields">
|
||||
<div class="col-md-4">
|
||||
@@ -130,7 +130,7 @@
|
||||
<input type="text" class="form-control" name="acl" id="acl" placeholder="acl_name">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="acl_action">Akcja</label>
|
||||
<label class="form-label" for="acl_action">Action</label>
|
||||
<input type="text" class="form-control" name="acl_action" id="acl_action" placeholder="hdr(host) -i test.com">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
@@ -141,19 +141,19 @@
|
||||
|
||||
<div class="form-check mt-3 http-only d-none" id="forbidden_acl_container">
|
||||
<input type="checkbox" class="form-check-input" name="add_acl_path" id="add_acl_path">
|
||||
<label class="form-check-label" for="add_acl_path"><i class="fas fa-ban me-2"></i>Blokuj wrażliwą ścieżkę</label>
|
||||
<label class="form-check-label" for="add_acl_path"><i class="fas fa-ban me-2"></i>Block path</label>
|
||||
</div>
|
||||
<div class="row g-3 mt-1 d-none" id="forbidden_fields">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="forbidden_name">Nazwa ACL</label>
|
||||
<label class="form-label" for="forbidden_name">ACL name</label>
|
||||
<input type="text" class="form-control" name="forbidden_name" id="forbidden_name">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="allowed_ip">Dozwolone IP</label>
|
||||
<label class="form-label" for="allowed_ip">Allowed IP</label>
|
||||
<input type="text" class="form-control" name="allowed_ip" id="allowed_ip">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="forbidden_path">Ścieżka (np. /admin)</label>
|
||||
<label class="form-label" for="forbidden_path">Path (ex. /admin)</label>
|
||||
<input type="text" class="form-control" name="forbidden_path" id="forbidden_path">
|
||||
</div>
|
||||
</div>
|
||||
@@ -179,10 +179,10 @@
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<h5 class="mb-3"><i class="fas fa-sitemap me-2"></i>Pula backendów</h5>
|
||||
<h5 class="mb-3"><i class="fas fa-sitemap me-2"></i>Backend pool</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="backend_name">Nazwa backendu</label>
|
||||
<label class="form-label" for="backend_name">Backend name</label>
|
||||
<input type="text" class="form-control" name="backend_name" id="backend_name" required>
|
||||
</div>
|
||||
</div>
|
||||
@@ -190,7 +190,7 @@
|
||||
<div id="backend_servers_container" class="mt-3">
|
||||
<div class="row g-3 backend-server-row">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" for="name1">Nazwa serwera</label>
|
||||
<label class="form-label" for="name1">Server name</label>
|
||||
<input type="text" id="name1" class="form-control" name="backend_server_names[]" placeholder="server1" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
@@ -208,8 +208,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2 mt-3">
|
||||
<button type="button" class="btn btn-secondary" id="add_backend_btn"><i class="bi bi-plus-lg me-1"></i>Dodaj backend</button>
|
||||
<button type="submit" class="btn btn-success" id="success_btn"><i class="bi bi-check2-circle me-1"></i>Zapisz</button>
|
||||
<button type="button" class="btn btn-secondary" id="add_backend_btn"><i class="bi bi-plus-lg me-1"></i>Add backend</button>
|
||||
<button type="submit" class="btn btn-success" id="success_btn"><i class="bi bi-check2-circle me-1"></i>Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% block title %}HAProxy • Logs{% endblock %}
|
||||
{% block breadcrumb %}<nav aria-label="breadcrumb" class="mb-3"><ol class="breadcrumb mb-0"><li class="breadcrumb-item"><a href="{{ url_for('main.index') }}"><i class="bi bi-house"></i></a></li><li class="breadcrumb-item active" aria-current="page">Logi</li></ol></nav>{% endblock %}
|
||||
{% block content %}
|
||||
<h3 class="mb-4" id="status_header">Status 403 Forbidden – wpisy</h3>
|
||||
<h3 class="mb-4" id="status_header">Status 403 Forbidden</h3>
|
||||
{% if entries %}
|
||||
<div class="vstack gap-3">
|
||||
{% for entry in entries %}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-info">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Frontendy</h6>
|
||||
<h6 class="card-title">Frontends</h6>
|
||||
<div class="fs-3 fw-bold">{{ stats|length }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-success">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Połączenia</h6>
|
||||
<h6 class="card-title">Connections</h6>
|
||||
<div class="fs-3 fw-bold">{{ stats|map(attribute='conn_tot')|sum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-warning">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Błędy 4xx</h6>
|
||||
<h6 class="card-title">Errirs 4xx</h6>
|
||||
<div class="fs-3 fw-bold">{{ stats|map(attribute='4xx_errors')|sum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-danger">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Błędy 5xx</h6>
|
||||
<h6 class="card-title">Errors 5xx</h6>
|
||||
<div class="fs-3 fw-bold">{{ stats|map(attribute='5xx_errors')|sum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,7 +47,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th><i class="fas fa-code"></i> Frontend</th>
|
||||
<th><i class="fas fa-server"></i> Serwer</th>
|
||||
<th><i class="fas fa-server"></i> Server</th>
|
||||
<th class="text-center">4xx</th>
|
||||
<th class="text-center">5xx</th>
|
||||
<th class="text-end">Bytes In (MB)</th>
|
||||
@@ -85,7 +85,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info"><i class="bi bi-info-circle me-1"></i>Brak statystyk.</div>
|
||||
<div class="alert alert-info"><i class="bi bi-info-circle me-1"></i>No stats.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>HAProxy Edit/add</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
/* Custom CSS for the header */
|
||||
header {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
padding-left: 100px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#editor_container{
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.logo {
|
||||
width: 300px; /* Adjust the width as needed */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
background-color: #3B444B;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Custom CSS for dark mode */
|
||||
.dark-mode {
|
||||
background-color: #121B2E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark-mode .header1{
|
||||
background-color: #25354e;
|
||||
color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.dark-mode .menu-link{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .logo {
|
||||
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .fas-fa-globe{
|
||||
color: #2bb9c7;
|
||||
}
|
||||
|
||||
.dark-mode .menu-link:hover{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode #editor_container{
|
||||
|
||||
box-shadow: 0 0 15px 5px rgba(43, 185, 199, 0.05);
|
||||
background-color: #1E2C42;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.dark-mode textarea {
|
||||
background-color: #1a2131;
|
||||
color: white;
|
||||
border: 1px solid #ccc; /* Add a border for visibility */
|
||||
padding: 5px; /* Add padding for a better visual appearance */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #1E2C42 #f1f1f1;
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #888888;
|
||||
border-radius: 6px; /* rounded thumb */
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply specific styles when the textarea is focused */
|
||||
.dark-mode textarea:focus {
|
||||
background-color: #1a2131;
|
||||
color: white;
|
||||
border-color: #fff; /* Change border color on focus */
|
||||
outline: none; /* Remove default focus outline */
|
||||
}
|
||||
|
||||
h3.edit_conf{
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.dark-mode h3.edit_conf {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.dark-mode #save_check{
|
||||
|
||||
background-color: #2bb9c7;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header1" id="header1">
|
||||
<a href="/home" style="text-decoration: none;">
|
||||
<h3 style="font-size: 22px;" class="logo">
|
||||
<i style="margin: 8px;" class="fas fa-globe"></i>Haproxy Configurator
|
||||
</h3>
|
||||
</a>
|
||||
<a href="/home" class="menu-link">Home</a>
|
||||
<a href="/" class="menu-link">Add Frontend & Backend</a>
|
||||
<a href="/edit" class="menu-link">Edit HAProxy Config</a>
|
||||
<a href="/logs" class="menu-link">Security Events</a>
|
||||
<a href="/statistics" class="menu-link">Statictics</a>
|
||||
<a href="http://{{ request.host.split(':')[0] }}:8404/stats" class="menu-link" target="_blank">HAProxy Stats</a>
|
||||
|
||||
<div class="custom-control custom-switch ml-auto">
|
||||
<input type="checkbox" class="custom-control-input" id="darkModeSwitch">
|
||||
<label class="custom-control-label" for="darkModeSwitch">Dark Mode</label>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
// Function to toggle dark mode
|
||||
function toggleDarkMode() {
|
||||
const body = document.body;
|
||||
body.classList.toggle('dark-mode');
|
||||
|
||||
// Save user's preference to localStorage
|
||||
const isDarkMode = body.classList.contains('dark-mode');
|
||||
localStorage.setItem('darkMode', isDarkMode); // Store the actual value
|
||||
}
|
||||
|
||||
// Check if dark mode preference is saved in localStorage
|
||||
const savedDarkMode = localStorage.getItem('darkMode');
|
||||
if (savedDarkMode === 'true') {
|
||||
document.body.classList.add('dark-mode');
|
||||
}
|
||||
|
||||
// Add event listener to the switch
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
darkModeSwitch.addEventListener('change', toggleDarkMode);
|
||||
</script>
|
||||
</header>
|
||||
<div style=" border-radius: 5px;" id="editor_container" class="container mt-5">
|
||||
<h3 style="color: grey; padding: 15px;" id="edit_conf" class="edit_conf">Edit HAProxy Config</h3>
|
||||
<form method="POST">
|
||||
<div class="form-group">
|
||||
<label for="haproxy_config">Configuration:</label>
|
||||
<textarea style="padding: 15px;" class="form-control" name="haproxy_config" rows="25" cols="120">{{ config_content }}</textarea>
|
||||
</div>
|
||||
<div style="padding-bottom: 20px;" class="form-group">
|
||||
<input type="submit" class="btn btn-warning" id="save_check" name="save_check" value="Save & Check">
|
||||
<input type="submit" class="btn btn-primary" name="save_reload" value="Save & Restart">
|
||||
</div>
|
||||
</form>
|
||||
{% if check_output %}
|
||||
<div style="padding-bottom: 15px;">
|
||||
{% if 'Fatal errors' in check_output %}
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<pre class="mt-3">{{ check_output }}</pre>
|
||||
</div>
|
||||
{% elif 'Warnings' in check_output %}
|
||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
||||
<pre class="mt-3">{{ check_output }}</pre>
|
||||
</div>
|
||||
{% elif 'error detected while parsing an' in check_output %}
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<pre class="mt-3">{{ check_output }}</pre>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<pre class="mt-3">{{ check_output }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Add Bootstrap JS and jQuery scripts here (if needed) -->
|
||||
<!-- You can get them from the official Bootstrap website or use CDN links -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,152 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>HAProxy Home</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
/* Custom CSS for the header */
|
||||
header {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
padding-left: 100px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 300px; /* Adjust the width as needed */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
background-color: #3B444B;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#summary_container{
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Custom CSS for dark mode */
|
||||
.dark-mode {
|
||||
background-color: #121B2E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark-mode .header1{
|
||||
background-color: #25354e;
|
||||
color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.dark-mode .menu-link{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .logo {
|
||||
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .fas-fa-globe{
|
||||
color: #2bb9c7;
|
||||
}
|
||||
|
||||
.dark-mode .menu-link:hover{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode #summary_container{
|
||||
|
||||
box-shadow: 0 0 15px 5px rgba(43, 185, 199, 0.05);
|
||||
border: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header1" id="header1">
|
||||
<a href="/home" style="text-decoration: none;">
|
||||
<h3 style="font-size: 22px;" class="logo">
|
||||
<i style="margin: 8px;" class="fas fa-globe"></i>Haproxy Configurator
|
||||
</h3>
|
||||
</a>
|
||||
<a href="/home" class="menu-link">Home</a>
|
||||
<a href="/" class="menu-link">Add Frontend & Backend</a>
|
||||
<a href="/edit" class="menu-link">Edit HAProxy Config</a>
|
||||
<a href="/logs" class="menu-link">Security Events</a>
|
||||
<a href="/statistics" class="menu-link">Statictics</a>
|
||||
<a href="http://{{ request.host.split(':')[0] }}:8404/stats" class="menu-link" >HAProxy Stats</a>
|
||||
|
||||
<div class="custom-control custom-switch ml-auto">
|
||||
<input type="checkbox" class="custom-control-input" id="darkModeSwitch">
|
||||
<label class="custom-control-label" for="darkModeSwitch">Dark Mode</label>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<div style=" border-radius: 5px; padding: 40px;" id="summary_container" class="container mt-5">
|
||||
<h3 style="margin-bottom: 20px;" class="mt-4">Welcome to Your HAProxy Configurator. Here's A Short Summary:</h3>
|
||||
|
||||
<p class="lead"><i style="margin: 8px;" class="fas fa-globe"></i> <strong>{{ frontend_count }}</strong> frontends</p>
|
||||
<p class="lead"><i style="margin-right: 8px;" class="fas fa-sitemap"></i> <strong>{{ backend_count }}</strong> backends</p>
|
||||
<p class="lead"><i style="margin: 8px;" class="fas fa-user-lock"></i> <strong>{{ acl_count }}</strong> acl's</p>
|
||||
<p class="lead"><i style="margin: 8px;" class="fas fa-code"></i> <strong>{{ layer7_count }}</strong> layer7(mode http) loadbalanced frontends</p>
|
||||
<p class="lead"><i style="margin: 8px;" class="fas fa-network-wired"></i> <strong>{{ layer4_count }}</strong> layer4(mode tcp)loadbalanced frontends</p>
|
||||
<div class="mt-4">
|
||||
<a href="/" class="btn btn-primary"><i style="margin: 8px;" class="fas fa-plus"></i>Add New Frontend/Backend</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Bootstrap JS and jQuery links here (if needed) -->
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle dark mode
|
||||
function toggleDarkMode() {
|
||||
const body = document.body;
|
||||
body.classList.toggle('dark-mode');
|
||||
|
||||
// Save user's preference to localStorage
|
||||
const isDarkMode = body.classList.contains('dark-mode');
|
||||
localStorage.setItem('darkMode', isDarkMode); // Store the actual value
|
||||
}
|
||||
|
||||
// Check if dark mode preference is saved in localStorage
|
||||
const savedDarkMode = localStorage.getItem('darkMode');
|
||||
if (savedDarkMode === 'true') {
|
||||
document.body.classList.add('dark-mode');
|
||||
}
|
||||
|
||||
// Add event listener to the switch
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
darkModeSwitch.addEventListener('change', toggleDarkMode);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,868 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>HAProxy Configurator</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
/* Custom CSS for the header */
|
||||
header {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
padding-left: 100px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#frontend_container{
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
|
||||
}
|
||||
#backend_container{
|
||||
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
|
||||
|
||||
}
|
||||
.logo {
|
||||
width: 300px; /* Adjust the width as needed */
|
||||
height: auto;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
background-color: #3B444B;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Custom CSS for dark mode */
|
||||
.dark-mode {
|
||||
background-color: #121B2E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark-mode .header1{
|
||||
background-color: #25354e;
|
||||
color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.dark-mode .menu-link{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .logo {
|
||||
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .fas-fa-globe{
|
||||
color: #2bb9c7;
|
||||
}
|
||||
|
||||
.dark-mode .menu-link:hover{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode input[type=text] {
|
||||
color: #BDBDBD;
|
||||
background-color: #25354e;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark-mode input[type=number] {
|
||||
color: white;
|
||||
background-color: #25354e;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.dark-mode #protocol{
|
||||
color: white;
|
||||
background-color: #25354e;
|
||||
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.dark-mode #lb_method{
|
||||
color: white;
|
||||
background-color: #25354e;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark-mode .logo {
|
||||
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.dark-mode #frontend_container{
|
||||
box-shadow: 0 0 15px 5px rgba(43, 185, 199, 0.05);
|
||||
|
||||
}
|
||||
|
||||
.dark-mode #backend_container{
|
||||
box-shadow: 0 0 15px 5px rgba(43, 185, 199, 0.05);
|
||||
|
||||
}
|
||||
|
||||
.dark-mode #succes_btn{
|
||||
|
||||
background-color: #2bb9c7;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header with the Edit link as a menu -->
|
||||
|
||||
<header id="header1" class="header1">
|
||||
<a href="/home" style="text-decoration: none;">
|
||||
<h3 style="font-size: 22px;" class="logo">
|
||||
<i style="margin: 8px;" class="fas fa-globe"></i>Haproxy Configurator
|
||||
</h3>
|
||||
</a>
|
||||
<a href="/home" class="menu-link" >Home</a>
|
||||
<a href="/" class="menu-link">Add Frontend&Backend</a>
|
||||
<a href="/edit" class="menu-link">Edit HAProxy Config</a>
|
||||
<a href="/logs" class="menu-link">Security Events</a>
|
||||
<a href="/statistics" class="menu-link">Statictics</a>
|
||||
<a href="http://{{ request.host.split(':')[0] }}:8404/stats" class="menu-link" >HAProxy Stats</a>
|
||||
<div class="custom-control custom-switch ml-auto">
|
||||
<input type="checkbox" class="custom-control-input" id="darkModeSwitch">
|
||||
<label class="custom-control-label" for="darkModeSwitch">Dark Mode</label>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
// Function to toggle dark mode
|
||||
function toggleDarkMode() {
|
||||
const body = document.body;
|
||||
body.classList.toggle('dark-mode');
|
||||
|
||||
// Save user's preference to localStorage
|
||||
const isDarkMode = body.classList.contains('dark-mode');
|
||||
localStorage.setItem('darkMode', isDarkMode); // Store the actual value
|
||||
}
|
||||
|
||||
// Check if dark mode preference is saved in localStorage
|
||||
const savedDarkMode = localStorage.getItem('darkMode');
|
||||
if (savedDarkMode === 'true') {
|
||||
document.body.classList.add('dark-mode');
|
||||
}
|
||||
|
||||
// Add event listener to the switch
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
darkModeSwitch.addEventListener('change', toggleDarkMode);
|
||||
</script>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container mt-4">
|
||||
<div style=" border-radius: 5px; padding: 20px;" class="container mt-5" id="frontend_container">
|
||||
<label style="margin: 20px auto; font-size: 18px; font-weight: bold;"><i style="margin: 8px;" class="fas fa-globe"></i> Add New Frontend:</label><br>
|
||||
<!-- Display success message when the form is submitted successfully -->
|
||||
{% if message %}
|
||||
<div class="alert {% if 'already exists' in message %}alert-danger{% else %}alert-success{% endif %} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="frontend_name">Frontend Name:</label>
|
||||
<input type="text" class="form-control" name="frontend_name" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-4">
|
||||
<label for="frontend_ip">Frontend IP:</label>
|
||||
<input type="text" class="form-control" name="frontend_ip" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-3">
|
||||
<label for="frontend_port">Frontend Port:</label>
|
||||
<input type="number" class="form-control" name="frontend_port" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Checkbox for SSL Certificate -->
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="ssl_checkbox" name="ssl_checkbox">
|
||||
<label class="form-check-label" for="ssl_checkbox"><i style="margin: 8px;" class="fas fa-lock"></i>Use SSL Certificate</label>
|
||||
</div>
|
||||
|
||||
<!-- Fields for SSL Certificate Path and SSL Key Path (Hidden by default) -->
|
||||
<div class="form-group" style="display: none;" id="ssl_fields">
|
||||
<label for="ssl_cert_path">SSL Certificate Path:</label>
|
||||
<input type="text" id="ssl_cert_path" class="form-control" name="ssl_cert_path">
|
||||
<div style="padding-bottom: 15px;" class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="ssl_redirect_checkbox" name="ssl_redirect_checkbox">
|
||||
<label class="form-check-label" for="ssl_redirect_checkbox"><i style="margin: 8px;" class="fas fa-arrow-circle-right"></i>Add Redirect to HTTPS</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px;" class="form-group">
|
||||
<label for="lb_method">Load Balancing Method:</label>
|
||||
<select class="form-control" name="lb_method" id="lb_method">
|
||||
<option value="roundrobin">Round Robin</option>
|
||||
<option value="leastconn">Least Connections</option>
|
||||
<option value="source">Source</option>
|
||||
<option value="wrr">WRR</option>
|
||||
<option value="wlc">WLC</option>
|
||||
<option value="random">Random</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="protocol">Protocol:</label>
|
||||
<select class="form-control" name="protocol" id="protocol" required>
|
||||
<option value="" disabled selected>--Select mode--</option>
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="http">HTTP</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- DOS Protection -->
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" name="add_dos" id="add_dos">
|
||||
<label style="margin-bottom: 10px;" class="form-check-label" for="add_dos"><i style="margin: 8px;" class="fas fa-shield-alt"></i> Add DOS Protection</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="dos_fields" style="display: none; padding-bottom: 20px;">
|
||||
<label for="limit_requests">Limit Requests, e.g: 20:</label>
|
||||
<input type="text" class="form-control" name="limit_requests">
|
||||
<label for="ban_duration">IP Ban Duration(in seconds, e.g: 15s):</label>
|
||||
<input type="text" class="form-control" name="ban_duration">
|
||||
</div>
|
||||
|
||||
<!-- SQL Injection -->
|
||||
<div style="margin-top: 8px; padding-bottom: 15px; display: none;" class="form-check" id="sql_injection_container">
|
||||
<input type="checkbox" class="form-check-input" id="sql_injection_check" name="sql_injection_check">
|
||||
<label class="form-check-label" for="sql_injection_check"><i style="margin: 8px;" class="fas fa-shield-alt"></i>Activate SQL Injection Protection</label>
|
||||
</div>
|
||||
|
||||
<!-- XSS -->
|
||||
<div style="margin-top: 8px; padding-bottom: 15px; display: none;" class="form-check" id="XSS_container">
|
||||
<input type="checkbox" class="form-check-input" id="xss_check" name="xss_check">
|
||||
<label class="form-check-label" for="xss_check"><i style="margin: 8px;" class="fas fa-shield-alt"></i>Activate XSS Protection</label>
|
||||
</div>
|
||||
|
||||
<!-- Remote File Uploads -->
|
||||
<div style="margin-top: 8px; padding-bottom: 15px; display: none;" class="form-check" id="remote_uploads_container">
|
||||
<input type="checkbox" class="form-check-input" id="remote_uploads_check" name="remote_uploads_check">
|
||||
<label class="form-check-label" for="remote_uploads_check"><i style="margin: 8px;" class="fas fa-shield-alt"></i>Activate Remote File Upload Protection</label>
|
||||
</div>
|
||||
|
||||
<!-- Deny Webshells -->
|
||||
<div style="margin-top: 8px; padding-bottom: 15px; display: none;" class="form-check" id="webshells_container">
|
||||
<input type="checkbox" class="form-check-input" id="webshells_check" name="webshells_check">
|
||||
<label class="form-check-label" for="webshells_check"><i style="margin: 8px;" class="fas fa-shield-alt"></i>Activate Webshells Protection</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check" style="margin-top: 8px;">
|
||||
<input type="checkbox" class="form-check-input" name="add_acl" id="add_acl">
|
||||
<label style="margin-bottom: 10px;" class="form-check-label" for="add_acl"><i style="margin: 8px;" class="fas fa-user-lock"></i> Add ACL for Frontend</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="acl_fields" style="display: none; padding-bottom: 20px;">
|
||||
<label for="acl">ACL:</label>
|
||||
<input type="text" class="form-control" name="acl" placeholder="example: acl_name">
|
||||
<label for="acl_action">ACL Action:</label>
|
||||
<input type="text" class="form-control" name="acl_action" placeholder="example: hdr(host) -i test.com">
|
||||
<label for="backend_name_acl">Backend Name:</label>
|
||||
<input type="text" class="form-control" name="backend_name_acl" placeholder="example: somebackend">
|
||||
</div>
|
||||
|
||||
<div class="form-check" id="forbidden_acl_container" style="display: none; margin-top: 8px;">
|
||||
<input type="checkbox" class="form-check-input" name="add_acl_path" id="add_acl_path">
|
||||
<label style="margin-bottom: 10px;" class="form-check-label" for="add_acl_path"><i style="margin: 8px;" class="fas fa-ban"></i> Block Sensitive Path</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="forbidden_fields" style="display: none; padding-bottom: 20px;">
|
||||
<label for="forbidden_name">ACL Name:</label>
|
||||
<input type="text" class="form-control" name="forbidden_name" id="forbidden_name">
|
||||
<label for="allowed_ip">Allowed IP Addresses(e.g: 192.168.3.13 193.168.3.14):</label>
|
||||
<input type="text" class="form-control" name="allowed_ip">
|
||||
<label for="forbidden_path">Path(e.g: /admin):</label>
|
||||
<input type="text" class="form-control" name="forbidden_path">
|
||||
</div>
|
||||
|
||||
<div class="form-check" id="path_based_container" style="display: none; margin-top: 8px;">
|
||||
<input type="checkbox" class="form-check-input" name="add_path_based" id="add_path_based">
|
||||
<label style="margin-bottom: 10px;" class="form-check-label" for="add_path_based"><i style="margin: 8px;" class="fas fa-arrow-circle-right"></i>Add Path Based Redirect</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="base_redirect_fields" style="display: none; padding-bottom: 20px;">
|
||||
<label for="redirect_domain_name">Domain to be redirected:</label>
|
||||
<input type="text" class="form-control" name="redirect_domain_name" id="redirect_domain_name" placeholder="e.g: test2.com or test2.com:8888 (port matters incase of unusual ports)">
|
||||
<label for="root_redirect">Root Path To Be Redirected:</label>
|
||||
<input type="text" class="form-control" name="root_redirect" placeholder="e.g: /">
|
||||
<label for="redirect_to">Redirect To Path:</label>
|
||||
<input type="text" class="form-control" name="redirect_to" placeholder="e.g: /test **this will redirect test2.com/ to test2.com/test**">
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 8px; padding-bottom: 15px; display: none;" class="form-check" id="forward_for_container">
|
||||
<input type="checkbox" class="form-check-input" id="forward_for_check" name="forward_for_check">
|
||||
<label class="form-check-label" for="forward_for_check"><i style="margin: 8px;" class="fas fa-network-wired"></i>Use option forwardfor</label>
|
||||
</div>
|
||||
|
||||
<div style="border-radius: 5px; padding: 20px; margin-bottom: 20px;" class="container mt-5" id="backend_container">
|
||||
<div class="form-group">
|
||||
<label style="margin-top: 40px; margin-bottom: 30px; font-size: 18px; font-weight: bold;"><i style="margin-right: 8px;" class="fas fa-sitemap"></i> Backend Servers Pool:</label><br>
|
||||
|
||||
<!-- HTTP Health Check -->
|
||||
<div class="form-group" id="health_check_container_http" style="display: none;">
|
||||
<input type="checkbox" name="health_check" id="health_check" onchange="toggleHealthCheck()">
|
||||
<label for="health_check">
|
||||
<i style="margin: 8px;" class="fas fa-heartbeat"></i>
|
||||
Enable Health Check <strong>(HTTP mode only)</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="health_check_field" style="display: none;">
|
||||
<label for="health_check_link">Health Check URL (e.g: your-website.com/health.html):</label>
|
||||
<input type="text" class="form-control" name="health_check_link">
|
||||
</div>
|
||||
|
||||
<!-- TCP Health Check -->
|
||||
<div class="form-group" id="health_check_container_tcp" style="display: none;">
|
||||
<input type="checkbox" name="health_check2" id="health_check2" onchange="toggleHealthCheck2()">
|
||||
<label for="health_check2">
|
||||
<i style="margin: 8px;" class="fas fa-heartbeat"></i>
|
||||
Enable Health Check <strong>(TCP mode)</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Sticky Session -->
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="sticky_session" id="sticky_session" onclick="toggleStickySession()">
|
||||
<label for="sticky_session"><i style="margin: 8px;" class="fas fa-link"></i> Enable Sticky Session</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="sticky_session_field" style="display: none;">
|
||||
<label for="sticky_session_type">Session Persistence Type:</label>
|
||||
<select class="form-control" name="sticky_session_type">
|
||||
<option value="cookie">Cookie SERVERID</option>
|
||||
<option value="stick-table">Stick-Table ip</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Custom Header -->
|
||||
<div class="form-group">
|
||||
<input type="checkbox" name="add_header" id="add_header" onclick="toggleCustomHeader()">
|
||||
<label for="add_header"><i style="margin: 8px;" class="fas fa-reply"></i> Add Custom Header</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="header_field" style="display: none;">
|
||||
<label for="header_name">Header Name:</label>
|
||||
<input type="text" class="form-control" name="header_name" placeholder="e.g: X-Client-IP">
|
||||
<label for="header_value">Header Value:</label>
|
||||
<input type="text" class="form-control" name="header_value" placeholder="e.g: test">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="backend_name">Backend Name:</label>
|
||||
<input type="text" class="form-control" name="backend_name" required>
|
||||
</div>
|
||||
|
||||
<!-- Backend Servers Section -->
|
||||
<div id="backend_servers_container">
|
||||
<!-- Initial Backend Server Row -->
|
||||
<div class="form-row backend-server-row">
|
||||
<div class="form-group col-md-3">
|
||||
<label for="name1">Backend Server Name:</label>
|
||||
<input type="text" id="name1" class="form-control" name="backend_server_names[]" placeholder="server1" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="ip1">Backend Server IP:</label>
|
||||
<input type="text" id="ip1" class="form-control" name="backend_server_ips[]" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="port1">Backend Server Port:</label>
|
||||
<input type="number" id="port1" class="form-control" name="backend_server_ports[]" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="maxconn1">MaxConn:</label>
|
||||
<input type="number" id="maxconn1" class="form-control" name="backend_server_maxconns[]">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-secondary" onclick="addBackendServer()">+ Add Backend Server</button>
|
||||
<input type="submit" id="success_btn" class="btn btn-success" value="Submit">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Function to add a new backend server row
|
||||
let serverCount = 1;
|
||||
|
||||
function addBackendServer() {
|
||||
serverCount++;
|
||||
const container = document.getElementById('backend_servers_container');
|
||||
const row = document.createElement('div');
|
||||
row.classList.add('form-row', 'backend-server-row', 'mt-2');
|
||||
|
||||
// Generate unique IDs
|
||||
const nameId = `name${serverCount}`;
|
||||
const ipId = `ip${serverCount}`;
|
||||
const portId = `port${serverCount}`;
|
||||
const maxconnId = `maxconn${serverCount}`;
|
||||
|
||||
row.innerHTML = `
|
||||
<div class="form-group col-md-3">
|
||||
<label for="${nameId}">Backend Server Name:</label>
|
||||
<input type="text" id="${nameId}" class="form-control" name="backend_server_names[]" placeholder="server${serverCount}" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="${ipId}">Backend Server IP:</label>
|
||||
<input type="text" id="${ipId}" class="form-control" name="backend_server_ips[]" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="${portId}">Backend Server Port:</label>
|
||||
<input type="number" id="${portId}" class="form-control" name="backend_server_ports[]" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="${maxconnId}">MaxConn:</label>
|
||||
<input type="number" id="${maxconnId}" class="form-control" name="backend_server_maxconns[]">
|
||||
<button type="button" class="btn btn-danger btn-sm mt-2" onclick="removeBackendServer(this)">Remove</button>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
function removeBackendServer(button) {
|
||||
const row = button.closest('.backend-server-row');
|
||||
if (document.querySelectorAll('.backend-server-row').length > 1) {
|
||||
row.remove();
|
||||
} else {
|
||||
alert("You must have at least one backend server.");
|
||||
}
|
||||
}
|
||||
|
||||
// Protocol change handler to show/hide health check options
|
||||
document.getElementById('protocol').addEventListener('change', function() {
|
||||
const protocol = this.value;
|
||||
const httpHealthCheck = document.getElementById('health_check_container_http');
|
||||
const tcpHealthCheck = document.getElementById('health_check_container_tcp');
|
||||
|
||||
if (protocol === 'http') {
|
||||
httpHealthCheck.style.display = 'block';
|
||||
tcpHealthCheck.style.display = 'none';
|
||||
} else if (protocol === 'tcp') {
|
||||
httpHealthCheck.style.display = 'none';
|
||||
tcpHealthCheck.style.display = 'block';
|
||||
} else {
|
||||
httpHealthCheck.style.display = 'none';
|
||||
tcpHealthCheck.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle functions (you'll need to implement these based on your existing JavaScript)
|
||||
function toggleHealthCheck() {
|
||||
const field = document.getElementById('health_check_field');
|
||||
const checkbox = document.getElementById('health_check');
|
||||
field.style.display = checkbox.checked ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function toggleHealthCheck2() {
|
||||
// Implement TCP health check toggle if needed
|
||||
}
|
||||
|
||||
function toggleStickySession() {
|
||||
const field = document.getElementById('sticky_session_field');
|
||||
const checkbox = document.getElementById('sticky_session');
|
||||
field.style.display = checkbox.checked ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function toggleCustomHeader() {
|
||||
const field = document.getElementById('header_field');
|
||||
const checkbox = document.getElementById('add_header');
|
||||
field.style.display = checkbox.checked ? 'block' : 'none';
|
||||
}
|
||||
</script>
|
||||
</form>
|
||||
|
||||
<!-- Add Bootstrap JS and jQuery (required for some Bootstrap components) -->
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.0.7/dist/umd/popper.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to hide the success message after a few seconds
|
||||
$(document).ready(function() {
|
||||
setTimeout(function() {
|
||||
$('.alert').alert('close');
|
||||
}, 5000); // Hide the message after 3 seconds (adjust the time as needed)
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Function to toggle the sticky session field based on checkbox selection
|
||||
function toggleCustomHeader() {
|
||||
const CustomHeaderbox = document.getElementById('add_header');
|
||||
const CustomHeaderField = document.getElementById('header_field');
|
||||
if (CustomHeaderbox.checked) {
|
||||
CustomHeaderField.style.display = 'block';
|
||||
} else {
|
||||
CustomHeaderField.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event listener to toggle the sticky session field when checkbox is clicked
|
||||
document.getElementById('add_header').addEventListener('click', toggleCustomHeader);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle the health check field based on the protocol selected
|
||||
function toggleHealthCheck() {
|
||||
const healthCheckField = document.getElementById('health_check_field');
|
||||
const healthCheckCheckbox = document.getElementById('health_check');
|
||||
|
||||
if (healthCheckCheckbox.checked) {
|
||||
healthCheckField.style.display = 'block';
|
||||
} else {
|
||||
healthCheckField.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event listener to toggle the health check field when protocol changes
|
||||
document.querySelector('select[name="protocol"]').addEventListener('change', toggleHealthCheck);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
function toggleHealthCheck2() {
|
||||
const protocolSelect = document.getElementById('protocol');
|
||||
const healthCheckContainer = document.getElementById('health_check_container');
|
||||
const healthCheckContainer2 = document.getElementById('health_check_container2');
|
||||
const healthCheckCheckbox2 = document.getElementById('health_check2');
|
||||
|
||||
|
||||
|
||||
if (protocolSelect.value !== 'http') {
|
||||
|
||||
healthCheckContainer.style.display = 'none';
|
||||
healthCheckContainer2.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
healthCheckContainer.style.display = 'block';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleHealthCheck2);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
function toggleHealthCheck() {
|
||||
const protocolSelect = document.getElementById('protocol');
|
||||
const healthCheckContainer = document.getElementById('health_check_container');
|
||||
const healthCheckField = document.getElementById('health_check_field');
|
||||
const healthCheckCheckbox = document.getElementById('health_check');
|
||||
const healthCheckContainer2 = document.getElementById('health_check_container2');
|
||||
const healthCheckCheckbox2 = document.getElementById('health_check2');
|
||||
|
||||
|
||||
|
||||
if (protocolSelect.value === 'http') {
|
||||
healthCheckContainer.style.display = 'block';
|
||||
if (healthCheckCheckbox.checked) {
|
||||
healthCheckField.style.display = 'block';
|
||||
} else {
|
||||
healthCheckField.style.display = 'none';
|
||||
healthCheckContainer2.style.display = 'none';
|
||||
healthCheckCheckbox2.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
healthCheckContainer.style.display = 'none';
|
||||
healthCheckField.style.display = 'none';
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleHealthCheck);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle the sticky session field based on checkbox selection
|
||||
function toggleStickySession() {
|
||||
const stickySessionCheckbox = document.getElementById('sticky_session');
|
||||
const stickySessionField = document.getElementById('sticky_session_field');
|
||||
if (stickySessionCheckbox.checked) {
|
||||
stickySessionField.style.display = 'block';
|
||||
} else {
|
||||
stickySessionField.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event listener to toggle the sticky session field when checkbox is clicked
|
||||
document.getElementById('sticky_session').addEventListener('click', toggleStickySession);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Function to toggle the visibility of ACL fields based on the checkbox
|
||||
const DosCheckbox = document.getElementById('add_dos');
|
||||
const DosFields = document.getElementById('dos_fields');
|
||||
|
||||
DosCheckbox.addEventListener('change', () => {
|
||||
if (DosCheckbox.checked) {
|
||||
DosFields.style.display = 'block';
|
||||
} else {
|
||||
DosFields.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Function to toggle the visibility of ACL fields based on the checkbox
|
||||
const aclCheckbox = document.getElementById('add_acl');
|
||||
const aclFields = document.getElementById('acl_fields');
|
||||
|
||||
aclCheckbox.addEventListener('change', () => {
|
||||
if (aclCheckbox.checked) {
|
||||
aclFields.style.display = 'block';
|
||||
} else {
|
||||
aclFields.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function toggleSqlInjection() {
|
||||
const protocolSelect5 = document.getElementById('protocol');
|
||||
const SqlInjectionContainer = document.getElementById('sql_injection_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect5.value === 'http') {
|
||||
|
||||
SqlInjectionContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
SqlInjectionContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleSqlInjection);
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
function Webshells() {
|
||||
const protocolSelect8 = document.getElementById('protocol');
|
||||
const WebshellsContainer = document.getElementById('webshells_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect8.value === 'http') {
|
||||
|
||||
WebshellsContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
WebshellsContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', Webshells);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function RemoteUploads() {
|
||||
const protocolSelect7 = document.getElementById('protocol');
|
||||
const RemoteUploadsContainer = document.getElementById('remote_uploads_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect7.value === 'http') {
|
||||
|
||||
RemoteUploadsContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
RemoteUploadsContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', RemoteUploads);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
function toggleXSS() {
|
||||
const protocolSelect6 = document.getElementById('protocol');
|
||||
const XSSContainer = document.getElementById('XSS_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect6.value === 'http') {
|
||||
|
||||
XSSContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
XSSContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleXSS);
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
function toggleForwardFor() {
|
||||
const protocolSelect4 = document.getElementById('protocol');
|
||||
const ForwardForContainer = document.getElementById('forward_for_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect4.value === 'http') {
|
||||
|
||||
ForwardForContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
ForwardForContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleForwardFor);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function toggleForbiddenCheck() {
|
||||
const protocolSelect3 = document.getElementById('protocol');
|
||||
const forbiddenContainer = document.getElementById('forbidden_acl_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect3.value === 'http') {
|
||||
|
||||
forbiddenContainer.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
forbiddenContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', toggleForbiddenCheck);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
function PathBasedToggle() {
|
||||
const protocolSelect7 = document.getElementById('protocol');
|
||||
const path_based_container = document.getElementById('path_based_container');
|
||||
|
||||
|
||||
|
||||
|
||||
if (protocolSelect7.value === 'http') {
|
||||
|
||||
path_based_container.style.display = 'block';
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
path_based_container.style.display = 'none';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('protocol').addEventListener('change', PathBasedToggle);
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle the visibility of based path redirect fields based on the checkbox
|
||||
const add_path_based_checkbox = document.getElementById('add_path_based');
|
||||
const redirect_path_fields = document.getElementById('base_redirect_fields');
|
||||
|
||||
add_path_based_checkbox.addEventListener('change', () => {
|
||||
if (add_path_based_checkbox.checked) {
|
||||
redirect_path_fields.style.display = 'block';
|
||||
} else {
|
||||
redirect_path_fields.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle the visibility of ACL forbidden paths fields based on the checkbox
|
||||
const aclCheckbox2 = document.getElementById('add_acl_path');
|
||||
const aclFields2 = document.getElementById('forbidden_fields');
|
||||
|
||||
aclCheckbox2.addEventListener('change', () => {
|
||||
if (aclCheckbox2.checked) {
|
||||
aclFields2.style.display = 'block';
|
||||
} else {
|
||||
aclFields2.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('ssl_checkbox').addEventListener('change', function () {
|
||||
const sslFields = document.getElementById('ssl_fields');
|
||||
sslFields.style.display = this.checked ? 'block' : 'none';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,211 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>HAProxy Logs</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
body {
|
||||
|
||||
}
|
||||
.log-entry {
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.collapse-trigger {
|
||||
cursor: pointer;
|
||||
}
|
||||
/* Custom CSS for the header */
|
||||
header {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
padding-left: 100px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.log-entry{
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
h3{
|
||||
color: grey;
|
||||
}
|
||||
.logo {
|
||||
width: 300px; /* Adjust the width as needed */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
background-color: #3B444B;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Custom CSS for dark mode */
|
||||
.dark-mode {
|
||||
background-color: #121B2E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark-mode .header1{
|
||||
background-color: #25354e;
|
||||
color: white;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.dark-mode .menu-link{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .logo {
|
||||
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .fas-fa-globe{
|
||||
color: #2bb9c7;
|
||||
}
|
||||
|
||||
.dark-mode .menu-link:hover{
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #2bb9c7;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.dark-mode #status_header{
|
||||
color: #2bb9c7;
|
||||
}
|
||||
|
||||
.dark-mode .log-entry{
|
||||
box-shadow: 0 0 15px 5px rgba(43, 185, 199, 0.05);
|
||||
background-color: #1E2C42;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark-mode #requested_url{
|
||||
|
||||
color: #2bb9c7;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="header1" id="header1>
|
||||
<a href="/home" style="text-decoration: none;">
|
||||
<h3 style="font-size: 22px;" class="logo">
|
||||
<i style="margin: 8px;" class="fas fa-globe"></i>Haproxy Configurator
|
||||
</h3>
|
||||
</a>
|
||||
<a href="/home" class="menu-link">Home</a>
|
||||
<a href="/edit" class="menu-link">Edit HAProxy Config</a>
|
||||
<a href="/" class="menu-link">Add Frontend&Backend</a>
|
||||
<a href="/logs" class="menu-link">Security Events</a>
|
||||
<a href="/statistics" class="menu-link">Statictics</a>
|
||||
<a href="http://{{ request.host.split(':')[0] }}:8484/stats" class="menu-link" >HAProxy Stats</a>
|
||||
<div class="custom-control custom-switch ml-auto">
|
||||
<input type="checkbox" class="custom-control-input" id="darkModeSwitch">
|
||||
<label class="custom-control-label" for="darkModeSwitch">Dark Mode</label>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
// Function to toggle dark mode
|
||||
function toggleDarkMode() {
|
||||
const body = document.body;
|
||||
body.classList.toggle('dark-mode');
|
||||
|
||||
// Save user's preference to localStorage
|
||||
const isDarkMode = body.classList.contains('dark-mode');
|
||||
localStorage.setItem('darkMode', isDarkMode); // Store the actual value
|
||||
}
|
||||
|
||||
// Check if dark mode preference is saved in localStorage
|
||||
const savedDarkMode = localStorage.getItem('darkMode');
|
||||
if (savedDarkMode === 'true') {
|
||||
document.body.classList.add('dark-mode');
|
||||
}
|
||||
|
||||
// Add event listener to the switch
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
darkModeSwitch.addEventListener('change', toggleDarkMode);
|
||||
</script>
|
||||
|
||||
</header>
|
||||
<h3 style="margin-top: 30px; margin-bottom: 30px; margin-left: 10%;" id="status_header">Status 403 Forbidden Log Entries</h3>
|
||||
<div>
|
||||
{% for entry in entries %}
|
||||
<div class="log-entry" style="padding: 20px; width: 80%; margin-left: 10%; margin-bottom: 1%;">
|
||||
<p><strong>Time Stamp:</strong> {{ entry['timestamp'] }}</p>
|
||||
<p><strong>IP Address:</strong> {{ entry['ip_address'] }}</p>
|
||||
<p><strong>HTTP Method:</strong> {{ entry['http_method'] }}</p>
|
||||
<p id="requested_url"><strong>Requested URL:</strong> {{ entry['requested_url'] }}</p>
|
||||
|
||||
<!-- XSS Category -->
|
||||
{% if entry['xss_alert'] %}
|
||||
<p class="collapse-trigger" data-bs-toggle="collapse" data-bs-target="#xssCollapse{{ loop.index }}">XSS Alert <span class="text-danger">(Click to show details)</span></p>
|
||||
<div id="xssCollapse{{ loop.index }}" class="collapse">
|
||||
<p style="color: red"><strong>{{ entry['xss_alert'] }}</strong></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- SQL Category -->
|
||||
{% if entry['sql_alert'] %}
|
||||
<p class="collapse-trigger" data-bs-toggle="collapse" data-bs-target="#sqlCollapse{{ loop.index }}">SQL Alert <span class="text-danger">(Click to show details)</span></p>
|
||||
<div id="sqlCollapse{{ loop.index }}" class="collapse">
|
||||
<p style="color: red"><strong>{{ entry['sql_alert'] }}</strong></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- PUT Method Category -->
|
||||
{% if entry['put_method'] %}
|
||||
<p class="collapse-trigger" data-bs-toggle="collapse" data-bs-target="#putMethodCollapse{{ loop.index }}">PUT Method Alert <span class="text-danger">(Click to show details)</span></p>
|
||||
<div id="putMethodCollapse{{ loop.index }}" class="collapse">
|
||||
<p style="color: red"><strong>{{ entry['put_method'] }}</strong></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Illegal Resource Access -->
|
||||
{% if entry['illegal_resource'] %}
|
||||
<p class="collapse-trigger" data-bs-toggle="collapse" data-bs-target="#putMethodCollapse{{ loop.index }}">Illegal Resource Access Alert <span class="text-danger">(Click to show details)</span></p>
|
||||
<div id="putMethodCollapse{{ loop.index }}" class="collapse">
|
||||
<p style="color: red"><strong>{{ entry['illegal_resource'] }}</strong></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Illegal Resource Access -->
|
||||
{% if entry['webshell_alert'] %}
|
||||
<p class="collapse-trigger" data-bs-toggle="collapse" data-bs-target="#putMethodCollapse{{ loop.index }}">WebShell Attack Alert <span class="text-danger">(Click to show details)</span></p>
|
||||
<div id="putMethodCollapse{{ loop.index }}" class="collapse">
|
||||
<p style="color: red"><strong>{{ entry['webshell_alert'] }}</strong></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p><strong>Status Code:</strong> 403</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,265 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>HAProxy Statistics</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
/* Header Styling */
|
||||
header {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
padding-left: 100px;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
background-color: #3B444B;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.menu-link.active {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.container {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Table Styling */
|
||||
.table-responsive {
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.table tbody tr:hover {
|
||||
background-color: #f5f5f5;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
vertical-align: middle;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Badge Styling */
|
||||
.badge {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Cards for Summary */
|
||||
.summary-card {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.summary-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.summary-card .card-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.summary-card h5 {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.summary-card h2 {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #f2f2f2;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header>
|
||||
<a href="/home" style="text-decoration: none;">
|
||||
<h3 style="color: grey; font-size: 22px;" class="logo">
|
||||
<i style="margin: 8px;" class="fas fa-globe"></i>Haproxy Configurator
|
||||
</h3>
|
||||
</a>
|
||||
<a href="/home" class="menu-link">Home</a>
|
||||
<a href="/" class="menu-link">Add Frontend&Backend</a>
|
||||
<a href="/edit" class="menu-link">Edit HAProxy Config</a>
|
||||
<a href="/logs" class="menu-link">Security Events</a>
|
||||
<a href="/statistics" class="menu-link active">Statistics</a>
|
||||
<a href="http://{{ request.host.split(':')[0] }}:8080/stats" class="menu-link" target="_blank">HAProxy Stats</a>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="container">
|
||||
<h1>
|
||||
<i class="fas fa-chart-line"></i> HAProxy Statistics
|
||||
</h1>
|
||||
|
||||
{% if stats %}
|
||||
<!-- Summary Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-info summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Frontends</h5>
|
||||
<h2>{{ stats|length }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-success summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Connections</h5>
|
||||
<h2>{{ stats|map(attribute='conn_tot')|sum }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-warning summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">4xx Errors</h5>
|
||||
<h2>{{ stats|map(attribute='4xx_errors')|sum }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-danger summary-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">5xx Errors</h5>
|
||||
<h2>{{ stats|map(attribute='5xx_errors')|sum }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics Table -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><i class="fas fa-code"></i> Frontend Name</th>
|
||||
<th><i class="fas fa-server"></i> Server Name</th>
|
||||
<th class="text-center">4xx Errors</th>
|
||||
<th class="text-center">5xx Errors</th>
|
||||
<th class="text-right">Bytes In (MB)</th>
|
||||
<th class="text-right">Bytes Out (MB)</th>
|
||||
<th class="text-center">Total Connections</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stat in stats %}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge bg-info">{{ stat.frontend_name }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ stat.server_name }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if stat['4xx_errors'] > 0 %}
|
||||
<span class="badge bg-warning">{{ stat['4xx_errors'] }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">{{ stat['4xx_errors'] }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if stat['5xx_errors'] > 0 %}
|
||||
<span class="badge bg-danger">{{ stat['5xx_errors'] }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">{{ stat['5xx_errors'] }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">{{ "%.2f"|format(stat.bytes_in_mb) }}</td>
|
||||
<td class="text-right">{{ "%.2f"|format(stat.bytes_out_mb) }}</td>
|
||||
<td class="text-center">
|
||||
<strong>{{ stat.conn_tot }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info no-data">
|
||||
<i class="fas fa-info-circle"></i> No statistics available
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<p>© 2025 HAProxy Configurator. All rights reserved.</p>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user