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
« prev ^ index » next coverage.py v7.7.1, created at 2024-01-01 00:00 +0000
1"""Module that implement all users endpoints."""
3from typing import Annotated
5from fastapi import APIRouter, Depends, HTTPException, status
6from loguru import logger
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)
41router = APIRouter()
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()
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.
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 )
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 )
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
123 result = presenter.get_document()
124 assert result, "There is no document created yet"
125 return result