Files
WGSecure/app/app_info.py
T
tuxgyver 8c09c02362 v0.7.0 : instance unique, handshake ré-affiché, sudoers fiabilisé, À propos refaite
- Instance unique : un second lancement réveille l'instance active.
- Autostart et reconnexion auto activés par défaut (nouvelle installation).
- Page « À propos » refaite en 5 onglets (contenu séparé dans app_info.py).
- Corrige le handshake/RX-TX qui ne s'affichaient plus (wg show sans élévation).
- Corrige le diagnostic sudo trompeur (sondes qui ne matchaient jamais les règles).
- Corrige make setup-sudoers bloqué hors session graphique (pkexec -> sudo), idempotent.
- Corrige le README : Kill Switch inexistant retiré, ordre d'élévation réel documenté.
2026-09-01 19:18:24 +02:00

129 lines
5.2 KiB
Python

"""Contenu de la page « À propos ».
Source de vérité unique pour les textes de la page : l'onglet Qt
(app/ui/admin_window.py, méthode `_tab_about`) ne fait que les mettre en
forme. La version, elle, vient de `app.__version__` (app/__init__.py), le
seul endroit où elle est bumpée à chaque release — jamais recopiée en dur ici.
"""
import os
from app import __version__
_CHANGELOG_PATH = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "CHANGELOG.md"
)
APP_NAME = "WGSecure"
TAGLINE = "Client WireGuard avec surcouche MFA TOTP, pour Linux et Windows"
VERSION = __version__
LICENSE = "Usage personnel"
REPO_URL = "https://git.tuxtech.fr/tuxgyver/WGSecure"
AUTHOR_NAME = "Johnny"
AUTHOR_ROLE = "Auteur"
FEATURES = [
(
"Connexion en un clic",
"Icône dans la barre système, montage/démontage du tunnel WireGuard "
"sans quitter le systray.",
),
(
"Suivi en direct",
"Statut RX/TX, dernier handshake et latence affichés en continu ; "
"graphique de bande passante sur les 30 dernières secondes.",
),
(
"Journal et historique",
"Horodatage de chaque connexion, déconnexion et erreur ; historique "
"des sessions passées (durée, volume transféré, serveur).",
),
(
"Multi-profils",
"Plusieurs configurations WireGuard sauvegardées et basculables, "
"avec import/export de fichiers .conf standards.",
),
(
"Génération de clés",
"Paire de clés Curve25519 générée nativement en Python, sans "
"dépendre du binaire `wg` pour cette étape.",
),
(
"Mode Admin protégé",
"Configuration complète (serveur, DNS, IP, keepalive, MTU) derrière "
"un mot de passe et, en option, une double authentification TOTP.",
),
(
"Diagnostic réseau",
"Test de handshake réel sans monter le tunnel, détection du "
"filtrage sur port source, et test de fuite DNS.",
),
(
"Auto-reconnexion",
"Surveillance du tunnel et reconnexion automatique en cas de "
"coupure, à l'intervalle choisi.",
),
]
GUARANTEES_INTRO = "Ce que l'application garantit, quel que soit le profil configuré :"
GUARANTEES = [
"Le mot de passe du mode Admin n'est jamais stocké en clair : il est "
"haché avec bcrypt (12 tours) avant d'être écrit dans la configuration.",
"La clé privée WireGuard est toujours écrite avec des permissions "
"restrictives (600) — aussi bien dans la configuration locale que dans "
"le fichier installé sous /etc/wireguard.",
"Le test de handshake et le sondage de statut (dernier handshake, "
"RX/TX) n'ouvrent jamais de tunnel et ne modifient aucun fichier : ce "
"sont des lectures ou un simple datagramme UDP jetable.",
"Les commandes système nécessitant les privilèges root sont exécutées "
"une par une, jamais l'application entière : `make setup-sudoers` "
"autorise sans mot de passe uniquement wg-quick, wg, et la suppression "
"d'interface/DNS orpheline — jamais un accès root généralisé.",
"Le sondage périodique de l'état du tunnel (toutes les 3 secondes) "
"n'ouvre jamais de dialogue de mot de passe ou d'UAC : il échoue "
"silencieusement si les privilèges nécessaires ne sont pas déjà "
"accordés.",
"Le test de fuite DNS vérifie que les requêtes sortent bien par le "
"resolver attendu une fois le tunnel monté, plutôt que de supposer la "
"configuration correcte.",
]
TECH_STACK = [
("Interface", "PyQt6"),
("Cryptographie", "cryptography (X25519, ChaCha20-Poly1305, bcrypt)"),
("MFA", "pyotp (TOTP) + qrcode/Pillow pour le QR code"),
("Tunnel", "wg-quick / wg (Linux), WireGuard for Windows"),
("Élévation de privilèges", "sudo NOPASSWD ciblé, repli askpass puis pkexec"),
("Empaquetage", "PyInstaller (Linux/Windows) + Inno Setup (installeur Windows)"),
]
def parse_changelog() -> list[dict]:
"""Lit CHANGELOG.md : titres `## [x.y.z] — date`, sous-titres `### ...`
et puces `- ...` (avec leurs lignes de continuation) uniquement — le
format effectivement utilisé par ce fichier, sans dépendance Markdown.
"""
entries: list[dict] = []
version = None
section = None
try:
with open(_CHANGELOG_PATH, encoding="utf-8") as f:
for raw in f:
line = raw.rstrip("\n")
if line.startswith("## "):
version = {"title": line[3:].strip(), "sections": []}
entries.append(version)
section = None
elif line.startswith("### ") and version is not None:
section = {"name": line[4:].strip(), "items": []}
version["sections"].append(section)
elif line.startswith("- ") and section is not None:
section["items"].append(line[2:].strip())
elif (line.strip() and section is not None and section["items"]
and not line.startswith(("#", "---"))):
# Ligne de continuation d'une puce étalée sur plusieurs lignes.
section["items"][-1] += " " + line.strip()
except FileNotFoundError:
pass
return entries