Skip to content

Commit

Permalink
Fix validation in AttributeSerializer
Browse files Browse the repository at this point in the history
The current implementation of `to_internal_value` doesn't call the base
class method, which is supposed to carry out generic validation of
serializer fields. This means that we essentially don't validate attribute
fields beyond what is done incidentally by database contraints.

Fix it by removing the overridden method entirely, and adding a special
field class for the `values` field.
  • Loading branch information
SpecLad committed Jul 13, 2023
1 parent 561b2d1 commit ff6b543
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- \[SDK\] Ability to create attributes with blank default values
(<https://github.com/opencv/cvat/pull/6454>)
- \[SDK\] SDK should not change input data in models (<https://github.com/opencv/cvat/pull/6455>)
- Server-side validation for attribute specifications
(<https://github.com/opencv/cvat/pull/6447>)

### Security
- TDB
Expand Down
24 changes: 8 additions & 16 deletions cvat/apps/engine/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,30 +212,22 @@ class Meta:
'last_login': { 'allow_null': True }
}

class DelimitedStringListField(serializers.ListField):
def to_representation(self, value):
return super().to_representation(value.split('\n'))

def to_internal_value(self, data):
return '\n'.join(super().to_internal_value(data))

class AttributeSerializer(serializers.ModelSerializer):
values = serializers.ListField(allow_empty=True,
values = DelimitedStringListField(allow_empty=True,
child=serializers.CharField(allow_blank=True, max_length=200),
)

class Meta:
model = models.AttributeSpec
fields = ('id', 'name', 'mutable', 'input_type', 'default_value', 'values')

# pylint: disable=no-self-use
def to_internal_value(self, data):
attribute = data.copy()
attribute['values'] = '\n'.join(data.get('values', []))
return attribute

def to_representation(self, instance):
if instance:
rep = super().to_representation(instance)
rep['values'] = instance.values.split('\n')
else:
rep = instance

return rep

class SublabelSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
attributes = AttributeSerializer(many=True, source='attributespec_set', default=[],
Expand Down

0 comments on commit ff6b543

Please sign in to comment.