This commit is contained in:
2026-05-09 22:50:51 +02:00
parent 520d3924af
commit ab5a0c7697
79 changed files with 285640 additions and 346 deletions

View File

@@ -0,0 +1,13 @@
Backup: Empfang Admin-Identitaet + Desktop Presence-Ping.
Geaenderte Datei: basis14.py
- _empfang_self_user_id_resolve_now bevorzugt role=admin bei gleichem
normalisierten display_name (deterministisch).
- _provision_empfang_account: nach Server-Antwort erneut Admin-Identitaet
binden, falls Server-uid nicht-Admin ist und Praxis einen Admin hat.
- Neuer Hintergrund-Ping POST /empfang/presence/ping (~28s),
Singleton, still bei Fehler, keine UI-Blockaden.
Rollback: basis14.py aus diesem Backup zurueck nach AzA march 2026/.
Hetzner-Deploy NICHT noetig (basis14.py laeuft clientseitig).
Zeitstempel: 20260509_125534

View File

@@ -0,0 +1,105 @@
"""Selbsttest: zwei gleichnamige Konten -> Admin wird bevorzugt.
Imitiert die Sortier- und Auswahl-Logik aus
``MainApplication._empfang_self_user_id_resolve_now`` ohne Tk-Stack.
"""
from __future__ import annotations
import importlib.util
import os
import sys
import unicodedata
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def _empfang_identity_key(label: str) -> str:
t = (label or "").strip().lower()
t = unicodedata.normalize("NFKD", t)
return "".join(ch for ch in t if unicodedata.combining(ch) == 0)
def resolve_admin_preferred(my_dn: str, users_full: list) -> str:
target = _empfang_identity_key(my_dn)
candidates = []
for u in users_full:
if not isinstance(u, dict):
continue
if _empfang_identity_key(u.get("display_name") or "") != target:
continue
uid = str(u.get("user_id") or "").strip()
if not uid:
continue
role = str(u.get("role") or "").strip().lower()
status = str(u.get("status") or "active").strip().lower()
candidates.append({
"user_id": uid,
"role": role,
"status": status,
})
if not candidates:
return ""
role_rank = {"admin": 0, "arzt": 1, "empfang": 2, "mpa": 3}
candidates.sort(key=lambda c: (
0 if c["status"] == "active" else 1,
role_rank.get(c["role"], 9),
))
return candidates[0]["user_id"]
users_full = [
# absichtlich Empfang-Doppelgaenger ZUERST in der Liste, um zu zeigen,
# dass die Auswahl nicht von der Reihenfolge abhaengt.
{
"user_id": "uid_empfang_001",
"display_name": "André M. Surovy",
"role": "empfang",
"status": "active",
"login_name": "André M. Surovy-325eHa6",
},
{
"user_id": "uid_admin_002",
"display_name": "André M. Surovy",
"role": "admin",
"status": "active",
"login_name": "André M. Surovy",
},
{
"user_id": "uid_other_003",
"display_name": "Anja",
"role": "arzt",
"status": "active",
"login_name": "Anja",
},
]
result = resolve_admin_preferred("André M. Surovy", users_full)
print(f"Resolved user_id (Admin-bevorzugt): {result}")
assert result == "uid_admin_002", f"Erwartet uid_admin_002, erhalten {result}"
# Edge: kein Admin -> Fallback auf arzt
users_full_no_admin = [
{"user_id": "uid_e", "display_name": "Foo", "role": "empfang", "status": "active"},
{"user_id": "uid_a", "display_name": "Foo", "role": "arzt", "status": "active"},
{"user_id": "uid_m", "display_name": "Foo", "role": "mpa", "status": "active"},
]
res2 = resolve_admin_preferred("Foo", users_full_no_admin)
print(f"Edge ohne Admin (sollte arzt sein): {res2}")
assert res2 == "uid_a"
# Edge: deaktivierter Admin verliert gegen aktiven arzt
users_full_inactive_admin = [
{"user_id": "uid_admin", "display_name": "Bar", "role": "admin", "status": "deactivated"},
{"user_id": "uid_arzt", "display_name": "Bar", "role": "arzt", "status": "active"},
]
res3 = resolve_admin_preferred("Bar", users_full_inactive_admin)
print(f"Edge inaktiver Admin: {res3}")
assert res3 == "uid_arzt"
# Edge: kein Treffer
res4 = resolve_admin_preferred("Niemand", users_full)
print(f"Edge kein Treffer: {res4!r}")
assert res4 == ""
print("ALLE TESTS BESTANDEN.")