Skip to main content

A package to add field permission support for Graphene

Project description

# Graphene Field Permission

A package to add field-level permissions for [graphene-django](https://github.com/graphql-python/graphene-django).


## Use
On schema nodes add a decorator "\@has_field_access" to a resolve for each field that you want checked.


Usage example in schema files:
```python
from graphene_field_permission.decorators import has_field_access

class GroupNode(DjangoObjectType):
@has_field_access('permission1')
def resolve_group_name(self, info):
return self.name

class Meta:
model = Group
...
```

Example showing checking for one of multiple (unlimited) permissions:

```python
from graphene_field_permission.decorators import has_field_access

class GroupNode(DjangoObjectType):
@has_field_access('permission1', 'permission2')
def resolve_group_description(self, info):
return self.description
```

Example showing checking for one of multiple permissions under a group, for cases where permissions differ by group id:

```python
from graphene_field_permission.decorators import has_field_access

class GroupNode(DjangoObjectType):
@has_field_access('permission1', 'permission2', filter_field='group_id')
def resolve_group_text(self, info):
return self.text
```
```group_id``` in the above example will look at the GroupNode group_id field. Add ```.``` separators for related objects. ```filter_fields``` processing will traverse related objects as necessary to reduce the number of queries.

It's recommended to try and reduce these as much as possible. e.g. using group.division.corporation_id instead of group.division.corporation.id

```python
@has_field_access('permission1', 'permission2', filter_field='group.division.corporation_id')
```

## Result in GraphQL output:

```javascript
{
"errors": [
{
"message": "No access for user on field 'group_name'",
"locations": [
{
"line": 7,
"column": 9
}
],
"path": [
"group",
"edges",
0,
"node",
"groupName"
]
}
],
"data": {
"group": {
"edges": [
{
"node": null
}
]
}
}
}
```

### Usage notes:

1. An exception is thrown should a user attempt to access a field for which they don't have access. Graphene-django doesn't allow returning None for fields which aren't set as nullable. That makes it necessary to have your graphql queries fine grained enough to not call those fields in the first place. Client side checking of permissions is recommended in order to limit the field's accessed in the query in the first place.
1. I tried about four different ways to do this so resolve_field wasn't necessary, but found this to be the best balance of making it schema-definable and performant. I'm open to pull requests if someone can think of a better way.


## Installation

```
pip install graphene-field-permission
```

## Setup

1. Set up graphene and graphene django following their own instructions.
1. Create a file that will return permissions allowed for the user as shown below. By default lists and dicts containing lists are supported. That capability can be overridden by the user fairly easily by using your own "has_field_access" decorator and any data structure you prefer.
1. Update settings.py to match the instructions below.

### Example permissions population

These get called once per graphql call. Recommended to use Django ORM's ```select_related``` on queries where necessary in order to minimise the number of queries.

Standard:

```python
def get_user_permissions(user):
# query database to determine the passed in user's permissions
return ['permission1', 'permission2', 'permission3']

```

Or grouped:

```python
def get_user_permissions(user):
# query database to determine the passed in user's permissions
return {
'group-id-123': ['permission1', 'permission2', 'permission3'],
'group-id-456': ['permission1', 'permission3', 'permission5'],
}
```

### Settings

With the above method at app/helpers/user_permissions.py (for example) update settings.py to add:

```python
GRAPHENE_FIELD_PERMISSION = {
'SRC_MODULE': 'app.helpers.user_permissions',
'SRC_METHOD': 'get_user_permissions',
}
```

Also update the main graphene settings to add the middleware.


```python
GRAPHENE = {
'MIDDLEWARE': [
'graphene_field_permission.permissions.PermissionsMiddleware'
]
}
```

## Future updates, notes

I don't plan to develop this a whole lot further. It has scratched my itch for now. I would like to add the following though:

1. This currently only supports Graphene under Django. I'm open to others adding support for other graphene-python projects if they want to submit pull requests.


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphene-field-permission-0.0.5.tar.gz (4.9 kB view details)

Uploaded Source

Built Distribution

File details

Details for the file graphene-field-permission-0.0.5.tar.gz.

File metadata

  • Download URL: graphene-field-permission-0.0.5.tar.gz
  • Upload date:
  • Size: 4.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.5.2

File hashes

Hashes for graphene-field-permission-0.0.5.tar.gz
Algorithm Hash digest
SHA256 6fd5ffced2204057ae4c218c5244b3c42af013d7680638c76a0a7e29e888b420
MD5 75bdd674e1bfb1caed5d46d094e9ac11
BLAKE2b-256 7cb2a32f4915bc289bb6d270fb40b347a6538f01f60dda01b9fcb244e2bdb424

See more details on using hashes here.

File details

Details for the file graphene_field_permission-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: graphene_field_permission-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 8.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.5.2

File hashes

Hashes for graphene_field_permission-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 9698ccccba337948a29a73f43ef028a90e8c3b4d249b4696fcf6ea37124c2157
MD5 9f2777da81101fbebd89cd1820664ef7
BLAKE2b-256 d52e2b47e0932715310a3b26c72efbbd6ce59c938803ccf34d0d321270f6bb12

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page