graphql-engine/docs/graphql/manual/auth/authorization/role-multiple-rules.rst

122 lines
3.7 KiB
ReStructuredText
Raw Normal View History

2019-12-26 15:05:37 +03:00
Multiple column + row permissions for the same role
===================================================
.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:
Use case
--------
In some cases we might want to allow access to certain columns for a role only if a particular condition is met
while allowing access to other columns based on a different condition
i.e. have different column permissions based on different row permissions.
Currently it is not possible to define multiple column + row permission rules for the same role.
We can work around this limitation by using :ref:`views <custom_views>`.
**Example**
Let's say we have a table called ``user_info`` with columns ``(id, name, city, email, phone, address)``.
We want the role ``user`` to be able to access:
- the ``email``, ``phone`` and ``address`` columns only if the ``id`` column is the requesting user's id i.e. the current
user is the owner of the row.
- the ``id``, ``name`` and ``city`` columns for all rows.
We can achieve this via the following steps:
Step 1: Create a view
---------------------
Create a :ref:`view <create_views>` called ``user_private`` with columns ``(user_id, email, phone, address)``:
.. code-block:: SQL
CREATE VIEW user_private AS
SELECT id AS user_id, email, phone, address
FROM user_info;
Step 2: Create a relationship
-----------------------------
For the table ``user_info``, create a :ref:`manual object relationship <create_manual_relationships>` called
``private_info`` using ``user_info : id -> user_private : user_id``:
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-create-manual-relationship.png
:alt: Create a manual object relationship
2019-12-26 15:05:37 +03:00
Step 3: Define permissions
--------------------------
For the role ``user``, create the following permissions for ``select``:
- Table ``user_info``: allow access to ``id``, ``name`` and ``city`` without any row conditions.
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-define-public-permissions.png
:alt: Column access for the role user
2019-12-26 15:05:37 +03:00
- View ``user_private``: allow access to ``id``, ``phone``, ``email`` and ``address`` if the ``user-id``
passed in the session variable is equal to the row's ``user_id``.
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-define-private-permissions.png
:alt: Column access for the role user based on row level permissions
2019-12-26 15:05:37 +03:00
Step 4: Query with appropriate access control
---------------------------------------------
Now we can fetch the required data with the appropriate access control by using the relationship.
If the ``X-Hasura-Role`` and the ``X-Hasura-User-Id`` session variables are set to ``user`` and ``2`` respectively, we'll get the following result:
.. graphiql::
:view_only:
:query:
query {
user_info {
id
name
city
private_info {
email
phone
address
}
}
}
:response:
{
"data": {
"user_info": [
{
"id": 1,
"name": "Julie",
"city": "Boston",
"private_info": null
},
{
"id": 2,
"name": "Josh",
"city": "Bangalore",
"private_info": {
"email": "josh@josh.com",
"phone": "+91-9787675678",
"address": "#141, 7th Main Road, Koramangala 3rd Block",
}
},
{
"id": 3,
"name": "John",
"city": "Berlin",
"private_info": null
}
]
}
}
Observe that the ``private_info`` field is returned as ``null`` for all rows without the appropriate access.