chore(release): v0.7.6
Ajoute un fichier log texte rotatif (wgsecure.log) dans le dossier applicatif, en complément du journal JSON interne, pour diagnostiquer un échec (ex. split-DNS) sans dépendre de l'UI. Corrige le panneau Journal qui coupait les messages longs sans moyen de les lire en entier (défilement horizontal réactivé + infobulle). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,16 @@ Ce projet suit le [Versionnage Sémantique](https://semver.org/lang/fr/).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [0.7.6] — 2026-09-04
|
||||||
|
|
||||||
|
### Ajouté
|
||||||
|
- **Fichier log texte des opérations.** En plus du journal JSON interne (`events.json`, limité à 200 entrées et illisible hors de l'application), chaque événement est désormais aussi écrit dans `wgsecure.log` (rotation automatique, 1 Mo × 3 fichiers) dans le dossier applicatif (`%APPDATA%\WGSecure` sous Windows, `~/.wgsecure` sous Linux) — consultable avec un simple éditeur de texte pour diagnostiquer un échec (ex. configuration du split-DNS) sans dépendre de l'interface.
|
||||||
|
|
||||||
|
### Corrigé
|
||||||
|
- **Messages du panneau Journal tronqués sans moyen de les lire en entier.** La barre de défilement horizontale était explicitement désactivée sur le panneau Journal, coupant net les messages longs (ex. une erreur NRPT complète sous Windows). Le défilement horizontal est réactivé et une infobulle affiche désormais le message complet au survol de chaque entrée.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [0.7.5] — 2026-09-04
|
## [0.7.5] — 2026-09-04
|
||||||
|
|
||||||
### Corrigé
|
### Corrigé
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
## ──────────────────────────────────────────────
|
## ──────────────────────────────────────────────
|
||||||
|
|
||||||
APP := wgsecure
|
APP := wgsecure
|
||||||
VERSION := 0.7.5
|
VERSION := 0.7.6
|
||||||
VENV := .venv
|
VENV := .venv
|
||||||
PYTHON := $(VENV)/bin/python3
|
PYTHON := $(VENV)/bin/python3
|
||||||
PIP := $(VENV)/bin/pip
|
PIP := $(VENV)/bin/pip
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 🛡️ WGSecure (WGS)
|
# 🛡️ WGSecure (WGS)
|
||||||
|
|
||||||
🚀 v0.7.5 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard
|
🚀 v0.7.6 · 🐍 · 🪟🐧 · 🔐 MFA TOTP · 🛡️ WireGuard
|
||||||
|
|
||||||
**WGSecure** est une interface graphique multiplateforme (Windows & Linux) pour gérer une connexion WireGuard avec une surcouche MFA (authentification à deux facteurs TOTP).
|
**WGSecure** est une interface graphique multiplateforme (Windows & Linux) pour gérer une connexion WireGuard avec une surcouche MFA (authentification à deux facteurs TOTP).
|
||||||
|
|
||||||
@@ -210,4 +210,4 @@ WGSecure/
|
|||||||
## 👤 Auteur
|
## 👤 Auteur
|
||||||
|
|
||||||
Développé par **Johnny** — [JT-Tools](https://github.com/JT-Tools)
|
Développé par **Johnny** — [JT-Tools](https://github.com/JT-Tools)
|
||||||
Version :  — Septembre 2026
|
Version :  — Septembre 2026
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
__version__ = "0.7.5"
|
__version__ = "0.7.6"
|
||||||
APP_NAME = "WGSecure"
|
APP_NAME = "WGSecure"
|
||||||
APP_SHORT = "WGS"
|
APP_SHORT = "WGS"
|
||||||
|
|||||||
@@ -1,17 +1,48 @@
|
|||||||
"""Journal des événements de connexion WGSecure."""
|
"""Journal des événements de connexion WGSecure."""
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
from app.utils.platform_utils import get_config_dir
|
from app.utils.platform_utils import get_config_dir
|
||||||
|
|
||||||
_FILE = "events.json"
|
_FILE = "events.json"
|
||||||
_MAX_ENTRIES = 200
|
_MAX_ENTRIES = 200
|
||||||
|
|
||||||
|
_LOG_FILE = "wgsecure.log"
|
||||||
|
_LOG_LEVELS = {
|
||||||
|
"error": logging.ERROR,
|
||||||
|
"warning": logging.WARNING,
|
||||||
|
}
|
||||||
|
_file_logger: logging.Logger | None = None
|
||||||
|
|
||||||
|
|
||||||
def _path() -> str:
|
def _path() -> str:
|
||||||
return os.path.join(get_config_dir(), _FILE)
|
return os.path.join(get_config_dir(), _FILE)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_file_logger() -> logging.Logger:
|
||||||
|
"""Logger fichier rotatif : trace texte des opérations, lisible sans
|
||||||
|
passer par l'UI (diagnostic d'un échec quand le panneau Journal ne
|
||||||
|
suffit pas)."""
|
||||||
|
global _file_logger
|
||||||
|
if _file_logger is None:
|
||||||
|
logger = logging.getLogger("wgsecure")
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
handler = RotatingFileHandler(
|
||||||
|
os.path.join(get_config_dir(), _LOG_FILE),
|
||||||
|
maxBytes=1_000_000, backupCount=3, encoding="utf-8",
|
||||||
|
)
|
||||||
|
handler.setFormatter(logging.Formatter(
|
||||||
|
"%(asctime)s [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S",
|
||||||
|
))
|
||||||
|
logger.addHandler(handler)
|
||||||
|
logger.propagate = False
|
||||||
|
_file_logger = logger
|
||||||
|
return _file_logger
|
||||||
|
|
||||||
|
|
||||||
def log_event(msg: str, kind: str = "info") -> None:
|
def log_event(msg: str, kind: str = "info") -> None:
|
||||||
"""Ajoute un événement horodaté au journal."""
|
"""Ajoute un événement horodaté au journal."""
|
||||||
events = _load()
|
events = _load()
|
||||||
@@ -21,6 +52,11 @@ def log_event(msg: str, kind: str = "info") -> None:
|
|||||||
"msg": msg,
|
"msg": msg,
|
||||||
})
|
})
|
||||||
_save(events[-_MAX_ENTRIES:])
|
_save(events[-_MAX_ENTRIES:])
|
||||||
|
# Une ligne = un événement, même si msg contient des retours à la ligne
|
||||||
|
# (ex. message de succès de connexion suivi d'un avertissement).
|
||||||
|
_get_file_logger().log(
|
||||||
|
_LOG_LEVELS.get(kind, logging.INFO), msg.replace("\n", " | ")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_events(n: int = 50) -> list[dict]:
|
def get_events(n: int = 50) -> list[dict]:
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class MainWindow(QMainWindow):
|
|||||||
" border: none; font-size: 10px; font-family: Courier; }"
|
" border: none; font-size: 10px; font-family: Courier; }"
|
||||||
"QListWidget::item { padding: 1px 6px; }"
|
"QListWidget::item { padding: 1px 6px; }"
|
||||||
)
|
)
|
||||||
self._log_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
self._log_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
d.addWidget(self._log_list)
|
d.addWidget(self._log_list)
|
||||||
d.addWidget(self._hsep())
|
d.addWidget(self._hsep())
|
||||||
|
|
||||||
@@ -454,6 +454,10 @@ class MainWindow(QMainWindow):
|
|||||||
color = theme.LOG_COLORS.get(kind, theme.ACCENT_LIGHT)
|
color = theme.LOG_COLORS.get(kind, theme.ACCENT_LIGHT)
|
||||||
item = QListWidgetItem(f"[{ts}] {msg}")
|
item = QListWidgetItem(f"[{ts}] {msg}")
|
||||||
item.setForeground(QColor(color))
|
item.setForeground(QColor(color))
|
||||||
|
# Ligne trop longue pour tenir dans le panneau : barre de défilement
|
||||||
|
# horizontale (ci-dessus) + tooltip pour lire le message complet
|
||||||
|
# sans avoir à défiler.
|
||||||
|
item.setToolTip(msg)
|
||||||
self._log_list.addItem(item)
|
self._log_list.addItem(item)
|
||||||
self._log_list.scrollToBottom()
|
self._log_list.scrollToBottom()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
; ──────────────────────────────────────────────
|
; ──────────────────────────────────────────────
|
||||||
|
|
||||||
#define MyAppName "WGSecure"
|
#define MyAppName "WGSecure"
|
||||||
#define MyAppVersion "0.7.5"
|
#define MyAppVersion "0.7.6"
|
||||||
#define MyAppPublisher "WGSecure"
|
#define MyAppPublisher "WGSecure"
|
||||||
#define MyAppExeName "wgsecure.exe"
|
#define MyAppExeName "wgsecure.exe"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user