Search code examples
pythonapigoogle-cloud-firestorefastapijsonresponse

python fastapi giving incorrect responses


I have a fastapi app connected to my firebase firestore. I am writing a simple endpoint to check if the current user has an admin role or not?

I have written the following code for the endpoint

@router.get("/isAdmin")
def is_admin(userId: str):  # sourcery skip: merge-nested-ifs
    """Enddpoint to check if the current user is an admin or not

    Args:
        email_id (str): email id of the user to be validated
    """
    # Check if the user exists in our firestore database based on the email ID
    db = firestore.client()
    print(userId)
    user_ref = db.collection("users").document(userId).get()
    print(user_ref, userId)

    # Check if the user exists and if the user has admin role
    if user_ref:

        # If the user exists, check if the user is an admin and return the roles if the user is an admin
        if user_ref.to_dict()["hasAdminRole"]:
            user_id = user_ref[0].id
            user_roles_ref = (
                db.collection("users").document(user_id).collection("roles")
            )
            user_roles_data = user_roles_ref.stream()

            roles = {role.id: role.to_dict() for role in user_roles_data}
            return {"hasAdminRole": True, "roles": roles}

    # If the user doesn't exist or doesn't have admin role,
    # check the tempAdmins collection to see if the user is a temporary admin
    temp_admin_ref = db.collection("tempAdmins").document(userId).get()
    temp_admin_data = temp_admin_ref.get()
    if temp_admin_data:
        # Get the documentID from the data
        temp_admin_id = temp_admin_data[0].id

        # Reference the roles document and get the data
        temp_admin_roles_ref = (
            db.collection("tempAdmins").document(temp_admin_id).collection("roles")
        )
        temp_admin_roles_data = temp_admin_roles_ref.stream()

        roles = {role.id: role.to_dict() for role in temp_admin_roles_data}
        return {"hasAdminRole": True, "roles": roles}

    # return no access message if the user is not an admin
    return JSONResponse(
        status_code=response_status.HTTP_401_UNAUTHORIZED,
        content={"message": NO_ADMIN_ACCESS_ERROR, "hasAdminRole": False},
    )

For any email ID, whether it's an admin or not, I get the following response.

{
  "message": "User does not exist"
}

The above response is very weird because I am not even writing the above message as a response anywhere and I don't know if this a fastapi swagger issue.

The endpoint I am hitting is - http://127.0.0.1:8000/users/isAdmin?email=test%40test.com


Solution

  • You should use path params for taking userId as input. Possibly rn your userId value is undefined or taken in invalid format resulting in exception raised by admin SDK

    Example -

    @router.get("/isAdmin/{userId}")
    def is_admin(userId: str):  # sourcery skip: merge-nested-ifs
        """Enddpoint to check if the current user is an admin or not
    
        Args:
            user_id (str): user id of the user to be validated
        """
    

    And use the endpoint as http://127.0.0.1:8000/users/isAdmin/11111111-1111-1111-1111-111111111111


    Regarding the unknown message "User not found"

    It is being raised by the SDK You can consider using try, catch block to surround the requests as admin sdk raises exceptions on errors and they need to be caught and managed.