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:
+34
-7
@@ -4,6 +4,8 @@ webui/api/wireguard.py - WireGuard tunnel management API blueprint.
|
||||
Exposed at /api/wireguard/* and delegates to lib.wireguard.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from lib.wireguard import (
|
||||
@@ -20,6 +22,7 @@ from lib.wireguard import (
|
||||
status,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
bp = Blueprint("wireguard", __name__)
|
||||
|
||||
|
||||
@@ -51,6 +54,7 @@ def get_config_bp():
|
||||
safe["interface"].pop("private_key", None)
|
||||
return _ok(safe)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to read WireGuard config: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -67,6 +71,7 @@ def post_config():
|
||||
safe["interface"].pop("private_key", None)
|
||||
return _ok(safe)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to save WireGuard config: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -79,8 +84,21 @@ def post_config():
|
||||
def apply_bp():
|
||||
try:
|
||||
apply()
|
||||
logger.info("WireGuard tunnel applied via API")
|
||||
return _ok(None)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to apply WireGuard config: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@bp.route("/up", methods=["POST"])
|
||||
def up_bp():
|
||||
try:
|
||||
apply()
|
||||
logger.info("WireGuard tunnel started via API")
|
||||
return _ok(None)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to start WireGuard tunnel: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -88,8 +106,10 @@ def apply_bp():
|
||||
def down_bp():
|
||||
try:
|
||||
down()
|
||||
logger.info("WireGuard tunnel brought down via API")
|
||||
return _ok(None)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to bring down WireGuard tunnel: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -103,6 +123,7 @@ def status_bp():
|
||||
try:
|
||||
return _ok(status())
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to get WireGuard status: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -115,8 +136,10 @@ def status_bp():
|
||||
def initialize_bp():
|
||||
try:
|
||||
initialize()
|
||||
logger.info("WireGuard initialized via API")
|
||||
return _ok(None)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to initialize WireGuard: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -125,7 +148,7 @@ def initialize_bp():
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@bp.route("/add-peer", methods=["POST"])
|
||||
@bp.route("/peers", methods=["POST"])
|
||||
def add_peer_bp():
|
||||
body = request.get_json(silent=True) or {}
|
||||
name = body.get("name", "").strip()
|
||||
@@ -141,23 +164,24 @@ def add_peer_bp():
|
||||
)
|
||||
safe = dict(peer)
|
||||
safe.pop("private_key", None)
|
||||
logger.info("WireGuard peer '%s' added via API", name)
|
||||
return _ok(safe)
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to add peer '%s': %s", name, exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@bp.route("/remove-peer", methods=["DELETE"])
|
||||
def remove_peer_bp():
|
||||
name = request.args.get("name", "").strip()
|
||||
if not name:
|
||||
return _error("Query parameter 'name' is required", 400)
|
||||
@bp.route("/peers/<name>", methods=["DELETE"])
|
||||
def remove_peer_bp(name):
|
||||
try:
|
||||
cfg = get_config()
|
||||
if name not in cfg.get("peers", {}):
|
||||
return _error(f"Peer '{name}' not found", 404)
|
||||
remove_peer(name)
|
||||
logger.info("WireGuard peer '%s' removed via API", name)
|
||||
return _ok({"name": name})
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to remove peer '%s': %s", name, exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -166,6 +190,7 @@ def peers_bp():
|
||||
try:
|
||||
return _ok(get_peers())
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to list WireGuard peers: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -174,6 +199,7 @@ def peer_status_bp():
|
||||
try:
|
||||
return _ok(get_peer_status())
|
||||
except RuntimeError as exc:
|
||||
logger.error("Failed to get WireGuard peer status: %s", exc)
|
||||
return _error(str(exc), 500)
|
||||
|
||||
|
||||
@@ -196,12 +222,13 @@ def generate_client_bp():
|
||||
server_pubkey = cfg["interface"].get("public_key", "")
|
||||
if not server_endpoint:
|
||||
_ = cfg["interface"].get("listen_port", 51820)
|
||||
# Can't auto-derive public IP; ask user to provide it
|
||||
return _error(
|
||||
"Field 'server_endpoint' is required (e.g., '203.0.113.1:51820')", 400
|
||||
)
|
||||
conf_text = generate_client_conf(name, server_endpoint, server_pubkey)
|
||||
logger.info("Client config generated for peer '%s' via API", name)
|
||||
return _ok({"config": conf_text})
|
||||
except (KeyError, ValueError, RuntimeError) as exc:
|
||||
code = 404 if isinstance(exc, (KeyError, ValueError)) else 500
|
||||
logger.error("Failed to generate client config for '%s': %s", name, exc)
|
||||
return _error(str(exc), code)
|
||||
|
||||
Reference in New Issue
Block a user