mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 11:33:59 +03:00
switch to a dedicated filter for read list object permissions
This commit is contained in:
parent
118645e480
commit
9ff0f6d3bf
|
@ -4,7 +4,7 @@ returned by list views.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from rest_framework.compat import django_filters, six
|
from rest_framework.compat import django_filters, six, guardian
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
@ -23,6 +23,22 @@ class BaseFilterBackend(object):
|
||||||
raise NotImplementedError(".filter_queryset() must be overridden.")
|
raise NotImplementedError(".filter_queryset() must be overridden.")
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectPermissionReaderFilter(BaseFilterBackend):
|
||||||
|
"""
|
||||||
|
A filter backend that limits results to those where the requesting user
|
||||||
|
has read object level permissions.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
assert guardian, 'Using ObjectPermissionReaderFilter, but django-guardian is not installed'
|
||||||
|
|
||||||
|
def filter_queryset(self, request, queryset, view):
|
||||||
|
user = request.user
|
||||||
|
model_cls = queryset.model
|
||||||
|
model_name = model_cls._meta.module_name
|
||||||
|
permission = 'read_' + model_name
|
||||||
|
return guardian.shortcuts.get_objects_for_user(user, permission, queryset)
|
||||||
|
|
||||||
|
|
||||||
class DjangoFilterBackend(BaseFilterBackend):
|
class DjangoFilterBackend(BaseFilterBackend):
|
||||||
"""
|
"""
|
||||||
A filter backend that uses django-filter.
|
A filter backend that uses django-filter.
|
||||||
|
|
|
@ -9,6 +9,7 @@ SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS']
|
||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework.compat import oauth2_provider_scope, oauth2_constants, guardian
|
from rest_framework.compat import oauth2_provider_scope, oauth2_constants, guardian
|
||||||
|
from rest_framework.filters import ObjectPermissionReaderFilter
|
||||||
|
|
||||||
|
|
||||||
class BasePermission(object):
|
class BasePermission(object):
|
||||||
|
@ -169,7 +170,7 @@ class DjangoObjectLevelModelPermissions(DjangoModelPermissions):
|
||||||
'destroy': 'delete',
|
'destroy': 'delete',
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_names(self, view):
|
def _get_model_name(self, view):
|
||||||
model_cls = getattr(view, 'model', None)
|
model_cls = getattr(view, 'model', None)
|
||||||
queryset = getattr(view, 'queryset', None)
|
queryset = getattr(view, 'queryset', None)
|
||||||
|
|
||||||
|
@ -182,19 +183,17 @@ class DjangoObjectLevelModelPermissions(DjangoModelPermissions):
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
if view.action == 'list':
|
if view.action == 'list':
|
||||||
user = request.user
|
|
||||||
queryset = view.get_queryset()
|
queryset = view.get_queryset()
|
||||||
model_name = self._get_names(view)
|
view.queryset = ObjectPermissionReaderFilter().filter_queryset(request, queryset, view)
|
||||||
view.queryset = guardian.shortcuts.get_objects_for_user(user, 'read_' + model_name, queryset) #TODO: move to filter
|
|
||||||
return super(DjangoObjectLevelModelPermissions, self).has_permission(request, view)
|
return super(DjangoObjectLevelModelPermissions, self).has_permission(request, view)
|
||||||
|
|
||||||
def has_object_permission(self, request, view, obj):
|
def has_object_permission(self, request, view, obj):
|
||||||
user = request.user
|
|
||||||
model_name = self._get_names(view)
|
|
||||||
action = self.action_perm_map.get(view.action)
|
action = self.action_perm_map.get(view.action)
|
||||||
|
|
||||||
assert action, "Tried to determine object permissions but no action specified in view"
|
assert action, "Tried to determine object permissions but no action specified in view"
|
||||||
|
|
||||||
|
user = request.user
|
||||||
|
model_name = self._get_model_name(view)
|
||||||
|
|
||||||
perm = "{action}_{model_name}".format(action=action, model_name=model_name)
|
perm = "{action}_{model_name}".format(action=action, model_name=model_name)
|
||||||
check = user.has_perm(perm, obj)
|
check = user.has_perm(perm, obj)
|
||||||
if not check:
|
if not check:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user