7
0
forked from yvv/decision

Compartimentation : isolation stricte des données par espace de travail
ci/woodpecker/push/woodpecker Pipeline was successful

- Ajout clause else IS NULL sur tous les endpoints list (protocols, decisions,
  mandates, documents, groups, votes) — sans X-Organization → données globales
  seulement, jamais le contenu d'un autre espace
- _get_protocol/_get_decision/_get_mandate : org_id propagé à tous les
  endpoints GET/PUT/DELETE/advance/assign/revoke/steps → 404 si UUID d'un
  autre espace
- votes.py : list_vote_sessions filtre via JOIN VotingProtocol.organization_id
- groups.py : suppression _org_id_from_header() mort, create_group assigne
  organization_id correctement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-04-26 18:52:16 +02:00
parent f56d84e76b
commit 59fff64f9e
6 changed files with 96 additions and 45 deletions
+11 -15
View File
@@ -11,6 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.database import get_db
from app.dependencies.org import get_active_org_id
from app.models.group import Group, GroupMember
from app.schemas.group import GroupCreate, GroupMemberCreate, GroupMemberOut, GroupOut, GroupSummary
from app.services.auth_service import get_current_identity
@@ -18,24 +19,18 @@ from app.services.auth_service import get_current_identity
router = APIRouter()
def _org_id_from_header(request_headers) -> uuid.UUID | None:
raw = request_headers.get("x-organization")
if not raw:
return None
try:
return uuid.UUID(raw)
except ValueError:
return None
@router.get("/", response_model=list[GroupSummary])
async def list_groups(
db: AsyncSession = Depends(get_db),
org_id: uuid.UUID | None = Depends(get_active_org_id),
) -> list[GroupSummary]:
"""List all groups. No auth required — groups are public within the workspace."""
result = await db.execute(
select(Group).options(selectinload(Group.members)).order_by(Group.name)
)
"""List groups within the active workspace."""
stmt = select(Group).options(selectinload(Group.members)).order_by(Group.name)
if org_id is not None:
stmt = stmt.where(Group.organization_id == org_id)
else:
stmt = stmt.where(Group.organization_id.is_(None))
result = await db.execute(stmt)
groups = result.scalars().all()
return [
GroupSummary(
@@ -54,8 +49,9 @@ async def create_group(
payload: GroupCreate,
db: AsyncSession = Depends(get_db),
_identity=Depends(get_current_identity),
org_id: uuid.UUID | None = Depends(get_active_org_id),
) -> GroupOut:
group = Group(name=payload.name, description=payload.description)
group = Group(name=payload.name, description=payload.description, organization_id=org_id)
db.add(group)
await db.commit()
await db.refresh(group)