98 Zeilen
4.9 KiB
HTML
98 Zeilen
4.9 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Gesperrte IPs{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container py-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<h1>🔒 Gesperrte IPs</h1>
|
||
<div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">IP-Sperrverwaltung</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
{% if blocked_ips %}
|
||
<div class="table-responsive">
|
||
<table class="table table-hover sortable-table">
|
||
<thead>
|
||
<tr>
|
||
<th class="sortable">IP-Adresse</th>
|
||
<th class="sortable" data-type="numeric">Versuche</th>
|
||
<th class="sortable" data-type="date">Erster Versuch</th>
|
||
<th class="sortable" data-type="date">Letzter Versuch</th>
|
||
<th class="sortable" data-type="date">Gesperrt bis</th>
|
||
<th class="sortable">Letzter User</th>
|
||
<th class="sortable">Letzte Meldung</th>
|
||
<th class="sortable">Status</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for ip in blocked_ips %}
|
||
<tr class="{% if ip.is_active %}table-danger{% else %}table-secondary{% endif %}">
|
||
<td><code>{{ ip.ip_address }}</code></td>
|
||
<td><span class="badge bg-danger">{{ ip.attempt_count }}</span></td>
|
||
<td>{{ ip.first_attempt }}</td>
|
||
<td>{{ ip.last_attempt }}</td>
|
||
<td>{{ ip.blocked_until }}</td>
|
||
<td>{{ ip.last_username or '-' }}</td>
|
||
<td><strong>{{ ip.last_error or '-' }}</strong></td>
|
||
<td>
|
||
{% if ip.is_active %}
|
||
<span class="badge bg-danger">GESPERRT</span>
|
||
{% else %}
|
||
<span class="badge bg-secondary">ABGELAUFEN</span>
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
<div class="btn-group btn-group-sm" role="group">
|
||
{% if ip.is_active %}
|
||
<form method="post" action="{{ url_for('admin.unblock_ip') }}" class="d-inline">
|
||
<input type="hidden" name="ip_address" value="{{ ip.ip_address }}">
|
||
<button type="submit" class="btn btn-success"
|
||
onclick="return confirm('IP {{ ip.ip_address }} wirklich entsperren?')">
|
||
🔓 Entsperren
|
||
</button>
|
||
</form>
|
||
{% endif %}
|
||
<form method="post" action="{{ url_for('admin.clear_attempts') }}" class="d-inline ms-1">
|
||
<input type="hidden" name="ip_address" value="{{ ip.ip_address }}">
|
||
<button type="submit" class="btn btn-warning"
|
||
onclick="return confirm('Alle Versuche für IP {{ ip.ip_address }} zurücksetzen?')">
|
||
🗑️ Reset
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% else %}
|
||
<div class="alert alert-info">
|
||
<strong>Keine gesperrten IPs vorhanden.</strong>
|
||
Das System läuft ohne Sicherheitsvorfälle.
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card mt-4">
|
||
<div class="card-body">
|
||
<h5 class="card-title">ℹ️ Informationen</h5>
|
||
<ul class="mb-0">
|
||
<li>IPs werden nach <strong>{{ 5 }} fehlgeschlagenen Login-Versuchen</strong> für <strong>24 Stunden</strong> gesperrt.</li>
|
||
<li>Nach <strong>2 Versuchen</strong> wird ein CAPTCHA angezeigt.</li>
|
||
<li>Bei <strong>5 Versuchen</strong> wird eine E-Mail-Benachrichtigung gesendet (wenn aktiviert).</li>
|
||
<li>Gesperrte IPs können manuell entsperrt werden.</li>
|
||
<li>Die Fehlermeldungen werden zufällig ausgewählt für zusätzliche Verwirrung.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %} |