Reverse zone suggestions: yours and public, dismiss, per-view switch; child zones take their records
Suggestions split into networks that are yours (private IPv4 /24, ULA /48, an IPv6 /48 this server has an address in), which Create all creates, and public addresses (/32 or /128) to create only if they are yours or dismiss. A view can turn suggestions off, which also keeps it out of choosing a reverse zone's view (database version 13). A zone created inside another in the same view takes the parent's records under it; a delegation and its glue stay, a linked parent keeps them with a warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
aa4b004a14
commit
b24c730b97
21 files changed
+543
-107
No files matched your search
@@ -281,7 +281,9 @@ export function pendingBadge(kind) {
|
||||
}
|
||||
|
||||
// suggestPanel lists the reverse zones the private views lack for their
|
||||
// records' addresses, to create filled with PTR records (docs/reverse.md).
|
||||
// records' addresses, to create filled with PTR records (docs/reverse.md):
|
||||
// networks that are yours, and public addresses, which may be a web
|
||||
// host's, to create one by one or dismiss.
|
||||
function suggestPanel(sugg, views) {
|
||||
const create = async (list) => {
|
||||
const reqs = list.map((s) => ({ op: "zone.create", data: { name: s.prefix, view_id: s.view_id || undefined, fill: true } }));
|
||||
@@ -292,15 +294,28 @@ function suggestPanel(sugg, views) {
|
||||
rerender();
|
||||
} catch (e) { toast(e.message, "err", 8000); }
|
||||
};
|
||||
const dismiss = async (s) => {
|
||||
try {
|
||||
const r = await change("POST", "/reverse-zones/dismiss", { view_id: s.view_id || undefined, prefix: s.prefix });
|
||||
toast(describeResult(r));
|
||||
rerender();
|
||||
} catch (e) { toast(e.message, "err", 8000); }
|
||||
};
|
||||
const cols = (pub) => [
|
||||
views.length ? { label: "View", render: (s) => s.view } : null,
|
||||
{ label: pub ? "Address" : "Network", render: (s) => [h("span", { class: "mono" }, pub ? s.prefix.replace(/\/(32|128)$/, "") : s.prefix), pub ? null : h("div", { class: "muted small" }, s.why)] },
|
||||
{ label: "Zone", render: (s) => h("span", { class: "mono small" }, s.zone) },
|
||||
{ label: pub ? "Name" : "PTR records", render: (s) => pub ? h("span", { class: "mono small" }, s.samples.map((x) => x.split(" ")[1]).join(", ")) : [String(s.fill), s.samples.length ? h("div", { class: "muted small mono" }, s.samples.join(", ") + (s.fill > s.samples.length ? ", …" : "")) : null] },
|
||||
{ label: "", render: (s) => [h("button", { class: "small", onclick: () => create([s]) }, "Create"), pub ? [" ", h("button", { class: "small", title: "Not yours (a web host's, say): don't suggest it again", onclick: () => dismiss(s) }, "Dismiss")] : null], tdClass: "actions-cell" },
|
||||
].filter(Boolean);
|
||||
const yours = sugg.filter((s) => s.group === "yours");
|
||||
const pub = sugg.filter((s) => s.group !== "yours");
|
||||
return h("div", { class: "panel" },
|
||||
h("div", { class: "page-head" }, h("h2", { class: "grow" }, "Missing reverse zones"),
|
||||
sugg.length > 1 ? h("div", { class: "actions" }, h("button", { onclick: () => create(sugg) }, "Create all " + sugg.length)) : null),
|
||||
yours.length > 1 ? h("div", { class: "actions" }, h("button", { onclick: () => create(yours) }, "Create all " + yours.length)) : null),
|
||||
h("p", { class: "muted small" }, "Your records use these addresses, but no reverse zone answers \"which host has this address?\" for them" + (views.length ? " in their view" : "") + ". Jarl creates each with a PTR record for every address there. Only your own clients ask this server: the internet asks whoever owns the addresses."),
|
||||
table([
|
||||
views.length ? { label: "View", render: (s) => s.view } : null,
|
||||
{ label: "Network", render: (s) => [h("span", { class: "mono" }, s.prefix), h("div", { class: "muted small" }, s.why)] },
|
||||
{ label: "Zone", render: (s) => h("span", { class: "mono small" }, s.zone) },
|
||||
{ label: "PTR records", render: (s) => [String(s.fill), s.samples.length ? h("div", { class: "muted small mono" }, s.samples.join(", ") + (s.fill > s.samples.length ? ", …" : "")) : null] },
|
||||
{ label: "", render: (s) => h("button", { class: "small", onclick: () => create([s]) }, "Create"), tdClass: "actions-cell" },
|
||||
].filter(Boolean), sugg));
|
||||
yours.length ? table(cols(false), yours) : null,
|
||||
pub.length ? [h("h3", null, "Public addresses: only if they're yours"),
|
||||
h("p", { class: "muted small" }, "Jarl can't tell your own servers from someone else's (a web host's). Create a zone for an address that is yours; dismiss the others. Each gets a zone of its own: the rest of its network belongs to others."),
|
||||
table(cols(true), pub)] : null);
|
||||
}
|
||||
Reference in new issue
Block a user