0

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

Prakhar Rathi
  • 905
  • 1
  • 11
  • 25
  • Which line in your is_admin function returning that "User does not exist" message? The response doesn't look to be coming from your is_admin function, which is returning "You do not have an admin role" if all checks above fail. – Porz Apr 13 '23 at 05:21
  • You're gonna have to show more of your application to get any meaningful help here. What does your API endpoint look like? – M.O. Apr 13 '23 at 08:26
  • @Porz that is the weird thing. I am not printing it and yet it's showing that. – Prakhar Rathi Apr 13 '23 at 19:05
  • Well, in that case you're gonna have to do some old fashioned debugging and figure out where `"User does not exist"` is coming from. There is no way to tell fro.m just this snippet. – M.O. Apr 14 '23 at 06:23
  • That's the point. It's not coming from anywhere. It's not being printed anywhere. I think it's a firebase issue. – Prakhar Rathi Apr 17 '23 at 11:07

1 Answers1

1

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.

DigiNova
  • 26
  • 3