feat(2a): Erlaubte Sprachen pro Nutzer (Admin-Vorgabe)

Der Admin schaltet pro Nutzer Sprachen frei (Toggle-Chips in der
Nutzerverwaltung). Die Haupt-App zeigt dann nur diese Sprachen; bei genau
einer erlaubten Sprache wird das Sprachmenü ausgeblendet (kein Stress).

- admin.py: PUT /admin/users/{id}/prefs (allowed_languages), list_users
  liefert allowed_languages mit.
- dependencies.py: resolve_route klemmt die Sprache auf eine erlaubte
  (Backend-Durchsetzung, nicht nur UI).
- app.js: applyAllowedLanguages (Haupt-UI-Filter) + Sprach-Chips je Nutzer
  im Admin. app.js v=44.
- Tests: Klemmung + Admin-Endpunkt. 213 passed.

Login-/nginx-Umbau (Ein-Klick-Link) folgt nach separater Design-Abstimmung.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 04:06:09 +02:00
commit cc354938df
7 changed files with 103 additions and 6 deletions

View file

@ -189,3 +189,17 @@ def test_delete_restores_base_value():
client.delete("/api/admin/config/default_language", headers=ADM_HDR)
invalidate_cache()
assert str(runtime_settings.default_language) == base
def test_admin_sets_user_allowed_languages():
created = client.post("/api/admin/users", headers=ADM_HDR,
json={"display_name": "Oma"}).json()
uid = created["user_id"]
resp = client.put(f"/api/admin/users/{uid}/prefs", headers=ADM_HDR,
json={"allowed_languages": "de,en"})
assert resp.status_code == 200
assert resp.json()["prefs"]["allowed_languages"] == "de,en"
# taucht in der Nutzerliste auf
users = client.get("/api/admin/users", headers=ADM_HDR).json()
entry = next(u for u in users if u["user_id"] == uid)
assert entry["allowed_languages"] == "de,en"

View file

@ -139,3 +139,20 @@ def test_route_has_no_language_mode():
route = resolve_route()
assert "language_mode" not in route.as_dict()
assert not hasattr(route, "language_mode")
def test_route_clamps_language_to_allowed():
store = get_store()
user, _ = store.create_user("Senior")
store.set_user_prefs(user.id, {"allowed_languages": "en,fr", "language": "de"})
user = store.get_user(user.id)
# de ist nicht erlaubt -> auf erste erlaubte Sprache (en) geklemmt
assert resolve_route(user).language == "en"
def test_route_keeps_allowed_language():
store = get_store()
user, _ = store.create_user("Senior2")
store.set_user_prefs(user.id, {"allowed_languages": "en,fr", "language": "fr"})
user = store.get_user(user.id)
assert resolve_route(user).language == "fr"