From 0c4ca76715bc76d4caf6718ca36a29d061b060ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B4mulo=20Penido?= Date: Thu, 28 Sep 2023 15:47:30 -0300 Subject: [PATCH] feat: make object_id field case insensitive (#86) --- openedx_learning/__init__.py | 2 +- .../0009_alter_objecttag_object_id.py | 20 ++++++++++ openedx_tagging/core/tagging/models/base.py | 4 +- .../openedx_tagging/core/tagging/test_api.py | 32 ++++++++++++++++ .../core/tagging/test_models.py | 37 +++++++++++++++++++ 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py diff --git a/openedx_learning/__init__.py b/openedx_learning/__init__.py index 8b70cf96..576d6b42 100644 --- a/openedx_learning/__init__.py +++ b/openedx_learning/__init__.py @@ -1,4 +1,4 @@ """ Open edX Learning ("Learning Core"). """ -__version__ = "0.1.7" +__version__ = "0.1.8" diff --git a/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py b/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py new file mode 100644 index 00000000..9e1150b2 --- /dev/null +++ b/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.19 on 2023-09-26 13:36 + +from django.db import migrations + +import openedx_learning.lib.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('oel_tagging', '0008_taxonomy_description_not_null'), + ] + + operations = [ + migrations.AlterField( + model_name='objecttag', + name='object_id', + field=openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_index=True, editable=False, help_text='Identifier for the object being tagged', max_length=255), + ), + ] diff --git a/openedx_tagging/core/tagging/models/base.py b/openedx_tagging/core/tagging/models/base.py index abb4eae1..58a7c950 100644 --- a/openedx_tagging/core/tagging/models/base.py +++ b/openedx_tagging/core/tagging/models/base.py @@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _ from typing_extensions import Self # Until we upgrade to python 3.11 -from openedx_learning.lib.fields import MultiCollationTextField, case_insensitive_char_field +from openedx_learning.lib.fields import MultiCollationTextField, case_insensitive_char_field, case_sensitive_char_field log = logging.getLogger(__name__) @@ -577,7 +577,7 @@ class ObjectTag(models.Model): """ id = models.BigAutoField(primary_key=True) - object_id = case_insensitive_char_field( + object_id = case_sensitive_char_field( max_length=255, db_index=True, editable=False, diff --git a/tests/openedx_tagging/core/tagging/test_api.py b/tests/openedx_tagging/core/tagging/test_api.py index 3525bc5c..422b15c1 100644 --- a/tests/openedx_tagging/core/tagging/test_api.py +++ b/tests/openedx_tagging/core/tagging/test_api.py @@ -494,6 +494,38 @@ def test_tag_object_same_value_multiple_free(self) -> None: ) assert len(object_tags) == 1 + def test_tag_object_case_id(self) -> None: + """ + Test that the case of the object_id is preserved. + """ + tagging_api.tag_object( + self.taxonomy, + [self.eubacteria.id], + "biology101", + ) + + tagging_api.tag_object( + self.taxonomy, + [self.archaea.id], + "BIOLOGY101", + ) + + object_tags_lower = tagging_api.get_object_tags( + taxonomy_id=self.taxonomy.pk, + object_id="biology101", + ) + + assert len(object_tags_lower) == 1 + assert object_tags_lower[0].tag_id == self.eubacteria.id + + object_tags_upper = tagging_api.get_object_tags( + taxonomy_id=self.taxonomy.pk, + object_id="BIOLOGY101", + ) + + assert len(object_tags_upper) == 1 + assert object_tags_upper[0].tag_id == self.archaea.id + @override_settings(LANGUAGES=test_languages) def test_tag_object_language_taxonomy(self) -> None: tags_list = [ diff --git a/tests/openedx_tagging/core/tagging/test_models.py b/tests/openedx_tagging/core/tagging/test_models.py index 44905c3a..aa7bca0a 100644 --- a/tests/openedx_tagging/core/tagging/test_models.py +++ b/tests/openedx_tagging/core/tagging/test_models.py @@ -3,6 +3,7 @@ """ import ddt # type: ignore[import] from django.contrib.auth import get_user_model +from django.db import transaction from django.db.utils import IntegrityError from django.test.testcases import TestCase @@ -525,3 +526,39 @@ def test_tag_object_invalid_tag(self): "biology101", ) assert "Invalid object tag for taxonomy" in str(exc.exception) + + def test_tag_case(self) -> None: + """ + Test that the object_id is case sensitive. + """ + # Tag with object_id with lower case + ObjectTag( + object_id="case:id:2", + taxonomy=self.taxonomy, + tag=self.domain_tags[0], + ).save() + + # Tag with object_id with upper case should not trigger IntegrityError + ObjectTag( + object_id="CASE:id:2", + taxonomy=self.taxonomy, + tag=self.domain_tags[0], + ).save() + + # Create another ObjectTag with lower case object_id should trigger IntegrityError + with transaction.atomic(): + with self.assertRaises(IntegrityError): + ObjectTag( + object_id="case:id:2", + taxonomy=self.taxonomy, + tag=self.domain_tags[0], + ).save() + + # Create another ObjectTag with upper case object_id should trigger IntegrityError + with transaction.atomic(): + with self.assertRaises(IntegrityError): + ObjectTag( + object_id="CASE:id:2", + taxonomy=self.taxonomy, + tag=self.domain_tags[0], + ).save()