Coverage for kwai/modules/identity/users/user_account.py: 98%

48 statements  

« prev     ^ index     » next       coverage.py v7.3.0, created at 2023-09-05 17:55 +0000

1"""Module that implements a user account entity.""" 

2 

3from kwai.core.domain.entity import Entity 

4from kwai.core.domain.value_objects.identifier import IntIdentifier 

5from kwai.core.domain.value_objects.local_timestamp import LocalTimestamp 

6from kwai.core.domain.value_objects.password import Password 

7from kwai.modules.identity.exceptions import NotAllowedException 

8from kwai.modules.identity.users.user import UserEntity 

9 

10UserAccountIdentifier = IntIdentifier 

11 

12 

13class UserAccountEntity(Entity[UserAccountIdentifier]): 

14 """A user account entity.""" 

15 

16 def __init__( 

17 self, 

18 *, 

19 user: UserEntity, 

20 password: Password, 

21 id_: UserAccountIdentifier | None = None, 

22 last_login: LocalTimestamp | None = None, 

23 last_unsuccessful_login: LocalTimestamp | None = None, 

24 revoked: bool = False, 

25 admin: bool = False, 

26 ): 

27 super().__init__(id_ or UserAccountIdentifier()) 

28 self._user = user 

29 self._password = password 

30 self._last_login = last_login or LocalTimestamp() 

31 self._last_unsuccessful_login = last_unsuccessful_login or LocalTimestamp() 

32 self._revoked = revoked 

33 self._admin = admin 

34 

35 @property 

36 def admin(self) -> bool: 

37 """Check if this user an administrator.""" 

38 return self._admin 

39 

40 @property 

41 def last_login(self) -> LocalTimestamp: 

42 """Return the timestamp of the last successful login.""" 

43 return self._last_login 

44 

45 @property 

46 def last_unsuccessful_login(self) -> LocalTimestamp: 

47 """Return the timestamp of the last unsuccessful login.""" 

48 return self._last_unsuccessful_login 

49 

50 def login(self, password: str) -> bool: 

51 """Check if the given password is correct. 

52 

53 When login succeeds, last_login will be updated. 

54 When login fails, last_unsuccessful_login will be updated. 

55 

56 Args: 

57 password(str): The password. 

58 """ 

59 if self._password.verify(password): 

60 self._last_login = LocalTimestamp.create_now() 

61 return True 

62 

63 self._last_unsuccessful_login = LocalTimestamp.create_now() 

64 return False 

65 

66 @property 

67 def password(self) -> Password: 

68 """Return the password of the user.""" 

69 return self._password 

70 

71 def reset_password(self, password: Password): 

72 """Reset the password of the user account. 

73 

74 Args: 

75 password(Password): The new password. 

76 """ 

77 if self._revoked: 

78 raise NotAllowedException() 

79 

80 self._password = password 

81 self._user.mark_for_update() 

82 

83 def revoke(self): 

84 """Revoke a user account.""" 

85 self._revoked = True 

86 self._user.mark_for_update() 

87 

88 @property 

89 def revoked(self) -> bool: 

90 """Check if this user is revoked.""" 

91 return self._revoked 

92 

93 @property 

94 def user(self) -> UserEntity: 

95 """Return the associated user entity.""" 

96 return self._user