diff --git a/src/tracker/api/attachments.py b/src/tracker/api/attachments.py index daec357..d906fc0 100644 --- a/src/tracker/api/attachments.py +++ b/src/tracker/api/attachments.py @@ -19,11 +19,11 @@ UPLOAD_DIR = os.environ.get("UPLOAD_DIR", "/data/uploads") MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB -def _get_member(request: Request) -> Member: - member = getattr(request.state, "member", None) - if not member: +def _get_member_id(request: Request) -> str: + member_id = getattr(request.state, "member_id", None) + if not member_id: raise HTTPException(401, "Not authenticated") - return member + return member_id @router.post("/upload") @@ -33,7 +33,7 @@ async def upload_file( db: AsyncSession = Depends(get_db), ): """Upload a file and return attachment metadata (not yet linked to a message).""" - member = _get_member(request) + member_id = _get_member_id(request) # Read file content = await file.read() diff --git a/src/tracker/api/project_files.py b/src/tracker/api/project_files.py index c036079..5d5672b 100644 --- a/src/tracker/api/project_files.py +++ b/src/tracker/api/project_files.py @@ -53,10 +53,15 @@ def project_file_out(f: ProjectFile) -> ProjectFileOut: updated_at=f.updated_at.isoformat() if f.updated_at else "", ) -def _get_member(request: Request) -> Member: - member = getattr(request.state, "member", None) - if not member: +async def _get_member(request: Request, db: AsyncSession) -> Member: + """Get member from request state, re-fetched from DB to avoid detached objects.""" + member_id = getattr(request.state, "member_id", None) + if not member_id: raise HTTPException(401, "Not authenticated") + result = await db.execute(select(Member).where(Member.id == uuid.UUID(member_id))) + member = result.scalar_one_or_none() + if not member: + raise HTTPException(401, "Member not found") return member @@ -97,7 +102,7 @@ async def upload_project_file( description: Optional[str] = Form(None), db: AsyncSession = Depends(get_db), ): - member = _get_member(request) + member = await _get_member(request, db) project = await _get_project(slug, db) content = await file.read() @@ -227,7 +232,7 @@ async def update_project_file( data: ProjectFileUpdate, db: AsyncSession = Depends(get_db), ): - member = _get_member(request) + member = await _get_member(request, db) project = await _get_project(slug, db) result = await db.execute( @@ -257,7 +262,7 @@ async def delete_project_file( file_id: str, db: AsyncSession = Depends(get_db), ): - member = _get_member(request) + member = await _get_member(request, db) project = await _get_project(slug, db) result = await db.execute( diff --git a/src/tracker/app.py b/src/tracker/app.py index 9a93e44..a1223d9 100644 --- a/src/tracker/app.py +++ b/src/tracker/app.py @@ -132,6 +132,7 @@ async def auth_middleware(request: Request, call_next): return JSONResponse(status_code=401, content={"error": "Invalid or expired token"}) request.state.member = member + request.state.member_id = str(member.id) return await call_next(request)