docs: add docstrings to all API endpoints and daemon handlers
Add comprehensive docstrings to firewall, DHCP, proxy, wireguard, certs, and logs API endpoints. Document parameters, return values, and error cases for the documentation system.
This commit is contained in:
+160
-4
@@ -49,6 +49,11 @@ _reloading = False
|
||||
|
||||
|
||||
def _sighup_handler(signum, frame):
|
||||
"""Handle SIGHUP by reloading modules then restarting via SIGTERM.
|
||||
|
||||
Reloads all ``webui.*`` and ``lib.*`` modules, re-registers blueprints,
|
||||
and requests systemd restart by sending SIGTERM with default handler.
|
||||
"""
|
||||
global _reloading
|
||||
if _reloading:
|
||||
return
|
||||
@@ -99,11 +104,20 @@ for name, _ in BLUEPRINTS:
|
||||
|
||||
@app.before_request
|
||||
def _log_request_start():
|
||||
"""Record request start time for duration tracking."""
|
||||
request._start_time = time.monotonic()
|
||||
|
||||
|
||||
@app.after_request
|
||||
def _log_request_finish(response):
|
||||
"""Log request duration and status code after response generation.
|
||||
|
||||
Args:
|
||||
response: The HTTP response object.
|
||||
|
||||
Returns:
|
||||
The unchanged response object.
|
||||
"""
|
||||
elapsed_ms = (
|
||||
time.monotonic() - getattr(request, "_start_time", time.monotonic())
|
||||
) * 1000
|
||||
@@ -124,6 +138,14 @@ def _log_request_finish(response):
|
||||
|
||||
@app.template_filter("timestamp")
|
||||
def timestamp_filter(value):
|
||||
"""Convert an ISO-8601 timestamp string to ``YYYY-MM-DD HH:MM:SS``.
|
||||
|
||||
Args:
|
||||
value: ISO timestamp string (may end with ``Z``).
|
||||
|
||||
Returns:
|
||||
Formatted date string, or original value on parse failure.
|
||||
"""
|
||||
if not value:
|
||||
return ""
|
||||
try:
|
||||
@@ -135,6 +157,14 @@ def timestamp_filter(value):
|
||||
|
||||
@app.template_filter("bytes")
|
||||
def bytes_filter(value):
|
||||
"""Convert a byte count to a human-readable size string (B/KB/MB…).
|
||||
|
||||
Args:
|
||||
value: Numeric byte count.
|
||||
|
||||
Returns:
|
||||
Formatted size string, or original value on parse failure.
|
||||
"""
|
||||
try:
|
||||
num = float(value)
|
||||
except (ValueError, TypeError):
|
||||
@@ -150,6 +180,14 @@ def bytes_filter(value):
|
||||
|
||||
@app.template_filter("duration")
|
||||
def duration_filter(value):
|
||||
"""Convert a duration in seconds to a human-readable string.
|
||||
|
||||
Args:
|
||||
value: Duration in seconds.
|
||||
|
||||
Returns:
|
||||
Formatted string (e.g. ``3d 2h 15m 30s``), or original value on failure.
|
||||
"""
|
||||
try:
|
||||
total = int(float(value))
|
||||
except (ValueError, TypeError):
|
||||
@@ -172,6 +210,14 @@ def duration_filter(value):
|
||||
|
||||
@app.template_filter("json_pretty")
|
||||
def json_pretty_filter(value):
|
||||
"""Serialize *value* as indented JSON for template display.
|
||||
|
||||
Args:
|
||||
value: Any JSON-serializable object.
|
||||
|
||||
Returns:
|
||||
Pretty-printed JSON string with 2-space indent.
|
||||
"""
|
||||
import json
|
||||
|
||||
try:
|
||||
@@ -186,7 +232,15 @@ def json_pretty_filter(value):
|
||||
|
||||
|
||||
def _safely(fn, default=None):
|
||||
"""Call *fn* and return *default* on any exception."""
|
||||
"""Call *fn* and return *default* on any exception.
|
||||
|
||||
Args:
|
||||
fn: Zero-argument callable to execute.
|
||||
default: Fallback value returned when *fn* raises.
|
||||
|
||||
Returns:
|
||||
The result of ``fn()``, or *default* if an exception occurred.
|
||||
"""
|
||||
try:
|
||||
return fn()
|
||||
except Exception as exc:
|
||||
@@ -195,7 +249,15 @@ def _safely(fn, default=None):
|
||||
|
||||
|
||||
def _get_service_status(dnsmasq_info, wg_info):
|
||||
"""Build a service status dict for the dashboard template."""
|
||||
"""Build a service status dict for the dashboard template.
|
||||
|
||||
Args:
|
||||
dnsmasq_info: Dnsmasq status payload from the daemon.
|
||||
wg_info: WireGuard status payload from the daemon.
|
||||
|
||||
Returns:
|
||||
Dict mapping service names to ``{running: bool}``.
|
||||
"""
|
||||
services = {}
|
||||
if dnsmasq_info:
|
||||
services["Dnsmasq"] = {
|
||||
@@ -209,17 +271,24 @@ def _get_service_status(dnsmasq_info, wg_info):
|
||||
|
||||
|
||||
def _fw_config_get() -> dict[str, Any]:
|
||||
"""Read firewall config via daemon."""
|
||||
"""Read the current firewall config from the daemon."""
|
||||
return get("/firewall/config")
|
||||
|
||||
|
||||
def _load_status_all() -> dict[str, Any]:
|
||||
"""Load all system state in one call."""
|
||||
"""Load all subsystem status from the daemon in a single call."""
|
||||
return get("/status/all")
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def root_redirect():
|
||||
"""Redirect root URL to the dashboard.
|
||||
|
||||
GET /
|
||||
|
||||
Returns:
|
||||
Redirect response to the dashboard page.
|
||||
"""
|
||||
from flask import redirect, url_for
|
||||
|
||||
return redirect(url_for("dashboard"))
|
||||
@@ -227,6 +296,21 @@ def root_redirect():
|
||||
|
||||
@app.route("/dashboard")
|
||||
def dashboard():
|
||||
"""Render the main dashboard overview page.
|
||||
|
||||
GET /
|
||||
|
||||
Template context:
|
||||
active_zones (dict): Active firewalld zones and bound interfaces.
|
||||
interfaces (list): Available network interfaces with zone bindings.
|
||||
dnsmasq (dict): Dnsmasq status information.
|
||||
domains (list): Configured proxy domains.
|
||||
certs (list): ACME certificate inventory.
|
||||
wg_status (dict): WireGuard tunnel status.
|
||||
services (dict): Service running indicators (Dnsmasq, WireGuard).
|
||||
firewall_config (dict): Declarative firewall JSON config.
|
||||
firewall_pending (dict): Pending firewall rules awaiting apply.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
fw_state = all_status.get("firewall", {}) or {}
|
||||
dm_state = all_status.get("dnsmasq", {}) or {}
|
||||
@@ -257,6 +341,16 @@ def dashboard():
|
||||
|
||||
@app.route("/interfaces")
|
||||
def interfaces_page():
|
||||
"""Render the network interfaces management page.
|
||||
|
||||
GET /interfaces
|
||||
|
||||
Template context:
|
||||
interfaces (list): Available network interfaces.
|
||||
zones (list): Zone names bound to interfaces.
|
||||
firewall_config (dict): Declarative firewall JSON config.
|
||||
firewall_pending (dict): Pending firewall rules awaiting apply.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
fw_state = all_status.get("firewall", {}) or {}
|
||||
return render_template(
|
||||
@@ -270,6 +364,16 @@ def interfaces_page():
|
||||
|
||||
@app.route("/zones")
|
||||
def zones_page():
|
||||
"""Render the firewall zones management page.
|
||||
|
||||
GET /zones
|
||||
|
||||
Template context:
|
||||
zones (list): All zone configurations.
|
||||
services (list): Available service identifiers for zone policies.
|
||||
firewall_config (dict): Declarative firewall JSON config.
|
||||
firewall_pending (dict): Pending firewall rules awaiting apply.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
fw_state = all_status.get("firewall", {}) or {}
|
||||
return render_template(
|
||||
@@ -283,6 +387,14 @@ def zones_page():
|
||||
|
||||
@app.route("/rules")
|
||||
def rules_page():
|
||||
"""Render the firewall rich-rules editor page.
|
||||
|
||||
GET /rules
|
||||
|
||||
Template context:
|
||||
zones (list): Zone names containing rich rules.
|
||||
rules (dict | None): Zone name → rich rule mappings (``None`` if empty).
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
fw_state = all_status.get("firewall", {}) or {}
|
||||
zones = list(fw_state.get("zones", {}).keys())
|
||||
@@ -296,6 +408,13 @@ def rules_page():
|
||||
|
||||
@app.route("/nat")
|
||||
def nat_page():
|
||||
"""Render the NAT rules management page.
|
||||
|
||||
GET /nat
|
||||
|
||||
Template context:
|
||||
zones (list): Zone configurations containing NAT rules.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
fw_state = all_status.get("firewall", {}) or {}
|
||||
return render_template("nat.html", zones=list(fw_state.get("zones", {}).values()))
|
||||
@@ -303,6 +422,15 @@ def nat_page():
|
||||
|
||||
@app.route("/dhcp")
|
||||
def dhcp_page():
|
||||
"""Render the DHCP/Dnsmasq configuration page.
|
||||
|
||||
GET /dhcp
|
||||
|
||||
Template context:
|
||||
config (dict): Dnsmasq configuration settings.
|
||||
status (dict): Dnsmasq runtime status.
|
||||
leases (list): Current DHCP lease table.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
dm_state = all_status.get("dnsmasq", {}) or {}
|
||||
return render_template(
|
||||
@@ -315,6 +443,14 @@ def dhcp_page():
|
||||
|
||||
@app.route("/proxy")
|
||||
def proxy_page():
|
||||
"""Render the reverse proxy / SSL termination management page.
|
||||
|
||||
GET /proxy
|
||||
|
||||
Template context:
|
||||
domains (list): Configured proxy domains with upstream targets.
|
||||
config (dict): Nginx configuration settings.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
ng_state = all_status.get("nginx", {}) or {}
|
||||
return render_template(
|
||||
@@ -326,6 +462,14 @@ def proxy_page():
|
||||
|
||||
@app.route("/certs")
|
||||
def certs_page():
|
||||
"""Render the SSL certificate management page.
|
||||
|
||||
GET /certs
|
||||
|
||||
Template context:
|
||||
certs (list): ACME certificate inventory.
|
||||
email (str): Configured ACME registration email.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
ac_state = all_status.get("acme", {}) or {}
|
||||
return render_template(
|
||||
@@ -337,6 +481,14 @@ def certs_page():
|
||||
|
||||
@app.route("/wireguard")
|
||||
def wireguard_page():
|
||||
"""Render the WireGuard VPN management page.
|
||||
|
||||
GET /wireguard
|
||||
|
||||
Template context:
|
||||
config (dict): WireGuard tunnel configuration.
|
||||
status (dict): WireGuard runtime status.
|
||||
"""
|
||||
all_status = _safely(_load_status_all, {})
|
||||
wg_state = all_status.get("wireguard", {}) or {}
|
||||
return render_template(
|
||||
@@ -348,6 +500,10 @@ def wireguard_page():
|
||||
|
||||
@app.route("/logs")
|
||||
def logs_page():
|
||||
"""Render the system logs viewer page.
|
||||
|
||||
GET /logs
|
||||
"""
|
||||
return render_template("logs.html")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user