How to check if curent user belongs to a role hierarchy?

In CloudCode, is there any utility function which I can determine that the current user belongs to a certain role?

Assume the following role hierarchy Admin->Manager->User

If I added user1 to the Admin role, this means if in cloud code if I query all the roles this user belongs to, then I will get an immediate list of roles, not hierarchy. I am wondering if there is a utility function that helps with this issue?

No. There is no utility function for that. maybe that’s something that we could add to the cloud code function since that it is calculated before the function execution. Anyways, what do you need to do? Maybe you can achieve what you need using cloud function validators.

1 Like

Thanks for coming to back me, Antonio. My use case required me to filter chatroom access based on the dynamic list of categories that have a pointer relation with chatroom. I am was using beforeFind to restrict and query and beforeSave to block. Now I have to check if the user belongs to a certain role but also its hierarchy.

But for now, I have decided to ditch the role hierarchy structure for my project altogether and decided to group permission in the client itself. This should be more performant solution as one doesn’t need to calculate hierarchy for each find.

But for the project, if there must be an internal function doing this which can be exposed and it might be not a bad idea.

1 Like

Hi @jascodes , a trick exists with Graphql API. If you know how deep your role hierarchy is. You can design a GraphQL that can reflect the hierarchy here (a tested example).

Created a: Role Admin, Role Manager, Role User
Manager Role is linked into the User roles relation
Admin Role is linked into the Manager roles relation

In parse the hierarchy is inverted, so you need to think not like Admin → Manager → User but like: User → Manager → Admin

So in our query we try to find the user id linked in the Admin Role users relation with 3 level deep search.

You can achieve this with the following graphql query

query level3RoleCheck($userId: ID!) {
  roles(
    where: {
      roles: {
        have: {
          roles: { have: { users: { have: { id: { equalTo: $userId } } } } }
        }
      }
    }
  ) {
    edges {
      node {
        name
        roles {
          edges {
            node {
              name
              roles {
                edges {
                  node {
                    name
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Response

{
  "data": {
    "roles": {
      "edges": [
        {
          "node": {
            "name": "User",
            "roles": {
              "edges": [
                {
                  "node": {
                    "name": "Manager",
                    "roles": {
                      "edges": [
                        {
                          "node": {
                            "name": "Admin"
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}

Here an example for a level 2 check (you only need to change the where)

query level2RoleCheck($userId: ID!) {
  roles(
    where: {
      roles: { have: { users: { have: { id: { equalTo: $userId } } } } }
    }
  ) {
    edges {
      node {
        name
        roles {
          edges {
            node {
              name
              roles {
                edges {
                  node {
                    name
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Note: This is a non optimal way to handle security. As i understand you add the Role pointer on the Chatroom object, i can suggest to add the Role in Chatroom ACLs (and linked ressources ACls like messages of the chatroom), then parse will filter objects for you.
Using beforeFind could be tedious to maintain.

1 Like

First of all thanks Antoine for taking time out to answer. As I mentioned in reply before, I will make roles as granular as possible and group them on the client-side. This will have additional performance benefits.

Sorry If I was not able to explain my use case properly. I am not adding a role pointer to the chat room. The chat room has a category pointer. And based on category these chatrooms will be accessible. But these categories are dynamic user-editable and there will be a list of people who will be assigned for a subset of these categories.

But for the Parse project, this calculation of hierarchy must for done somewhere. So in the end I was just saying it might be useful to make the function public for cloud code.

Anycase thanks guys @davimacedo @Moumouls for your help. Possibly I will be more involved with the community. For now, I am going through my learning curve of good practices and have started looking at the codebase.