def check_post_permissions(self, request, view, obj=None): if hasattr(view, 'parent_model'): get_object_or_400(view.parent_model, pk=view.kwargs['pk']) return True else: if obj: return True if hasattr(view, 'model'): return check_user_access(request.user, view.model, 'add', request.DATA) return True
def check_get_permissions(self, request, view, obj=None): if hasattr(view, 'parent_model'): parent_obj = get_object_or_400(view.parent_model, pk=view.kwargs['pk']) if not check_user_access(request.user, view.parent_model, 'read', parent_obj): return False if not obj: return True return check_user_access(request.user, view.model, 'read', obj)
def unattach(self, request, *args, **kwargs): sub_id = request.DATA.get('id', None) if not sub_id: data = dict(msg='"id" is required to disassociate') return Response(data, status=status.HTTP_400_BAD_REQUEST) parent = self.get_parent_object() parent_key = getattr(self, 'parent_key', None) relationship = getattr(parent, self.relationship) sub = get_object_or_400(self.model, pk=sub_id) #if not request.user.can_access(self.parent_model, 'unattach', parent, if not check_user_access(request.user, self.parent_model, 'unattach', parent, sub, self.relationship): raise PermissionDenied() if parent_key: # sub object has a ForeignKey to the parent, so we can't remove it # from the set, only mark it as inactive. sub.mark_inactive() else: relationship.remove(sub) return Response(status=status.HTTP_204_NO_CONTENT)
def attach(self, request, *args, **kwargs): attached = False created = False modified = False parent = self.get_parent_object() relationship = getattr(parent, self.relationship) sub_id = request.DATA.get('id', None) data = request.DATA # FIXME: We have special case handling for RoleRatings # which would probably be better moved into # a new class and overridden completely is_role_rating = isinstance(parent, RoleRating) #logger.debug('SubListCreateAPIView.attach: parent=%s', parent.__class__.__name__) # Create the sub object if an ID is not provided. # We never create objects when attaching to a RoleRating if not sub_id and not is_role_rating: try: response = self.create(request, *args, **kwargs) if response.status_code != status.HTTP_201_CREATED: return response sub_id = response.data['id'] data = response.data try: location = response['Location'] except KeyError: location = None created = True except: # logger.debug('SubListCreateAPIView.attach: not sub_id and not is_role_rating threw Permission Denied') raise PermissionDenied() # Retrive the sub object (whether created or by ID). sub = get_object_or_400(self.model, pk=sub_id) # likewise with creation, we never try and update # the sub-object if we're dealing with a RoleRating if not created and not is_role_rating: # Update the object to make sure the data is correct, but # verify we have permission to edit before trying to update if not check_user_access(request.user, self.model, 'change', sub, data): raise PermissionDenied() else: sub.__dict__.update(data) if sub.is_dirty: sub.save() modified = True # Verify we have permission to attach. if not check_user_access(request.user, self.parent_model, 'attach', parent, sub, self.relationship, data, skip_sub_obj_read_check=created): raise PermissionDenied() # Attach the object to the collection. if sub not in relationship.all(): relationship.add(sub) attached = True # SPECIAL CASE # FIXME: the base view for objects with mutually exclusive # relationship should probably be split off into a # new view, which codifies the mutually exclusive things #if attached and is_role_rating: """ Up/down votes are mutually exclusive. If we've attached the user to one of the lists, we need to make sure we remove them from the other (if they're in it). """ # mux_relationship = None # if self.relationship == 'up_votes': # mux_relationship = getattr(parent, 'down_votes') # elif self.relationship == 'down_votes': # mux_relationship = getattr(parent, 'up_votes') # if mux_relationship and sub in mux_relationship.all(): # mux_relationship.remove(sub) if created: headers = {} if location: headers['Location'] = location return Response(data, status=status.HTTP_201_CREATED, headers=headers) elif modified or attached: return Response(data, status=status.HTTP_200_OK) else: return Response(status=status.HTTP_204_NO_CONTENT)
def attach(self, request, *args, **kwargs): attached = False created = False modified = False parent = self.get_parent_object() relationship = getattr(parent, self.relationship) sub_id = request.DATA.get('id', None) data = request.DATA # Create the sub object if an ID is not provided. if not sub_id: try: response = self.create(request, *args, **kwargs) if response.status_code != status.HTTP_201_CREATED: return response sub_id = response.data['id'] data = response.data try: location = response['Location'] except KeyError: location = None created = True except Exception: raise PermissionDenied() # Retrive the sub object (whether created or by ID). sub = get_object_or_400(self.model, pk=sub_id) # likewise with creation, we never try and update if not created: # Update the object to make sure the data is correct, but # verify we have permission to edit before trying to update if not check_user_access(request.user, self.model, 'change', sub, data): raise PermissionDenied() else: sub.__dict__.update(data) if sub.is_dirty: sub.save() modified = True # Verify we have permission to attach. if not check_user_access(request.user, self.parent_model, 'attach', parent, sub, self.relationship, data, skip_sub_obj_read_check=created): raise PermissionDenied() # Attach the object to the collection. if sub not in relationship.all(): relationship.add(sub) attached = True if created: headers = {} if location: headers['Location'] = location return Response(data, status=status.HTTP_201_CREATED, headers=headers) elif modified or attached: return Response(data, status=status.HTTP_200_OK) else: return Response(status=status.HTTP_204_NO_CONTENT)