File: permissions.md

package info (click to toggle)
strawberry-graphql-django 0.62.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,968 kB
  • sloc: python: 27,530; sh: 17; makefile: 16
file content (101 lines) | stat: -rw-r--r-- 3,884 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
---
title: Permissions
---

# Permissions

This integration exposes a field extension to extend fields into using the
[Django's Permissioning System](https://docs.djangoproject.com/en/4.2/topics/auth/default/)
for checking for permissions.

It supports protecting any field for cases like:

- The user is authenticated
- The user is a superuser
- The user or a group they belongs to has a given permission
- The user or the group they belongs has a given permission to the resolved value
- The user or the group they belongs has a given permission to the parent of the field
- etc

## How it works

```mermaid
graph TD
  A[Extension Check for Permissions] --> B;
  B[User Passes Checks] -->|Yes| BF[Return Resolved Value];
  B -->|No| C;
  C[Can return 'OperationInfo'?] -->|Yes| CF[Return 'OperationInfo'];
  C -->|No| D;
  D[Field is Optional] -->|Yes| DF[Return 'None'];
  D -->|No| E;
  E[Field is a 'List'] -->|Yes| EF[Return an empty 'List'];
  E -->|No| F;
  F[Field is a relay 'Connection'] -->|Yes| FF[Return an empty relay 'Connection'];
  F -->|No| GF[Raises 'PermissionDenied' error];
```

## Example

```python title="types.py"
import strawberry_django
from strawberry_django.permissions import (
    IsAuthenticated,
    HasPerm,
    HasRetvalPerm,
)


@strawberry_django.type
class SomeType:
    login_required_field: RetType = strawberry_django.field(
        # will check if the user is authenticated
        extensions=[IsAuthenticated()],
    )
    perm_required_field: OtherType = strawberry_django.field(
        # will check if the user has `"some_app.some_perm"` permission
        extensions=[HasPerm("some_app.some_perm")],
    )
    obj_perm_required_field: OtherType = strawberry_django.field(
        # will check the permission for the resolved value
        extensions=[HasRetvalPerm("some_app.some_perm")],
    )
```

## Available Options

Available options are:

- `IsAuthenticated`: Checks if the user is authenticated (i.e. `user.is_autenticated`)
- `IsStaff`: Checks if the user is a staff member (i.e. `user.is_staff`)
- `IsSuperuser`: Checks if the user is a superuser (i.e. `user.is_superuser`)
- `HasPerm(perms: str | list[str], any_perm: bool = True)`: Checks if the user has any or all of
  the given permissions (i.e. `user.has_perm(perm)`)
- `HasSourcePerm(perms: str | list[str], any: bool = True)`: Checks if the user has any or all
  of the given permissions for the root of that field (i.e. `user.has_perm(perm, root)`)
- `HasRetvalPerm(perms: str | list[str], any: bool = True)`: Resolves the retval and then
  checks if the user has any or all of the given permissions for that specific value
  (i.e. `user.has_perm(perm, retval)`). If the return value is a list, this extension
  will filter the return value, removing objects that fails the check (check below for more
  information regarding other possibilities).

> [!NOTE]
> The `HasSourcePerm` and `HasRetvalPerm` require having an
> [authentication backend](https://docs.djangoproject.com/en/4.2/topics/auth/customizing/)
> which supports resolving object permissions. This lib works out of the box with
> [django-guardian](https://django-guardian.readthedocs.io/en/stable/), so if you are
> using it you don't need to do anything else.

## No Permission Handling

When the condition fails, the following will be returned on the field (following this priority):

1. `OperationInfo`/`OperationMessage` if those types are allowed at the return type
2. `null` in case the field is not mandatory (e.g. `String` or `[String]`)
3. An empty list in case the field is a list (e.g. `[String]!`)
4. An empty `Connection` in case the return type is a relay connection
5. Otherwise, an error will be raised

## Custom Permissions Checking

You can create your own permission checking extension by subclassing
`DjangoPermissionExtension` and implementing your own `resolve_for_user` method.