Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server error during API validation when required custom field is empty #1489

Closed
arionl opened this issue Sep 15, 2017 · 3 comments
Closed

Server error during API validation when required custom field is empty #1489

arionl opened this issue Sep 15, 2017 · 3 comments
Labels
type: bug A confirmed report of unexpected behavior in the application

Comments

@arionl
Copy link

arionl commented Sep 15, 2017

Issue type

[ ] Feature request
[X] Bug report
[ ] Documentation

Environment

  • Python version: 3.6.2
  • NetBox version: 2.1.4

Description

If I try to manipulate an object via the API (a Site in my case) that has a custom field of type "Selection", the PUT request results in an error even if I'm not changing the contents of the custom field.

Example:
Site "1" named "Home" with two custom fields:

  • Customtext
  • Customselection (options are: 'one', 'two', 'three')
curl -H "Authorization: Token XXX" "Accept: application/json; indent=4" http://netbox/api/dcim/sites/1/
{"id":1,"name":"Home","slug":"home","region":{"id":2,"url":"http://netbox/api/dcim/regions/2/","name":"USA","slug":"usa"},"tenant":null,"facility":"Home","asn":55,"physical_address":"Vienna, VA","shipping_address":"","contact_name":"Arion","contact_phone":"","contact_email":"","comments":"Testing","custom_fields":{"CustomSelection":{"value":4,"label":"one"},"CustomText":"My custom text"},"count_prefixes":5,"count_vlans":0,"count_racks":2,"count_devices":13,"count_circuits":1}

Changing something like the ASN field (from 55 to 56) and then attempting to resubmit:

curl -X PUT -H "Authorization: Token XXX" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://netbox/api/dcim/sites/1/ --data '{"id":1,"name":"Home","slug":"home","region":2,"tenant":null,"facility":"Home","asn":56,"physical_address":"Vienna, VA","shipping_address":"","contact_name":"Arion","contact_phone":"","contact_email":"","comments":"Testing","custom_fields":{"CustomSelection":{"value":4,"label":"one"},"CustomText":"My custom text"},"count_prefixes":5,"count_vlans":0,"count_racks":2,"count_devices":13,"count_circuits":1}'

..results in:

<pre><strong>&lt;class &#39;TypeError&#39;&gt;</strong><br />
int() argument must be a string, a bytes-like object or a number, not &#39;dict&#39;</pre>

I also tried a Site that had both custom fields set to 'null' and same result. If I remove the "Customselection" custom field completely, everything works as intended.

I first stumbled upon this problem because I got an error while trying to use the pynetbox library. Working backwards it seems like the raw PUT request gives an error. I believe this is a NetBox API issue not pynetbox, but I'm still a bit fuzzy and learning. Hope I'm reporting this properly.

@huzichunjohn
Copy link
Contributor

@arionl : hi, try to modify your custom fields in request like below. i try and it works for me.
"custom_fields": {"CustomSelection": 4, "CustomText": "My custom text"}

@arionl
Copy link
Author

arionl commented Sep 15, 2017

Ah, if I change:

"custom_fields":{"CustomSelection":{"value":7,"label":"one"},"CustomText":"My custom text"}

..to:

"custom_fields":{"CustomSelection":7,"CustomText":"My custom text"}

the PUT request works. However, this custom field isn't marked as required so if it doesn't have a value (null) or I try to set it back to null, I then get the 'int' error:

"custom_fields":{"CustomSelection":null,"CustomText":"My custom text"}

@huzichunjohn
Copy link
Contributor

--- a/netbox/extras/api/customfields.py
+++ b/netbox/extras/api/customfields.py
@@ -36,27 +36,37 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
                 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))
+            if cf.type == CF_TYPE_BOOLEAN:
+               if value and value not in [True, False, 1, 0]:
+                    raise ValidationError("Invalid value for boolean field {}: {}".format(field_name, value))
+               elif not value and cf.required:
+                   raise ValidationError("{} is required field and can't be None, you should pass a bool value.".format(field_nam
 
             # 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
-                    ))
+                if value:
+                    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
+                        ))
+               elif not value and cf.required:
+                    raise ValidationError("{} is required field and can't be None, you should pass a date.".format(field_name))
 
             # Validate selected choice
             if cf.type == CF_TYPE_SELECT:
-                try:
-                    value = int(value)
-                except ValueError:
-                    raise ValidationError("{}: Choice selections must be passed as integers.".format(field_name))
-                valid_choices = [c.pk for c in cf.choices.all()]
-                if value not in valid_choices:
-                    raise ValidationError("Invalid choice for field {}: {}".format(field_name, value))
+               if value:
+                    try:
+                        value = int(value)
+                    except ValueError:
+                        raise ValidationError("{}: Choice selections must be passed as integers.".format(field_name))
+                   valid_choices = [c.pk for c in cf.choices.all()]
+                    if value not in valid_choices:
+                        raise ValidationError("Invalid choice for field {}: {}".format(field_name, value))
+
+               elif not value and cf.required:
+                   raise ValidationError("{} is required field and can't be None, you should pass a integer.".format(field_name))
 
         # Check for missing required fields
         missing_fields = []

@jeremystretch jeremystretch changed the title API error when updating objects with "Selection" type custom fields Server error during API validation when required custom field is empty Sep 25, 2017
@jeremystretch jeremystretch added the type: bug A confirmed report of unexpected behavior in the application label Sep 25, 2017
lampwins pushed a commit to lampwins/netbox that referenced this issue Oct 13, 2017
@lock lock bot locked as resolved and limited conversation to collaborators Jan 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug A confirmed report of unexpected behavior in the application
Projects
None yet
Development

No branches or pull requests

3 participants