""" 接受/拒绝邀请 Use Case """ from datetime import datetime, timezone from typing import Optional from uuid import uuid4 from packages.domain.entities import InvitationStatus, WorkspaceMember class AcceptInvitationRequest: """接受邀请请求""" def __init__(self, invitation_token: str, user_id: str): self.invitation_token = invitation_token self.user_id = user_id class AcceptInvitationResponse: """接受邀请响应""" def __init__( self, workspace_id: str, workspace_name: str, role: str, ): self.workspace_id = workspace_id self.workspace_name = workspace_name self.role = role class AcceptInvitationUseCase: """接受邀请用例""" def __init__( self, workspace_repository, workspace_member_repository, workspace_invitation_repository, user_repository, ): self.workspace_repository = workspace_repository self.workspace_member_repository = workspace_member_repository self.workspace_invitation_repository = workspace_invitation_repository self.user_repository = user_repository def execute(self, request: AcceptInvitationRequest) -> tuple[Optional[AcceptInvitationResponse], Optional[str]]: """ 执行接受邀请 Args: request: 接受请求 Returns: (响应, 错误信息) """ try: # 1. 验证输入 if not request.invitation_token: return None, "Invitation token is required" if not request.user_id: return None, "User ID is required" # 2. 查找邀请 invitation = self.workspace_invitation_repository.find_by_token(request.invitation_token) if not invitation: return None, "Invalid invitation token" # 3. 检查邀请状态 if invitation.status != InvitationStatus.PENDING: return None, f"Invitation has already been {invitation.status}" # 4. 检查是否过期 expires_at = invitation.expires_at if expires_at and expires_at.tzinfo is None: expires_at = expires_at.replace(tzinfo=timezone.utc) if expires_at and datetime.now(timezone.utc) > expires_at: # 更新状态为过期 invitation.status = InvitationStatus.EXPIRED self.workspace_invitation_repository.save(invitation) return None, "Invitation has expired" # 5. 验证用户存在 user = self.user_repository.find_by_id(request.user_id) if not user: return None, "User not found" # 6. 验证用户邮箱匹配 if user.email.lower() != invitation.invitee_email.lower(): return None, "This invitation is for a different email address" # 7. 验证 Workspace 存在 workspace = self.workspace_repository.find_by_id(invitation.workspace_id) if not workspace: return None, "Workspace not found" # 8. 检查用户是否已经是成员 existing_member = self.workspace_member_repository.find_by_workspace_and_user( invitation.workspace_id, request.user_id, ) if existing_member: # 已经是成员,标记邀请为已接受 invitation.status = InvitationStatus.ACCEPTED invitation.accepted_at = datetime.now(timezone.utc) self.workspace_invitation_repository.save(invitation) return ( AcceptInvitationResponse( workspace_id=workspace.id, workspace_name=workspace.name, role=existing_member.role, ), None, ) # 9. 创建成员记录 member = WorkspaceMember( id=uuid4().hex, workspace_id=invitation.workspace_id, user_id=request.user_id, role=invitation.role, invited_by=invitation.inviter_user_id, joined_at=datetime.now(timezone.utc), ) self.workspace_member_repository.save(member) # 10. 更新邀请状态 invitation.status = InvitationStatus.ACCEPTED invitation.accepted_at = datetime.now(timezone.utc) self.workspace_invitation_repository.save(invitation) # 11. 返回响应 return ( AcceptInvitationResponse( workspace_id=workspace.id, workspace_name=workspace.name, role=member.role, ), None, ) except Exception as e: return None, f"Failed to accept invitation: {str(e)}" class DeclineInvitationRequest: """拒绝邀请请求""" def __init__(self, invitation_token: str): self.invitation_token = invitation_token class DeclineInvitationUseCase: """拒绝邀请用例""" def __init__(self, workspace_invitation_repository): self.workspace_invitation_repository = workspace_invitation_repository def execute(self, request: DeclineInvitationRequest) -> tuple[bool, Optional[str]]: """ 执行拒绝邀请 Args: request: 拒绝请求 Returns: (是否成功, 错误信息) """ try: # 1. 验证输入 if not request.invitation_token: return False, "Invitation token is required" # 2. 查找邀请 invitation = self.workspace_invitation_repository.find_by_token(request.invitation_token) if not invitation: return False, "Invalid invitation token" # 3. 检查邀请状态 if invitation.status != InvitationStatus.PENDING: return False, f"Invitation has already been {invitation.status}" # 4. 更新状态为已拒绝 invitation.status = InvitationStatus.DECLINED self.workspace_invitation_repository.save(invitation) return True, None except Exception as e: return False, f"Failed to decline invitation: {str(e)}"