Skip to content

Commit ff625ec

Browse files
authored
Document object level permissions gotchas (encode#7446)
* Document the limitation that object level permissions do not apply to object creation. See for example encode#6409. * Add overview of three different ways to restrict access
1 parent 883f6fe commit ff625ec

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

docs/api-guide/permissions.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ For performance reasons the generic views will not automatically apply object le
7070

7171
Often when you're using object level permissions you'll also want to [filter the queryset][filtering] appropriately, to ensure that users only have visibility onto instances that they are permitted to view.
7272

73+
Because the `get_object()` method is not called, object level permissions from the `has_object_permission()` method **are not applied** when creating objects. In order to restrict object creation you need to implement the permission check either in your Serializer class or override the `perform_create()` method of your ViewSet class.
74+
7375
## Setting the permission policy
7476

7577
The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example.
@@ -272,6 +274,30 @@ Note that the generic views will check the appropriate object level permissions,
272274

273275
Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the [filtering documentation][filtering] for more details.
274276

277+
# Overview of access restriction methods
278+
279+
REST framework offers three different methods to customize access restrictions on a case-by-case basis. These apply in different scenarios and have different effects and limitations.
280+
281+
* `queryset`/`get_queryset()`: Limits the general visibility of existing objects from the database. The queryset limits which objects will be listed and which objects can be modified or deleted. The `get_queryset()` method can apply different querysets based on the current action.
282+
* `permission_classes`/`get_permissions()`: General permission checks based on the current action, request and targeted object. Object level permissions can only be applied to retrieve, modify and deletion actions. Permission checks for list and create will be applied to the entire object type. (In case of list: subject to restrictions in the queryset.)
283+
* `serializer_class`/`get_serializer()`: Instance level restrictions that apply to all objects on input and output. The serializer may have access to the request context. The `get_serializer()` method can apply different serializers based on the current action.
284+
285+
The following table lists the access restriction methods and the level of control they offer over which actions.
286+
287+
| | `queryset` | `permission_classes` | `serializer_class` |
288+
|------------------------------------|------------|----------------------|--------------------|
289+
| Action: list | global | no | object-level* |
290+
| Action: create | no | global | object-level |
291+
| Action: retrieve | global | object-level | object-level |
292+
| Action: update | global | object-level | object-level |
293+
| Action: partial_update | global | object-level | object-level |
294+
| Action: destroy | global | object-level | no |
295+
| Can reference action in decision | no** | yes | no** |
296+
| Can reference request in decision | no** | yes | yes |
297+
298+
\* A Serializer class should not raise PermissionDenied in a list action, or the entire list would not be returned. <br>
299+
\** The `get_*()` methods have access to the current view and can return different Serializer or QuerySet instances based on the request or action.
300+
275301
---
276302

277303
# Third party packages

0 commit comments

Comments
 (0)