diff --git a/app/routers/dashboard.py b/app/routers/dashboard.py index c5bd1bc..80cfca3 100644 --- a/app/routers/dashboard.py +++ b/app/routers/dashboard.py @@ -1096,6 +1096,45 @@ async def app_settings_page(request: Request): return template.render(**ctx) +@router.post("/api/settings/avatar") +async def upload_avatar(request: Request): + """Upload a user avatar image.""" + from fastapi import UploadFile, File + from pathlib import Path + import uuid, os + form = await request.form() + file = form.get("file") + if not file: + return {"error": "No file"}, 400 + user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) + if not user: + return {"error": "Not authenticated"}, 401 + # Save to data/avatars + avatars_dir = Path("/data/avatars") + avatars_dir.mkdir(parents=True, exist_ok=True) + ext = os.path.splitext(file.filename)[1] or ".png" + filename = f"{user['id']}_{uuid.uuid4().hex[:8]}{ext}" + filepath = avatars_dir / filename + content = await file.read() + filepath.write_bytes(content) + # Update user avatar_url + avatar_url = f"/api/settings/avatar/{filename}" + with get_conn() as conn: + conn.execute("UPDATE users SET avatar_url = ? WHERE id = ?", (avatar_url, user["id"])) + conn.commit() + return {"avatar_url": avatar_url} + + +@router.get("/api/avatar/{user_id:int}") +async def get_avatar(user_id: int): + """Redirect to the user's avatar.""" + with get_conn() as conn: + row = conn.execute("SELECT avatar_url FROM users WHERE id = ?", (user_id,)).fetchone() + if row and row["avatar_url"]: + return RedirectResponse(row["avatar_url"], status_code=302) + return JSONResponse({"error": "No avatar"}, status_code=404) + + # ═══════════ Tag Management API (global) ═══════════ @router.post("/api/settings/tags") diff --git a/app/templates/settings.html b/app/templates/settings.html index 93b931a..6e2bf56 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -15,77 +15,223 @@ {% block content %} -
Manage all tags across your workspace. Changes apply globally.
-