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)=>{