diff --git a/src/tracker/api/members.py b/src/tracker/api/members.py index 98eaa4a..252aa3b 100644 --- a/src/tracker/api/members.py +++ b/src/tracker/api/members.py @@ -228,8 +228,14 @@ async def update_my_status( @router.delete("/members/{slug}") -async def delete_member(slug: str, db: AsyncSession = Depends(get_db)): - """Soft delete member by setting is_active=False.""" +async def delete_member( + slug: str, + current_member: Member = Depends(get_current_member), + db: AsyncSession = Depends(get_db), +): + """Soft delete member by setting is_active=False. Only owners can delete.""" + if current_member.role != MemberRole.OWNER: + raise HTTPException(403, "Only owners can delete members") result = await db.execute(select(Member).where(Member.slug == slug)) member = result.scalar_one_or_none() if not member: diff --git a/src/tracker/api/projects.py b/src/tracker/api/projects.py index 5e35b1b..e0929a8 100644 --- a/src/tracker/api/projects.py +++ b/src/tracker/api/projects.py @@ -1,6 +1,6 @@ """Projects API.""" -from fastapi import APIRouter, Depends, HTTPException +from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession @@ -119,7 +119,10 @@ async def update_project(slug: str, req: ProjectUpdate, db: AsyncSession = Depen @router.delete("/projects/{slug}") -async def delete_project(slug: str, db: AsyncSession = Depends(get_db)): +async def delete_project(slug: str, request: Request, db: AsyncSession = Depends(get_db)): + member = getattr(request.state, "member", None) + if not member or member.role != MemberRole.OWNER: + raise HTTPException(403, "Only owners can delete projects") result = await db.execute(select(Project).where(Project.slug == slug)) project = result.scalar_one_or_none() if not project: