Coverage for src/kwai/api/v1/auth/endpoints/users.py: 52%

40 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2024-01-01 00:00 +0000

1"""Module that implement all users endpoints.""" 

2 

3from typing import Annotated 

4 

5from fastapi import APIRouter, Depends, HTTPException, status 

6from loguru import logger 

7 

8from kwai.api.dependencies import create_database, get_current_user 

9from kwai.api.v1.auth.presenters import ( 

10 JsonApiUserAccountPresenter, 

11 JsonApiUserAccountsPresenter, 

12) 

13from kwai.api.v1.auth.schemas.user_account import ( 

14 CreateUserAccountResource, 

15 UserAccountDocument, 

16) 

17from kwai.core.db.database import Database 

18from kwai.core.db.uow import UnitOfWork 

19from kwai.core.domain.exceptions import UnprocessableException 

20from kwai.core.json_api import PaginationModel, SingleDocument 

21from kwai.modules.identity.accept_user_invitation import ( 

22 AcceptUserInvitation, 

23 AcceptUserInvitationCommand, 

24) 

25from kwai.modules.identity.get_user_accounts import ( 

26 GetUserAccounts, 

27 GetUserAccountsCommand, 

28) 

29from kwai.modules.identity.user_invitations.user_invitation_db_repository import ( 

30 UserInvitationDbRepository, 

31) 

32from kwai.modules.identity.user_invitations.user_invitation_repository import ( 

33 UserInvitationNotFoundException, 

34) 

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

36from kwai.modules.identity.users.user_account_db_repository import ( 

37 UserAccountDbRepository, 

38) 

39 

40 

41router = APIRouter() 

42 

43 

44@router.get( 

45 "", 

46 summary="Get all users", 

47 responses={ 

48 200: {"description": "Ok."}, 

49 401: {"description": "Not Authorized."}, 

50 }, 

51) 

52async def get( 

53 database: Annotated[Database, Depends(create_database)], 

54 pagination: Annotated[PaginationModel, Depends(PaginationModel)], 

55 user: Annotated[UserEntity, Depends(get_current_user)], 

56): 

57 """Get all user accounts.""" 

58 command = GetUserAccountsCommand( 

59 offset=pagination.offset or 0, limit=pagination.limit or 0 

60 ) 

61 presenter = JsonApiUserAccountsPresenter() 

62 await GetUserAccounts(UserAccountDbRepository(database), presenter).execute(command) 

63 return presenter.get_document() 

64 

65 

66@router.post( 

67 "", 

68 summary="Create a new user account", 

69 status_code=status.HTTP_201_CREATED, 

70 responses={ 

71 201: {"description": "User account created"}, 

72 400: {"description": "Wrong or missing user invitation relationship"}, 

73 404: {"description": "User invitation does not exist"}, 

74 422: {"description": "Invalid email address or user invitation was invalid"}, 

75 }, 

76) 

77async def create_user_account( 

78 document: SingleDocument[CreateUserAccountResource, None], 

79 database: Annotated[Database, Depends(create_database)], 

80) -> UserAccountDocument: 

81 """Create a new user account. 

82 

83 A user account can only be created when a related user invitation 

84 is not yet expired. 

85 """ 

86 if ( 

87 document.data.relationships is None 

88 or document.data.relationships.user_invitation.data is None 

89 or isinstance(document.data.relationships.user_invitation.data, list) 

90 or document.data.relationships.user_invitation.data.id is None 

91 ): 

92 raise HTTPException( 

93 status_code=status.HTTP_400_BAD_REQUEST, 

94 detail="Wrong or missing user_invitation relationship", 

95 ) 

96 

97 command = AcceptUserInvitationCommand( 

98 uuid=document.data.relationships.user_invitation.data.id, 

99 first_name=document.data.attributes.first_name, 

100 last_name=document.data.attributes.last_name, 

101 password=document.data.attributes.password, 

102 remark=document.data.attributes.remark, 

103 ) 

104 

105 presenter = JsonApiUserAccountPresenter() 

106 async with UnitOfWork(database): 

107 try: 

108 await AcceptUserInvitation( 

109 UserInvitationDbRepository(database), 

110 UserAccountDbRepository(database), 

111 presenter, 

112 ).execute(command) 

113 except UnprocessableException as exc: 

114 logger.warning(f"User account could not be created: {exc}") 

115 raise HTTPException( 

116 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(exc) 

117 ) from exc 

118 except UserInvitationNotFoundException as exc: 

119 raise HTTPException( 

120 status_code=status.HTTP_404_NOT_FOUND, detail=str(exc) 

121 ) from exc 

122 

123 result = presenter.get_document() 

124 assert result, "There is no document created yet" 

125 return result