feat(rbac): enforce procurement write restrictions and support supervisor role in SSO

This commit is contained in:
2026-09-26 12:32:01 +03:30
parent 730d0bd496
commit 5a9b543040
31 changed files with 480 additions and 139 deletions
+19 -3
View File
@@ -3,6 +3,7 @@ from fastapi import APIRouter, Depends, Query
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth import require_role
from app.db.engine import get_db
from app.models.catalog import Material, Unit
from app.models.procurement import ItemDecision, LineItem, Quote
@@ -14,6 +15,7 @@ from app.utils.errors import ConflictError, NotFoundError
from app.utils.pagination import paginate, sort_query
router = APIRouter(prefix="/quotes/{quote_id}/line-items", tags=["line-items"])
_procurement_writer = require_role("admin", "procurement_manager")
async def _quote_or_404(db: AsyncSession, quote_id) -> Quote:
@@ -50,7 +52,12 @@ async def list_line_items(
@router.post("", status_code=201)
async def create_line_item(quote_id, payload: LineItemCreate, db: AsyncSession = Depends(get_db)):
async def create_line_item(
quote_id,
payload: LineItemCreate,
db: AsyncSession = Depends(get_db),
_auth=Depends(_procurement_writer),
):
async with db.begin():
quote = await _quote_or_404(db, quote_id)
if quote.status != "offered":
@@ -89,7 +96,11 @@ async def get_line_item(
@router.patch("/{line_item_id}")
async def update_line_item(
quote_id, line_item_id, payload: LineItemUpdate, db: AsyncSession = Depends(get_db)
quote_id,
line_item_id,
payload: LineItemUpdate,
db: AsyncSession = Depends(get_db),
_auth=Depends(_procurement_writer),
):
li = await _line_item_or_404(db, quote_id, line_item_id)
quote = await _quote_or_404(db, quote_id)
@@ -131,7 +142,12 @@ async def update_line_item(
@router.delete("/{line_item_id}")
async def delete_line_item(quote_id, line_item_id, db: AsyncSession = Depends(get_db)):
async def delete_line_item(
quote_id,
line_item_id,
db: AsyncSession = Depends(get_db),
_auth=Depends(_procurement_writer),
):
li = await _line_item_or_404(db, quote_id, line_item_id)
quote = await _quote_or_404(db, quote_id)
if quote.status != "offered":