Skip to content

Commit

Permalink
Fixes #1226: Improve validation for custom field values submitted via…
Browse files Browse the repository at this point in the history
… the API
  • Loading branch information
jeremystretch committed May 31, 2017
1 parent f03a378 commit 293dbd8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
25 changes: 21 additions & 4 deletions netbox/extras/api/customfields.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import unicode_literals
from datetime import datetime

from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from django.contrib.contenttypes.models import ContentType
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,
)


#
Expand All @@ -25,16 +28,30 @@ def to_internal_value(self, data):

for field_name, value in data.items():

cf = custom_fields[field_name]

# Validate custom field name
if field_name not in custom_fields:
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
cf = custom_fields[field_name]
if cf.type == CF_TYPE_SELECT:
valid_choices = [c.pk for c in cf.choices.all()]
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
missing_fields = []
Expand Down Expand Up @@ -87,7 +104,7 @@ def _save_custom_fields(self, instance, custom_fields):
field=custom_field,
obj_type=content_type,
obj_id=instance.pk,
defaults={'serialized_value': value},
defaults={'serialized_value': custom_field.serialize_value(value)},
)

def create(self, validated_data):
Expand Down
6 changes: 5 additions & 1 deletion netbox/extras/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ def serialize_value(self, value):
if self.type == CF_TYPE_BOOLEAN:
return str(int(bool(value)))
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:
# Could be ModelChoiceField or TypedChoiceField
return str(value.id) if hasattr(value, 'id') else str(value)
Expand Down

0 comments on commit 293dbd8

Please sign in to comment.