如何限制用户创建他们无权访问的模型
How to restrict users from creating a model that they don't have access to
我有 Workspace 和 Request 模型。一个 Workspace 可以分配多个 Users。任何 User 都可以创建请求。我想限制用户仅在 he/she 有权访问的那些 Workspaces 上创建请求。
目前,在我的 create 方法中,我正在明确检查用户是否已分配到工作区,如所附代码所示。但我很想知道我是否可以使用 django 权限以更好的方式执行此操作。我试图实现 get_permissions 方法,如代码所示。
# models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Workspace(models.Model):
name = models.CharField(max_length=50)
creation_date = models.DateTimeField('creation_date', auto_now_add=True)
users = models.ManyToManyField(User)
def __repr__(self):
return '<Workspace: %r, %r, %r>' % (self.id, self.name, self.users)
class Request(models.Model):
name = models.CharField(max_length=50)
status = models.CharField(max_length=10, default='NEW')
status_msg = models.CharField(max_length=100, default=None, blank=True, null=True)
query_str = models.CharField(max_length=1000)
# user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
workspace = models.ForeignKey(Workspace, on_delete=models.DO_NOTHING)
request_type = models.CharField(max_length=20, default='AD')
creation_date = models.DateTimeField('creation_date', auto_now_add=True)
def __repr__(self):
return '<Request %r, %r, %r, %r>' % (self.id, self.query_str, self.status, self.status_msg)
# views.py
class RequestViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
workspace_id = request.data['workspace']
# check if user has access to this workspace
if Workspace.objects.filter(pk=workspace_id).filter(users=request.user.id).exists():
print('workspace exists')
request.data['user'] = request.user.id
print(request.data)
return super(RequestViewSet, self).create(request, *args, **kwargs)
return Response(status=status.HTTP_403_FORBIDDEN)
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
print(self.action)
if self.action == 'create':
permission_classes = [IsAuthenticated,]
else:
permission_classes = [IsAuthenticated,]
print(permission_classes)
return [permission() for permission in permission_classes]
您要申请的是对象级权限。你不需要使用 django 权限来做到这一点。相反,您可以通过使用 request.user
来做到这一点,它持有发出该请求的当前用户。所以你需要这样的东西:
def your_view(request, pk):
workspace = models.Workspace.objects.get(pk=pk)
if request.user not in workspace.users.all():
# user is not related to that workspace, permission denied
raise PermissionDenied
else:
# permission granted, do what you want
pass
您可以在用户没有权限时更改您的行为,例如返回 403 html 模板等,而不是引发异常。这取决于您的设计。
我有 Workspace 和 Request 模型。一个 Workspace 可以分配多个 Users。任何 User 都可以创建请求。我想限制用户仅在 he/she 有权访问的那些 Workspaces 上创建请求。
目前,在我的 create 方法中,我正在明确检查用户是否已分配到工作区,如所附代码所示。但我很想知道我是否可以使用 django 权限以更好的方式执行此操作。我试图实现 get_permissions 方法,如代码所示。
# models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Workspace(models.Model):
name = models.CharField(max_length=50)
creation_date = models.DateTimeField('creation_date', auto_now_add=True)
users = models.ManyToManyField(User)
def __repr__(self):
return '<Workspace: %r, %r, %r>' % (self.id, self.name, self.users)
class Request(models.Model):
name = models.CharField(max_length=50)
status = models.CharField(max_length=10, default='NEW')
status_msg = models.CharField(max_length=100, default=None, blank=True, null=True)
query_str = models.CharField(max_length=1000)
# user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
workspace = models.ForeignKey(Workspace, on_delete=models.DO_NOTHING)
request_type = models.CharField(max_length=20, default='AD')
creation_date = models.DateTimeField('creation_date', auto_now_add=True)
def __repr__(self):
return '<Request %r, %r, %r, %r>' % (self.id, self.query_str, self.status, self.status_msg)
# views.py
class RequestViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
workspace_id = request.data['workspace']
# check if user has access to this workspace
if Workspace.objects.filter(pk=workspace_id).filter(users=request.user.id).exists():
print('workspace exists')
request.data['user'] = request.user.id
print(request.data)
return super(RequestViewSet, self).create(request, *args, **kwargs)
return Response(status=status.HTTP_403_FORBIDDEN)
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
print(self.action)
if self.action == 'create':
permission_classes = [IsAuthenticated,]
else:
permission_classes = [IsAuthenticated,]
print(permission_classes)
return [permission() for permission in permission_classes]
您要申请的是对象级权限。你不需要使用 django 权限来做到这一点。相反,您可以通过使用 request.user
来做到这一点,它持有发出该请求的当前用户。所以你需要这样的东西:
def your_view(request, pk):
workspace = models.Workspace.objects.get(pk=pk)
if request.user not in workspace.users.all():
# user is not related to that workspace, permission denied
raise PermissionDenied
else:
# permission granted, do what you want
pass
您可以在用户没有权限时更改您的行为,例如返回 403 html 模板等,而不是引发异常。这取决于您的设计。