This commit is contained in:
Mateusz Gruszczyński
2025-03-18 12:53:33 +01:00
commit 2a065aba3b
19 changed files with 1617 additions and 0 deletions

89
templates/base.html Normal file
View 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>

View 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 %}

View 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
View 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
View 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
View 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 %}

View 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
View 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
View 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 %}