mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Fixes #1226: Improve validation for custom field values submitted via the API
This commit is contained in:
parent
f03a378ce0
commit
293dbd8a8b
@ -1,4 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
@ -6,7 +7,9 @@ from rest_framework.exceptions import ValidationError
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
from extras.models import CF_TYPE_SELECT, CustomField, CustomFieldChoice, CustomFieldValue
|
from extras.models import (
|
||||||
|
CF_TYPE_BOOLEAN, CF_TYPE_DATE, CF_TYPE_SELECT, CustomField, CustomFieldChoice, CustomFieldValue,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -25,16 +28,30 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
|
|||||||
|
|
||||||
for field_name, value in data.items():
|
for field_name, value in data.items():
|
||||||
|
|
||||||
|
cf = custom_fields[field_name]
|
||||||
|
|
||||||
# Validate custom field name
|
# Validate custom field name
|
||||||
if field_name not in custom_fields:
|
if field_name not in custom_fields:
|
||||||
raise ValidationError("Invalid custom field for {} objects: {}".format(content_type, field_name))
|
raise ValidationError("Invalid custom field for {} objects: {}".format(content_type, field_name))
|
||||||
|
|
||||||
|
# Validate boolean
|
||||||
|
if cf.type == CF_TYPE_BOOLEAN and value not in [True, False, 1, 0]:
|
||||||
|
raise ValidationError("Invalid value for boolean field {}: {}".format(field_name, value))
|
||||||
|
|
||||||
|
# Validate date
|
||||||
|
if cf.type == CF_TYPE_DATE:
|
||||||
|
try:
|
||||||
|
datetime.strptime(value, '%Y-%m-%d')
|
||||||
|
except ValueError:
|
||||||
|
raise ValidationError("Invalid date for field {}: {}. (Required format is YYYY-MM-DD.)".format(
|
||||||
|
field_name, value
|
||||||
|
))
|
||||||
|
|
||||||
# Validate selected choice
|
# Validate selected choice
|
||||||
cf = custom_fields[field_name]
|
|
||||||
if cf.type == CF_TYPE_SELECT:
|
if cf.type == CF_TYPE_SELECT:
|
||||||
valid_choices = [c.pk for c in cf.choices.all()]
|
valid_choices = [c.pk for c in cf.choices.all()]
|
||||||
if value not in valid_choices:
|
if value not in valid_choices:
|
||||||
raise ValidationError("Invalid choice ({}) for field {}".format(value, field_name))
|
raise ValidationError("Invalid choice for field {}: {}".format(field_name, value))
|
||||||
|
|
||||||
# Check for missing required fields
|
# Check for missing required fields
|
||||||
missing_fields = []
|
missing_fields = []
|
||||||
@ -87,7 +104,7 @@ class CustomFieldModelSerializer(serializers.ModelSerializer):
|
|||||||
field=custom_field,
|
field=custom_field,
|
||||||
obj_type=content_type,
|
obj_type=content_type,
|
||||||
obj_id=instance.pk,
|
obj_id=instance.pk,
|
||||||
defaults={'serialized_value': value},
|
defaults={'serialized_value': custom_field.serialize_value(value)},
|
||||||
)
|
)
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
@ -139,7 +139,11 @@ class CustomField(models.Model):
|
|||||||
if self.type == CF_TYPE_BOOLEAN:
|
if self.type == CF_TYPE_BOOLEAN:
|
||||||
return str(int(bool(value)))
|
return str(int(bool(value)))
|
||||||
if self.type == CF_TYPE_DATE:
|
if self.type == CF_TYPE_DATE:
|
||||||
return value.strftime('%Y-%m-%d')
|
# Could be date/datetime object or string
|
||||||
|
try:
|
||||||
|
return value.strftime('%Y-%m-%d')
|
||||||
|
except AttributeError:
|
||||||
|
return value
|
||||||
if self.type == CF_TYPE_SELECT:
|
if self.type == CF_TYPE_SELECT:
|
||||||
# Could be ModelChoiceField or TypedChoiceField
|
# Could be ModelChoiceField or TypedChoiceField
|
||||||
return str(value.id) if hasattr(value, 'id') else str(value)
|
return str(value.id) if hasattr(value, 'id') else str(value)
|
||||||
|
Loading…
Reference in New Issue
Block a user