GUI: add persistent QR/config view and handshake-based online status

This commit is contained in:
Ruslan
2026-04-14 12:27:26 +03:00
parent bdfc648bba
commit bb6cdb58ed
2 changed files with 56 additions and 8 deletions

View File

@@ -4,6 +4,7 @@ import io
import os
import sqlite3
import subprocess
import time
from datetime import datetime
import qrcode
@@ -38,9 +39,13 @@ def ensure_schema():
public_key TEXT UNIQUE NOT NULL,
client_address TEXT,
advertised_routes TEXT,
client_conf TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
""")
cols = {row[1] for row in cur.execute("PRAGMA table_info(peers)").fetchall()}
if "client_conf" not in cols:
cur.execute("ALTER TABLE peers ADD COLUMN client_conf TEXT")
conn.commit()
@@ -83,15 +88,18 @@ def wg_dump():
parts = line.split("\t")
if len(parts) < 8:
continue
latest_ts = 0
latest = "never"
if parts[5].isdigit() and int(parts[5]) > 0:
latest = datetime.utcfromtimestamp(int(parts[5])).strftime("%Y-%m-%d %H:%M:%S UTC")
latest_ts = int(parts[5])
latest = datetime.utcfromtimestamp(latest_ts).strftime("%Y-%m-%d %H:%M:%S UTC")
peers.append(
{
"public_key": parts[0],
"endpoint": parts[2] or "-",
"allowed_ips": parts[3],
"latest_handshake": latest,
"latest_handshake_ts": latest_ts,
"rx_bytes": int(parts[6] or 0),
"tx_bytes": int(parts[7] or 0),
}
@@ -160,11 +168,15 @@ def index():
items = []
seen = set()
now = int(time.time())
for row in db_peers:
rt = runtime.get(row["public_key"], {})
ts = int(rt.get("latest_handshake_ts", 0) or 0)
is_online = ts > 0 and (now - ts) <= 180
seen.add(row["public_key"])
items.append(
{
"id": row["id"],
"name": row["name"],
"public_key": row["public_key"],
"client_address": row.get("client_address") or "-",
@@ -174,15 +186,18 @@ def index():
"latest_handshake": rt.get("latest_handshake", "offline"),
"rx": bytes_h(rt.get("rx_bytes", 0)),
"tx": bytes_h(rt.get("tx_bytes", 0)),
"status": "online" if rt else "offline",
"status": "online" if is_online else "offline",
}
)
for pk, rt in runtime.items():
if pk in seen:
continue
ts = int(rt.get("latest_handshake_ts", 0) or 0)
is_online = ts > 0 and (now - ts) <= 180
items.append(
{
"id": None,
"name": "(external)",
"public_key": pk,
"client_address": rt.get("allowed_ips", "-").split(",", 1)[0],
@@ -192,7 +207,7 @@ def index():
"latest_handshake": rt.get("latest_handshake", "offline"),
"rx": bytes_h(rt.get("rx_bytes", 0)),
"tx": bytes_h(rt.get("tx_bytes", 0)),
"status": "online",
"status": "online" if is_online else "offline",
}
)
@@ -267,13 +282,13 @@ def new_peer():
with db_conn() as conn:
cur = conn.cursor()
cur.execute(
"UPDATE peers SET name=?, client_address=?, advertised_routes=? WHERE public_key=?",
(name, client_addr, routes, client_pub),
"UPDATE peers SET name=?, client_address=?, advertised_routes=?, client_conf=? WHERE public_key=?",
(name, client_addr, routes, client_conf, client_pub),
)
if cur.rowcount == 0:
cur.execute(
"INSERT INTO peers(name, public_key, client_address, advertised_routes) VALUES (?,?,?,?)",
(name, client_pub, client_addr, routes),
"INSERT INTO peers(name, public_key, client_address, advertised_routes, client_conf) VALUES (?,?,?,?,?)",
(name, client_pub, client_addr, routes, client_conf),
)
conn.commit()
@@ -286,6 +301,32 @@ def new_peer():
)
@app.route("/peers/<int:peer_id>")
def peer_view(peer_id: int):
with db_conn() as conn:
cur = conn.cursor()
cur.execute("SELECT * FROM peers WHERE id = ?", (peer_id,))
row = cur.fetchone()
if not row:
flash("Клиент не найден", "error")
return redirect(url_for("index"))
item = dict(row)
conf = item.get("client_conf") or ""
if not conf:
flash("Для этого клиента не найден сохраненный конфиг", "error")
return redirect(url_for("index"))
qr_b64 = to_png_b64(conf)
return render_template(
"peer_created.html",
name=item.get("name", "peer"),
client_conf=conf,
qr_b64=qr_b64,
public_key=item.get("public_key", ""),
)
@app.route("/scripts")
def scripts():
commands = {