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:
parent
f758db218c
commit
cc354938df
7 changed files with 103 additions and 6 deletions
|
|
@ -17,7 +17,7 @@ from app.auth import is_admin_user, require_admin, require_admin_or_user
|
|||
from app.config import settings
|
||||
from app.dependencies import get_store
|
||||
from app.runtime_config import RUNTIME_SETTABLE, invalidate_cache, runtime_settings
|
||||
from app.schemas import MemoryCreate, MemoryOut, UserCreate, UserCreated, UserUpdate
|
||||
from app.schemas import AdminUserPrefsUpdate, MemoryCreate, MemoryOut, UserCreate, UserCreated, UserUpdate
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
|
@ -94,6 +94,18 @@ async def reset_token(user_id: str):
|
|||
return UserCreated(user_id=user.id, display_name=user.display_name, token=token)
|
||||
|
||||
|
||||
@router.put("/admin/users/{user_id}/prefs", dependencies=[Depends(require_admin)])
|
||||
async def update_user_prefs(user_id: str, payload: AdminUserPrefsUpdate):
|
||||
"""Setzt Nutzer-Einstellungen (z. B. erlaubte Sprachen). Merge mit bestehenden Prefs."""
|
||||
store = get_store()
|
||||
current = store.get_user(user_id)
|
||||
if current is None:
|
||||
raise HTTPException(status_code=404, detail=f"Nutzer {user_id!r} nicht gefunden.")
|
||||
new = {k: v for k, v in payload.model_dump().items() if v is not None}
|
||||
updated = store.set_user_prefs(user_id, {**current.prefs, **new})
|
||||
return {"user_id": updated.id, "prefs": updated.prefs}
|
||||
|
||||
|
||||
@router.put("/admin/users/{user_id}", dependencies=[Depends(require_admin)])
|
||||
async def update_user(user_id: str, payload: UserUpdate):
|
||||
"""Aktualisiert den Anzeigenamen eines Nutzers (z. B. nach erstem SSO-Login)."""
|
||||
|
|
@ -122,6 +134,7 @@ async def list_users():
|
|||
"display_name": u.display_name,
|
||||
"external_id": u.external_id,
|
||||
"created_at": u.created_at,
|
||||
"allowed_languages": (u.prefs or {}).get("allowed_languages", ""),
|
||||
}
|
||||
for u in get_store().list_users()
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue