... | ... | @@ -208,6 +208,66 @@ This methods uses the *rest_framework.authtoken.models.Token* model to store per |
|
|
|
|
|
# The permission classes
|
|
|
|
|
|
[Official DRF documentation about permission](https://www.django-rest-framework.org/api-guide/permissions/)
|
|
|
|
|
|
In addition to the authentication, DRF introduces a permission mechanism to restrict the user's possible actions. The provided DRF permissions classes are simple basic checks and did not fit into our custom ACL system, so custom permission classes were created in `api.permissions`.
|
|
|
|
|
|
## Selecting the permission classes
|
|
|
|
|
|
By default, *api.permissions.AutodetectACLPermission* is used on all view as specified in [the settings file](#the-settings-file). But this behavior can be changed on specific views like that:
|
|
|
|
|
|
```python
|
|
|
from rest_framework.views import APIView
|
|
|
from rest_framework.permissions import IsAuthenticated, IsAdminUser
|
|
|
from .permissions import ACLPermission
|
|
|
|
|
|
class MyView1(APIView):
|
|
|
permission_classes = (IsAuthenticated, )
|
|
|
# Request are authorized only if the user is authenticated
|
|
|
|
|
|
class MyView1(APIView):
|
|
|
permission_classes = (ACLPermission, )
|
|
|
# Request are authorized only if the user has the right ACL
|
|
|
|
|
|
class MyView1(APIView):
|
|
|
permission_classes = (IsAuthenticated, IsAdminUser)
|
|
|
# Request are authorized only if the user is authenticated and is an admin
|
|
|
|
|
|
class MyView1(APIView):
|
|
|
# Default permission class is used
|
|
|
```
|
|
|
|
|
|
|
|
|
## api.permissions.AutodetectACLPermission
|
|
|
|
|
|
This permission requires a `.queryset` or a `.get_queryset` method to be set on the view. It is used to determine the model against which to check the users's ACL. The ACL used are the one that makes the most sense according the HTTP method used (e.g. GET will lead to checking `model.can_view_all`, POST will lead to checking `model.can_create`).
|
|
|
|
|
|
If the view is targeting an object precisely, DRF's generic views will additionally call the method `has_obj_permission` whose role is to check the user has the correct ACL for the operation asked (e.g. GET will lead to checking `obj.can_see`, DELETE will lead to checking `obj.can_delete`).
|
|
|
|
|
|
Moreover, for every request made, it is also checking that the user has the right to use the API by calling `api.can_use`.
|
|
|
|
|
|
|
|
|
## api.permissions.ACLPermission
|
|
|
|
|
|
For views that do not define a queryset or requires a different behavior, this permission can be used. Its behavior is intended to be more flexible and generic but the configuration is more complex. To use it, the view should have a `.perms_map` attribute defined. This attribute has a quite strict syntax but is still easy to read:
|
|
|
```python
|
|
|
# It is a dictionary
|
|
|
perms_map = {
|
|
|
# Define a list of permission to have for each HTTP method
|
|
|
# If the HTTP method is not defined here, the request is refused
|
|
|
'GET': [
|
|
|
# Each elements here should be a an acl function that takes a user
|
|
|
# To be authorized, all permission must return `True` for the user
|
|
|
users.User.can_view_all,
|
|
|
machines.Interface.can_view_all,
|
|
|
users.User.get(pk=1).can_see
|
|
|
],
|
|
|
'POST': [topologie.SOA.can_view_all]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
It is also important to note that this permission will also checks that the user can use the api by systematically calling `api.can_use` in addition to all other ACL functions. So there is no need to specify this ACL in the `.perms_map` attribute.
|
|
|
|
|
|
|
|
|
# The serializers
|
|
|
|
... | ... | |