"""Testet UsersConfig gegen eine realistische users.cfg.""" import shutil, sys, tempfile from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from kerio_users_config import UsersConfig, validate_login from kerio_common import AbortedError SAMPLE = ''' Admin local.lan 1 CDE8D0A3-929B-4AC6-8197-4C39D58C8A64 D3S:0faed6fd Administrator max.mustermann local.lan 1 94480090-4C04-4FE2-9126-0DBDAEC85F5F D3S:b6a11602 Max Mustermann max.mustermann andere.lan 1 AAAAAAAA-0000-0000-0000-000000000000 D3S:anders Max in anderer Domain ldap.user local.lan 1 BBBBBBBB-0000-0000-0000-000000000000 LDAP Benutzer testgruppe local.lan E78FEFAB-2C65-4D08-946B-76E3989EEF9D max.mustermann local.lan 1 SHA:28108e32 ldap.user local.lan 0 ''' tmp = Path(tempfile.mkdtemp()) cfg_path = tmp / "users.cfg" cfg_path.write_text(SAMPLE, encoding="utf-8") ok = True def check(label, cond): global ok print(f" {'ok ' if cond else 'FEHLER'} {label}") if not cond: ok = False print("== 1. Lesen ==") c = UsersConfig(cfg_path) check("Domains gefunden", set(c.domains()) == {"local.lan", "andere.lan"}) check("4 Benutzer gesamt", len(c.users()) == 4) check("3 in local.lan", len(c.users("local.lan")) == 3) u = c.find_user("max.mustermann", "local.lan") check("Benutzer gefunden", u is not None and u["guid"].startswith("94480090")) check("fullName gelesen", u["fullName"] == "Max Mustermann") check("Domain-Trennung: andere.lan hat eigenen Eintrag", c.find_user("max.mustermann", "andere.lan")["guid"].startswith("AAAA")) print("\n== 2. Verzeichnisdienst erkennen ==") check("max.mustermann ist intern", c.is_internal("max.mustermann", "local.lan")) check("ldap.user ist NICHT intern", not c.is_internal("ldap.user", "local.lan")) print("\n== 3. Login-Namen validieren ==") for good in ("anna.schmidt", "a", "a-b_c.d", "user123"): try: validate_login(good); check(f"{good!r} erlaubt", True) except AbortedError: check(f"{good!r} erlaubt", False) for bad in ("", ".anfang", "ende.", "mit leerzeichen", "boes", "a"*100, "a&b"): try: validate_login(bad); check(f"{bad!r} abgelehnt", False) except AbortedError: check(f"{bad!r} abgelehnt", True) print("\n== 4. Umbenennen ==") c2 = UsersConfig(cfg_path) n = c2.rename_user("max.mustermann", "maxi.musterfrau", "local.lan", "Maxi Musterfrau") check("2 Bloecke geaendert (User + UserAdditionalData)", n == 2) c2.save() c3 = UsersConfig(cfg_path) check("neuer Name da", c3.find_user("maxi.musterfrau", "local.lan") is not None) check("alter Name weg in local.lan", c3.find_user("max.mustermann", "local.lan") is None) check("fullName geaendert", c3.find_user("maxi.musterfrau","local.lan")["fullName"] == "Maxi Musterfrau") check("Guid unveraendert", c3.find_user("maxi.musterfrau","local.lan")["guid"].startswith("94480090")) check("ANDERE DOMAIN unberuehrt", c3.find_user("max.mustermann", "andere.lan") is not None) check("Passworthistorie mitgewandert", c3.is_internal("maxi.musterfrau", "local.lan")) txt = cfg_path.read_text(encoding="utf-8") check("Passwort-Hash erhalten", "D3S:b6a11602" in txt) check("PasswordHistory erhalten", "SHA:28108e32" in txt) check("Admin unberuehrt", "Admin" in txt) check("Gruppe unberuehrt", "testgruppe" in txt) check("kein max.mustermann mehr in UserAdditionalData/local.lan", txt.count("max.mustermann") == 1) # nur noch andere.lan print("\n== 5. other_occurrences ==") c4 = UsersConfig(cfg_path) hits = c4.other_occurrences("testgruppe", "local.lan") check("findet Treffer in Group-Liste", any("Group" in h for h in hits)) check("keine Treffer fuer unbekannten Namen", c4.other_occurrences("gibtsnicht", "local.lan") == []) print("\n== 6. Abgelehnter Login-Name aendert nichts ==") c5 = UsersConfig(cfg_path) before = c5.text try: c5.rename_user("maxi.musterfrau", "boes", "local.lan") check("haette ablehnen muessen", False) except AbortedError: check("ungueltiger Zielname abgelehnt", True) check("Text unveraendert", c5.text == before) print("\n" + ("ALLE TESTS BESTANDEN" if ok else "FEHLGESCHLAGEN")) sys.exit(0 if ok else 1)