mitlist/be/app/api/v1/endpoints/invites.py

74 lines
3.0 KiB
Python

# app/api/v1/endpoints/invites.py
import logging
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_transactional_session
from app.auth import current_active_user
from app.models import User as UserModel, UserRoleEnum
from app.schemas.invite import InviteAccept
from app.schemas.message import Message
from app.crud import invite as crud_invite
from app.crud import group as crud_group
from app.core.exceptions import (
InviteNotFoundError,
InviteExpiredError,
InviteAlreadyUsedError,
InviteCreationError,
GroupNotFoundError,
GroupMembershipError
)
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post(
"/accept", # Route relative to prefix "/invites"
response_model=Message,
summary="Accept Group Invite",
tags=["Invites"]
)
async def accept_invite(
invite_in: InviteAccept,
db: AsyncSession = Depends(get_transactional_session),
current_user: UserModel = Depends(current_active_user),
):
"""Accepts a group invite using the provided invite code."""
logger.info(f"User {current_user.email} attempting to accept invite code: {invite_in.invite_code}")
# Get the invite
invite = await crud_invite.get_invite_by_code(db, invite_code=invite_in.invite_code)
if not invite:
logger.warning(f"Invalid invite code attempted by user {current_user.email}: {invite_in.invite_code}")
raise InviteNotFoundError(invite_in.invite_code)
# Check if invite is expired
if invite.is_expired():
logger.warning(f"Expired invite code attempted by user {current_user.email}: {invite_in.invite_code}")
raise InviteExpiredError(invite_in.invite_code)
# Check if invite has already been used
if invite.used_at:
logger.warning(f"Already used invite code attempted by user {current_user.email}: {invite_in.invite_code}")
raise InviteAlreadyUsedError(invite_in.invite_code)
# Check if group still exists
group = await crud_group.get_group_by_id(db, group_id=invite.group_id)
if not group:
logger.error(f"Group {invite.group_id} not found for invite {invite_in.invite_code}")
raise GroupNotFoundError(invite.group_id)
# Check if user is already a member
is_member = await crud_group.is_user_member(db, group_id=invite.group_id, user_id=current_user.id)
if is_member:
logger.warning(f"User {current_user.email} already a member of group {invite.group_id}")
raise GroupMembershipError(invite.group_id, "join (already a member)")
# Add user to group and mark invite as used
success = await crud_invite.accept_invite(db, invite=invite, user_id=current_user.id)
if not success:
logger.error(f"Failed to accept invite {invite_in.invite_code} for user {current_user.email}")
raise InviteCreationError(invite.group_id)
logger.info(f"User {current_user.email} successfully joined group {invite.group_id} via invite {invite_in.invite_code}")
return Message(detail="Successfully joined the group")