Files
vibedns/web/templates/pages/policy_form.html
T
2026-08-16 21:18:45 -05:00

168 lines
7.3 KiB
HTML

{{define "content"}}
{{$p := .Data.Policy}}{{$new := .Data.IsNew}}{{$sel := .Data.Selected}}
<nav aria-label="breadcrumb">
<ol class="breadcrumb small">
<li class="breadcrumb-item"><a href="/policies">Policy Rules</a></li>
<li class="breadcrumb-item active" aria-current="page">
{{if $new}}New policy{{else}}{{$p.Name}}{{end}}
</li>
</ol>
</nav>
<h1 class="page-title mb-4">{{if $new}}Create a policy{{else}}Edit {{$p.Name}}{{end}}</h1>
<form method="post" action="{{.Data.FormAction}}">
<input type="hidden" name="_csrf" value="{{.CSRF}}">
<div class="row g-3">
<div class="col-12 col-lg-5">
<div class="card mb-3">
<div class="card-header">Policy</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label" for="polName">Name</label>
<input type="text" class="form-control" id="polName" name="name" value="{{$p.Name}}"
placeholder="Guest Wi-Fi Filtering" required>
</div>
<div class="mb-3">
<label class="form-label" for="polDescription">Description</label>
<textarea class="form-control" id="polDescription" name="description" rows="2"
placeholder="What this policy is for">{{$p.Description}}</textarea>
</div>
<div class="form-check form-switch">
<input type="hidden" name="enabled" value="false">
<input class="form-check-input" type="checkbox" role="switch" id="polEnabled"
name="enabled" value="true" {{if or $new $p.Enabled}}checked{{end}}>
<label class="form-check-label" for="polEnabled">Enabled</label>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">When a name is blocked</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label" for="blockAction">Response</label>
<select class="form-select" id="blockAction" name="block_action">
<option value="nxdomain" {{if eq (printf "%s" $p.BlockAction) "nxdomain"}}selected{{end}}>
NXDOMAIN — tell the client the name does not exist
</option>
<option value="refused" {{if eq (printf "%s" $p.BlockAction) "refused"}}selected{{end}}>
REFUSED — tell the client the query was rejected
</option>
<option value="sinkhole" {{if eq (printf "%s" $p.BlockAction) "sinkhole"}}selected{{end}}>
Sinkhole — answer with an address you control
</option>
</select>
<div class="form-text">
NXDOMAIN is the usual choice: clients treat it as a normal negative answer
and stop retrying.
</div>
</div>
<div class="row g-2 mb-3">
<div class="col-12 col-sm-6">
<label class="form-label" for="sink4">Sinkhole IPv4</label>
<input type="text" class="form-control mono" id="sink4" name="sinkhole_ipv4"
value="{{default "0.0.0.0" $p.SinkholeIPv4}}" placeholder="0.0.0.0">
</div>
<div class="col-12 col-sm-6">
<label class="form-label" for="sink6">Sinkhole IPv6</label>
<input type="text" class="form-control mono" id="sink6" name="sinkhole_ipv6"
value="{{default "::" $p.SinkholeIPv6}}" placeholder="::">
</div>
</div>
<div>
<label class="form-label" for="blockTTL">Block response TTL</label>
<input type="number" class="form-control" id="blockTTL" name="block_ttl"
value="{{default 60 $p.BlockTTL}}" min="1" max="86400">
<div class="form-text">
Seconds a client should cache the block. A short value makes list changes
take effect quickly.
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body d-grid gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-lg me-1"></i>{{if $new}}Create policy{{else}}Save changes{{end}}
</button>
<a href="/policies" class="btn btn-outline-secondary">Cancel</a>
</div>
</div>
</div>
<div class="col-12 col-lg-7">
<div class="card mb-3">
<div class="card-header">
<i class="bi bi-shield-slash me-1 text-danger"></i>Blacklists
</div>
<div class="card-body">
<p class="text-body-secondary small">
A query matching any of these lists is blocked using the response chosen on the left.
</p>
{{if .Data.Blacklists}}
<div class="list-group">
{{range .Data.Blacklists}}
<label class="list-group-item d-flex gap-3 align-items-center">
<input class="form-check-input flex-shrink-0" type="checkbox"
name="list_id" value="{{.ID}}" {{if index $sel .ID}}checked{{end}}>
<span class="flex-grow-1">
<span class="fw-semibold">{{.Name}}</span>
{{if not .Enabled}}<span class="badge text-bg-secondary ms-1">disabled</span>{{end}}
<span class="d-block small text-body-secondary">
{{num .DomainCount}} domain{{if ne .DomainCount 1}}s{{end}}
{{if .Description}} · {{truncate 60 .Description}}{{end}}
</span>
</span>
</label>
{{end}}
</div>
{{else}}
<p class="text-body-secondary fst-italic mb-2">No blacklists exist yet.</p>
<a href="/policies/blacklists" class="btn btn-sm btn-outline-primary">Create a blacklist</a>
{{end}}
</div>
</div>
<div class="card">
<div class="card-header">
<i class="bi bi-shield-check me-1 text-success"></i>Allowlists
</div>
<div class="card-body">
<p class="text-body-secondary small">
A name on any allowlist is never blocked, whatever the blacklists say. This is
how you carve an exception out of a large imported list without editing it.
</p>
{{if .Data.Allowlists}}
<div class="list-group">
{{range .Data.Allowlists}}
<label class="list-group-item d-flex gap-3 align-items-center">
<input class="form-check-input flex-shrink-0" type="checkbox"
name="list_id" value="{{.ID}}" {{if index $sel .ID}}checked{{end}}>
<span class="flex-grow-1">
<span class="fw-semibold">{{.Name}}</span>
{{if not .Enabled}}<span class="badge text-bg-secondary ms-1">disabled</span>{{end}}
<span class="d-block small text-body-secondary">
{{num .DomainCount}} domain{{if ne .DomainCount 1}}s{{end}}
{{if .Description}} · {{truncate 60 .Description}}{{end}}
</span>
</span>
</label>
{{end}}
</div>
{{else}}
<p class="text-body-secondary fst-italic mb-2">No allowlists exist yet.</p>
<a href="/policies/allowlists" class="btn btn-sm btn-outline-primary">Create an allowlist</a>
{{end}}
</div>
</div>
</div>
</div>
</form>
{{end}}