diff --git a/modoboa/admin/forms/domain.py b/modoboa/admin/forms/domain.py index 58a5b1f4f..93653368a 100644 --- a/modoboa/admin/forms/domain.py +++ b/modoboa/admin/forms/domain.py @@ -96,6 +96,14 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): "name", _("A %s with this name already exists") % unicode(label) ) + condition = ( + self.cleaned_data["quota"] != 0 and + 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..5c6aee1b9 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.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": + _("Cannot be greater than domain quota") + }) + return data + def create(self, validated_data): """Set permissions.""" domain = models.Domain(**validated_data) 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