commit
This commit is contained in:
89
templates/base.html
Normal file
89
templates/base.html
Normal file
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}SSL Monitor{% endblock %}</title>
|
||||
<!-- Bootstrap CSS (Bootstrap 5.3.0) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Własny plik CSS -->
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}">
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
<body class="dark-mode">
|
||||
<!-- Pasek nawigacyjny -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="{{ url_for('dashboard') }}">SSL Monitor</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
|
||||
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Przełącz nawigację">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
{% if session.get('user_id') %}
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('dashboard') }}">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('history') }}">Historia</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('preferences') }}">Preferencje widoku</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('app_settings') }}">Ustawienia</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
{% endif %}
|
||||
<ul class="navbar-nav ms-auto align-items-center">
|
||||
|
||||
{% if session.get('user_id') %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('change_password') }}">Zmiana hasła</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link btn btn-danger ms-2" href="{{ url_for('logout') }}">Wyloguj</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link btn btn-success ms-2" href="{{ url_for('login') }}">Zaloguj</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link btn btn-info ms-2" href="{{ url_for('register') }}">Rejestracja</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Kontener alertów dla dynamicznych komunikatów -->
|
||||
<div id="alert-container" class="container mt-3"></div>
|
||||
<!-- Główny kontener treści -->
|
||||
<div class="container mt-4">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Zamknij"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<!-- Stopka -->
|
||||
<footer class="bg-dark text-center text-lg-start mt-5 py-3">
|
||||
<div class="container">
|
||||
<span class="text-light">© 2025 SSL Monitor, @linuxiarz.pl</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS Bundle (Bootstrap 5.3.0) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{% block extra_js %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
15
templates/cert_details.html
Normal file
15
templates/cert_details.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Szczegóły certyfikatu - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Szczegóły certyfikatu</h2>
|
||||
{% if details.error %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ details.error }}
|
||||
</div>
|
||||
{% else %}
|
||||
<pre>{{ details | tojson(indent=2) }}</pre>
|
||||
{% endif %}
|
||||
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary">Powrót</a>
|
||||
</div>
|
||||
{% endblock %}
|
22
templates/change_password.html
Normal file
22
templates/change_password.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Zmiana hasła - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Zmiana hasła</h2>
|
||||
<form method="POST" action="{{ url_for('change_password') }}">
|
||||
<div class="mb-3">
|
||||
<label for="current_password" class="form-label">Aktualne hasło</label>
|
||||
<input type="password" class="form-control" id="current_password" name="current_password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="new_password" class="form-label">Nowe hasło</label>
|
||||
<input type="password" class="form-control" id="new_password" name="new_password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirm" class="form-label">Potwierdź nowe hasło</label>
|
||||
<input type="password" class="form-control" id="confirm" name="confirm" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Zmień hasło</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
453
templates/dashboard.html
Normal file
453
templates/dashboard.html
Normal file
@@ -0,0 +1,453 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Dashboard - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<h2 class="mb-4 text-center">Dashboard</h2>
|
||||
|
||||
<!-- Przyciski akcji na górze -->
|
||||
<div class="mb-4 text-center">
|
||||
<button class="btn btn-success me-2" onclick="showAddServiceModal()">Dodaj Serwis</button>
|
||||
<button class="btn btn-primary me-2" onclick="bulkUpdate()">Bulk Update</button>
|
||||
</div>
|
||||
|
||||
<!-- Opcje grupowania -->
|
||||
<div class="mb-4 d-flex justify-content-center">
|
||||
<div style="max-width:300px;">
|
||||
<label for="groupingCriteria" class="form-label">Grupuj usługi:</label>
|
||||
<select id="groupingCriteria" class="form-select">
|
||||
<option value="none" {% if default_grouping == 'none' %}selected{% endif %}>Brak grupowania</option>
|
||||
<option value="protocol" {% if default_grouping == 'protocol' %}selected{% endif %}>Grupuj według protokołu</option>
|
||||
<option value="host" {% if default_grouping == 'host' %}selected{% endif %}>Grupuj według hosta</option>
|
||||
<option value="region" {% if default_grouping == 'region' %}selected{% endif %}>Grupuj według regionu</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="cardsContainer" class="row">
|
||||
{% for s in services %}
|
||||
{% set card_class = "" %}
|
||||
{% if s.status == "Expired" %}
|
||||
{% set card_class = "bg-danger text-white" %}
|
||||
{% elif s.status == "ExpiringSoon" %}
|
||||
{% set card_class = "bg-warning text-dark" %}
|
||||
{% elif s.status == "OK" %}
|
||||
{% set card_class = "bg-success text-white" %}
|
||||
{% elif s.status == "Error" %}
|
||||
{% set card_class = "bg-secondary text-white" %}
|
||||
{% else %}
|
||||
{% set card_class = "bg-light" %}
|
||||
{% endif %}
|
||||
<div class="col-md-4 mb-4 service-card" data-protocol="{{ s.protocol|lower|trim }}" data-host="{{ s.host }}" data-region="{{ s.region }}">
|
||||
|
||||
<div class="card {{ card_class }} shadow-sm rounded">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ s.host }}:{{ s.port }} ({{ s.protocol }})</h5>
|
||||
<p class="card-text">
|
||||
Status: <strong>{{ s.status }}</strong><br>
|
||||
Last Check: {{ s.last_check if s.last_check else '---' }}<br>
|
||||
Expiry: {{ s.expiry_date if s.expiry_date else '---' }}
|
||||
</p>
|
||||
<div class="d-flex justify-content-center gap-2 flex-wrap">
|
||||
<button class="btn btn-sm btn-light" onclick="showEditServiceModal({{ s.id }})">Edytuj</button>
|
||||
<button class="btn btn-sm btn-info" onclick="updateService({{ s.id }})">Aktualizuj</button>
|
||||
<button class="btn btn-sm btn-danger" onclick="deleteService({{ s.id }})">Usuń</button>
|
||||
{% if s.protocol|lower == 'https' %}
|
||||
<button class="btn btn-sm btn-secondary" onclick="showCertDetails({{ s.id }})">Szczegóły certyfikatu</button>
|
||||
<button class="btn btn-sm btn-secondary" onclick="showCertChain({{ s.id }})">Łańcuch certyfikatów</button>
|
||||
{% else %}
|
||||
<button class="btn btn-sm btn-secondary" onclick="showResponse({{ s.id }})">Odpowiedź serwera</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Modale -->
|
||||
<!-- Modal dodawania serwisu -->
|
||||
<div class="modal" tabindex="-1" id="addServiceModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark text-white">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Dodaj nowy serwis</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close" onclick="hideAddServiceModal()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="addServiceForm">
|
||||
<div class="mb-3">
|
||||
<label for="host" class="form-label">Host</label>
|
||||
<input type="text" class="form-control" id="host" name="host" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="protocol" class="form-label">Protocol</label>
|
||||
<select class="form-select" id="protocol" name="protocol">
|
||||
<option value="https">HTTPS (443)</option>
|
||||
<option value="smtp_starttls">SMTP STARTTLS (587)</option>
|
||||
<option value="smtp_ssl">SMTP SSL (465)</option>
|
||||
<option value="imap_starttls">IMAP STARTTLS (143)</option>
|
||||
<option value="imap_ssl">IMAP SSL (993)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="port" class="form-label">Port</label>
|
||||
<input type="number" class="form-control" id="port" name="port" value="443">
|
||||
</div>
|
||||
<!-- Nowe pole dla regionu -->
|
||||
<div class="mb-3">
|
||||
<label for="region" class="form-label">Region</label>
|
||||
<input type="text" class="form-control" id="region" name="region">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" onclick="hideAddServiceModal()">Anuluj</button>
|
||||
<button class="btn btn-primary" onclick="addService()">Dodaj</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal edycji serwisu -->
|
||||
<!-- Modal edycji serwisu -->
|
||||
<div class="modal" tabindex="-1" id="editServiceModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark text-white">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edytuj serwis</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close" onclick="hideEditServiceModal()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editServiceForm">
|
||||
<input type="hidden" id="editServiceId">
|
||||
<div class="mb-3">
|
||||
<label for="editHost" class="form-label">Host</label>
|
||||
<input type="text" class="form-control" id="editHost" name="host" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="editProtocol" class="form-label">Protocol</label>
|
||||
<select class="form-select" id="editProtocol" name="protocol">
|
||||
<option value="https">HTTPS (443)</option>
|
||||
<option value="smtp_starttls">SMTP STARTTLS (587)</option>
|
||||
<option value="smtp_ssl">SMTP SSL (465)</option>
|
||||
<option value="imap_starttls">IMAP STARTTLS (143)</option>
|
||||
<option value="imap_ssl">IMAP SSL (993)</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- Nowe pole dla regionu -->
|
||||
<div class="mb-3">
|
||||
<label for="editRegion" class="form-label">Region</label>
|
||||
<input type="text" class="form-control" id="editRegion" name="region">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="editPort" class="form-label">Port</label>
|
||||
<input type="number" class="form-control" id="editPort" name="port" value="443">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" onclick="hideEditServiceModal()">Anuluj</button>
|
||||
<button class="btn btn-primary" onclick="editService()">Zapisz zmiany</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal wyświetlania certyfikatu / łańcucha certyfikatów (dla HTTPS) -->
|
||||
<div class="modal" tabindex="-1" id="certDetailsModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content bg-dark text-white">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Szczegóły certyfikatu / Łańcuch certyfikatów</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close" onclick="hideCertDetailsModal()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="certDetails"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" onclick="hideCertDetailsModal()">Zamknij</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal wyświetlania odpowiedzi serwera (dla nie-HTTPS) -->
|
||||
<div class="modal" tabindex="-1" id="responseModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content bg-dark text-white">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Odpowiedź serwera</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close" onclick="hideResponseModal()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre id="serverResponse" style="white-space: pre-wrap;"></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" onclick="hideResponseModal()">Zamknij</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
let addServiceModal = null;
|
||||
let editServiceModal = null;
|
||||
let certDetailsModal = null;
|
||||
let responseModal = null;
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
addServiceModal = new bootstrap.Modal(document.getElementById('addServiceModal'), {});
|
||||
editServiceModal = new bootstrap.Modal(document.getElementById('editServiceModal'), {});
|
||||
certDetailsModal = new bootstrap.Modal(document.getElementById('certDetailsModal'), {});
|
||||
responseModal = new bootstrap.Modal(document.getElementById('responseModal'), {});
|
||||
|
||||
// Aktualizacja domyślnej wartości portu w formularzu dodawania
|
||||
document.getElementById('protocol').addEventListener('change', function() {
|
||||
let portField = document.getElementById('port');
|
||||
switch(this.value) {
|
||||
case 'https': portField.value = 443; break;
|
||||
case 'smtp_starttls': portField.value = 587; break;
|
||||
case 'smtp_ssl': portField.value = 465; break;
|
||||
case 'imap_starttls': portField.value = 143; break;
|
||||
case 'imap_ssl': portField.value = 993; break;
|
||||
default: portField.value = 443;
|
||||
}
|
||||
});
|
||||
|
||||
// Aktualizacja domyślnej wartości portu w formularzu edycji
|
||||
document.getElementById('editProtocol').addEventListener('change', function() {
|
||||
let portField = document.getElementById('editPort');
|
||||
switch(this.value) {
|
||||
case 'https': portField.value = 443; break;
|
||||
case 'smtp_starttls': portField.value = 587; break;
|
||||
case 'smtp_ssl': portField.value = 465; break;
|
||||
case 'imap_starttls': portField.value = 143; break;
|
||||
case 'imap_ssl': portField.value = 993; break;
|
||||
default: portField.value = 443;
|
||||
}
|
||||
});
|
||||
|
||||
// Grupowanie kart przy zmianie kryterium
|
||||
document.getElementById('groupingCriteria').addEventListener('change', function() {
|
||||
groupCards(this.value);
|
||||
});
|
||||
groupCards(document.getElementById('groupingCriteria').value);
|
||||
});
|
||||
|
||||
function showAlert(message, type) {
|
||||
const alertContainer = document.getElementById('alert-container');
|
||||
const alertDiv = document.createElement('div');
|
||||
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
|
||||
alertDiv.setAttribute('role', 'alert');
|
||||
alertDiv.innerHTML = message +
|
||||
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Zamknij"></button>';
|
||||
alertContainer.appendChild(alertDiv);
|
||||
setTimeout(function(){
|
||||
alertDiv.classList.remove('show');
|
||||
alertDiv.remove();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function groupCards(criteria) {
|
||||
const container = document.getElementById('cardsContainer');
|
||||
const cards = Array.from(container.getElementsByClassName('service-card'));
|
||||
container.innerHTML = "";
|
||||
|
||||
if (criteria === "none") {
|
||||
cards.forEach(card => container.appendChild(card));
|
||||
} else {
|
||||
const groups = {};
|
||||
cards.forEach(card => {
|
||||
const key = card.getAttribute("data-" + criteria);
|
||||
if (!groups[key]) {
|
||||
groups[key] = [];
|
||||
}
|
||||
groups[key].push(card);
|
||||
});
|
||||
for (let group in groups) {
|
||||
const header = document.createElement("h4");
|
||||
header.className = "mt-4";
|
||||
header.innerText = criteria === "protocol" ? group.toUpperCase() : group;
|
||||
container.appendChild(header);
|
||||
const rowDiv = document.createElement("div");
|
||||
rowDiv.className = "row";
|
||||
groups[group].forEach(card => rowDiv.appendChild(card));
|
||||
container.appendChild(rowDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showAddServiceModal() { addServiceModal.show(); }
|
||||
function hideAddServiceModal() { addServiceModal.hide(); }
|
||||
|
||||
function showEditServiceModal(serviceId) {
|
||||
fetch("{{ url_for('api_get_services') }}")
|
||||
.then(r => r.json())
|
||||
.then(services => {
|
||||
const svc = services.find(s => s.id === serviceId);
|
||||
if (svc) {
|
||||
document.getElementById("editServiceId").value = svc.id;
|
||||
document.getElementById("editHost").value = svc.host;
|
||||
document.getElementById("editPort").value = svc.port;
|
||||
document.getElementById("editProtocol").value = svc.protocol;
|
||||
document.getElementById("editRegion").value = svc.region ? svc.region : "default";
|
||||
editServiceModal.show();
|
||||
}
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
}
|
||||
|
||||
function showCertDetails(serviceId) {
|
||||
fetch(`{{ url_for('api_cert_details', service_id=0) }}`.replace("0", serviceId))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
let htmlContent = "";
|
||||
if (data.error) {
|
||||
htmlContent = `<p class="text-danger">Błąd: ${data.error}</p>`;
|
||||
} else {
|
||||
htmlContent = data.html;
|
||||
}
|
||||
document.getElementById("certDetails").innerHTML = htmlContent;
|
||||
certDetailsModal.show();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
document.getElementById("certDetails").innerHTML = `<p class="text-danger">Błąd przy pobieraniu szczegółów certyfikatu.</p>`;
|
||||
certDetailsModal.show();
|
||||
});
|
||||
}
|
||||
|
||||
function showCertChain(serviceId) {
|
||||
fetch(`{{ url_for('api_cert_chain', service_id=0) }}`.replace("0", serviceId))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
let htmlContent = "";
|
||||
if (data.error) {
|
||||
htmlContent = `<p class="text-danger">Błąd: ${data.error}</p>`;
|
||||
} else {
|
||||
htmlContent = data.html;
|
||||
}
|
||||
document.getElementById("certDetails").innerHTML = htmlContent;
|
||||
certDetailsModal.show();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
document.getElementById("certDetails").innerHTML = `<p class="text-danger">Błąd przy pobieraniu łańcucha certyfikatów.</p>`;
|
||||
certDetailsModal.show();
|
||||
});
|
||||
}
|
||||
|
||||
function showResponse(serviceId) {
|
||||
fetch(`{{ url_for('api_service_response', service_id=0) }}`.replace("0", serviceId))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
let responseText = "";
|
||||
if (data.error) {
|
||||
responseText = "Błąd: " + data.error;
|
||||
} else {
|
||||
responseText = data.response;
|
||||
}
|
||||
document.getElementById("serverResponse").innerText = responseText;
|
||||
responseModal.show();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
document.getElementById("serverResponse").innerText = "Błąd przy pobieraniu odpowiedzi serwera.";
|
||||
responseModal.show();
|
||||
});
|
||||
}
|
||||
|
||||
function hideCertDetailsModal() { certDetailsModal.hide(); }
|
||||
function hideResponseModal() { responseModal.hide(); }
|
||||
|
||||
function addService() {
|
||||
const host = document.getElementById("host").value;
|
||||
const port = document.getElementById("port").value;
|
||||
const protocol = document.getElementById("protocol").value;
|
||||
const region = document.getElementById("region").value; // Pobranie wartości regionu
|
||||
|
||||
fetch("{{ url_for('api_add_service') }}", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({host, port, protocol, region})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(resp => {
|
||||
showAlert("Serwis został dodany.", "success");
|
||||
setTimeout(() => window.location.reload(), 1500);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showAlert("Błąd przy dodawaniu serwisu.", "danger");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function deleteService(serviceId) {
|
||||
if (!confirm("Czy na pewno chcesz usunąć ten serwis?")) return;
|
||||
const url = "{{ url_for('api_delete_service', service_id=0) }}".replace("0", serviceId);
|
||||
|
||||
fetch(url, { method: "DELETE" })
|
||||
.then(r => r.json())
|
||||
.then(resp => {
|
||||
showAlert("Serwis został usunięty.", "success");
|
||||
setTimeout(() => window.location.reload(), 1500);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showAlert("Błąd przy usuwaniu serwisu.", "danger");
|
||||
});
|
||||
}
|
||||
|
||||
function editService() {
|
||||
const serviceId = document.getElementById("editServiceId").value;
|
||||
const host = document.getElementById("editHost").value;
|
||||
const port = document.getElementById("editPort").value;
|
||||
const protocol = document.getElementById("editProtocol").value;
|
||||
const region = document.getElementById("editRegion").value; // Pobranie wartości regionu
|
||||
|
||||
fetch(`{{ url_for('api_edit_service', service_id=0) }}`.replace("0", serviceId), {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({host, port, protocol, region})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(resp => {
|
||||
showAlert("Serwis został zaktualizowany.", "success");
|
||||
setTimeout(() => window.location.reload(), 1500);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showAlert("Błąd przy aktualizacji serwisu.", "danger");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateService(serviceId) {
|
||||
fetch(`{{ url_for('api_update_service', service_id=0) }}`.replace("0", serviceId), { method: "POST" })
|
||||
.then(r => r.json())
|
||||
.then(resp => {
|
||||
showAlert("Serwis został zaktualizowany.", "success");
|
||||
setTimeout(() => window.location.reload(), 1500);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showAlert("Błąd przy aktualizacji serwisu.", "danger");
|
||||
});
|
||||
}
|
||||
|
||||
function bulkUpdate() {
|
||||
fetch("{{ url_for('api_bulk_update') }}", { method: "POST" })
|
||||
.then(r => r.json())
|
||||
.then(resp => {
|
||||
showAlert("Masowa aktualizacja wykonana.", "success");
|
||||
setTimeout(() => window.location.reload(), 1500);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showAlert("Błąd przy masowej aktualizacji.", "danger");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
31
templates/history.html
Normal file
31
templates/history.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Historia - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Historia sprawdzeń certyfikatów</h2>
|
||||
<table class="table table-dark table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Usługa</th>
|
||||
<th>Status</th>
|
||||
<th>Data sprawdzenia</th>
|
||||
<th>Data wygaśnięcia</th>
|
||||
<th>Komunikat</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for record in history %}
|
||||
<tr>
|
||||
<td>{{ record.id }}</td>
|
||||
<td>{{ record.service.host }}:{{ record.service.port }} ({{ record.service.protocol }})</td>
|
||||
<td>{{ record.status }}</td>
|
||||
<td>{{ record.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</td>
|
||||
<td>{{ record.expiry_date.strftime('%Y-%m-%d %H:%M:%S') if record.expiry_date else '---' }}</td>
|
||||
<td>{{ record.message }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
27
templates/login.html
Normal file
27
templates/login.html
Normal file
@@ -0,0 +1,27 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Logowanie - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h3 class="mb-3 text-center">Logowanie</h3>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
<form method="POST" action="{{ url_for('login') }}">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Użytkownik</label>
|
||||
<input type="text" class="form-control" name="username" id="username" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Hasło</label>
|
||||
<input type="password" class="form-control" name="password" id="password" required>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Zaloguj</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
24
templates/preferences.html
Normal file
24
templates/preferences.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Preferencje Widoku - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Preferencje Widoku</h2>
|
||||
<form method="POST" action="{{ url_for('preferences') }}">
|
||||
<div class="mb-3">
|
||||
<label for="default_grouping" class="form-label">Domyślne kryterium grupowania:</label>
|
||||
<select id="default_grouping" name="default_grouping" class="form-select">
|
||||
<option value="none" {% if prefs.default_grouping == 'none' %}selected{% endif %}>Brak grupowania</option>
|
||||
<option value="protocol" {% if prefs.default_grouping == 'protocol' %}selected{% endif %}>Grupuj według protokołu</option>
|
||||
<option value="host" {% if prefs.default_grouping == 'host' %}selected{% endif %}>Grupuj według hosta</option>
|
||||
<option value="region" {% if prefs.default_grouping == 'region' %}selected{% endif %}>Grupuj według regionu</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="filters" class="form-label">Filtry (JSON):</label>
|
||||
<textarea id="filters" name="filters" class="form-control" rows="3">{{ prefs.filters }}</textarea>
|
||||
<div class="form-text">Np. {"region": "EU", "certificate_type": "DV"}</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Zapisz preferencje</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
29
templates/register.html
Normal file
29
templates/register.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Rejestracja - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 class="mb-3 text-center">Rejestracja</h2>
|
||||
<form method="POST" action="{{ url_for('register') }}">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Nazwa użytkownika</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Hasło</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirm" class="form-label">Potwierdź hasło</label>
|
||||
<input type="password" class="form-control" id="confirm" name="confirm" required>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Zarejestruj się</button>
|
||||
</div>
|
||||
</form>
|
||||
<p class="mt-2 text-center">Masz już konto? <a href="{{ url_for('login') }}">Zaloguj się</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
48
templates/settings.html
Normal file
48
templates/settings.html
Normal file
@@ -0,0 +1,48 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Ustawienia - SSL Monitor{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Ustawienia</h2>
|
||||
<form method="POST" action="{{ url_for('app_settings') }}">
|
||||
<div class="mb-3">
|
||||
<label for="check_interval_minutes" class="form-label">Częstotliwość sprawdzania (minuty)</label>
|
||||
<input type="number" class="form-control" id="check_interval_minutes" name="check_interval_minutes" value="{{ settings.check_interval_minutes }}">
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="pushover_enabled" name="pushover_enabled" {% if settings.pushover_enabled %}checked{% endif %}>
|
||||
<label class="form-check-label" for="pushover_enabled">Włącz powiadomienia Pushover</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="pushover_token" class="form-label">Pushover Token</label>
|
||||
<input type="text" class="form-control" id="pushover_token" name="pushover_token" value="{{ settings.pushover_token }}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="pushover_userkey" class="form-label">Pushover User Key</label>
|
||||
<input type="text" class="form-control" id="pushover_userkey" name="pushover_userkey" value="{{ settings.pushover_userkey }}">
|
||||
</div>
|
||||
<!-- Nowe pola dla konfiguracji alertów -->
|
||||
<div class="mb-3">
|
||||
<label for="alert_threshold_info" class="form-label">Informacyjne: Ilość dni przed wygaśnięciem dla powiadomienia</label>
|
||||
<input type="number" class="form-control" id="alert_threshold_info" name="alert_threshold_info" value="{{ settings.alert_threshold_30 }}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="alert_threshold_warning" class="form-label">Ostrzegawcze: Ilość dni przed wygaśnięciem dla powiadomienia</label>
|
||||
<input type="number" class="form-control" id="alert_threshold_warning" name="alert_threshold_warning" value="{{ settings.alert_threshold_14 }}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="alert_threshold_critical" class="form-label">Krytyczne: Ilość dni przed wygaśnięciem dla powiadomienia</label>
|
||||
<input type="number" class="form-control" id="alert_threshold_critical" name="alert_threshold_critical" value="{{ settings.alert_threshold_7 }}">
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" id="alert_repeat" name="alert_repeat" {% if settings.alert_repeat %}checked{% endif %}>
|
||||
<label class="form-check-label" for="alert_repeat">Wysyłaj powiadomienia wielokrotnie</label>
|
||||
</div>
|
||||
<!-- Nowe pole do kasowania logów -->
|
||||
<div class="mb-3">
|
||||
<label for="logs_retention_days" class="form-label">Kasuj logi starsze niż (dni)</label>
|
||||
<input type="number" class="form-control" id="logs_retention_days" name="logs_retention_days" value="{{ settings.logs_retention_days }}">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Zapisz ustawienia</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user