06/03 Optimize app

This commit is contained in:
2026-06-03 16:22:02 -04:00
parent ec1c0fc7c1
commit eb85e70793
16 changed files with 406 additions and 5 deletions
+83
View File
@@ -0,0 +1,83 @@
{% extends "base.html" %}
{% block title %}Audit Log{% endblock %}
{% block page_title %}Audit Log{% endblock %}
{% block content %}
<div class="pcard pcard-sm mb-3">
<form method="GET" class="d-flex gap-2 align-items-center flex-wrap">
<select name="action" class="form-select form-select-sm" style="max-width:220px;">
<option value="">All events</option>
{% for a in actions %}
<option value="{{ a }}" {% if a == action %}selected{% endif %}>{{ a | replace('_',' ') | title }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-sm btn-outline-secondary"><i class="bi bi-filter me-1"></i>Filter</button>
{% if action %}<a href="{{ url_for('settings.audit_log') }}" class="btn btn-sm btn-outline-secondary"><i class="bi bi-x-lg"></i></a>{% endif %}
</form>
</div>
<div class="pcard p-0">
{% if logs %}
<table class="pfm-table">
<thead>
<tr>
<th style="padding-left:20px;">Time</th>
<th>Event</th>
<th class="d-mob-none">Details</th>
<th class="d-mob-none" style="padding-right:20px;">IP</th>
</tr>
</thead>
<tbody>
{% for entry in logs %}
<tr>
<td style="padding-left:20px;font-size:12px;color:var(--muted);white-space:nowrap;">
{{ entry.timestamp.strftime('%b %d, %H:%M:%S') }}
</td>
<td>
{% set colors = {
'login_success':'#d1fae5|#065f46',
'login_success_2fa':'#d1fae5|#065f46',
'login_failed':'#fee2e2|#991b1b',
'totp_enabled':'#dbeafe|#1e40af',
'totp_disabled':'#fef3c7|#92400e',
'schwab_connected':'#d1fae5|#065f46',
'schwab_disconnected':'#fee2e2|#991b1b',
'teller_connected':'#d1fae5|#065f46',
'teller_disconnected':'#fee2e2|#991b1b',
'password_changed':'#ede9fe|#5b21b6',
}.get(entry.action, '#f1f5f9|#475569').split('|') %}
<span style="font-size:12px;font-weight:600;background:{{ colors[0] }};color:{{ colors[1] }};padding:2px 8px;border-radius:4px;">
{{ entry.action | replace('_',' ') | title }}
</span>
</td>
<td class="d-mob-none" style="font-size:12px;color:var(--muted);">{{ entry.description or '—' }}</td>
<td class="d-mob-none" style="padding-right:20px;font-size:12px;color:var(--muted);">
<span class="mono">{{ entry.ip_address or '—' }}</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pagination.pages > 1 %}
<div class="d-flex justify-content-between align-items-center px-4 py-3" style="border-top:1px solid var(--border);font-size:12px;color:var(--muted);">
<span>Page {{ pagination.page }} of {{ pagination.pages }} · {{ pagination.total }} events</span>
<div class="d-flex gap-1">
{% if pagination.has_prev %}
<a href="{{ url_for('settings.audit_log', page=pagination.prev_num, action=action) }}" class="btn btn-sm btn-outline-secondary" style="font-size:11px;">← Prev</a>
{% endif %}
{% if pagination.has_next %}
<a href="{{ url_for('settings.audit_log', page=pagination.next_num, action=action) }}" class="btn btn-sm btn-outline-secondary" style="font-size:11px;">Next →</a>
{% endif %}
</div>
</div>
{% endif %}
{% else %}
<div class="text-center py-5">
<i class="bi bi-shield-check text-muted" style="font-size:2.5rem;opacity:.4;"></i>
<p class="text-muted small mt-3 mb-0">No audit events recorded yet.</p>
</div>
{% endif %}
</div>
{% endblock %}