diff --git a/backend/main.py b/backend/main.py
index fd54af7..d446dfa 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -149,6 +149,12 @@ def require_auth(x_auth_token: Optional[str]=Header(default=None)):
if not session: raise HTTPException(401, "Nicht eingeloggt")
return session
+def require_auth_flexible(x_auth_token: Optional[str]=Header(default=None), token: Optional[str]=Query(default=None)):
+ """Auth via header OR query parameter (for
tags)."""
+ session = get_session(x_auth_token or token)
+ if not session: raise HTTPException(401, "Nicht eingeloggt")
+ return session
+
def require_admin(x_auth_token: Optional[str]=Header(default=None)):
session = get_session(x_auth_token)
if not session: raise HTTPException(401, "Nicht eingeloggt")
@@ -500,13 +506,17 @@ async def upload_photo(file: UploadFile=File(...), date: str="",
return {"id":fid,"date":date}
@app.get("/api/photos/{fid}")
-def get_photo(fid: str, session: dict=Depends(require_auth)):
+def get_photo(fid: str, session: dict=Depends(require_auth_flexible)):
+ """Get photo by ID. Auth via header or query param (for
tags)."""
with get_db() as conn:
cur = get_cursor(conn)
cur.execute("SELECT path FROM photos WHERE id=%s", (fid,))
row = cur.fetchone()
- if not row: raise HTTPException(404)
- return FileResponse(row['path'])
+ if not row: raise HTTPException(404, "Photo not found")
+ photo_path = Path(PHOTOS_DIR) / row['path']
+ if not photo_path.exists():
+ raise HTTPException(404, "Photo file not found")
+ return FileResponse(photo_path)
@app.get("/api/photos")
def list_photos(x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)):
diff --git a/frontend/src/utils/api.js b/frontend/src/utils/api.js
index 5b6792b..a0634a1 100644
--- a/frontend/src/utils/api.js
+++ b/frontend/src/utils/api.js
@@ -68,7 +68,10 @@ export const api = {
return fetch(`${BASE}/photos`,{method:'POST',body:fd,headers:hdrs()}).then(r=>r.json())
},
listPhotos: () => req('/photos'),
- photoUrl: (pid) => `${BASE}/photos/${pid}`,
+ photoUrl: (pid) => {
+ const token = getToken()
+ return `${BASE}/photos/${pid}${token ? `?token=${token}` : ''}`
+ },
// Nutrition
importCsv: async(file)=>{