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)
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)
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
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)
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)
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