Example #1
0
 def value_to_python_for_field(self, field, value):
     if isinstance(field, models.NullBooleanField):
         return to_python_boolean(value, allow_none=True)
     elif isinstance(field, models.BooleanField):
         return to_python_boolean(value)
     elif isinstance(field, (ForeignObjectRel, ManyToManyField,
                             GenericForeignKey, ForeignKey)):
         return self.to_python_related(value)
     else:
         return field.to_python(value)
Example #2
0
 def value_to_python_for_field(self, field, value):
     if isinstance(field, models.NullBooleanField):
         return to_python_boolean(value, allow_none=True)
     elif isinstance(field, models.BooleanField):
         return to_python_boolean(value)
     elif isinstance(field, (ForeignObjectRel, ManyToManyField, GenericForeignKey, ForeignKey)):
         try:
             return self.to_python_related(value)
         except ValueError:
             raise ParseError(_('Invalid {field_name} id: {field_id}').format(
                 field_name=getattr(field, 'name', 'related field'),
                 field_id=value)
             )
     else:
         return field.to_python(value)
Example #3
0
    def value_to_python(self, model, lookup, value):
        try:
            lookup.encode("ascii")
        except UnicodeEncodeError:
            raise ValueError(
                "%r is not an allowed field name. Must be ascii encodable." %
                lookup)

        field_list, new_lookup = self.get_fields_from_lookup(model, lookup)
        field = field_list[-1]

        needs_distinct = not all(
            isinstance(f, self.NO_DUPLICATES_ALLOW_LIST) for f in field_list)

        # Type names are stored without underscores internally, but are presented and
        # and serialized over the API containing underscores so we remove `_`
        # for polymorphic_ctype__model lookups.
        if new_lookup.startswith('polymorphic_ctype__model'):
            value = value.replace('_', '')
        elif new_lookup.endswith('__isnull'):
            value = to_python_boolean(value)
        elif new_lookup.endswith('__in'):
            items = []
            if not value:
                raise ValueError('cannot provide empty value for __in')
            for item in value.split(','):
                items.append(self.value_to_python_for_field(field, item))
            value = items
        elif new_lookup.endswith('__regex') or new_lookup.endswith('__iregex'):
            try:
                re.compile(value)
            except re.error as e:
                raise ValueError(e.args[0])
        elif new_lookup.endswith('__iexact'):
            if not isinstance(field, (CharField, TextField)):
                raise ValueError(
                    f'{field.name} is not a text field and cannot be filtered by case-insensitive search'
                )
        elif new_lookup.endswith('__search'):
            related_model = getattr(field, 'related_model', None)
            if not related_model:
                raise ValueError('%s is not searchable' % new_lookup[:-8])
            new_lookups = []
            for rm_field in related_model._meta.fields:
                if rm_field.name in ('username', 'first_name', 'last_name',
                                     'email', 'name', 'description',
                                     'playbook'):
                    new_lookups.append('{}__{}__icontains'.format(
                        new_lookup[:-8], rm_field.name))
            return value, new_lookups, needs_distinct
        else:
            if isinstance(field, JSONField):
                new_lookup = new_lookup.replace(field.name,
                                                f'{field.name}_as_txt')
            value = self.value_to_python_for_field(field, value)
        return value, new_lookup, needs_distinct
Example #4
0
    def post(self, request):
        if not isinstance(request.data, dict):
            return Response({"error": _("Invalid subscription data")}, status=status.HTTP_400_BAD_REQUEST)
        if "eula_accepted" not in request.data:
            return Response({"error": _("Missing 'eula_accepted' property")}, status=status.HTTP_400_BAD_REQUEST)
        try:
            eula_accepted = to_python_boolean(request.data["eula_accepted"])
        except ValueError:
            return Response({"error": _("'eula_accepted' value is invalid")}, status=status.HTTP_400_BAD_REQUEST)

        if not eula_accepted:
            return Response({"error": _("'eula_accepted' must be True")}, status=status.HTTP_400_BAD_REQUEST)
        request.data.pop("eula_accepted")
        try:
            data_actual = json.dumps(request.data)
        except Exception:
            logger.info(smart_text(u"Invalid JSON submitted for license."), extra=dict(actor=request.user.username))
            return Response({"error": _("Invalid JSON")}, status=status.HTTP_400_BAD_REQUEST)

        from awx.main.utils.common import get_licenser

        license_data = json.loads(data_actual)
        if 'license_key' in license_data:
            return Response({"error": _('Legacy license submitted. A subscription manifest is now required.')}, status=status.HTTP_400_BAD_REQUEST)
        if 'manifest' in license_data:
            try:
                json_actual = json.loads(base64.b64decode(license_data['manifest']))
                if 'license_key' in json_actual:
                    return Response({"error": _('Legacy license submitted. A subscription manifest is now required.')}, status=status.HTTP_400_BAD_REQUEST)
            except Exception:
                pass
            try:
                license_data = validate_entitlement_manifest(license_data['manifest'])
            except ValueError as e:
                return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
            except Exception:
                logger.exception('Invalid manifest submitted. {}')
                return Response({"error": _('Invalid manifest submitted.')}, status=status.HTTP_400_BAD_REQUEST)

            try:
                license_data_validated = get_licenser().license_from_manifest(license_data)
            except Exception:
                logger.warning(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
                return Response({"error": _("Invalid License")}, status=status.HTTP_400_BAD_REQUEST)
        else:
            license_data_validated = get_licenser().validate()

        # If the license is valid, write it to the database.
        if license_data_validated['valid_key']:
            if not settings_registry.is_setting_read_only('TOWER_URL_BASE'):
                settings.TOWER_URL_BASE = "{}://{}".format(request.scheme, request.get_host())
            return Response(license_data_validated)

        logger.warning(smart_text(u"Invalid subscription submitted."), extra=dict(actor=request.user.username))
        return Response({"error": _("Invalid subscription")}, status=status.HTTP_400_BAD_REQUEST)
Example #5
0
    def post(self, request):
        if not isinstance(request.data, dict):
            return Response({"error": _("Invalid license data")},
                            status=status.HTTP_400_BAD_REQUEST)
        if "eula_accepted" not in request.data:
            return Response({"error": _("Missing 'eula_accepted' property")},
                            status=status.HTTP_400_BAD_REQUEST)
        try:
            eula_accepted = to_python_boolean(request.data["eula_accepted"])
        except ValueError:
            return Response({"error": _("'eula_accepted' value is invalid")},
                            status=status.HTTP_400_BAD_REQUEST)

        if not eula_accepted:
            return Response({"error": _("'eula_accepted' must be True")},
                            status=status.HTTP_400_BAD_REQUEST)
        request.data.pop("eula_accepted")
        try:
            data_actual = json.dumps(request.data)
        except Exception:
            logger.info(smart_text(u"Invalid JSON submitted for license."),
                        extra=dict(actor=request.user.username))
            return Response({"error": _("Invalid JSON")},
                            status=status.HTTP_400_BAD_REQUEST)
        try:
            from awx.main.utils.common import get_licenser
            license_data = json.loads(data_actual)
            license_data_validated = get_licenser(**license_data).validate()
        except Exception:
            logger.warning(smart_text(u"Invalid license submitted."),
                           extra=dict(actor=request.user.username))
            return Response({"error": _("Invalid License")},
                            status=status.HTTP_400_BAD_REQUEST)

        # If the license is valid, write it to the database.
        if license_data_validated['valid_key']:
            settings.LICENSE = license_data
            if not settings_registry.is_setting_read_only('TOWER_URL_BASE'):
                settings.TOWER_URL_BASE = "{}://{}".format(
                    request.scheme, request.get_host())
            return Response(license_data_validated)

        logger.warning(smart_text(u"Invalid license submitted."),
                       extra=dict(actor=request.user.username))
        return Response({"error": _("Invalid license")},
                        status=status.HTTP_400_BAD_REQUEST)
Example #6
0
    def value_to_python(self, model, lookup, value):
        try:
            lookup.encode("ascii")
        except UnicodeEncodeError:
            raise ValueError(
                "%r is not an allowed field name. Must be ascii encodable." %
                lookup)

        field, new_lookup = self.get_field_from_lookup(model, lookup)

        # Type names are stored without underscores internally, but are presented and
        # and serialized over the API containing underscores so we remove `_`
        # for polymorphic_ctype__model lookups.
        if new_lookup.startswith('polymorphic_ctype__model'):
            value = value.replace('_', '')
        elif new_lookup.endswith('__isnull'):
            value = to_python_boolean(value)
        elif new_lookup.endswith('__in'):
            items = []
            if not value:
                raise ValueError('cannot provide empty value for __in')
            for item in value.split(','):
                items.append(self.value_to_python_for_field(field, item))
            value = items
        elif new_lookup.endswith('__regex') or new_lookup.endswith('__iregex'):
            try:
                re.compile(value)
            except re.error as e:
                raise ValueError(e.args[0])
        elif new_lookup.endswith('__search'):
            related_model = getattr(field, 'related_model', None)
            if not related_model:
                raise ValueError('%s is not searchable' % new_lookup[:-8])
            new_lookups = []
            for rm_field in related_model._meta.fields:
                if rm_field.name in ('username', 'first_name', 'last_name',
                                     'email', 'name', 'description',
                                     'playbook'):
                    new_lookups.append('{}__{}__icontains'.format(
                        new_lookup[:-8], rm_field.name))
            return value, new_lookups
        else:
            value = self.value_to_python_for_field(field, value)
        return value, new_lookup