feat: Login-Name vs. Anzeigename (Server)
- Neue Spalte users.display_name (Original-Schreibweise); username bleibt der lowercase Login-Name. Setup/Create setzen display_name aus der Eingabe. - Login bleibt case-insensitive (Anzeigename eingeben funktioniert -> wird lowercased -> trifft den Login-Namen). - Profil: PUT /api/profile/ kann display_name UND username (Login-Name) aendern; bei Login-Namen-Wechsel kommt ein frischer Token zurueck (JWT sub haengt am Namen). Stabile interne ID (Integer-PK) traegt alle Verweise -> Umbenennen bricht Shares/Gruppen/creator_id nicht. - display_name ueberall ausgeliefert/genutzt (me, profile, users, directory, shares, Gruppen-Mitglieder, creator/owner, ORGANIZER-Export). - Migration + Backfill (display_name = username). Tests ergaenzt (17 gruen). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,13 @@ class ChangePasswordRequest(BaseModel):
|
||||
|
||||
|
||||
def _user_dict(u: models.User) -> dict:
|
||||
return {"id": u.id, "username": u.username, "email": u.email, "is_admin": u.is_admin}
|
||||
return {
|
||||
"id": u.id,
|
||||
"username": u.username,
|
||||
"display_name": u.display_name or u.username,
|
||||
"email": u.email,
|
||||
"is_admin": u.is_admin,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/")
|
||||
@@ -51,7 +57,7 @@ def user_directory(
|
||||
.order_by(models.User.username)
|
||||
.all()
|
||||
)
|
||||
return [{"id": u.id, "display_name": u.username} for u in users]
|
||||
return [{"id": u.id, "display_name": u.display_name or u.username} for u in users]
|
||||
|
||||
|
||||
@router.post("/")
|
||||
@@ -64,6 +70,7 @@ def create_user(
|
||||
raise HTTPException(400, "Username already taken")
|
||||
user = models.User(
|
||||
username=req.username.lower(),
|
||||
display_name=req.username.strip(), # keep the original casing for display
|
||||
email=req.email,
|
||||
password_hash=get_password_hash(req.password),
|
||||
is_admin=req.is_admin,
|
||||
|
||||
Reference in New Issue
Block a user