Esempio n. 1
0
    def run_validation(self, data=empty):
        """
        We patch this function because we want to see all the errors at once.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data

        errors = OrderedDict()

        try:
            data = self.to_internal_value(data)
        except ValidationError as exc:
            errors.update(exc.detail)

        try:
            self.run_validators(data)
        except (ValidationError, DjangoValidationError) as exc:
            errors.update(as_serializer_error(exc))

        try:
            data = self.validate(data)
            assert data is not None, '.validate() should return the validated data'
        except (ValidationError, DjangoValidationError) as exc:
            errors.update(as_serializer_error(exc))

        if errors:
            raise ValidationError(errors)

        return data
Esempio n. 2
0
    def run_validation(self, data=empty):
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data

        # mapping to internal values
        value, to_internal_errors = self.to_internal_value(data)

        # running validators
        validators_errors = OrderedDict()
        try:
            self.run_validators(value)
        except (ValidationError, DjangoValidationError) as exc:
            validators_errors = as_serializer_error(exc)

        # running final validation
        validation_errors = OrderedDict()
        try:
            value = self.validate(value)
            assert value is not None, ".validate() should return the validated data"
        except (ValidationError, DjangoValidationError) as exc:
            validation_errors = as_serializer_error(exc)

        # if there were any errors - raise the combination of them
        if to_internal_errors or validators_errors or validation_errors:
            # update dicts in reverse - to show most basic error for a given field if errors overlap
            validation_errors.update(validators_errors)
            validation_errors.update(to_internal_errors)
            raise ValidationError(detail=validation_errors)

        return value
 def __exit__(self, exc_type, exc_val, exc_tb):
     if exc_type and issubclass(exc_type, ValidationError):
         error = exc_val if exc_val else ValidationError()
         if self.field_name not in self.serializer_instance._errors:
             self.serializer_instance._errors.update({self.field_name: [as_serializer_error(error)]})
         else:
             self.serializer_instance._errors[self.field_name].append(as_serializer_error(error))
     return True
    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data

        result = self.to_internal_value(data)
        assert isinstance(
            result,
            dict), '.to_internal_value() should return the dict data type'

        value = result.get('ret')
        errors = result.get('errors')
        try:
            self.run_validators(value)
            value = self.validate(value)
            assert value is not None, '.validate() should return the validated data'
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))

        return {'value': value, 'errors': errors}
Esempio n. 5
0
def validate_user_password(password):
    try:
        validate_password(password)
    except exceptions.ValidationError as e:
        serializer_error = serializers.as_serializer_error(e)
        raise serializers.ValidationError(serializer_error["non_field_errors"])
    return password
Esempio n. 6
0
    def full_clean(self):
        """
        Performs full validation, additionally performing validation using the validators
        from InteractionSerializer if the interaction was matched to a contact.

        Errors are mapped to CSV fields where possible. If not possible, they are
        added to NON_FIELD_ERRORS (but this should not happen).
        """
        super().full_clean()

        if not self.is_valid_and_matched():
            return

        transformed_data = self.cleaned_data_as_serializer_dict()
        serializer = InteractionSerializer(
            context={'check_association_permissions': False})

        try:
            serializer.run_validators(transformed_data)
        except serializers.ValidationError as exc:
            # Make sure that errors are wrapped in a dict, and values are always a list
            normalised_errors = serializers.as_serializer_error(exc)

            for field, errors in normalised_errors.items():
                self._add_serializer_error(field, errors)
Esempio n. 7
0
    def save(self):
        """POST: Perform final save of submitted BOM data:

        - By this stage each line in the BOM has been validated
        - Individually 'save' (create) each BomItem line
        """
        data = self.validated_data

        items = data['items']

        try:
            with transaction.atomic():

                for item in items:

                    part = item['part']
                    sub_part = item['sub_part']

                    # Ignore duplicate BOM items
                    if BomItem.objects.filter(part=part,
                                              sub_part=sub_part).exists():
                        continue

                    # Create a new BomItem object
                    BomItem.objects.create(**item)

        except Exception as e:
            raise serializers.ValidationError(
                detail=serializers.as_serializer_error(e))
Esempio n. 8
0
    def save(self):

        data = self.validated_data

        items = data.get('items', [])

        build = self.context['build']

        with transaction.atomic():
            for item in items:
                bom_item = item['bom_item']
                stock_item = item['stock_item']
                quantity = item['quantity']
                output = item.get('output', None)

                try:
                    # Create a new BuildItem to allocate stock
                    BuildItem.objects.create(build=build,
                                             bom_item=bom_item,
                                             stock_item=stock_item,
                                             quantity=quantity,
                                             install_into=output)
                except (ValidationError, DjangoValidationError) as exc:
                    # Catch model errors and re-throw as DRF errors
                    raise ValidationError(
                        detail=serializers.as_serializer_error(exc))
Esempio n. 9
0
    def run_validation(self, data=empty):
        """
        Perform serializer validation.
        In addition to running validators on the serializer fields,
        this class ensures that the underlying model is also validated.
        """

        # Run any native validation checks first (may raise a ValidationError)
        data = super().run_validation(data)

        # Now ensure the underlying model is correct

        if not hasattr(self, 'instance') or self.instance is None:
            # No instance exists (we are creating a new one)
            instance = self.Meta.model(**data)
        else:
            # Instance already exists (we are updating!)
            instance = self.instance

            # Update instance fields
            for attr, value in data.items():
                setattr(instance, attr, value)

        # Run a 'full_clean' on the model.
        # Note that by default, DRF does *not* perform full model validation!
        try:
            instance.full_clean()
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=serializers.as_serializer_error(exc))

        return data
Esempio n. 10
0
    def validate(self, attrs):
        user = self.context["request"].user
        old_password = attrs['old_password']
        new_password = attrs['new_password']

        if old_password == new_password:
            raise serializers.ValidationError({
                'new_password': '******'
            })

        if user.check_password(old_password):

            try:
                validate_password(new_password, user)

            except django_exceptions.ValidationError as e:
                serializer_errors = serializers.as_serializer_error(e)
                raise serializers.ValidationError({
                    'new_password': serializer_errors[
                        api_settings.NON_FIELD_ERRORS_KEY]
                })
        else:
            raise serializers.ValidationError({
                'old_password': '******'
            })
        return attrs
Esempio n. 11
0
	def create(self, data):
		logger.debug('QuestionAnswerSerializer.create(%r)', data)

		question = data['question']

		if isinstance(question, models.TextQuestion):
			answer = models.TextAnswer(**data)

		if isinstance(question, models.ChoiceQuestion):
			choices = data.pop('choices', [])
			answer  = models.ChoiceAnswer(**data)

		try:
			answer.full_clean()
			answer.save(force_insert=True)
		except _djexc.ValidationError as exc:
			# @xxx: {'__all__': [...]} -> {'non_field_errors': [...]}
			raise _drfexcs.ValidationError(detail=_drfsers.as_serializer_error(exc))

		if isinstance(question, models.ChoiceQuestion) and choices:
			try:
				# @todo: transaction
				answer.choices.set(choices)
				answer.save()
			except Exception:
				answer.delete()
				logger.exception('Unhandled error')
				self.fail('internal_error')
			except:
				answer.delete()
				raise

		return answer
Esempio n. 12
0
    def filter_queryset(self, request, queryset, view):
        try:
            if self.filter_param_name:
                filter_value_raw = request.GET.get(self.filter_param_name, "")
                if filter_value_raw != "":
                    filter = self.build_filter(filter_value_raw)
                    queryset = queryset.filter(filter)
        except ParseException as e:
            raise BadQuery("Filtering position: {0}".format(e.col))
        except django_exceptions.ValidationError as exc:
            raise rest_exceptions.ValidationError(
                detail=as_serializer_error(exc))
        except django_exceptions.FieldError as exc:
            raise BadQuery("Bad filter: {0}".format(exc))

        try:
            if self.sort_param_name:
                sort_value_raw = request.GET.get(self.sort_param_name, "")
                if sort_value_raw != "":
                    sort_value = self.build_sort(sort_value_raw)
                    if sort_value:
                        queryset = queryset.order_by(*sort_value)
        except ParseException as e:
            raise BadQuery("Sorting error position: {0}".format(e.col))
        except django_exceptions.FieldError as exc:
            raise BadQuery("Bad sorting: {0}".format(exc))

        #print queryset.query
        return queryset
Esempio n. 13
0
    def save(self):
        """
        Perform the actual database transaction to receive purchase order items
        """

        data = self.validated_data

        request = self.context['request']
        order = self.context['order']

        items = data['items']
        location = data.get('location', None)

        # Now we can actually receive the items into stock
        with transaction.atomic():
            for item in items:

                # Select location
                loc = item.get('location', None) or item['line_item'].get_destination() or location

                try:
                    order.receive_line_item(
                        item['line_item'],
                        loc,
                        item['quantity'],
                        request.user,
                        status=item['status'],
                        barcode=item.get('barcode', ''),
                    )
                except (ValidationError, DjangoValidationError) as exc:
                    # Catch model errors and re-throw as DRF errors
                    raise ValidationError(detail=serializers.as_serializer_error(exc))
Esempio n. 14
0
    def save(self):

        data = self.validated_data

        items = data['items']

        try:
            with transaction.atomic():

                for item in items:

                    part = item['part']
                    sub_part = item['sub_part']

                    # Ignore duplicate BOM items
                    if BomItem.objects.filter(part=part,
                                              sub_part=sub_part).exists():
                        continue

                    # Create a new BomItem object
                    BomItem.objects.create(**item)

        except Exception as e:
            raise serializers.ValidationError(
                detail=serializers.as_serializer_error(e))
Esempio n. 15
0
 def validate(self, attrs):
     if attrs.get("plugin_data"):
         section = attrs["section"]
         try:
             if not section.plugin_identifier:
                 raise ValidationError(
                     "The section %s has no plugin; no plugin data is allowed."
                     % section)
             plugin = section.plugin_implementation
             attrs["plugin_data"] = plugin.clean_client_data(
                 attrs["plugin_data"])
         except (ValidationError, DjangoValidationError) as ve:
             # Massage the validation error slightly...
             detail = as_serializer_error(ve)
             detail.setdefault("plugin_data", []).extend(
                 detail.pop(api_settings.NON_FIELD_ERRORS_KEY, ()))
             raise ValidationError(detail=detail)
         attrs["plugin_identifier"] = section.plugin_identifier
     if not any([
             attrs.get(field)
             for field in SectionComment.fields_to_check_for_data
     ]):
         raise ValidationError(
             "You must supply at least one of the following data in a comment: "
             + str(SectionComment.fields_to_check_for_data))
     return attrs
Esempio n. 16
0
    def has_permission(self, request: Request, view) -> bool:
        # permission checks run before the handler is determined. if there is no handler,
        # a "method is not allowed" must be raised, not an HTTP 403 (see #385)
        # this implementation works for both APIView and viewsets
        has_handler = hasattr(view, request.method.lower())
        if not has_handler:
            view.http_method_not_allowed(request)

        # JWTs are only valid for a short amount of time
        self.check_jwt_expiry(request.jwt_auth.payload)

        from rest_framework.viewsets import ViewSetMixin

        if bypass_permissions(request):
            return True

        scopes_required = get_required_scopes(view)
        component = self.get_component(view)

        if not self.permission_fields:
            return request.jwt_auth.has_auth(scopes_required, component)

        main_resource = self.get_main_resource()

        if view.action == "create":
            if view.__class__ is main_resource:
                main_object_data = request.data

            else:
                main_object_url = request.data[view.permission_main_object]
                main_object_path = urlparse(main_object_url).path
                try:
                    main_object = get_resource_for_path(main_object_path)
                except ObjectDoesNotExist:
                    raise ValidationError({
                        view.permission_main_object:
                        ValidationError(
                            _("The object does not exist in the database"),
                            code="object-does-not-exist",
                        ).detail
                    })
                except DjangoValidationError as exc:
                    err_dict = as_serializer_error(
                        ValidationError({view.permission_main_object: exc}))
                    raise ValidationError(err_dict)

                main_object_data = self.format_data(main_object, request)

            fields = self.get_fields(main_object_data)
            return request.jwt_auth.has_auth(scopes_required, component,
                                             **fields)

        # detect if this is an unsupported method - if it's a viewset and the
        # action was not mapped, it's not supported and DRF will catch it
        if view.action is None and isinstance(view, ViewSetMixin):
            return True

        # by default - check if the action is allowed at all
        return request.jwt_auth.has_auth(scopes_required, component)
Esempio n. 17
0
 def get(self, request, *args, **kwargs):
     try:
         self.queryset.filter(user=request.user,
                              read=False).update(read=True)
         return Response({'status': 'ok'})
     except Exception as exc:
         raise serializers.ValidationError(
             detail=serializers.as_serializer_error(exc))
Esempio n. 18
0
 def perform_create(self, serializer):
     message = self.get_object()
     try:
         message.read = self.target
         message.save()
     except Exception as exc:
         raise serializers.ValidationError(
             detail=serializers.as_serializer_error(exc))
Esempio n. 19
0
    def update(self, instance, validated_data):
        """Catch any django ValidationError, and re-throw as a DRF ValidationError."""
        try:
            instance = super().update(instance, validated_data)
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=serializers.as_serializer_error(exc))

        return instance
Esempio n. 20
0
    def save(self, **kwargs):
        """Catch any django ValidationError thrown at the moment `save` is called, and re-throw as a DRF ValidationError."""
        try:
            super().save(**kwargs)
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=serializers.as_serializer_error(exc))

        return self.instance
Esempio n. 21
0
 def perform_create(self, serializer):
     """Set the `read` status to the target value."""
     message = self.get_object()
     try:
         message.read = self.target
         message.save()
     except Exception as exc:
         raise serializers.ValidationError(
             detail=serializers.as_serializer_error(exc))
Esempio n. 22
0
 def to_representation(self, status):
     data = super().to_representation(status)
     order = self.context['order']
     try:
         app_settings.SALESMAN_ORDER_STATUS.validate_transition(status, order)
     except (ValidationError, DjangoValidationError) as e:
         error = serializers.as_serializer_error(e)
         data['error'] = error[api_settings.NON_FIELD_ERRORS_KEY][0]
     return data
Esempio n. 23
0
    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get("password")
        try:
            validate_password(password, user)
        except django_exceptions.ValidationError as e:
            serializer_error = serializers.as_serializer_error(e)
            raise serializers.ValidationError(
                {"password": serializer_error["non_field_errors"]})

        return attrs
Esempio n. 24
0
def exception_handler(exc, context):
    """
    Custom exception handler for DRF framework.
    Ref: https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling

    Catches any errors not natively handled by DRF, and re-throws as an error DRF can handle
    """

    response = None

    # Catch any django validation error, and re-throw a DRF validation error
    if isinstance(exc, DjangoValidationError):
        exc = DRFValidationError(detail=serializers.as_serializer_error(exc))

    # Default to the built-in DRF exception handler
    response = drfviews.exception_handler(exc, context)

    if response is None:
        # DRF handler did not provide a default response for this exception

        if settings.DEBUG:
            error_detail = str(exc)
        else:
            error_detail = _("Error details can be found in the admin panel")

        response_data = {
            'error': type(exc).__name__,
            'error_class': str(type(exc)),
            'detail': error_detail,
            'path': context['request'].path,
            'status_code': 500,
        }

        response = Response(response_data, status=500)

        # Log the exception to the database, too
        kind, info, data = sys.exc_info()

        Error.objects.create(
            kind=kind.__name__,
            info=info,
            data='\n'.join(traceback.format_exception(kind, info, data)),
            path=context['request'].path,
            html=ExceptionReporter(context['request'], kind, info,
                                   data).get_traceback_html(),
        )

    if response is not None:
        # Convert errors returned under the label '__all__' to 'non_field_errors'
        if '__all__' in response.data:
            response.data['non_field_errors'] = response.data['__all__']
            del response.data['__all__']

    return response
Esempio n. 25
0
    def update(self, instance, validated_data):
        if isinstance(instance, models.Manager):
            instance = instance.all()
        exists_instances = {i.pk: i for i in instance}
        excess_instances_pks = set(exists_instances.keys())

        model = self.child.Meta.model

        result = list()
        errors = list()
        has_error = False
        for data in validated_data:
            errors.append(dict())

            # PK used to detect exists objects.
            try:
                pk = get_attribute(data, self.child.pk_field.source_attrs)
            except KeyError:
                pk = None

            try:

                if pk:
                    if pk not in exists_instances:
                        raise serializers.ValidationError({
                            self.child.pk_field.field_name:
                            _('{} with pk `{}` doesn\'t exists.').format(
                                model._meta.verbose_name.title(), pk),
                        })

                    if pk not in excess_instances_pks:
                        raise serializers.ValidationError({
                            self.child.pk_field.field_name:
                            _('Duplication {} with pk `{}`.').format(
                                model._meta.verbose_name, pk)
                        })
                    excess_instances_pks.remove(pk)

                    result.append(self.child.update(exists_instances[pk],
                                                    data))
                else:
                    result.append(self.child.create(data))

            except serializers.ValidationError as exc:
                has_error = True
                errors[-1] = serializers.as_serializer_error(exc)

        if has_error:
            raise serializers.ValidationError(errors)

        if excess_instances_pks and not getattr(self.root, 'partial', False):
            model._default_manager.filter(pk__in=excess_instances_pks).delete()

        return result
Esempio n. 26
0
    def test_nested_validation_error_detail(self):
        """
        Ensure nested validation error detail is rendered correctly.
        """
        e = serializers.ValidationError({'nested': {
            'field': ['error'],
        }})

        self.assertEqual(serializers.as_serializer_error(e),
                         {'nested': {
                             'field': ['error'],
                         }})
Esempio n. 27
0
    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get('password')

        try:
            validate_password(password, user)
        except ValidationError as e:
            serializer_error = serializers.as_serializer_error(e)
            raise serializers.ValidationError(
                {'password': serializer_error['non_field_errors']})

        return attrs
Esempio n. 28
0
    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get('password')

        try:
            validate_password(password, user, self.password_validators())
        except django_exceptions.ValidationError as e:
            serializer_error = serializers.as_serializer_error(e)
            raise serializers.ValidationError({
                'password': serializer_error[api_settings.NON_FIELD_ERRORS_KEY]
            })
        return attrs
Esempio n. 29
0
    def run_validation(self, data=empty):

        def merge_err_dict(errs, new_errors):
            errs_copy = {**errs, **new_errors}
            for key, value in errs_copy.items():
                if key in errs and key in new_errors:
                    errs_copy[key] = value + errs[key]

            return errs_copy

        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data

        errs = {}
        value = None
        try:
            value = self.to_internal_value(data)
        except (ValidationError, DjangoValidationError) as exc:
            errs = as_serializer_error(exc)

        try:
            self.run_validators(data)
        except (ValidationError, DjangoValidationError) as exc:
            errs = merge_err_dict(errs, as_serializer_error(exc))

        try:
            if value:
                value = self.validate(value)
            else:
                value = self.validate(data)
            assert value is not None, \
                '.validate() should return the validated data'
        except (ValidationError, DjangoValidationError) as exc:
            errs = merge_err_dict(errs, as_serializer_error(exc))

        if errs:
            raise serializers.ValidationError(errs)
        else:
            return value
Esempio n. 30
0
    def validate(self, attrs):
        user = User(**attrs)
        password = attrs.get('password')

        try:
            validate_password(password, user)
        except django_exceptions.ValidationError as e:
            serializer_error = serializers.as_serializer_error(e)
            raise serializers.ValidationError({
                'password': serializer_error['non_field_errors']
            })

        return attrs
Esempio n. 31
0
 def to_representation(self, payment_method):
     data = super().to_representation(payment_method)
     payment = payment_methods_pool.get_payment(payment_method.identifier)
     request = self.context['request']
     try:
         if 'basket' in self.context:
             payment.validate_basket(basket=self.context['basket'], request=request)
         if 'order' in self.context:
             payment.validate_order(order=self.context['order'], request=request)
     except (ValidationError, DjangoValidationError) as e:
         error = serializers.as_serializer_error(e)
         data['error'] = error[api_settings.NON_FIELD_ERRORS_KEY][0]
     return data
    def test_nested_validation_error_detail(self):
        """
        Ensure nested validation error detail is rendered correctly.
        """
        e = serializers.ValidationError({
            'nested': {
                'field': ['error'],
            }
        })

        assert serializers.as_serializer_error(e) == {
            'nested': {
                'field': ['error'],
            }
        }