graphql-engine icon indicating copy to clipboard operation
graphql-engine copied to clipboard

Increase the scope of inheritance in inherited roles for mutations and remote schema permissions

Open codingkarthik opened this issue 2 years ago • 1 comments

Is your proposal related to a problem?

Currently, when a parent role inherits mutations or remote schema permissions from its children's roles, the parent role will only be able to inherit the permission if the permissions of the children roles are exactly the same, otherwise the permission for that entity of the parent role is marked as inconsistent in the metadata. This is quite limiting as it is very rare that two roles will have exactly the same permissions as it defeats the purpose of having different roles in the first place.

Describe the solution you'd like

Ideally, we'd like to have the inheritance as we have in select permissions, where two permissions can be combined to create a new combined permission, but unfortunately, that will not be possible because with select permissions there can be no conflicts while combining two permissions, but in mutation and remote schema permissions there can be conflicts.

For example:

Consider the following update permissions for two different roles:

  1. role1
{
  "columns": [
    "title",
    "content",
    "category"
  ],
  "filter": {
    "author_id": "X-HASURA-AUTHOR-ID"
  },
  "check": {
    "content": {
      "_ne": ""
    }
  },
  "set": {
    "updated_at": "NOW()"
  }
}
  1. role2
{
  "columns": [
    "title",
    "content",
    "category"
  ],
  "filter": {
    "author_id": "X-HASURA-USER-ID"
  },
  "check": {
    "content": {
      "_ne": ""
    }
  },
  "set": {
    "updated_at": "NOW()"
  }
}

The permissions are similar except the filter path which refer different session variables, in this case, there is no good way to combine these permissions into one and this is called as a conflict.

Proposed solutions

TODO

Describe alternatives you've considered

Currently, the user can resolve an inconsitency by explicitly adding a permission for the inconsistent role entity which overrides the inherited permission.

If the feature is approved, would you be willing to submit a PR?

Related issues

https://github.com/hasura/graphql-engine/issues/8063 https://github.com/hasura/graphql-engine/issues/8343 https://github.com/hasura/graphql-engine/issues/8334

codingkarthik avatar Apr 04 '22 13:04 codingkarthik

A user has reached out with a detailed use case that requires this feature. Leaving details here

The use case is dynamically granting write access to columns at runtime.

Given the below tables:

-- grant table used to dynamically grant permissions at runtime
CREATE TABLE user_grants (
  user_id INT,
  grant_name TEXT,
  PRIMARY KEY (user_id, grant_name)
);

-- entry table users will have dynamic access to
CREATE TABLE entry (
  id INT PRIMARY KEY,
  status TEXT DEFAULT 'DRAFT',
  title TEXT,
  body TEXT
);

We want two roles: writer and editor The writer role can insert or update the title or body columns. The editor role can update the status column.

We are trying to create a single inherited role that will dynamically (de)activate the above roles based on the records in user_grants

This works for select permissions:


[
  {
    "role": "writer",
    "permission": {
      "columns": [
        "body",
        "title"
      ],
      "filter": {
        "_exists": {
          "_where": {
            "_and": [
              {
                "permission_name": {
                  "_eq": "writer"
                }
              },
              {
                "user_id": {
                  "_eq": "X-Hasura-User-Id"
                }
              }
            ]
          },
          "_table": {
            "schema": "public",
            "name": "user_grants"
          }
        }
      }
    }
  },
  {
    "role": "editor",
    "permission": {
      "columns": [
        "status"
      ],
      "filter": {
        "_exists": {
          "_where": {
            "_and": [
              {
                "permission_name": {
                  "_eq": "editor"
                }
              },
              {
                "user_id": {
                  "_eq": "X-Hasura-User-Id"
                }
              }
            ]
          },
          "_table": {
            "schema": "public",
            "name": "user_grants"
          }
        }
      }
    }
  }
]

We then create a single inherited role that includes both writer and editor. Users of this role will be able to query the status,title, and body columns, but will get null values if they don't have the correct grants.

The ask is for this method to also work for mutations, so that edit permissions can be dynamically granted.

BenoitRanque avatar Jun 01 '22 13:06 BenoitRanque

When you are doing a query and you have multiple possible roles for the content, you cannot know if you are a writer or an editor of a given content, but when you perform an action like editing the status, you should know from the frontend which rule should be used. For example there could be some query parameters or header like X-HASURA-AS-ROLE: editor to change the status of an article, which would also reduce the server costs, as you can apply this role directly to the query instead of a more complicated composition of rules.

And this would also reduce the cost of a query like on my profile settings page, where you know that you are not an anonymous, or some random user, and you can apply directly the role, owner, just as an example..

So basically the idea here is to allow sending the inherited_role as X-HASURA-ROLE: user_editor_writer but also a single role from the roles set as X-HASURA-AS-ROLE: editor for a given request, and the above issue could be solved with a minimal client side adjustment on the specific places, but also cut some performance overhead for queries where you know, who you are going to access them as, and give more freedom in creating and using inherited roles.

PS: I also believe, that this should be a very simple feature to implement, as I understand the roles are compiled to memory and can be accessed and replaced very quickly.

webdeb avatar Oct 03 '22 03:10 webdeb

any updates on this?

I want multiple roles with different permissions inherited for each remote schema

jflambert avatar Oct 31 '22 18:10 jflambert

Can anyone explain why there is a conflict with mutations and not select?

GavanWilhite avatar Apr 28 '23 21:04 GavanWilhite