From 6ecb50deabeafa5ebd54cdeab071934af65e04c3 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 20 Feb 2017 16:57:38 +0100 Subject: [PATCH 1/3] Default mailbox quota should not be greater than quota. see #1035 --- modoboa/admin/forms/domain.py | 7 +++++++ modoboa/admin/models/domain.py | 5 +++++ modoboa/admin/serializers.py | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/modoboa/admin/forms/domain.py b/modoboa/admin/forms/domain.py index 58a5b1f4f..00ac7c962 100644 --- a/modoboa/admin/forms/domain.py +++ b/modoboa/admin/forms/domain.py @@ -96,6 +96,13 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): "name", _("A %s with this name already exists") % unicode(label) ) + condition = ( + self.cleaned_data["default_mailbox_quota"] > + self.cleaned_data["quota"]) + if condition: + self.add_error( + "default_mailbox_quota", + _("Cannot be greater than domain quota")) if self.user.role == "Resellers": limit = self.user.userobjectlimit_set.get(name="quota") if limit.max_value != 0: diff --git a/modoboa/admin/models/domain.py b/modoboa/admin/models/domain.py index 666514796..cfae8f6f3 100644 --- a/modoboa/admin/models/domain.py +++ b/modoboa/admin/models/domain.py @@ -265,6 +265,11 @@ class Domain(AdminObject): _("Invalid default mailbox quota value for domain '{}'") .format(self.name) ) + if self.quota != 0 and self.default_mailbox_quota > self.quota: + raise BadRequest( + _("Default mailbox quota cannot be greater than domain " + "quota") + ) self.enabled = (row[4].strip() in ["True", "1", "yes", "y"]) core_signals.can_create_object.send( sender=self.__class__, context=user, klass=Domain, diff --git a/modoboa/admin/serializers.py b/modoboa/admin/serializers.py index 20a4e10fd..3376c73a6 100644 --- a/modoboa/admin/serializers.py +++ b/modoboa/admin/serializers.py @@ -27,6 +27,17 @@ class DomainSerializer(serializers.ModelSerializer): "pk", "name", "quota", "default_mailbox_quota", "enabled", "type", ) + def validate(self, data): + """Check quota values.""" + quota = data["quota"] + default_mailbox_quota = data["default_mailbox_quota"] + if quota != 0 and default_mailbox_quota > quota: + raise serializers.ValidationError({ + "default_mailbox_quota": + _("Cannot be greater than domain quota") + }) + return data + def create(self, validated_data): """Set permissions.""" domain = models.Domain(**validated_data) From 9044bfadadb99b338e56d25adaed5b2e1d1aa3eb Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 20 Feb 2017 17:11:48 +0100 Subject: [PATCH 2/3] Fixed unit tests. see #1035 --- modoboa/admin/forms/domain.py | 1 + modoboa/admin/serializers.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/forms/domain.py b/modoboa/admin/forms/domain.py index 00ac7c962..93653368a 100644 --- a/modoboa/admin/forms/domain.py +++ b/modoboa/admin/forms/domain.py @@ -97,6 +97,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): % unicode(label) ) condition = ( + self.cleaned_data["quota"] != 0 and self.cleaned_data["default_mailbox_quota"] > self.cleaned_data["quota"]) if condition: diff --git a/modoboa/admin/serializers.py b/modoboa/admin/serializers.py index 3376c73a6..5c6aee1b9 100644 --- a/modoboa/admin/serializers.py +++ b/modoboa/admin/serializers.py @@ -29,8 +29,8 @@ class DomainSerializer(serializers.ModelSerializer): def validate(self, data): """Check quota values.""" - quota = data["quota"] - default_mailbox_quota = data["default_mailbox_quota"] + quota = data.get("quota", 0) + default_mailbox_quota = data.get("default_mailbox_quota", 0) if quota != 0 and default_mailbox_quota > quota: raise serializers.ValidationError({ "default_mailbox_quota": From 5e637f7f0a8d4fe493adc99b4ee4add4ee5038b4 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 21 Feb 2017 09:53:54 +0100 Subject: [PATCH 3/3] Improve coverage. see #1035 --- modoboa/admin/tests/test_api.py | 6 ++++++ modoboa/admin/tests/test_domain.py | 30 +++++++++++++++++++++++++++-- modoboa/admin/tests/test_import_.py | 6 ++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/tests/test_api.py b/modoboa/admin/tests/test_api.py index a56eb0161..0d17f9702 100644 --- a/modoboa/admin/tests/test_api.py +++ b/modoboa/admin/tests/test_api.py @@ -53,6 +53,12 @@ class DomainAPITestCase(ModoAPITestCase): self.assertEqual(response.status_code, 400) self.assertIn("name", response.data) + response = self.client.post( + url, {"name": "test5.com", "quota": 1, "default_mailbox_quota": 10} + ) + self.assertEqual(response.status_code, 400) + self.assertIn("default_mailbox_quota", response.data) + self.client.credentials( HTTP_AUTHORIZATION='Token ' + self.da_token.key) response = self.client.post( diff --git a/modoboa/admin/tests/test_domain.py b/modoboa/admin/tests/test_domain.py index 859d985d6..5165a5722 100644 --- a/modoboa/admin/tests/test_domain.py +++ b/modoboa/admin/tests/test_domain.py @@ -126,6 +126,33 @@ class DomainTestCase(ModoTestCase): self.assertTrue( self.client.login(username="toto@pouet.com", password=password)) + def test_quota_constraints(self): + """Check quota constraints.""" + values = { + "name": "pouet.com", "quota": 10, "default_mailbox_quota": 100, + "create_dom_admin": True, "dom_admin_username": "toto", + "create_aliases": True, "type": "domain", "stepid": 'step3' + } + response = self.ajax_post( + reverse("admin:domain_add"), + values, status=400 + ) + self.assertEqual( + response["form_errors"]["default_mailbox_quota"][0], + "Cannot be greater than domain quota") + + dom = Domain.objects.get(name="test.com") + values["name"] = dom.name + values["quota"] = 10 + values["default_mailbox_quota"] = 100 + response = self.ajax_post( + reverse("admin:domain_change", args=[dom.pk]), + values, status=400 + ) + self.assertEqual( + response["form_errors"]["default_mailbox_quota"][0], + "Cannot be greater than domain quota") + def test_create_using_default_quota(self): """Check that default value is used for creation.""" self.set_global_parameter("default_domain_quota", 500) @@ -157,8 +184,7 @@ class DomainTestCase(ModoTestCase): dom.alias_set.filter(address="postmaster@pouet.com").exists()) def test_delete(self): - """Test the removal of a domain - """ + """Test the removal of a domain.""" dom = Domain.objects.get(name="test.com") self.ajax_post( reverse("admin:domain_delete", args=[dom.id]), diff --git a/modoboa/admin/tests/test_import_.py b/modoboa/admin/tests/test_import_.py index 067c50cab..73d8aea76 100644 --- a/modoboa/admin/tests/test_import_.py +++ b/modoboa/admin/tests/test_import_.py @@ -64,6 +64,12 @@ domainalias; domalias1.com; domain1.com; True name="domains.csv") response = self.client.post(url, {"sourcefile": f}) self.assertContains(response, "Invalid default mailbox quota") + f = ContentFile("domain; domain1.com; 10; 100; True", + name="domains.csv") + response = self.client.post(url, {"sourcefile": f}) + self.assertContains( + response, + "Default mailbox quota cannot be greater than domain quota") def test_import_domains_with_conflict(self): f = ContentFile(b"""domain;test.alias;100;10;True