Renaming of users in registration, profile and admin app.
This commit is contained in:
@@ -487,6 +487,40 @@ def register_api_routes(app: FastAPI):
|
||||
"aaguid_info": aaguid_info,
|
||||
}
|
||||
|
||||
@app.put("/auth/user/display-name")
|
||||
async def user_update_display_name(payload: dict = Body(...), auth=Cookie(None)):
|
||||
"""Authenticated user updates their own display name."""
|
||||
if not auth:
|
||||
raise HTTPException(status_code=401, detail="Authentication Required")
|
||||
s = await get_session(auth)
|
||||
new_name = (payload.get("display_name") or "").strip()
|
||||
if not new_name:
|
||||
raise HTTPException(status_code=400, detail="display_name required")
|
||||
if len(new_name) > 64:
|
||||
raise HTTPException(status_code=400, detail="display_name too long")
|
||||
await db.instance.update_user_display_name(s.user_uuid, new_name)
|
||||
return {"status": "ok"}
|
||||
|
||||
@app.put("/auth/admin/users/{user_uuid}/display-name")
|
||||
async def admin_update_user_display_name(
|
||||
user_uuid: UUID, payload: dict = Body(...), auth=Cookie(None)
|
||||
):
|
||||
"""Admin updates a user's display name."""
|
||||
ctx, is_global_admin, is_org_admin = await _get_ctx_and_admin_flags(auth)
|
||||
try:
|
||||
user_org, _role_name = await db.instance.get_user_organization(user_uuid)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
if not (is_global_admin or (is_org_admin and user_org.uuid == ctx.org.uuid)):
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||||
new_name = (payload.get("display_name") or "").strip()
|
||||
if not new_name:
|
||||
raise HTTPException(status_code=400, detail="display_name required")
|
||||
if len(new_name) > 64:
|
||||
raise HTTPException(status_code=400, detail="display_name too long")
|
||||
await db.instance.update_user_display_name(user_uuid, new_name)
|
||||
return {"status": "ok"}
|
||||
|
||||
# Admin API: Permissions (global)
|
||||
|
||||
@app.get("/auth/admin/permissions")
|
||||
|
||||
@@ -5,9 +5,10 @@ from uuid import UUID
|
||||
from fastapi import Cookie, FastAPI, WebSocket, WebSocketDisconnect
|
||||
from webauthn.helpers.exceptions import InvalidAuthenticationResponse
|
||||
|
||||
from ..authsession import create_session, get_reset, get_session
|
||||
from ..authsession import create_session, expires, get_reset, get_session
|
||||
from ..globals import db, passkey
|
||||
from ..util import passphrase
|
||||
from ..util.tokens import create_token, session_key
|
||||
from .session import infodict
|
||||
|
||||
|
||||
@@ -55,7 +56,7 @@ async def register_chat(
|
||||
@app.websocket("/register")
|
||||
@websocket_error_handler
|
||||
async def websocket_register_add(
|
||||
ws: WebSocket, reset: str | None = None, auth=Cookie(None)
|
||||
ws: WebSocket, reset: str | None = None, name: str | None = None, auth=Cookie(None)
|
||||
):
|
||||
"""Register a new credential for an existing user.
|
||||
|
||||
@@ -64,11 +65,9 @@ async def websocket_register_add(
|
||||
- Reset token supplied as ?reset=... (auth cookie ignored)
|
||||
"""
|
||||
origin = ws.headers["origin"]
|
||||
is_reset = False
|
||||
if reset is not None:
|
||||
if not passphrase.is_well_formed(reset):
|
||||
raise ValueError("Invalid reset token")
|
||||
is_reset = True
|
||||
s = await get_reset(reset)
|
||||
else:
|
||||
if not auth:
|
||||
@@ -76,23 +75,30 @@ async def websocket_register_add(
|
||||
s = await get_session(auth)
|
||||
user_uuid = s.user_uuid
|
||||
|
||||
# Get user information to get the user_name
|
||||
# Get user information and determine effective user_name for this registration
|
||||
user = await db.instance.get_user_by_uuid(user_uuid)
|
||||
user_name = user.display_name
|
||||
if name is not None:
|
||||
stripped = name.strip()
|
||||
if stripped:
|
||||
user_name = stripped
|
||||
challenge_ids = await db.instance.get_credentials_by_user_uuid(user_uuid)
|
||||
|
||||
# WebAuthn registration
|
||||
credential = await register_chat(ws, user_uuid, user_name, challenge_ids, origin)
|
||||
# IMPORTANT: Insert the credential before creating a session that references it
|
||||
# to satisfy the sessions.credential_uuid foreign key (now enforced).
|
||||
await db.instance.create_credential(credential)
|
||||
|
||||
if is_reset:
|
||||
# Invalidate the one-time reset session only after credential persisted
|
||||
await db.instance.delete_session(s.key)
|
||||
auth = await create_session(
|
||||
user_uuid, credential.uuid, infodict(ws, "authenticated")
|
||||
)
|
||||
# Create a new session and store everything in database
|
||||
token = create_token()
|
||||
await db.instance.create_credential_session( # type: ignore[attr-defined]
|
||||
user_uuid=user_uuid,
|
||||
credential=credential,
|
||||
reset_key=(s.key if reset is not None else None),
|
||||
session_key=session_key(token),
|
||||
session_expires=expires(),
|
||||
session_info=infodict(ws, "authenticated"),
|
||||
display_name=user_name,
|
||||
)
|
||||
auth = token
|
||||
|
||||
assert isinstance(auth, str) and len(auth) == 16
|
||||
await ws.send_json(
|
||||
|
||||
Reference in New Issue
Block a user