diff --git a/digid_eherkenning/migrations/0004_alter_eherkenningconfiguration_loa.py b/digid_eherkenning/migrations/0004_alter_eherkenningconfiguration_loa.py new file mode 100644 index 0000000..da7f366 --- /dev/null +++ b/digid_eherkenning/migrations/0004_alter_eherkenningconfiguration_loa.py @@ -0,0 +1,46 @@ +# Generated by Django 4.2.4 on 2023-08-15 13:47 + +import digid_eherkenning.choices +from django.db import migrations, models +from ..choices import AssuranceLevels + + +def set_default_loa(apps, schema_editor): + EherkenningConfiguration = apps.get_model( + "digid_eherkenning", "EherkenningConfiguration" + ) + EherkenningConfiguration.objects.filter(loa="").update(loa=AssuranceLevels.low_plus) + + +class Migration(migrations.Migration): + dependencies = [ + ("digid_eherkenning", "0003_digidconfiguration_artifact_resolve_content_type"), + ] + + operations = [ + migrations.RunPython(set_default_loa), + migrations.AlterField( + model_name="eherkenningconfiguration", + name="loa", + field=models.CharField( + choices=[ + ("urn:etoegang:core:assurance-class:loa1", "Non existent (1)"), + ("urn:etoegang:core:assurance-class:loa2", "Low (2)"), + ("urn:etoegang:core:assurance-class:loa2plus", "Low (2+)"), + ("urn:etoegang:core:assurance-class:loa3", "Substantial (3)"), + ("urn:etoegang:core:assurance-class:loa4", "High (4)"), + ], + default="urn:etoegang:core:assurance-class:loa3", + help_text="Level of Assurance (LoA) to use for all the services.", + max_length=100, + verbose_name="LoA", + ), + ), + migrations.AddConstraint( + model_name="eherkenningconfiguration", + constraint=models.CheckConstraint( + check=models.Q(("loa__in", digid_eherkenning.choices.AssuranceLevels)), + name="valid_loa", + ), + ), + ] diff --git a/digid_eherkenning/models/eherkenning.py b/digid_eherkenning/models/eherkenning.py index d5ce0a5..202d8fe 100644 --- a/digid_eherkenning/models/eherkenning.py +++ b/digid_eherkenning/models/eherkenning.py @@ -12,7 +12,6 @@ class EherkenningConfiguration(BaseConfiguration): loa = models.CharField( _("LoA"), - blank=True, choices=AssuranceLevels.choices, default=AssuranceLevels.substantial, help_text=_("Level of Assurance (LoA) to use for all the services."), @@ -119,6 +118,11 @@ class EherkenningConfiguration(BaseConfiguration): class Meta: verbose_name = _("Eherkenning/eIDAS configuration") + constraints = [ + models.constraints.CheckConstraint( + name="valid_loa", check=models.Q(loa__in=AssuranceLevels) + ), + ] def as_dict(self) -> dict: """ diff --git a/setup.cfg b/setup.cfg index 446abdb..f53c9e5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,6 +43,7 @@ install_requires = furl maykin-python3-saml tests_require = + django-test-migrations freezegun pytest pytest-django @@ -59,6 +60,7 @@ include = [options.extras_require] tests = + django-test-migrations pytest pytest-django responses diff --git a/tests/test_migrations.py b/tests/test_migrations.py new file mode 100644 index 0000000..718fcef --- /dev/null +++ b/tests/test_migrations.py @@ -0,0 +1,32 @@ +from django.db import IntegrityError + +import pytest + +from digid_eherkenning.choices import AssuranceLevels + + +@pytest.mark.django_db() +def test_fixing_misconfigured_eherkenning(migrator): + old_state = migrator.apply_initial_migration( + ("digid_eherkenning", "0003_digidconfiguration_artifact_resolve_content_type") + ) + OldEherkenningConfiguration = old_state.apps.get_model( + "digid_eherkenning", "EherkenningConfiguration" + ) + + # misconfigured entry; attribute had default, but also blank=True + OldEherkenningConfiguration(loa="").save() + + new_state = migrator.apply_tested_migration( + ("digid_eherkenning", "0004_alter_eherkenningconfiguration_loa") + ) + EherkenningConfiguration = new_state.apps.get_model( + "digid_eherkenning", "EherkenningConfiguration" + ) + config = EherkenningConfiguration.objects.get() + assert config.loa == AssuranceLevels.low_plus + + # impossible to misconfigure + config.loa = "" + with pytest.raises(IntegrityError): + config.save()