From bd271c8ead92c70c2ad3f739a8733f4cdbc354c5 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Mon, 15 Jul 2019 11:32:14 +0200 Subject: [PATCH] See #432: Moved tag validation in the tags app --- api/funkwhale_api/music/metadata.py | 8 +++----- api/funkwhale_api/tags/models.py | 5 +++++ api/funkwhale_api/tags/serializers.py | 8 ++++++++ api/tests/tags/test_serializers.py | 17 +++++++++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py index 77f85aef5..6f608f35c 100644 --- a/api/funkwhale_api/music/metadata.py +++ b/api/funkwhale_api/music/metadata.py @@ -2,7 +2,6 @@ import base64 import datetime import logging import pendulum -import re import mutagen._util import mutagen.oggtheora @@ -12,6 +11,8 @@ import mutagen.flac from rest_framework import serializers from rest_framework.compat import Mapping +from funkwhale_api.tags import models as tags_models + logger = logging.getLogger(__name__) NODEFAULT = object() # default title used when imported tracks miss the `Album` tag, see #122 @@ -491,9 +492,6 @@ class PermissiveDateField(serializers.CharField): return None -TAG_REGEX = re.compile(r"^((\w+)([\d_]*))$") - - def extract_tags_from_genre(string): tags = [] delimiter = "@@@@@" @@ -511,7 +509,7 @@ def extract_tags_from_genre(string): if not tag: continue final_tag = "" - if not TAG_REGEX.match(tag.replace(" ", "")): + if not tags_models.TAG_REGEX.match(tag.replace(" ", "")): # the string contains some non words chars ($, €, etc.), right now # we simply skip such tags continue diff --git a/api/funkwhale_api/tags/models.py b/api/funkwhale_api/tags/models.py index ef3178b2b..2905f3d8d 100644 --- a/api/funkwhale_api/tags/models.py +++ b/api/funkwhale_api/tags/models.py @@ -1,3 +1,5 @@ +import re + from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import CICharField @@ -8,6 +10,9 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ +TAG_REGEX = re.compile(r"^((\w+)([\d_]*))$") + + class Tag(models.Model): name = CICharField(max_length=100, unique=True) creation_date = models.DateTimeField(default=timezone.now) diff --git a/api/funkwhale_api/tags/serializers.py b/api/funkwhale_api/tags/serializers.py index f656f856c..1f53ffdbd 100644 --- a/api/funkwhale_api/tags/serializers.py +++ b/api/funkwhale_api/tags/serializers.py @@ -7,3 +7,11 @@ class TagSerializer(serializers.ModelSerializer): class Meta: model = models.Tag fields = ["name", "creation_date"] + + +class TagNameField(serializers.CharField): + def to_internal_value(self, value): + value = super().to_internal_value(value) + if not models.TAG_REGEX.match(value): + raise serializers.ValidationError('Invalid tag "{}"'.format(value)) + return value diff --git a/api/tests/tags/test_serializers.py b/api/tests/tags/test_serializers.py index 8909a9edc..f9c78a87b 100644 --- a/api/tests/tags/test_serializers.py +++ b/api/tests/tags/test_serializers.py @@ -1,3 +1,5 @@ +import pytest + from funkwhale_api.tags import serializers @@ -12,3 +14,18 @@ def test_tag_serializer(factories): } assert serializer.data == expected + + +@pytest.mark.parametrize( + "name", + [ + "", + "invalid because spaces", + "invalid-because-dashes", + "invalid because non breaking spaces", + ], +) +def test_tag_name_field_validation(name): + field = serializers.TagNameField() + with pytest.raises(serializers.serializers.ValidationError): + field.to_internal_value(name)