"""Valeurs par defaut d'un groupe (dossier de sessions) : username, port, cle SSH, bastion, keepalive. Choix delibere : l'heritage s'applique au moment de la creation d'une session (pre-remplissage explicite dans l'editeur), pas par une resolution dynamique a chaque connexion. Modifier les parametres d'un groupe ne change donc jamais retroactivement les sessions deja creees - elles restent des valeurs normales, librement modifiables, sans indirection a suivre dans tout le reste du code (ConnectionController, SSHConnection, resolve_bastion_target...).""" from __future__ import annotations from dataclasses import asdict, dataclass, field from pathlib import Path from app.paths import DATA_DIR from app.session_manager import AUTH_AUTO, BastionConfig from app.storage.json_store import load_json_document, save_json_document GROUPS_FILE = DATA_DIR / "groups.json" SCHEMA_VERSION = 1 @dataclass class GroupSettings: path: str = "" # ex: "Production/Web", correspond a Session.group username: str = "" port: int = 22 auth_type: str = AUTH_AUTO key_path: str = "" bastion: BastionConfig = field(default_factory=BastionConfig) keepalive_enabled: bool = True keepalive_interval: int = 30 keepalive_count_max: int = 3 def to_dict(self) -> dict: return asdict(self) @staticmethod def from_dict(data: dict) -> GroupSettings: g = GroupSettings() for k in GroupSettings.__dataclass_fields__: if k not in data: continue v = data[k] if k == "bastion" and isinstance(v, dict): v = BastionConfig.from_dict(v) setattr(g, k, v) return g class GroupSettingsStore: """Charge/sauvegarde les parametres par defaut de chaque groupe depuis data/groups.json. Un groupe sans entree ici n'a simplement aucune valeur par defaut (comportement actuel, inchange).""" def __init__(self, path: Path = GROUPS_FILE): self.path = path self.groups: list[GroupSettings] = [] self.load_warning: str | None = None self.load() def load(self) -> None: was_missing = not self.path.exists() document, warning = load_json_document( self.path, default={"schema_version": SCHEMA_VERSION, "groups": []}, current_version=SCHEMA_VERSION, ) self.load_warning = warning self.groups = [GroupSettings.from_dict(g) for g in document.get("groups", [])] if was_missing: self.save() def save(self) -> None: payload = {"schema_version": SCHEMA_VERSION, "groups": [g.to_dict() for g in self.groups]} save_json_document(self.path, payload) def get(self, group_path: str) -> GroupSettings | None: return next((g for g in self.groups if g.path == group_path), None) def set(self, settings: GroupSettings) -> None: """Cree ou remplace les parametres du groupe (identifie par son path).""" for i, g in enumerate(self.groups): if g.path == settings.path: self.groups[i] = settings self.save() return self.groups.append(settings) self.save() def delete(self, group_path: str) -> None: self.groups = [g for g in self.groups if g.path != group_path] self.save()