def post(self, request, *args, **kwargs): self.check_object_permissions(request, self) try: kproperty_pk = request.data.pop('kproperty') except KeyError: key_exc = APIException( detail={'error': "field `kproperty` not specified."}) key_exc.status_code = status.HTTP_400_BAD_REQUEST raise key_exc try: kproperty = Property.objects.get(pk=kproperty_pk) except Property.DoesNotExist: dne_exc = APIException( detail={ 'error': "property with pk {} does not exist.".format(kproperty_pk) }) dne_exc.status_code = status.HTTP_400_BAD_REQUEST raise dne_exc # Add the user to property's subscription list. kproperty._subscribers.add(request.user) kproperty.save() response = Response({}, status=status.HTTP_201_CREATED) response.data['subscribed'] = kproperty_pk return response
def post(self, request, *args, **kwargs): document = self._get_parent() parent_field_name = 'document' # Get the Clause ID, and the actual clause object. contract = document.closing.transaction.contracts.all()[0] if 'clause' not in request.data.keys(): error_msg = {'error': '`clause` must be provided.'} dne_exc = APIException(detail=error_msg) dne_exc.status_code = 401 raise dne_exc clause_pk = request.data.pop('clause') try: clause = contract.static_clauses.get(pk=clause_pk) except StaticClause.DoesNotExist: try: clause = contract.dynamic_clauses.get(pk=clause_pk) except DynamicClause.DoesNotExist: error_msg = { "error": "clause with pk {} does not exist in " "the transaction's contract.".format(clause_pk) } dne_exc = APIException(detail=error_msg) dne_exc.status_code = 404 raise dne_exc # Create the serializer. Note, we need to check for duplicates here. serializer = self.get_serializer(data=request.data, context=request.FILES) if serializer.is_valid(): try: serializer.save( **{ parent_field_name: document, 'clause': clause, 'sender': request.user }) except ValueError as value_error: error_msg = {'error': str(value_error)} duplicate_exc = APIException(detail=error_msg) duplicate_exc.status_code = 400 raise duplicate_exc return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def apply_bulk_edits(self): """ Apply all actions. """ response_data = [] statuses = [] for attrs in self.validated_data: response = self.child.apply_action(attrs) statuses.append(response.status_code) response_data.append(response.data) if not self.okay_statuses.issuperset(statuses): # TODO: are these full content responses *useful* ? # Maybe we should just pass on the *errored* responses error_statuses = set(statuses).difference(self.okay_statuses) if len(error_statuses) == 1: # There was only one unique error status, use that status = set(error_statuses).pop() elif all(s < 500 for s in error_statuses): # The parsing and validation of the request happened okay, # but we still received a 4xx error from at least one subresource. # We raise a 400 here to keep things simplish. status = 400 else: # mixed errors, including server errors status = 500 e = APIException(response_data) e.status_code = status raise e return response_data
def custom_exception_handler(exc, context): # Convert UnknownOrgIDError into an appropriate API exception if isinstance(exc, UnknownOrgIDError): org_id = exc.args[0] exc = APIException(detail=f"Unknown organisation ID: {org_id}") exc.status_code = status.HTTP_400_BAD_REQUEST return exception_handler(exc, context)
def test_handle_exception(self): exc = APIException('There was a problem!') exc.status_code = 400 # set the status code to 400 not possible to set in init exc.code = 400 # rest framework APIError is not compatible with integration APIError exception type resp = self.endpoint.handle_exception(HttpRequest(), exc) assert resp.status_code == 400 assert resp.exception is True
def _generate_filter_chain(self, filters): filter_args = [] # Parse any map filters. map_filters = {}; map_coordinates = ['ne_lng', 'ne_lat', 'sw_lng', 'sw_lat'] if any(map_filter in filters.keys() for map_filter in map_coordinates): if not all(map_filter in filters.keys() for map_filter in map_coordinates): exc = APIException(detail={'error': 'incomplete map query.'}) exc.status_code = 401; raise exc for coordinate in map_coordinates: map_filters[coordinate] = filters.pop(coordinate)[0] filter_args.append(self._parse_mapkeys(map_filters)) # Construct the filter chain. Note, we'll need to handle multi-keys # in a different manner. for kfilter in filters.keys(): if len(filters.getlist(kfilter)[0].split(',')) > 1: filters[kfilter] = self._parse_multikey(filters[kfilter]) next_filter = Q((kfilter, filters[kfilter])) filter_args.append(next_filter) return filter_args
def test_handle_exception(self): exc = APIException("There was a problem!") exc.status_code = 400 # set the status code to 400 not possible to set in init exc.code = 400 # rest framework APIError is not compatible with integration APIError exception type resp = self.endpoint.handle_exception(HttpRequest(), exc) assert resp.status_code == 400 assert resp.exception is True
def to_internal_value(self, data): controller = None try: controller = Controller.objects.get(token__in=[data.get('token')]) request = self._kwargs.get('context')['request'] except Exception: return data if controller and request.method == 'POST': if request.user not in controller.owner.all(): controller.owner.add(request.user) ControllerSpecification.objects.create(owner=request.user, controller=controller, name=data.get('name')) return data else: invalid_association = APIException({ 'detail': ('This user has already been associated ' 'with this controller.') }) invalid_association.status_code = 400 raise invalid_association else: return data
def check(res): if res['errors']: print 'errors:', res e = APIException() e.status_code = 500 e.detail = "Internal Error" raise e return res
def _raiseException(self, field): """ Raise 400 exceptions for invalid or missing parameters """ e = APIException( "The request parameter '{}' is required.".format(field)) e.status_code = 400 raise e
def get_object(self): try: profile = self.queryset.get(user=self.request.user) return profile except ObjectDoesNotExist: status_code = status.HTTP_404_NOT_FOUND exception = APIException() exception.status_code = status_code raise exception
def destroy(self, request, *args, **kwargs): try: return super().destroy(request, *args, **kwargs) except ProtectedError: detail = 'Can not delete package with tracking information' exc = APIException(detail) exc.status_code = status.HTTP_400_BAD_REQUEST response = exception_handler(exc, None) return response
def to_internal_value(self, data): if data.get('validation_key') == os.getenv('SECRET_KEY'): return data else: exception = APIException( {'error': 'Validation key not match with registration key.'}) exception.status_code = 403 raise exception
def get(self, request, pk): # Ensure the user has permission. if request.user.pk != int(pk): error_msg = 'error: you do not have permission to view this resource' no_auth_exc = APIException(detail=error_msg) no_auth_exc.status_code = status.HTTP_403_FORBIDDEN raise no_auth_exc return Response(status=status.HTTP_200_OK)
def create(self, validated_data): try: controller = Controller.objects.get( token=validated_data.get('token')) zone = controller.zone_set.get( name=validated_data.get('zone_name')) schedule = Schedule.objects.get(zone=zone, schedule=datetime.strptime( validated_data.get('time'), '%Y-%m-%d %H:%M')) exception = APIException( {'error': 'This schedule is just registered.'}) exception.status_code = 400 raise exception except Schedule.DoesNotExist: schedule = Schedule.objects.create(zone=zone, schedule=datetime.strptime( validated_data.get('time'), '%Y-%m-%d %H:%M')) exception = APIException({ 'zone': schedule.zone.name, 'schedule': schedule.schedule }) exception.status_code = 201 raise exception except Zone.DoesNotExist: raise APIException({ 'error': 'Name does not match with any controller zone name.' }) except Controller.DoesNotExist: raise APIException( {'error': 'Token does not match with any controller.'}) return schedule
def post(self, request, *args, **kwargs): payment = self.get_object() try: result = {"result": payment.forward()} except AssertionError as error: payment_exc = APIException(detail={"error": str(error)}) payment_exc.status_code = 400 raise payment_exc return Response(result, status=status.HTTP_201_CREATED)
def get_object(self, pk): try: kuser = User.objects.get(pk=pk) self.check_object_permissions(self.request, self) return kuser except User.DoesNotExist: dne_exc = APIException( detail={'error': 'user {} does not exist.'.format(pk)}) dne_exc.status_code = 404 raise dne_exc
def get_object(self): try: user_id = self.kwargs.get('id') profile = self.queryset.get(user=user_id) self.check_object_permissions(self.request, profile) return profile except ObjectDoesNotExist: status_code = status.HTTP_404_NOT_FOUND exception = APIException() exception.status_code = status_code raise exception
def get_object(self, pk): try: kuser = User.objects.get(pk=pk) self.check_object_permissions(self.request, kuser) return kuser except User.DoesNotExist: user_dne_exc = APIException(detail={'error': 'user with id ' + str(pk) +\ ' does not exist.'}) user_dne_exc.status_code = status.HTTP_400_BAD_REQUEST raise user_dne_exc
def validate(self, data): if "username" in data: try: User.objects.get(username=data['username']) except ObjectDoesNotExist: exc = APIException(code='invalid', detail={"user": ["Unknown user " + data['username']]}) # hack to update status code. :-( exc.status_code = status.HTTP_400_BAD_REQUEST raise exc data = super().validate(data) return data
def post(self, request, pk, *args, **kwargs): kuser = self.get_object(pk=pk) # Ensure that the user has a phone number, and has enabled # two-factor-auth error_msg = None if not hasattr(kuser, 'phone_num'): error_msg = 'user {} has no attribute `phone_num`.'.format( kuser.pk) if kuser.tfa_enabled is False: error_msg = 'user {} does not have two-factor authentication ' \ 'enabled.'.format(kuser.pk) if error_msg: user_exc = APIException(detail={'error': error_msg}) user_exc.status_code = 403 raise user_exc # Generate a two-factor auth code. tfa_code = self._generate_tfa_code() # Send an SMS message to the user's phone. client = messagebird.Client(settings.MESSAGEBIRD_ACCESS_KEY) try: message = client.message_create( originator=settings.MESSAGEBIRD_SENDER, recipients=kuser.phone_num, body=tfa_code, ) except messagebird.client.ErrorException as e: sms_exc = APIException( detail={'error': 'the SMS message failed to send.'}) sms_exc.status_code = 403 raise sms_exc # Set the user's TFA code, and reset its validation status. kuser.tfa_code = tfa_code kuser._tfa_code_validated = False kuser.save() return Response({'success': True}, status=status.HTTP_201_CREATED)
def save(self, *args, **kwargs): #TODO: Move the exception raising to child classes. if not self.pk: try: self.full_clean() except ValidationError as validation_error: validation_exc = APIException(detail=validation_error.messages[0]) validation_exc.status_code = 403 raise validation_exc super(Property, self).save(*args, **kwargs)
def paginate_queryset(self, *args, **kwargs): """Adds a machine readable error code if the page is not found.""" try: return super().paginate_queryset(*args, **kwargs) except NotFound as e: exception = APIException({ 'error': 'ERROR_INVALID_PAGE', 'detail': str(e) }) exception.status_code = HTTP_400_BAD_REQUEST raise exception
def get_object(self, rsvp_pk): try: rsvp = RSVP.objects.get(pk=rsvp_pk) self.check_object_permissions(self.request, rsvp) return rsvp except RSVP.DoesNotExist: error_msg = { 'error': 'RSVP with id=' + str(pk) + ' does not exist.' } dne_exc = APIException(detail=error_msg) dne_exc.status_code = status.HTTP_400_BAD_REQUEST raise dne_exc
def get_page_size(self, request): page_size = super().get_page_size(request) if self.limit_page_size and page_size > self.limit_page_size: exception = APIException({ 'error': 'ERROR_PAGE_SIZE_LIMIT', 'detail': f'The page size is limited to {self.limit_page_size}.' }) exception.status_code = HTTP_400_BAD_REQUEST raise exception return page_size
def get_page_size(self, request): page_size = super().get_page_size(request) if self.limit_page_size and page_size > self.limit_page_size: exception = APIException({ "error": "ERROR_PAGE_SIZE_LIMIT", "detail": f"The page size is limited to {self.limit_page_size}.", }) exception.status_code = HTTP_400_BAD_REQUEST raise exception return page_size
def get_queryset(self): queryset = Property.objects.select_subclasses() # Construct a filter chain from the given parameters. filter_args = self._generate_filter_chain(self.request.GET) if filter_args: try: queryset = queryset.filter(reduce(AND, filter_args)) except FieldError: field_exc = APIException(detail={'error': 'invalid search field.'}) field_exc.status_code = 400; raise field_exc return queryset
def get_object(self, oh_pk): try: open_house = OpenHouse.objects.get(pk=oh_pk) self.check_object_permissions(self.request, open_house) return open_house except OpenHouse.DoesNotExist: error_msg = { 'error': 'open house with id=' + str(oh_pk) + ' does not exist.' } dne_exc = APIException(detail=error_msg) dne_exc.status_code = status.HTTP_400_BAD_REQUEST raise dne_exc
def get_object(self): try: nested_parent = self._get_parent() nested_set = getattr(nested_parent, self.model_tree[-1][0]) instance = nested_set.get(pk=self.kwargs[self.pk]) self.check_object_permissions(self.request, instance) return instance except nested_set.model.DoesNotExist: error_msg = {'error': 'nested model with pk {} does not exist.'.\ format(self.kwargs[self.pk])} dne_exc = APIException(detail=error_msg) dne_exc.status_code = 404 raise dne_exc
def get_paginator(self, request): try: limit, offset = request.GET.pop('limit')[0], request.GET.pop('offset')[0] if (int(limit) <= 0) or (int(offset) < 0): exc = APIException(detail={ 'error': 'pagination params cannot be negative.' }) exc.status_code = 401; raise exc paginator = self.pagination_class() paginator.limit = limit; paginator.offset = offset return paginator except KeyError: return None
def get_object(self, pk, chat_pk): try: chat = Chat.objects.get(pk=chat_pk) self.check_object_permissions(self.request, chat) # Update Chat status. if not chat.opened: chat.opened = True; chat.save() return chat except Chat.DoesNotExist: error_msg = {'error': 'chat with id={} does not exist'} dne_exc = APIException(detail=error_msg) dne_exc.status_code = status.HTTP_400_BAD_REQUEST; raise dne_exc
def map_exceptions(mapping): """ This utility function simplifies mapping uncaught exceptions to a standard api response exception. Example: with map_api_exceptions({ SomeException: 'ERROR_1' }): raise SomeException('This is a test') HTTP/1.1 400 { "error": "ERROR_1", "detail": "This is a test" } Example 2: with map_api_exceptions({ SomeException: ('ERROR_1', 404, 'Other message') }): raise SomeException('This is a test') HTTP/1.1 404 { "error": "ERROR_1", "detail": "Other message" } """ try: yield except tuple(mapping.keys()) as e: value = mapping.get(e.__class__) status_code = status.HTTP_400_BAD_REQUEST detail = "" if isinstance(value, str): error = value if isinstance(value, tuple): error = value[0] if len(value) > 1 and value[1] is not None: status_code = value[1] if len(value) > 2 and value[2] is not None: detail = value[2].format(e=e) exc = APIException({"error": error, "detail": detail}) exc.status_code = status_code raise exc