from __future__ import annotations from typing import List from fastapi import APIRouter, Depends, HTTPException, Response, status from app.auth import get_current_user_optional from app.models import ( AddMemberRequest, CreateGroupRequest, Group, MessageResponse, User, ) from app.store import DatabaseStore, get_store from app.telemetry import record_group_created, record_group_member_invited router = APIRouter() @router.get("", response_model=List[Group], status_code=status.HTTP_200_OK) async def list_groups( current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> List[Group]: return store.get_groups(user=current_user) @router.post("", response_model=Group, status_code=status.HTTP_201_CREATED) async def create_group( payload: CreateGroupRequest, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> Group: group = store.create_group(user=current_user, name=payload.name) record_group_created() return group @router.get("/{id}", response_model=Group, status_code=status.HTTP_200_OK) async def get_group( id: str, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> Group: group = store.get_group_by_id(id) if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found", ) if not store.is_group_accessible(group, current_user): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized to access this group", ) return group @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_group( id: str, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> Response: group = store.get_group_by_id(id) if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found", ) deleted, err = store.delete_group(requester=current_user, group_id=id) if not deleted: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=err or "Could not delete group", ) return Response(status_code=status.HTTP_204_NO_CONTENT) @router.post("/{groupId}/members", response_model=Group, status_code=status.HTTP_200_OK) async def add_member( groupId: str, payload: AddMemberRequest, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> Group: group = store.get_group_by_id(groupId) if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found", ) try: updated_group = store.add_member( user=current_user, group_id=groupId, email=payload.email ) if not updated_group: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Group not found") record_group_member_invited() return updated_group except PermissionError as exc: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) @router.delete("/{groupId}/members/{memberEmail}", response_model=Group, status_code=status.HTTP_200_OK) async def remove_member( groupId: str, memberEmail: str, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> Group: group = store.get_group_by_id(groupId) if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found", ) updated_group, err = store.remove_member( requester=current_user, group_id=groupId, member_email=memberEmail ) if not updated_group: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=err or "Could not remove member", ) return updated_group @router.post("/{groupId}/leave", response_model=MessageResponse, status_code=status.HTTP_200_OK) async def leave_group( groupId: str, current_user: User = Depends(get_current_user_optional), store: DatabaseStore = Depends(get_store), ) -> MessageResponse: group = store.get_group_by_id(groupId) if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found", ) success, err = store.leave_group(user=current_user, group_id=groupId) if not success: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=err or "Could not leave group", ) return MessageResponse(message="Left group successfully")