DRY-rest-permissions 以某种方式不检查我的对象权限,除了全局权限
DRY-rest-permissions somehow does not check my object permissions except global permissions
我最近开始实施 dry-rest-permissions,但我似乎无法检查 has_object_permissions
,似乎只有全局权限对我有用。
我对实现权限相当陌生,这是我第一次实现 DRY-rest-permissions 并且最近才开始在 django rest 框架中编码,因此对于缺乏知识提前表示歉意。
目前我正在尝试通过简单地让用户调用 URL 来删除公司对象,然后 URL 获取当前用户的 active_company
然后仅将其删除如果当前 user
是 active_company
的 company_owner
。
但我发现,我无法has_object_permissions
在任何地方工作?
我注意到,如果我删除 has_write_permission(request)
,然后点击 company_delete
URL,则会出现以下错误:
'<class 'company.models.Company'>' does not have 'has_write_permission' or 'has_company_delete_permission' defined.
这意味着它甚至不查找 has_object_company_delete_permission
。这意味着它只检查全局权限而不是任何对象权限,我在这里可能做错了什么?
我的模型:
class Company(models.Model):
company_name = models.CharField(max_length=100)
company_orders = models.IntegerField(blank=True, null=True)
company_icon = models.ImageField(
upload_to='media/company_icon', blank=True)
company_owner = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
company_employees = models.ManyToManyField(
User, blank=True, null=True, related_name="company_employees")
def __str__(self):
return self.company_name
@staticmethod
def has_write_permission(request):
return False
def has_object_company_delete_permission(self, request):
return self.company_owner == request.user
我的观点
class CompanyView(viewsets.ModelViewSet): # made for viewing details
permission_classes = (DRYPermissions, )
queryset = Company.objects.all()
serializer_class = CompanySerializer
def create(self, request):
try:
company_name = request.data['company_name']
company_orders = request.data['company_orders']
company_owner = request.data['company_owner']
company_owner_obj = User.objects.get(id=company_owner)
company = Company(company_name=company_name,
company_orders=company_orders, company_owner=company_owner_obj)
company.save()
except Exception as error:
response = {
'error': str(error)
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
response = {
'message': 'Company created'
}
return Response(response, status=status.HTTP_201_CREATED)
def company_details(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serialized_data = CompanySerializer(company)
except Exception as error:
response = {
'error': str(error)
}
return Response(response)
return Response(serialized_data.data)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)
def company_delete(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.filter(id=company_id)
company.delete()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Deleted Successfully'
}
return Response(response)
我的网址
urlpatterns = [
# Company URLs
path('company_create/',
CompanyView.as_view({'post': 'create'}), name='company_create'), # Create company
path('company_edit/',
CompanyView.as_view(), name='company_edit'), # Edit company details
path('company_delete/',
CompanyView.as_view({'delete': 'company_delete'}), name='company_delete'), # Delete company
path('company_details/',
CompanyView.as_view({'get': 'company_details'}), name='company_details'), # get company details (owner, employees etc)
]
我的序列化器
class CompanySerializer(serializers.ModelSerializer):
company_owner = LimitedUserSerializer(read_only=True)
class Meta:
model = Company
fields = ['id', 'company_name', 'company_orders',
'company_icon', 'company_owner']
如 this part of the documentation 中所述,始终首先检查全局权限,只有在通过全局权限时才检查对象权限。
文档来源:
DRY Rest Permissions allows you to define both global and object level permissions.
Global permissions are always checked first and define the ability of a user to take an action on an entire model. For example you can define whether a user has the ability to update any projects from the database.
Object permissions are checked if global permissions pass and define whether a user has the ability to perform a specific action on a single object. These are also known as row level permissions. Note: list and create actions are the only standard actions that are only global. There is no such object level permission call because they are whole table actions.
在这种情况下,您实际上有多个问题需要更正:
- 确保所有拥有活跃公司的用户
has_write_permission
return True
- 确保重命名
has_object_company_delete_permission
因为我们不需要函数名称中的模型名称
示例:
@staticmethod
def has_write_permission(request):
# Everybody can create/update/delete if no specific rule says otherwise
return True
def has_object_delete_permission(self, request):
# Only owner can delete
return self.company_owner == request.user
def has_object_update_permission(self, request):
# Only owner can update
return self.company_owner == request.user
输出:
- 每个人都可以创造
- 只有所有者可以更新
- 只有所有者可以删除
我知道仅仅删除一个对象似乎有点矫枉过正,但根据一些经验,它允许您清楚地定义 ans setup 权限,还可以通过使用 [=15= 轻松地与前端共享通用规则] 和 DRYGlobalPermissionsField
PS:这个答案来自 my origin answer on Github 让人们可以轻松地从 Whosebug
找到解决方案
它似乎以某种方式不检查我的任何自定义操作中的对象权限,因此在 get_object() 中添加以下检查或自定义操作本身修复了此问题。
self.check_object_permissions(self.request, obtainedObject)
我的代码中的示例:
@action(detail=True, methods=['patch'], pk=None)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
self.check_object_permissions(self.request, company)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)
我最近开始实施 dry-rest-permissions,但我似乎无法检查 has_object_permissions
,似乎只有全局权限对我有用。
我对实现权限相当陌生,这是我第一次实现 DRY-rest-permissions 并且最近才开始在 django rest 框架中编码,因此对于缺乏知识提前表示歉意。
目前我正在尝试通过简单地让用户调用 URL 来删除公司对象,然后 URL 获取当前用户的 active_company
然后仅将其删除如果当前 user
是 active_company
的 company_owner
。
但我发现,我无法has_object_permissions
在任何地方工作?
我注意到,如果我删除 has_write_permission(request)
,然后点击 company_delete
URL,则会出现以下错误:
'<class 'company.models.Company'>' does not have 'has_write_permission' or 'has_company_delete_permission' defined.
这意味着它甚至不查找 has_object_company_delete_permission
。这意味着它只检查全局权限而不是任何对象权限,我在这里可能做错了什么?
我的模型:
class Company(models.Model):
company_name = models.CharField(max_length=100)
company_orders = models.IntegerField(blank=True, null=True)
company_icon = models.ImageField(
upload_to='media/company_icon', blank=True)
company_owner = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
company_employees = models.ManyToManyField(
User, blank=True, null=True, related_name="company_employees")
def __str__(self):
return self.company_name
@staticmethod
def has_write_permission(request):
return False
def has_object_company_delete_permission(self, request):
return self.company_owner == request.user
我的观点
class CompanyView(viewsets.ModelViewSet): # made for viewing details
permission_classes = (DRYPermissions, )
queryset = Company.objects.all()
serializer_class = CompanySerializer
def create(self, request):
try:
company_name = request.data['company_name']
company_orders = request.data['company_orders']
company_owner = request.data['company_owner']
company_owner_obj = User.objects.get(id=company_owner)
company = Company(company_name=company_name,
company_orders=company_orders, company_owner=company_owner_obj)
company.save()
except Exception as error:
response = {
'error': str(error)
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
response = {
'message': 'Company created'
}
return Response(response, status=status.HTTP_201_CREATED)
def company_details(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serialized_data = CompanySerializer(company)
except Exception as error:
response = {
'error': str(error)
}
return Response(response)
return Response(serialized_data.data)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)
def company_delete(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.filter(id=company_id)
company.delete()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Deleted Successfully'
}
return Response(response)
我的网址
urlpatterns = [
# Company URLs
path('company_create/',
CompanyView.as_view({'post': 'create'}), name='company_create'), # Create company
path('company_edit/',
CompanyView.as_view(), name='company_edit'), # Edit company details
path('company_delete/',
CompanyView.as_view({'delete': 'company_delete'}), name='company_delete'), # Delete company
path('company_details/',
CompanyView.as_view({'get': 'company_details'}), name='company_details'), # get company details (owner, employees etc)
]
我的序列化器
class CompanySerializer(serializers.ModelSerializer):
company_owner = LimitedUserSerializer(read_only=True)
class Meta:
model = Company
fields = ['id', 'company_name', 'company_orders',
'company_icon', 'company_owner']
如 this part of the documentation 中所述,始终首先检查全局权限,只有在通过全局权限时才检查对象权限。
文档来源:
DRY Rest Permissions allows you to define both global and object level permissions.
Global permissions are always checked first and define the ability of a user to take an action on an entire model. For example you can define whether a user has the ability to update any projects from the database.
Object permissions are checked if global permissions pass and define whether a user has the ability to perform a specific action on a single object. These are also known as row level permissions. Note: list and create actions are the only standard actions that are only global. There is no such object level permission call because they are whole table actions.
在这种情况下,您实际上有多个问题需要更正:
- 确保所有拥有活跃公司的用户
has_write_permission
returnTrue
- 确保重命名
has_object_company_delete_permission
因为我们不需要函数名称中的模型名称
示例:
@staticmethod
def has_write_permission(request):
# Everybody can create/update/delete if no specific rule says otherwise
return True
def has_object_delete_permission(self, request):
# Only owner can delete
return self.company_owner == request.user
def has_object_update_permission(self, request):
# Only owner can update
return self.company_owner == request.user
输出:
- 每个人都可以创造
- 只有所有者可以更新
- 只有所有者可以删除
我知道仅仅删除一个对象似乎有点矫枉过正,但根据一些经验,它允许您清楚地定义 ans setup 权限,还可以通过使用 [=15= 轻松地与前端共享通用规则] 和 DRYGlobalPermissionsField
PS:这个答案来自 my origin answer on Github 让人们可以轻松地从 Whosebug
找到解决方案它似乎以某种方式不检查我的任何自定义操作中的对象权限,因此在 get_object() 中添加以下检查或自定义操作本身修复了此问题。
self.check_object_permissions(self.request, obtainedObject)
我的代码中的示例:
@action(detail=True, methods=['patch'], pk=None)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
self.check_object_permissions(self.request, company)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)