2026-10-11 19:59:07 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Le plan de `forge_cles.py` : ajouter la cle publiee, retirer la perimee, refuser l'ecriture.
|
|
|
|
|
|
|
|
|
|
Pur : aucun appel a la forge. Ce que le script ECRIT est rendu par `plan()` ; s'il se trompe
|
|
|
|
|
ici, il se trompe sur la forge — c'est donc ici qu'on l'epingle.
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
import unittest
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "scripts"))
|
|
|
|
|
import forge_cles as fc # noqa: E402
|
|
|
|
|
|
|
|
|
|
CLE = "ssh-ed25519 AAAALECTURE"
|
|
|
|
|
AUTRE = "ssh-ed25519 AAAAANCIENNE"
|
|
|
|
|
SITE = "ssh-ed25519 AAAASITE"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def voulue(depot="ops-essai", cle=CLE):
|
|
|
|
|
return {"locataire": "OPS-Essai", "depot": depot, "cle": cle}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestPlan(unittest.TestCase):
|
|
|
|
|
def test_une_cle_absente_s_ajoute(self):
|
|
|
|
|
a, r, x = fc.plan([voulue()], {"ops-essai": []})
|
|
|
|
|
self.assertEqual((len(a), r, x), (1, [], []))
|
|
|
|
|
|
|
|
|
|
def test_une_cle_deja_la_ne_change_rien(self):
|
|
|
|
|
cles = [{"id": 1, "title": fc.titre_de("OPS-Essai"), "key": CLE + " setops@ops-01", "read_only": True}]
|
|
|
|
|
self.assertEqual(fc.plan([voulue()], {"ops-essai": cles}), ([], [], []))
|
|
|
|
|
|
|
|
|
|
def test_une_cle_perimee_sous_le_meme_titre_se_retire(self):
|
|
|
|
|
cles = [{"id": 7, "title": fc.titre_de("OPS-Essai"), "key": AUTRE, "read_only": True}]
|
|
|
|
|
a, r, x = fc.plan([voulue()], {"ops-essai": cles})
|
|
|
|
|
self.assertEqual(len(a), 1)
|
|
|
|
|
self.assertEqual([y["id"] for y in r], [7])
|
|
|
|
|
|
|
|
|
|
def test_la_cle_du_runner_du_site_n_est_jamais_touchee(self):
|
|
|
|
|
cles = [{"id": 3, "title": "runner du site — site-ops-01", "key": SITE, "read_only": False}]
|
|
|
|
|
a, r, x = fc.plan([voulue()], {"ops-essai": cles})
|
|
|
|
|
self.assertEqual(r, [], "la cle d'ecriture du site n'est pas une cle de lecture perimee")
|
|
|
|
|
|
|
|
|
|
def test_une_cle_de_lecture_en_ecriture_est_refusee(self):
|
|
|
|
|
cles = [{"id": 4, "title": "autre", "key": CLE, "read_only": False}]
|
|
|
|
|
a, r, x = fc.plan([voulue()], {"ops-essai": cles})
|
|
|
|
|
self.assertEqual((a, r), ([], []))
|
|
|
|
|
self.assertEqual(len(x), 1)
|
|
|
|
|
|
|
|
|
|
def test_une_face_sans_cle_est_refusee(self):
|
|
|
|
|
a, r, x = fc.plan([voulue(cle="")], {})
|
|
|
|
|
self.assertEqual((a, r, len(x)), ([], [], 1))
|
|
|
|
|
|
|
|
|
|
|
2026-10-11 20:58:08 -04:00
|
|
|
class TestVisibilite(unittest.TestCase):
|
|
|
|
|
def test_seuls_les_ecarts_sont_bascules(self):
|
|
|
|
|
voulues = {"set-ops-public": False, "ops-essai": True, "site-essai": True}
|
|
|
|
|
actuelles = {"set-ops-public": False, "ops-essai": False, "site-essai": True}
|
|
|
|
|
self.assertEqual(fc.plan_visibilite(voulues, actuelles), [("ops-essai", True)])
|
|
|
|
|
|
|
|
|
|
def test_un_depot_introuvable_n_est_pas_bascule(self):
|
|
|
|
|
self.assertEqual(fc.plan_visibilite({"absent": True}, {}), [])
|
|
|
|
|
|
|
|
|
|
def test_un_public_redevient_public(self):
|
|
|
|
|
self.assertEqual(fc.plan_visibilite({"set-ops-public": False}, {"set-ops-public": True}),
|
|
|
|
|
[("set-ops-public", False)])
|
|
|
|
|
|
|
|
|
|
|
2026-10-11 22:47:06 -04:00
|
|
|
class TestCollaborations(unittest.TestCase):
|
|
|
|
|
"""`forge_comptes` : chaque mainteneur sur les seuls depots de ses locataires."""
|
|
|
|
|
|
|
|
|
|
def test_ajoute_ce_qui_manque_et_retire_ce_qui_n_est_plus_declare(self):
|
|
|
|
|
import forge_comptes as fco
|
|
|
|
|
voulues = {"daniel": {"ops-a", "ops-b"}}
|
|
|
|
|
actuelles = {"daniel": {"ops-a"}, "ancien": {"ops-b"}}
|
|
|
|
|
self.assertEqual(fco.plan_collaborations(voulues, actuelles),
|
|
|
|
|
([("daniel", "ops-b")], [("ancien", "ops-b")]))
|
|
|
|
|
|
|
|
|
|
def test_rien_a_faire(self):
|
|
|
|
|
import forge_comptes as fco
|
|
|
|
|
self.assertEqual(fco.plan_collaborations({"d": {"x"}}, {"d": {"x"}}), ([], []))
|
|
|
|
|
|
|
|
|
|
|
2026-10-11 20:33:38 -04:00
|
|
|
class TestClassement(unittest.TestCase):
|
|
|
|
|
"""`forge_etancheite` : un refus RESEAU n'est jamais lu comme une protection."""
|
|
|
|
|
|
|
|
|
|
def test_https(self):
|
|
|
|
|
import forge_etancheite as fe
|
|
|
|
|
self.assertEqual(fe.classer_https(0, ""), "lu")
|
|
|
|
|
self.assertEqual(fe.classer_https(128, "fatal: could not read Username for 'https://x'"),
|
|
|
|
|
"authentification")
|
|
|
|
|
self.assertEqual(fe.classer_https(128, "fatal: unable to access: Connection timed out"), "reseau")
|
|
|
|
|
|
|
|
|
|
def test_ssh(self):
|
|
|
|
|
import forge_etancheite as fe
|
|
|
|
|
self.assertEqual(fe.classer_ssh(0, ""), "lu")
|
|
|
|
|
self.assertEqual(fe.classer_ssh(1, "Forgejo: Deploy Key: 4 is not authorized to read genome/x"),
|
|
|
|
|
"refuse")
|
|
|
|
|
self.assertEqual(fe.classer_ssh(1, "ssh: connect to host 10.37.33.11 port 22: No route to host"),
|
|
|
|
|
"reseau")
|
|
|
|
|
|
|
|
|
|
|
2026-10-11 19:59:07 -04:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main(verbosity=2)
|