来自 BasePermission 的 Django (drf) 动态权限



我想有一个简单的方法来检查某人是否是post的所有者或管理员,proposal等等,他正在尝试编辑\删除。

因此,每次我使用IsAuthenticated权限并以ModelViewSet的方法获取实例并检查instance.author或有时instance.owner是否是请求它的用户(在某些对象上request.user == instance.owner它是request.user == instance.author(。

问题

主要问题是:如何创建权限类,以检查实例上的动态用户属性名称的这种所有权?

我的解决方案之一(我认为不是最好的(

我创建了采用用户属性实例名称返回权限类的函数:

def is_owner_or_admin_permission_factory(owner_prop_name):
class IsOwnerOrAdmin(BasePermission):
def has_permission(self, request, view, *args, **kwargs):
instance = view.get_object()
try:
owner = getattr(instance, owner_prop_name)
except AttributeError:
return False
return (
request.user and request.user.id and (owner == request.user or request.user.is_staff)
)
return IsOwnerOrAdmin

几天来,我也对同一个确切的问题感到沮丧,在处理具有不同查找名称的用户属性的多个模型时,我设法找到了一个合适的解决方法(当然,至少对我来说是这样(。

解决方法是这样的,在ModelViewSet中定义了一个单独的属性user_lookup_kwarg视图中,可用于检查适当的权限。

例如,

class YourViewSet(viewsets.ModelViewSet):
queryset = YourModel.objects.all()
serializer_class = YourSerializer
user_lookup_kwarg = 'user' #or 'account/created_by' whatever.

现在,你的permission_class会有点像这样,

class CustomPermission(BasePermission):
def has_object_permission(self, request, view, obj):
try:
return request.user.is_superuser or getattr(obj, view.user_lookup_kwarg) == request.user
except:
return False
return request.user.is_superuser

您只需覆盖has_object_permission()方法来检查实例级别权限。

对于发现这个问题的人,我的变体:

class IsInGroup:
"""
Usage:
class MyView(ReadOnlyModelViewSet):
permission_classes = (IsInGroup('Admins'),)
"""
def __new__(cls, group_name):
return type(
f'IsInGroup{group_name}',
(IsAuthenticated,),
{
'group_name': group_name,
**{key: value for key, value in cls.__dict__.items() if not key.startswith('__')},
},
)
group_name: str
def has_permission(self, request, view):
return request.user.groups.filter(name=self.group_name).exists()

最新更新