Coverage for src/kwai/modules/identity/accept_user_invitation.py: 100%
38 statements
« prev ^ index » next coverage.py v7.7.1, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2024-01-01 00:00 +0000
1"""Module that implements the use case for accepting a user invitation."""
3from dataclasses import dataclass
5from kwai.core.domain.exceptions import UnprocessableException
6from kwai.core.domain.presenter import Presenter
7from kwai.core.domain.value_objects.name import Name
8from kwai.core.domain.value_objects.password import Password
9from kwai.core.domain.value_objects.unique_id import UniqueId
10from kwai.modules.identity.user_invitations.user_invitation_repository import (
11 UserInvitationRepository,
12)
13from kwai.modules.identity.users.user import UserEntity
14from kwai.modules.identity.users.user_account import UserAccountEntity
15from kwai.modules.identity.users.user_account_repository import UserAccountRepository
18@dataclass(kw_only=True, frozen=True, slots=False)
19class AcceptUserInvitationCommand:
20 """Input for the AcceptUserInvitation use case.
22 See: [AcceptUserInvitation][kwai.modules.identity.accept_user_invitation.AcceptUserInvitation]
24 Attributes:
25 uuid: The unique id of the user invitation.
26 first_name: The first name of the new user.
27 last_name: The last name of the new user.
28 password: The password for the new user.
29 remark: A remark about the new user.
30 """
32 uuid: str
33 first_name: str
34 last_name: str
35 password: str
36 remark: str
39class AcceptUserInvitation:
40 """Use case for accepting a user invitation."""
42 def __init__(
43 self,
44 user_invitation_repo: UserInvitationRepository,
45 user_account_repo: UserAccountRepository,
46 presenter: Presenter[UserAccountEntity],
47 ):
48 """Create the use case.
50 Args:
51 user_invitation_repo: Repository for checking the user invitation.
52 user_account_repo: Repository that creates a new user account.
53 presenter: A presenter for a user account entity.
54 """
55 self._user_invitation_repo = user_invitation_repo
56 self._user_account_repo = user_account_repo
57 self._presenter = presenter
59 async def execute(self, command: AcceptUserInvitationCommand) -> None:
60 """Execute the use case.
62 Args:
63 command: The input for this use case.
65 Returns:
66 An entity for a user account.
68 Raises:
69 UserInvitationNotFoundExeption: when the user invitation does not
70 exist.
71 UnprocessableException: when the email address is already used by another
72 user.
73 When the user invitation is expired or was already accepted.
74 When the user invitation is revoked.
75 """
76 uuid = UniqueId.create_from_string(command.uuid)
77 user_invitation = await self._user_invitation_repo.get_invitation_by_uuid(uuid)
78 if user_invitation.revoked:
79 raise UnprocessableException(
80 f"The user invitation with id {uuid} is revoked."
81 )
82 if user_invitation.is_expired:
83 raise UnprocessableException(
84 f"The user invitation with id {uuid} is expired."
85 )
86 if user_invitation.confirmed:
87 raise UnprocessableException(
88 f"The user invitation with id {uuid} was already accepted."
89 )
91 if await self._user_account_repo.exists_with_email(user_invitation.email):
92 raise UnprocessableException(
93 f"A user with email {user_invitation.email} already exists."
94 )
96 user_account = UserAccountEntity(
97 user=UserEntity(
98 email=user_invitation.email,
99 remark=command.remark,
100 name=Name(first_name=command.first_name, last_name=command.last_name),
101 ),
102 password=Password.create_from_string(command.password),
103 )
105 user_invitation = user_invitation.confirm()
106 await self._user_invitation_repo.update(user_invitation)
108 user_account = await self._user_account_repo.create(user_account)
109 self._presenter.present(user_account)