196 lines
6.3 KiB
Python
196 lines
6.3 KiB
Python
"""
|
|
接受/拒绝邀请 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)}"
|