fix htmx refactor route mismatches and remaining TODO items

- wireguard: POST /peers with JSON encoding (was /add-peer)
- rules: delete by rule_id in URL path (was JSON body); pass rule objects with id from server; add hx-disable to initial render
- nat: port forward delete uses URL path params to match blueprint
- nat: masquerade toggle uses native hx-post/hx-vals (was inline fetch)
- app.js renderers updated to use URL path deletes for rules and forwards
- remove TODO.md
This commit is contained in:
2026-05-17 01:15:52 +00:00
parent 0e7090a2cb
commit 37039351be
26 changed files with 1737 additions and 848 deletions
+21 -7
View File
@@ -6,12 +6,15 @@ bootstrap, basic-auth htpasswd files, and nginx reload cycles.
"""
import json
import logging
import os
import subprocess
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
logger = logging.getLogger(__name__)
PROJECT_DIR = Path(__file__).resolve().parent.parent
CONFIG_DIR = PROJECT_DIR / "config" / "nginx"
DATA_DIR = PROJECT_DIR / "data" / "nginx"
@@ -141,6 +144,13 @@ def add_domain(
entry["headers"] = extra_headers
cfg["domains"][domain] = entry
save_config(cfg)
logger.info(
"Proxy domain '%s' added -> %s:%d (%s)",
domain,
backend_host,
backend_port,
backend_proto,
)
def remove_domain(domain) -> None:
@@ -150,6 +160,7 @@ def remove_domain(domain) -> None:
site = SITES_DIR / f"{domain}.conf"
if site.exists():
site.unlink()
logger.info("Proxy domain '%s' removed", domain)
def update_domain(domain, **kwargs) -> None:
@@ -163,6 +174,7 @@ def update_domain(domain, **kwargs) -> None:
else:
entry[key] = val
save_config(cfg)
logger.info("Proxy domain '%s' updated: %s", domain, list(kwargs.keys()))
# ------------------------------------------------------------------
@@ -240,6 +252,8 @@ def write_all_sites() -> None:
if old.suffix == ".conf" and old.name not in written:
old.unlink()
logger.info("All nginx site configs written (%d sites)", len(written))
def write_include_file() -> None:
tmpl = ENV.get_template("nginx/include.conf")
@@ -282,6 +296,10 @@ def test_config() -> tuple[bool, str]:
output = (result.stderr or result.stdout or "").strip()
if not output and ok:
output = "nginx configuration test passed"
if ok:
logger.info("nginx config test passed")
else:
logger.error("nginx config test failed: %s", output)
return ok, output
@@ -293,6 +311,7 @@ def apply() -> None:
if not ok:
raise RuntimeError(f"nginx config test failed: {msg}")
_run(["sudo", "nginx", "-s", "reload"])
logger.info("nginx configuration applied and reloaded")
# ------------------------------------------------------------------
@@ -321,6 +340,7 @@ def set_management_proxy(
save_config(cfg)
if auth_user and auth_pass:
write_htpasswd(auth_user, auth_pass)
logger.info("Management proxy set to '%s'", domain)
# ------------------------------------------------------------------
@@ -329,13 +349,7 @@ def set_management_proxy(
def write_htpasswd(user, password) -> None:
"""
Append (or create) an htpasswd entry for *user*.
Uses passlib's apache_passwd hash so the file remains portable.
If passlib is unavailable falls back to Python's built-in crypt.
If the user already exists the line is replaced in-place.
"""
"""Append (or create) an htpasswd entry for *user*."""
_ensure_dirs()
hashed = _hash_password(password)
existing = {}