67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
"""Organization-related API endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from pydantic import BaseModel, EmailStr
|
|
|
|
from app.api.deps import (
|
|
get_current_user,
|
|
get_organization_context,
|
|
get_organization_repository,
|
|
get_organization_service,
|
|
get_user_repository,
|
|
)
|
|
from app.models.organization import OrganizationRead
|
|
from app.models.organization_member import OrganizationMemberRead, OrganizationRole
|
|
from app.models.user import User
|
|
from app.repositories.org_repo import OrganizationRepository
|
|
from app.repositories.user_repo import UserRepository
|
|
from app.services.organization_service import (
|
|
OrganizationContext,
|
|
OrganizationForbiddenError,
|
|
OrganizationMemberAlreadyExistsError,
|
|
OrganizationService,
|
|
)
|
|
|
|
router = APIRouter(prefix="/organizations", tags=["organizations"])
|
|
|
|
|
|
class AddMemberPayload(BaseModel):
|
|
email: EmailStr
|
|
role: OrganizationRole = OrganizationRole.MEMBER
|
|
|
|
|
|
@router.get("/me", response_model=list[OrganizationRead])
|
|
async def list_user_organizations(
|
|
current_user: User = Depends(get_current_user),
|
|
repo: OrganizationRepository = Depends(get_organization_repository),
|
|
) -> list[OrganizationRead]:
|
|
"""Return organizations the authenticated user belongs to."""
|
|
|
|
organizations = await repo.list_for_user(current_user.id)
|
|
return [OrganizationRead.model_validate(org) for org in organizations]
|
|
|
|
|
|
@router.post("/members", response_model=OrganizationMemberRead, status_code=status.HTTP_201_CREATED)
|
|
async def add_member_to_organization(
|
|
payload: AddMemberPayload,
|
|
context: OrganizationContext = Depends(get_organization_context),
|
|
service: OrganizationService = Depends(get_organization_service),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> OrganizationMemberRead:
|
|
"""Allow owners/admins to add existing users to their organization."""
|
|
|
|
user = await user_repo.get_by_email(payload.email)
|
|
if user is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
|
|
|
try:
|
|
membership = await service.add_member(context=context, user_id=user.id, role=payload.role)
|
|
except OrganizationMemberAlreadyExistsError as exc:
|
|
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(exc)) from exc
|
|
except OrganizationForbiddenError as exc:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(exc)) from exc
|
|
|
|
return OrganizationMemberRead.model_validate(membership)
|