Files
vacuum-wall/webui/templates/rules.html
T
mteehan e2f56b8cc8 Initial commit: SSL proxy / firewall appliance
Flask WebUI behind nginx reverse proxy with zone-based firewall, DHCP,
WireGuard, and ACME certificate management.
2026-05-07 22:24:24 +00:00

81 lines
3.2 KiB
HTML

{% extends "base.html" %}
{% block title %}Rules - Vacuum Wall{% endblock %}
{% block content %}
<div class="page-header">
<div>
<h1>Rich Rules</h1>
<div class="subtitle">Firewalld rich firewall rules per zone</div>
</div>
</div>
<div class="card mb-4">
<h3>Add Rule</h3>
<form hx-post="/api/firewall/rules" hx-swap="none" class="htmx-on-success" data-success="Rule added" onsuccess="setTimeout(function(){ location.reload(); }, 300);">
<div class="inline-form">
<div class="form-group">
<label for="rule-zone">Zone</label>
<select id="rule-zone" name="zone" required>
<option value="">— Select zone —</option>
{% for zone in (zones or []) %}
<option value="{{ zone.get('name', '') }}">{{ zone.get('name', '') }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="rule-text">Rule Expression</label>
<input type="text" id="rule-text" name="rule" placeholder="e.g., rule family=ipv4 source address=192.168.1.0/24 accept" required style="min-width:420px;">
</div>
<button type="submit" class="btn btn-primary">Add Rule</button>
</div>
</form>
<div class="text-muted text-sm mt-2">
Reference: <a href="https://firewalld.org/documentation/man-pages/firewalld.richlanguage.html" target="_blank" style="color:var(--accent);">firewalld rich language syntax</a>
</div>
</div>
{% if rules or False %}
{% for zone_name, zone_rules in rules.items() %}
<div class="card">
<h3>Zone: <span style="color:var(--accent);">{{ zone_name or '(default)' }}</span></h3>
{% if zone_rules %}
<table>
<thead>
<tr>
<th>#</th>
<th>Rule</th>
<th style="width:80px;">Action</th>
</tr>
</thead>
<tbody>
{% for rule in zone_rules %}
<tr>
<td class="text-muted">{{ loop.index }}</td>
<td style="font-family:monospace;font-size:12px;word-break:break-all;">{{ rule }}</td>
<td>
<form hx-delete="/api/firewall/rules/{{ zone_name | urlencode }}/{{ loop.index0 }}" hx-swap="none" class="htmx-on-success" data-success="Rule removed" onsuccess="setTimeout(function(){ location.reload(); }, 300);">
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Remove this rule?')">Remove</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="text-muted text-sm">No rich rules configured for this zone.</div>
{% endif %}
</div>
{% endfor %}
{% else %}
<div class="card">
<div class="text-muted text-sm">No rules loaded. Add rules using the form above, or ensure the zones API is providing rule data.</div>
</div>
{% endif %}
{% if not (zones or []) %}
<div class="card" style="border-color:var(--warning);">
<div class="text-muted text-sm" style="color:var(--warning);">No zones configured. Create a zone first before adding rich rules.</div>
</div>
{% endif %}
{% endblock %}