我想有一个简单的方法来检查某人是否是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()