Access control use-cases ======================== .. contents:: Table of contents :backlinks: none :depth: 1 :local: The following are the different permutations in which you can configure a single permission rule to support different use-cases. Add a simple access control rule for a logged in user ----------------------------------------------------- Let's say that we want to restrict users to fetch only their own data. Head to the ``Permissions`` tab of the ``author`` table. Now add a ``select`` access control rule for the ``user`` role on the ``author`` table: .. thumbnail:: ../../../../img/graphql/manual/auth/author-select-perms.png This rule reads as: .. list-table:: :header-rows: 1 :widths: 25 20 45 * - Definition - Condition - Representation * - allow user to access only their own row - ``id`` in the row is equal to ``user-id`` from the request session variable - .. code-block:: json { "id": { "_eq": "X-Hasura-User-Id" } } Now, let's make the same query as above but also include two dynamic authorization variables ``X-Hasura-Role`` and ``X-Hasura-User-Id`` via request headers. These will automatically get used according to the permission rule we set up. .. thumbnail:: ../../../../img/graphql/manual/auth/query-with-perms.png You can notice above how the same query now only includes the right slice of data. .. admonition:: Defining access control rules Access control, or permission rules can be as complex as you need them to be, even using a nested object's fields if required. You can use the same operators that you use to filter query results to define permission rules. See :doc:`filtering query results <../../queries/query-filters>` for more details. For example, for an ``article`` table with a nested ``author`` table, we can define the select permission as: .. code-block:: json { "_and": [ { "published_on": { "_gt": "31-12-2018" } }, { "author": { "id": { "_eq": "X-Hasura-User-Id" } } } ] } This rule reads as: allow selecting an article if it was published after "31-12-2018" and its author is the current user. .. _restrict_columns: Restrict access to certain columns ---------------------------------- We can restrict the columns of a table that a particular role has access to. Head to the ``Permissions`` tab of the table and edit the ``Select`` permissions for the role: .. thumbnail:: ../../../../img/graphql/manual/auth/restrict-columns.png .. _limit_rows: Limit number of rows returned in a single request ------------------------------------------------- We can set a hard limit on the maximum number of rows that will be returned in a single request for a table for a particular role. Head to the ``Permissions`` tab of the table and edit the ``Select`` permissions for the role: .. thumbnail:: ../../../../img/graphql/manual/auth/limit-results.png .. _using-relationships-in-permissions: Using relationships or nested objects in permissions ---------------------------------------------------- You can leverage relationships to define permission rules with fields from a nested object. Let's take the following example: * An author/articles schema where an article can have one or more reviewers i.e. users with the role ``reviewer`` can only edit those articles that have been assigned to them: .. thumbnail:: ../../../../img/graphql/manual/auth/schema-for-nested-object-based-permissions.png * The foreign key constraint from ``reviewers`` :: ``article_id`` → ``articles`` :: ``id`` is used for an array relationship called ``reviewers`` in the ``articles`` table: .. thumbnail:: ../../../../img/graphql/manual/auth/array-relationship-reviewers.png :class: no-shadow We can use this relationship in a permission rule for the ``articles`` table to limit access for users with the role ``reviewer`` to only assigned rows: .. thumbnail:: ../../../../img/graphql/manual/auth/nested-object-permissions-rule.gif Via the relationship, we are using the ``reviewer_id`` field of the nested object ``reviewers`` in the the above permission rule that reads as "Allow updating an article if the **reviewer_id of any of the reviewers assigned to this article** is the same as the requesting user's id (*which is sent in the resolved session variable* ``X-Hasura-User-ID``)". Let's say we have the following test data for the list of reviewers: .. list-table:: Data in the ``reviewers`` table :header-rows: 1 * - id - article_id - reviewer_id * - 1 - 1 - 5 * - 2 - 3 - 5 * - 3 - 5 - 5 * - 4 - 2 - 6 * - 5 - 4 - 6 Applying the above permission rule for "update" to "select" operation also, let's query the ``articles`` table to watch this permission rule in action: .. thumbnail:: ../../../../img/graphql/manual/auth/restricted-data-for-role-reviewer.png :class: no-shadow As we've made this query with the role ``reviewer`` and user ID ``5`` (*highlighted in the request headers in the above image*), we can only query those articles for which this user is a reviewer. This will be the case for update mutations too. As the user with id ``5`` does not have access to article with id ``2`` (*refer to the table above*), the following mutation will not update any rows of the ``articles`` table: .. thumbnail:: ../../../../img/graphql/manual/auth/unsuccessful-mutation-for-role-reviewer.png :class: no-shadow .. admonition:: Array and Object relationships work similarly The above example would have worked even if the relationship were an object relationship. In our example, the corresponding rule for an object relationship would have read "*if this article's reviewer's id is the same as the requesting user's id, allow access to it*". More about permissions ---------------------- Next: :doc:`Roles and dynamic variables `