Protection multi-postes + reorganisation dashboard Vision
Imposing Tool : - Genere un ID machine unique (hash hostname + MAC) - Envoie machine_id + hostname NetBIOS au check de licence - Bloque si nombre max de postes atteint Vision (LXC 112) : - Table license_devices (machine_id, hostname, first/last_seen) - Colonne max_devices dans licenses (defaut 1) - API : verifie le nombre de postes, enregistre chaque device - API : endpoint devices (liste + suppression par poste) - Dashboard : colonne "Postes" cliquable (X/max) avec modal - Modal devices : liste des postes avec hostname, suppression - Champ "Postes max" dans le modal licence - Onglet 1 = Licences (copycaisse + imposing unifies) - Onglet 2 = Clients (gestion clients) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
main.py
28
main.py
@@ -21,10 +21,34 @@ sys.path.insert(0, BUNDLE_DIR)
|
|||||||
|
|
||||||
from PyQt6.QtWidgets import QApplication, QInputDialog, QMessageBox, QLineEdit
|
from PyQt6.QtWidgets import QApplication, QInputDialog, QMessageBox, QLineEdit
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import platform
|
||||||
|
import socket
|
||||||
|
import uuid
|
||||||
|
|
||||||
LICENSE_API = "https://vision.copydev.fr/api/license.php"
|
LICENSE_API = "https://vision.copydev.fr/api/license.php"
|
||||||
LICENSE_FILE = os.path.join(BASE_DIR, ".license")
|
LICENSE_FILE = os.path.join(BASE_DIR, ".license")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_machine_id():
|
||||||
|
"""Generer un identifiant unique pour cette machine."""
|
||||||
|
raw = ""
|
||||||
|
try:
|
||||||
|
raw += platform.node()
|
||||||
|
raw += str(uuid.getnode()) # MAC address
|
||||||
|
except Exception:
|
||||||
|
raw += "unknown"
|
||||||
|
return hashlib.sha256(raw.encode()).hexdigest()[:32]
|
||||||
|
|
||||||
|
|
||||||
|
def _get_hostname():
|
||||||
|
"""Recuperer le nom NetBIOS / hostname."""
|
||||||
|
try:
|
||||||
|
return platform.node() or socket.gethostname()
|
||||||
|
except Exception:
|
||||||
|
return "inconnu"
|
||||||
|
|
||||||
|
|
||||||
def _load_license_cache():
|
def _load_license_cache():
|
||||||
"""Charger le cache de licence local."""
|
"""Charger le cache de licence local."""
|
||||||
if not os.path.exists(LICENSE_FILE):
|
if not os.path.exists(LICENSE_FILE):
|
||||||
@@ -48,7 +72,9 @@ def _save_license_cache(data):
|
|||||||
def _check_license_online(key):
|
def _check_license_online(key):
|
||||||
"""Verifier la licence aupres du serveur Vision."""
|
"""Verifier la licence aupres du serveur Vision."""
|
||||||
try:
|
try:
|
||||||
url = f"{LICENSE_API}?key={urllib.parse.quote(key)}"
|
mid = _get_machine_id()
|
||||||
|
hname = _get_hostname()
|
||||||
|
url = f"{LICENSE_API}?key={urllib.parse.quote(key)}&machine_id={urllib.parse.quote(mid)}&hostname={urllib.parse.quote(hname)}"
|
||||||
req = urllib.request.Request(url, headers={"User-Agent": "CopydevImposingTool/1.0"})
|
req = urllib.request.Request(url, headers={"User-Agent": "CopydevImposingTool/1.0"})
|
||||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||||
data = json.loads(resp.read().decode())
|
data = json.loads(resp.read().decode())
|
||||||
|
|||||||
Reference in New Issue
Block a user