Fix #13: Basic RBAC — only owners can delete projects and members
Some checks failed
Deploy Tracker / deploy (push) Failing after 4s

This commit is contained in:
markov 2026-02-26 15:15:25 +01:00
parent 7360c79eeb
commit 8a54a2d609
2 changed files with 13 additions and 4 deletions

View File

@ -228,8 +228,14 @@ async def update_my_status(
@router.delete("/members/{slug}") @router.delete("/members/{slug}")
async def delete_member(slug: str, db: AsyncSession = Depends(get_db)): async def delete_member(
"""Soft delete member by setting is_active=False.""" 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)) result = await db.execute(select(Member).where(Member.slug == slug))
member = result.scalar_one_or_none() member = result.scalar_one_or_none()
if not member: if not member:

View File

@ -1,6 +1,6 @@
"""Projects API.""" """Projects API."""
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession 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}") @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)) result = await db.execute(select(Project).where(Project.slug == slug))
project = result.scalar_one_or_none() project = result.scalar_one_or_none()
if not project: if not project: