test_task_crm/app/api/v1/organizations.py

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)