More tests updated

This commit is contained in:
Antoine Nguyen
2025-06-08 15:12:48 +02:00
parent defef9c15f
commit abae9bb7c3
20 changed files with 640 additions and 1528 deletions
+18
View File
@@ -72,6 +72,24 @@ class DomainAPITestCase(ModoAPITestCase):
)
self.assertEqual(response.status_code, 403)
def test_create_utf8(self):
"""Test the creation of a domain with non-ASCII characters."""
url = reverse("v1:domain-list")
values = {
"name": "pouét.com",
"quota": 1000,
"default_mailbox_quota": 100,
"type": "domain",
}
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 201)
dom = models.Domain.objects.get(name="pouét.com")
self.assertEqual(dom.name, "pouét.com")
self.assertEqual(dom.quota, 1000)
self.assertEqual(dom.default_mailbox_quota, 100)
self.assertEqual(dom.enabled, False)
self.assertFalse(dom.admins)
@mock.patch.object(dns.resolver.Resolver, "resolve")
@mock.patch("socket.getaddrinfo")
def test_create_domain_with_mx_check(self, mock_getaddrinfo, mock_query):
+10 -1
View File
@@ -71,6 +71,15 @@ class DomainSerializer(v1_serializers.DomainSerializer):
many=True, source="domainobjectlimit_set", required=False
)
def validate_enable_dkim(self, value):
"""Check prerequisites."""
if not value:
return value
storage_dir = param_tools.get_global_parameter("dkim_keys_storage_dir")
if not storage_dir:
raise ValidationError(_("DKIM keys storage directory not configured"))
return value
def validate(self, data):
result = super().validate(data)
dtype = data.get("type", "domain")
@@ -205,7 +214,7 @@ class AdminGlobalParametersSerializer(serializers.Serializer):
# Domain settings
enable_mx_checks = serializers.BooleanField(default=True)
valid_mxs = serializers.CharField(allow_blank=True)
valid_mxs = serializers.CharField(default="", allow_blank=True)
domains_must_have_authorized_mx = serializers.BooleanField(default=False)
enable_ipv6_mx_checks = serializers.BooleanField(default=True)
enable_spf_checks = serializers.BooleanField(default=True)
+152 -3
View File
@@ -7,7 +7,7 @@ from django.utils.encoding import force_str
from rest_framework.authtoken.models import Token
from modoboa.admin import factories, models, constants
from modoboa.core import models as core_models
from modoboa.core import factories as core_factories, models as core_models
from modoboa.lib.tests import ModoAPITestCase
@@ -98,6 +98,18 @@ class DomainViewSetTestCase(ModoAPITestCase):
resp = self.client.post(url)
self.assertEqual(resp.status_code, 204)
def test_delete_auto_account_removal(self):
self.set_global_parameter("auto_account_removal", True)
dom = models.Domain.objects.get(name="test2.com")
url = reverse("v2:domain-delete", args=[dom.pk])
response = self.client.post(url, {}, format="json")
self.assertEqual(response.status_code, 204)
with self.assertRaises(models.Domain.DoesNotExist):
dom.refresh_from_db()
self.assertFalse(
core_models.User.objects.filter(username="admin@test2.com").exists()
)
def test_administrators(self):
domain = models.Domain.objects.get(name="test.com")
url = reverse("v2:domain-administrators", args=[domain.pk])
@@ -169,8 +181,9 @@ class AccountViewSetTestCase(ModoAPITestCase):
def test_create(self):
url = reverse("v2:account-list")
username = "toto@test.com"
data = {
"username": "toto@test.com",
"username": username,
"role": "SimpleUsers",
"mailbox": {"use_domain_quota": True},
"password": "Toto12345",
@@ -180,6 +193,30 @@ class AccountViewSetTestCase(ModoAPITestCase):
resp = self.client.post(url, data, format="json")
self.assertEqual(resp.status_code, 201)
self.assertTrue(models.Alias.objects.filter(address="alias3@test.com").exists())
# Check if self alias has been created
self.assertTrue(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=username,
address=username,
alias__internal=True,
)
.exists()
)
def test_create_with_existing_alias(self):
alias = models.Alias.objects.get(address="alias@test.com")
alias.set_recipients(["user@external.com"])
values = {
"username": "tester@test.com",
"role": "SimpleUsers",
"mailbox": {"use_domain_quota": True},
"is_active": True,
"aliases": ["alias@test.com"],
}
response = self.client.post(reverse("v2:account-list"), values, format="json")
self.assertTrue(response.status_code, 201)
self.assertTrue(alias.aliasrecipient_set.count() == 2)
def test_create_admin(self):
url = reverse("v2:account-list")
@@ -241,12 +278,43 @@ class AccountViewSetTestCase(ModoAPITestCase):
self.assertIn("password", resp.json())
def test_delete(self):
account = core_models.User.objects.get(username="user@test.com")
username = "user@test.com"
account = core_models.User.objects.get(username=username)
url = reverse("v2:account-delete", args=[account.pk])
resp = self.client.post(url)
self.assertEqual(resp.status_code, 204)
with self.assertRaises(core_models.User.DoesNotExist):
account.refresh_from_db()
# Check if self alias has been deleted
self.assertFalse(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=username,
address=username,
alias__internal=True,
)
.exists()
)
def test_delete_default_superadmin(self):
"""Delete default superadmin."""
sadmin2 = core_factories.UserFactory(username="admin2", is_superuser=True)
sadmin = core_models.User.objects.get(username="admin")
self.authenticate_user(sadmin2)
response = self.client.post(reverse("v2:account-delete", args=[sadmin.pk]), {})
self.assertEqual(response.status_code, 204)
values = {
"username": "user@test.com",
"role": "DomainAdmins",
"is_active": True,
"language": "en",
"mailbox": {"use_domain_quota": True},
}
account = core_models.User.objects.get(username="user@test.com")
response = self.client.put(
reverse("v2:account-detail", args=[account.pk]), values, format="json"
)
self.assertEqual(response.status_code, 200)
def test_update(self):
account = core_models.User.objects.get(username="user@test.com")
@@ -261,6 +329,30 @@ class AccountViewSetTestCase(ModoAPITestCase):
resp = self.client.patch(url, data, format="json")
self.assertEqual(resp.status_code, 200)
def test_rename(self):
account = core_models.User.objects.get(username="user@test.com")
url = reverse("v2:account-detail", args=[account.pk])
new_username = "user_updated@test.com"
data = {
"username": new_username,
"role": "SimpleUsers",
"password": "Toto12345",
"mailbox": {"quota": 10},
"aliases": ["aliasupdate1@test.com"],
}
response = self.client.put(url, data, format="json")
self.assertEqual(response.status_code, 200)
# Check if self alias has been updated
self.assertTrue(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=new_username,
address=new_username,
alias__internal=True,
)
.exists()
)
def test_mailbox_options_update(self):
account = core_models.User.objects.get(username="user@test.com")
url = reverse("v2:account-detail", args=[account.pk])
@@ -408,6 +500,49 @@ class AccountViewSetTestCase(ModoAPITestCase):
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.json()["resources"]), 2)
def _set_quota(self, email, value, expected_status=200):
account = core_models.User.objects.get(username=email)
values = {
"username": email,
"role": "SimpleUsers",
"mailbox": {"use_domain_quota": False, "quota": value},
"is_active": True,
"language": "en",
}
response = self.client.put(
reverse("v2:account-detail", args=[account.id]), values, format="json"
)
self.assertEqual(response.status_code, expected_status)
def test_set_nul_quota_as_superadmin(self):
self._set_quota("user@test.com", 0)
def test_set_nul_quota_as_domainadmin(self):
"""Check cases where a domain admin set unlimited quota."""
dadmin = core_models.User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
# Fails because domain has a quota
self._set_quota("user@test.com", 0, 400)
dadmin = core_models.User.objects.get(username="admin@test2.com")
self.authenticate_user(dadmin)
# Ok because domain has no quota
self._set_quota("user@test2.com", 0)
def test_domain_quota(self):
"""Check domain quota."""
dom = models.Domain.objects.get(name="test.com")
dom.quota = 100
dom.save(update_fields=["quota"])
# 2 x 10MB
self.assertEqual(dom.allocated_quota, 20)
self._set_quota("user@test.com", 80)
del dom.allocated_quota
# 10 + 80 < 100 => ok
self.assertEqual(dom.allocated_quota, 90)
# 30 + 80 > 100 => failure
self._set_quota("admin@test.com", 30, 400)
class IdentityViewSetTestCase(ModoAPITestCase):
@classmethod
@@ -525,6 +660,20 @@ class AliasViewSetTestCase(ModoAPITestCase):
self.assertEqual(resp.status_code, 200)
self.assertIn("address", resp.json())
def test_create_on_existing_account(self):
values = {
"address": "user@test.com",
"recipients": ["ext@doman.test"],
"enabled": True,
}
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
# Check that internal alias has not been updated
alias = models.Alias.objects.get(address="user@test.com", internal=True)
self.assertTrue(alias.aliasrecipient_set.count() == 1)
alias = models.Alias.objects.get(address="user@test.com", internal=False)
self.assertTrue(alias.aliasrecipient_set.count() == 1)
class UserAccountViewSetTestCase(ModoAPITestCase):
@classmethod
+2 -1
View File
@@ -13,7 +13,8 @@ class MXRecordQuerySet(models.QuerySet):
def has_valids(self):
"""Return managed results."""
if param_tools.get_global_parameter("valid_mxs").strip():
valid_mxs = param_tools.get_global_parameter("valid_mxs")
if valid_mxs and valid_mxs.strip():
return self.filter(managed=True).exists()
return self.exists()
+100 -604
View File
@@ -6,12 +6,12 @@ from django.urls import reverse
from modoboa.core import factories as core_factories
from modoboa.core.models import User
from modoboa.core.tests import test_ldap
from modoboa.lib.tests import NO_LDAP, ModoTestCase
from modoboa.lib.tests import NO_LDAP, ModoAPITestCase
from modoboa.limits import utils as limits_utils
from .. import factories, models
class AuthenticationTestCase(ModoTestCase):
class AuthenticationTestCase(ModoAPITestCase):
"""Check authentication."""
@classmethod
@@ -34,10 +34,10 @@ class AuthenticationTestCase(ModoTestCase):
data = {"username": self.mb.full_address, "password": password}
response = self.client.post(reverse("core:login"), data)
self.assertEqual(response.status_code, 302)
self.assertTrue(response.url.endswith(reverse("core:user_index")))
self.assertEqual(response.url, "/")
class AccountTestCase(ModoTestCase):
class AccountTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
@@ -45,154 +45,6 @@ class AccountTestCase(ModoTestCase):
super().setUpTestData()
factories.populate_database()
def test_crud(self):
values = {
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "tester@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username="tester@test.com")
mb = account.mailbox
self.assertEqual(mb.full_address, "tester@test.com")
self.assertEqual(mb.quota, 10)
self.assertTrue(mb.enabled)
self.assertEqual(mb.quota_value.username, "tester@test.com")
self.assertEqual(account.username, mb.full_address)
self.assertTrue(account.check_password("Toto1234"))
self.assertEqual(account.first_name, "Tester")
self.assertEqual(account.last_name, "Toto")
self.assertEqual(mb.domain.mailbox_count, 3)
# Check if self alias has been created
self.assertTrue(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=mb.full_address,
address=mb.full_address,
alias__internal=True,
)
.exists()
)
values.update(
{
"username": "pouet@test.com",
"language": "en",
"secondary_email": "homer@simpson.com",
"phone_number": "+33612345678",
"subject": "subject",
"content": "content",
}
)
self.ajax_post(reverse("admin:account_change", args=[account.id]), values)
account.refresh_from_db()
self.assertEqual(account.secondary_email, values["secondary_email"])
mb = models.Mailbox.objects.get(pk=mb.pk)
self.assertEqual(mb.full_address, "pouet@test.com")
self.assertEqual(mb.quota_value.username, "pouet@test.com")
# Check if self alias has been updated
self.assertTrue(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=mb.full_address,
address=mb.full_address,
alias__internal=True,
)
.exists()
)
self.ajax_post(reverse("admin:account_delete", args=[account.id]), {})
# Check if self alias has been deleted
self.assertFalse(
models.AliasRecipient.objects.select_related("alias")
.filter(
alias__address=mb.full_address,
address=mb.full_address,
alias__internal=True,
)
.exists()
)
@override_settings(LANGUAGE_CODE="fr")
def test_create_account_default_lang(self):
"""Check if default language is applied."""
values = {
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "tester@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username=values["username"])
self.assertEqual(account.language, "fr")
def test_create_account_with_existing_alias(self):
alias = models.Alias.objects.get(address="alias@test.com")
alias.set_recipients(["user@external.com"])
values = {
"email": "tester@test.com",
"username": "tester@test.com",
"role": "SimpleUsers",
"random_password": "on",
"quota_act": True,
"is_active": True,
"stepid": "step2",
"aliases": "alias@test.com",
}
self.ajax_post(reverse("admin:account_add"), values)
self.assertTrue(alias.aliasrecipient_set.count() == 2)
def test_create_alias_on_existing_account(self):
values = {
"email": "tester@test.com",
"username": "tester@test.com",
"role": "SimpleUsers",
"random_password": "on",
"quota_act": True,
"is_active": True,
"stepid": "step2",
"aliases": "user@test.com",
}
self.ajax_post(reverse("admin:account_add"), values)
# Check that internal alias has not been updated
alias = models.Alias.objects.get(address="user@test.com", internal=True)
self.assertTrue(alias.aliasrecipient_set.count() == 1)
alias = models.Alias.objects.get(address="user@test.com", internal=False)
self.assertTrue(alias.aliasrecipient_set.count() == 1)
def test_create_disabled_account(self):
"""Check if account and alias are disabled."""
values = {
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": False,
"email": "tester@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username=values["username"])
self.assertEqual(account.enabled, False)
alias = models.Alias.objects.get(address=account.email)
self.assertEqual(alias.enabled, False)
def test_aliases_update_on_disable(self):
"""Check if aliases are updated when account is disabled."""
account = User.objects.get(username="user@test.com")
@@ -220,371 +72,6 @@ class AccountTestCase(ModoTestCase):
forward.refresh_from_db()
self.assertTrue(forward.enabled)
def test_aliases_update_on_rename(self):
"""Check if aliases are updated on mailbox rename."""
account = User.objects.get(username="user@test.com")
values = {
"username": "new_user@test.com",
"first_name": account.first_name,
"last_name": account.last_name,
"role": account.role,
"quota_act": True,
"is_active": account.is_active,
"email": "new_user@test.com",
"language": "en",
"subject": "subject",
"content": "content",
"create_alias_with_old_address": False,
"aliases_1": "alias@test.com",
}
url = reverse("admin:account_change", args=[account.pk])
self.ajax_post(url, values)
qset = account.mailbox.aliasrecipient_set.filter(alias__internal=False)
for alr in qset:
self.assertEqual(alr.address, values["email"])
def test_create_alias_on_rename(self):
"""Check if alias is automatically created."""
account = User.objects.get(username="user@test.com")
values = {
"username": "new_user@test.com",
"first_name": account.first_name,
"last_name": account.last_name,
"role": account.role,
"quota_act": True,
"is_active": account.is_active,
"email": "new_user@test.com",
"language": "en",
"subject": "subject",
"content": "content",
"create_alias_with_old_address": False,
}
url = reverse("admin:account_change", args=[account.pk])
# Rename while option is set to False -> no alias created
self.ajax_post(url, values)
self.assertFalse(
models.AliasRecipient.objects.filter(
address="new_user@test.com",
alias__address="user@test.com",
alias__internal=False,
).exists()
)
# Now rename while option set to True -> alias created
values.update(
{
"username": "user@test.com",
"email": "user@test.com",
"create_alias_with_old_address": True,
}
)
self.ajax_post(url, values)
self.assertTrue(
models.AliasRecipient.objects.filter(
address="user@test.com",
alias__address="new_user@test.com",
alias__internal=False,
).exists()
)
# Change domain while option set to True -> alias created
values.update(
{
"username": "new_user@test2.com",
"email": "new_user@test2.com",
}
)
self.ajax_post(url, values)
self.assertTrue(
models.AliasRecipient.objects.filter(
address="new_user@test2.com",
alias__address="user@test.com",
alias__domain__name="test.com",
alias__internal=False,
).exists()
)
def test_password_constraints(self):
"""Check password constraints."""
values = {
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "",
"password2": "",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "tester@test.com",
"stepid": "step2",
}
resp = self.ajax_post(reverse("admin:account_add"), values, 400)
self.assertEqual(resp["form_errors"]["password1"][0], "This field is required.")
values["password1"] = "Toto1234"
values["password2"] = "Toto12345"
resp = self.ajax_post(reverse("admin:account_add"), values, 400)
self.assertEqual(
resp["form_errors"]["password2"][0], "The two password fields didn't match."
)
values["password1"] = "toto1234"
values["password2"] = "toto1234"
resp = self.ajax_post(reverse("admin:account_add"), values, 400)
self.assertEqual(
resp["form_errors"]["password2"][0],
"Password must contain at least 1 uppercase letter.",
)
def test_random_password(self):
"""Try to create an account with a random password."""
values = {
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"random_password": True,
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "tester@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username=values["username"])
password = account.password
values["language"] = "en"
values["subject"] = "subject"
values["content"] = "content"
# Since 'random_password' is still True, a new password should
# be generated
self.ajax_post(reverse("admin:account_change", args=[account.pk]), values)
account.refresh_from_db()
self.assertNotEqual(password, account.password)
password = account.password
values["random_password"] = False
self.ajax_post(reverse("admin:account_change", args=[account.pk]), values)
account.refresh_from_db()
self.assertEqual(password, account.password)
def test_delete_default_superadmin(self):
"""Delete default superadmin."""
sadmin2 = core_factories.UserFactory(username="admin2", is_superuser=True)
sadmin = User.objects.get(username="admin")
self.client.force_login(sadmin2)
self.ajax_post(reverse("admin:account_delete", args=[sadmin.pk]), {})
values = {
"username": "user@test.com",
"role": "DomainAdmins",
"is_active": True,
"email": "user@test.com",
"language": "en",
"subject": "subject",
"content": "content",
}
account = User.objects.get(username="user@test.com")
self.ajax_post(reverse("admin:account_change", args=[account.pk]), values)
def test_sender_address(self):
"""Check if sender addresses are saved."""
account = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"first_name": "Tester",
"last_name": "Toto",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "user@test.com",
"senderaddress": "test@titi.com",
"senderaddress_1": "toto@go.com",
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[account.pk]), values)
self.assertEqual(
models.SenderAddress.objects.filter(mailbox__address="user").count(), 2
)
del values["senderaddress_1"]
self.ajax_post(reverse("admin:account_change", args=[account.pk]), values)
self.assertEqual(
models.SenderAddress.objects.filter(mailbox__address="user").count(), 1
)
def test_sender_address_as_domainadmin(self):
"""Check that restrictions are applied."""
admin = User.objects.get(username="admin@test.com")
self.client.force_login(admin)
account = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"first_name": "Tester",
"last_name": "Toto",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "user@test.com",
"senderaddress": "test@titi.com",
"senderaddress_1": "toto@test2.com",
}
response = self.ajax_post(
reverse("admin:account_change", args=[account.pk]), values, 400
)
self.assertEqual(
response["form_errors"]["senderaddress_1"][0],
"You don't have access to this domain",
)
def test_conflicts(self):
"""Check if unicity constraints are respected."""
values = {
"username": "user@test.com",
"password1": "Toto1234",
"password2": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "user@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values, status=400)
values.update({"username": "fakeuser@test.com", "email": "fakeuser@test.com"})
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username="fakeuser@test.com")
values = {
"username": "user@test.com",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "user@test.com",
}
self.ajax_post(
reverse("admin:account_change", args=[account.pk]), values, status=400
)
def test_utf8_username(self):
"""Create an account with non-ASCII characters."""
values = {
"username": "téster@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "téster@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
def _set_quota(self, email, value, expected_status=200):
account = User.objects.get(username=email)
values = {
"username": email,
"role": "SimpleUsers",
"quota_act": False,
"is_active": True,
"quota": value,
"email": email,
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(
reverse("admin:account_change", args=[account.id]),
values,
status=expected_status,
)
def test_set_nul_quota_as_superadmin(self):
self._set_quota("user@test.com", 0)
def test_set_nul_quota_as_domainadmin(self):
"""Check cases where a domain admin set unlimited quota."""
self.client.logout()
self.assertTrue(self.client.login(username="admin@test.com", password="toto"))
# Fails because domain has a quota
self._set_quota("user@test.com", 0, 400)
self.client.logout()
self.assertTrue(self.client.login(username="admin@test2.com", password="toto"))
# Ok because domain has no quota
self._set_quota("user@test2.com", 0)
def test_domain_quota(self):
"""Check domain quota."""
dom = models.Domain.objects.get(name="test.com")
dom.quota = 100
dom.save(update_fields=["quota"])
# 2 x 10MB
self.assertEqual(dom.allocated_quota, 20)
self._set_quota("user@test.com", 80)
del dom.allocated_quota
# 10 + 80 < 100 => ok
self.assertEqual(dom.allocated_quota, 90)
# 30 + 80 > 100 => failure
self._set_quota("admin@test.com", 30, 400)
def test_master_user(self):
"""Validate the master user mode."""
values = {
"username": "masteruser",
"role": "SuperAdmins",
"quota_act": False,
"is_active": True,
"master_user": True,
"stepid": "step2",
"password1": "Toto1234",
"password2": "Toto1234",
}
self.ajax_post(reverse("admin:account_add"), values)
self.assertTrue(User.objects.get(username="masteruser").master_user)
values = {
"username": "testuser",
"role": "DomainAdmins",
"quota_act": False,
"is_active": True,
"master_user": True,
"stepid": "step2",
"password1": "Toto1234",
"password2": "Toto1234",
}
self.ajax_post(reverse("admin:account_add"), values, status=400)
def test_account_detail_view(self):
"""Test account detail view."""
self.set_global_parameter("enable_admin_limits", False, app="limits")
account = User.objects.get(username="admin@test.com")
url = reverse("admin:account_detail", args=[account.pk])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Summary", response.content.decode())
self.assertIn("Administered domains", response.content.decode())
self.assertNotIn("Resources usage", response.content.decode())
self.set_global_parameter("enable_admin_limits", True, app="limits")
response = self.client.get(url)
self.assertIn("Resources usage", response.content.decode())
def test_quota_list_view(self):
"""Test quota list view."""
models.Quota.objects.filter(username="user@test.com").update(bytes=5 * 1048576)
url = reverse("admin:identity_quota_list")
response = self.ajax_get(url)
self.assertIn("5M", response["rows"])
self.assertIn('title="50%"', response["rows"])
self.assertIn("user@test.com", response["rows"])
old_rows = response["rows"]
response = self.ajax_get(f"{url}?sort_order=-quota_value__bytes")
self.assertNotEqual(old_rows, response["rows"])
old_rows = response["rows"]
response = self.ajax_get(f"{url}?sort_order=-quota_usage")
self.assertEqual(old_rows, response["rows"])
response = self.ajax_get(f"{url}?sort_order=-unknown", status=400)
@skipIf(NO_LDAP, "No ldap module installed")
@override_settings(
@@ -593,7 +80,7 @@ class AccountTestCase(ModoTestCase):
"django.contrib.auth.backends.ModelBackend",
)
)
class LDAPAccountTestCase(test_ldap.LDAPTestCaseMixin, ModoTestCase):
class LDAPAccountTestCase(test_ldap.LDAPTestCaseMixin, ModoAPITestCase):
"""Check LDAP related code."""
def test_autocreate_disabled(self):
@@ -607,7 +94,7 @@ class LDAPAccountTestCase(test_ldap.LDAPTestCaseMixin, ModoTestCase):
self.assertFalse(models.Mailbox.objects.filter(address="testuser").exists())
class PermissionsTestCase(ModoTestCase):
class PermissionsTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
@@ -630,32 +117,34 @@ class PermissionsTestCase(ModoTestCase):
"username": self.user.username,
"role": "DomainAdmins",
"is_active": self.user.is_active,
"email": "user@test.com",
"quota_act": True,
"mailbox": {
"use_domain_quota": True,
},
"language": "en",
"subject": "subject",
"content": "content",
}
def tearDown(self):
self.client.logout()
def test_domain_admins(self):
factories.DomainFactory(name="test2.com")
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertEqual(self.user.role, "DomainAdmins")
self.values["mailboxes_limit"] = "0"
self.values["mailbox_aliases_limit"] = "0"
self.values["domains"] = ""
self.values["domains_1"] = "test.com"
self.values["domains_2"] = "test2.com"
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
self.values["resources"] = [
{"name": "mailboxes", "max_value": 0},
{"name": "mailbox_aliases", "max_value": 0},
]
self.values["domains"] = ["test.com", "test2.com"]
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertIn(
self.user, models.Domain.objects.get(name="test.com").admins.all()
)
@@ -663,10 +152,13 @@ class PermissionsTestCase(ModoTestCase):
self.user, models.Domain.objects.get(name="test2.com").admins.all()
)
del self.values["domains_2"]
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
self.values["domains"].remove("test2.com")
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertIn(
self.user, models.Domain.objects.get(name="test.com").admins.all()
)
@@ -675,9 +167,12 @@ class PermissionsTestCase(ModoTestCase):
)
self.values["role"] = "SimpleUsers"
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertFalse(self.user.groups.filter(name="DomainAdmins").exists())
self.assertNotIn(
self.user, models.Domain.objects.get(name="test.com").admins.all()
@@ -685,74 +180,72 @@ class PermissionsTestCase(ModoTestCase):
def test_superusers(self):
self.values["role"] = "SuperAdmins"
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertEqual(User.objects.get(username="user@test.com").is_superuser, True)
self.values["role"] = "SimpleUsers"
self.ajax_post(
reverse("admin:account_change", args=[self.user.id]), self.values
response = self.client.put(
reverse("v2:account-detail", args=[self.user.id]),
self.values,
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertEqual(User.objects.get(username="user@test.com").is_superuser, False)
def test_self_modif(self):
self.client.logout()
self.assertTrue(self.client.login(username="admin@test.com", password="toto"))
admin = User.objects.get(username="admin@test.com")
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
values = {
"username": "admin@test.com",
"first_name": "Admin",
"password1": "",
"password2": "",
"quota": 10,
"role": "DomainAdmins",
"mailbox": {
"quota": 10,
},
"is_active": True,
"email": "admin@test.com",
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[admin.id]), values)
self.assertEqual(admin.role, "DomainAdmins")
self.assertTrue(admin.can_access(models.Domain.objects.get(name="test.com")))
response = self.client.put(
reverse("v2:account-detail", args=[dadmin.id]), values, format="json"
)
print(response.json())
self.assertEqual(response.status_code, 200)
self.assertEqual(dadmin.role, "DomainAdmins")
self.assertTrue(dadmin.can_access(models.Domain.objects.get(name="test.com")))
values["role"] = "SuperAdmins"
self.ajax_post(reverse("admin:account_change", args=[admin.id]), values)
admin.refresh_from_db()
self.assertEqual(admin.role, "DomainAdmins")
response = self.client.put(
reverse("v2:account-detail", args=[dadmin.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
dadmin.refresh_from_db()
self.assertEqual(dadmin.role, "DomainAdmins")
self.client.logout()
self.client.login(username=self.reseller.username, password="toto")
self.authenticate_user(self.reseller)
self.assertTrue(self.reseller.can_access(self.reseller))
values = {
"username": self.reseller.username,
"first_name": "Reseller",
"password1": "",
"password2": "",
"is_active": True,
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[self.reseller.pk]), values)
response = self.client.put(
reverse("v2:account-detail", args=[self.reseller.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
self.assertEqual(self.reseller.role, "Resellers")
values["role"] = "SuperAdmins"
self.ajax_post(reverse("admin:account_change", args=[self.reseller.pk]), values)
self.assertEqual(self.reseller.role, "Resellers")
def test_domadmin_access(self):
self.client.logout()
self.assertEqual(
self.client.login(username="admin@test.com", password="toto"), True
response = self.client.put(
reverse("v2:account-detail", args=[self.reseller.id]), values, format="json"
)
response = self.client.get(reverse("admin:domain_list"))
self.assertEqual(response.status_code, 200)
response = self.client.get(
reverse("admin:account_change", args=[self.user.id]),
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertNotEqual(response["Content-Type"], "application/json")
self.assertEqual(self.reseller.role, "Resellers")
def test_domainadmin_deletes_superadmin(self):
"""Check domain admins restrictions about super admins
@@ -765,45 +258,51 @@ class PermissionsTestCase(ModoTestCase):
"username": "superadmin2@test.com",
"first_name": "Super",
"last_name": "Admin",
"password1": "Toto1234",
"password2": "Toto1234",
"password": "Toto1234",
"role": "SuperAdmins",
"is_active": True,
"email": "superadmin2@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
response = self.client.post(reverse("v2:account-list"), values, format="json")
self.assertEqual(response.status_code, 201)
account = User.objects.get(username="superadmin2@test.com")
self.client.logout()
self.client.login(username="admin@test.com", password="toto")
self.ajax_post(reverse("admin:account_delete", args=[account.id]), {}, 403)
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
response = self.client.post(
reverse("v2:account-delete", args=[account.id]), {}, format="json"
)
self.assertEqual(response.status_code, 404)
def test_domainadmin_dlist_local_domain_not_owned(self):
"""Check if a domain admin can use a local mailbox he can't
access as a recipient in a distribution list"""
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
values = {
"address": "all@test.com",
"recipients": "user@test.com",
"recipients_1": "user@test2.com",
"recipients": ["user@test.com", "user@test2.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
def test_domainadmin_master_user(self):
"""Check domain administrator is not allowed to access this feature."""
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
values = {
"username": "user10@test.com",
"first_name": "Test",
"last_name": "Test",
"password1": "Toto1234",
"password2": "Toto1234",
"password": "Toto1234",
"role": "SimpleUsers",
"is_active": True,
"master_user": True,
"email": "user10@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values, status=400)
response = self.client.post(reverse("v2:account-list"), values, format="json")
self.assertEqual(response.status_code, 201)
user = User.objects.get(username="user10@test.com")
self.assertFalse(user.master_user)
def test_domadmins_permissions(self):
"""
@@ -819,19 +318,16 @@ class PermissionsTestCase(ModoTestCase):
user__password="{PLAIN}toto",
)
dom.add_admin(mb.user)
self.client.logout()
self.assertTrue(self.client.login(username="admin@test.com", password="toto"))
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
values = {
"username": "new@test.com",
"password1": "Toto1234",
"password2": "Toto1234",
"password": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"mailbox": {"use_domain_quota": True},
"is_active": True,
"email": "new@test.com",
"stepid": "step2",
}
self.ajax_post(reverse("admin:account_add"), values)
self.client.post(reverse("v2:account-list"), values, format="json")
new_mb = models.Mailbox.objects.get(user__username="new@test.com")
self.assertTrue(mb.user.can_access(new_mb))
+64 -160
View File
@@ -3,12 +3,12 @@
from django.urls import reverse
from modoboa.core.models import User
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase
from .. import factories
from ..models import Alias, AliasRecipient, Domain
from ..models import Alias, AliasRecipient
class AliasTestCase(ModoTestCase):
class AliasTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
@@ -16,44 +16,15 @@ class AliasTestCase(ModoTestCase):
super().setUpTestData()
factories.populate_database()
def test_alias(self):
user = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"role": user.role,
"is_active": user.is_active,
"email": "user@test.com",
"aliases": "toto@test.com",
"aliases_1": "titi@test.com",
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[user.id]), values)
self.assertEqual(
AliasRecipient.objects.filter(
alias__internal=False, r_mailbox=user.mailbox
).count(),
2,
)
del values["aliases_1"]
self.ajax_post(reverse("admin:account_change", args=[user.id]), values)
self.assertEqual(
AliasRecipient.objects.filter(
alias__internal=False, r_mailbox=user.mailbox
).count(),
1,
)
def test_alias_with_duplicated_recipient(self):
"""Check for duplicates."""
values = {
"address": "badalias@test.com",
"recipients": "user@test.com",
"recipients_1": "user@test.com",
"recipients": ["user@test.com", "user@test.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
alias = Alias.objects.get(address="badalias@test.com")
self.assertEqual(alias.recipients_count, 1)
@@ -61,56 +32,32 @@ class AliasTestCase(ModoTestCase):
"""Try to create an upper case alias."""
user = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"role": user.role,
"is_active": user.is_active,
"email": "user@test.com",
"aliases": "Toto@test.com",
"language": "en",
"subject": "subject",
"content": "content",
"address": "Toto@test.com",
"recipients": ["user@test.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:account_change", args=[user.id]), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
mb = user.mailbox
self.assertEqual(
AliasRecipient.objects.filter(alias__internal=False, r_mailbox=mb).count(),
1,
2,
)
self.assertEqual(
AliasRecipient.objects.get(
alias__internal=False, r_mailbox=mb
).alias.address,
"toto@test.com",
self.assertTrue(
AliasRecipient.objects.filter(
alias__internal=False, r_mailbox=mb, alias__address="toto@test.com"
).exists()
)
values = {
"address": "Titi@test.com",
"recipients": "user@test.com",
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
self.assertTrue(Alias.objects.filter(address="titi@test.com").exists())
def test_append_alias_with_tag(self):
"""Try to create a alias with tag in recipient address"""
user = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"role": user.role,
"is_active": user.is_active,
"email": "user@test.com",
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[user.id]), values)
values = {
"address": "foobar@test.com",
"recipients": "user+spam@test.com",
"recipients": ["user+spam@test.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
alias = Alias.objects.get(address="foobar@test.com")
self.assertTrue(
alias.aliasrecipient_set.filter(
@@ -124,22 +71,20 @@ class AliasTestCase(ModoTestCase):
"""Test alias with non-ASCII characters."""
values = {
"address": "testé@test.com",
"recipients": "user@test.com",
"recipients_1": "admin@test.com",
"recipients_2": "ext@titi.com",
"recipients": ["user@test.com", "admin@test.com", "ext@titi.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertTrue(response.status_code, 201)
def test_dlist(self):
values = {
"address": "all@test.com",
"recipients": "user@test.com",
"recipients_1": "admin@test.com",
"recipients_2": "ext@titi.com",
"recipients": ["user@test.com", "admin@test.com", "ext@titi.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
user = User.objects.get(username="user@test.com")
mb = user.mailbox
self.assertEqual(
@@ -154,39 +99,29 @@ class AliasTestCase(ModoTestCase):
)
dlist = Alias.objects.get(address="all@test.com")
self.assertEqual(dlist.recipients_count, 3)
del values["recipients_1"]
self.ajax_post(reverse("admin:alias_change", args=[dlist.id]), values)
values["recipients"].remove("admin@test.com")
response = self.client.put(
reverse("v2:alias-detail", args=[dlist.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
self.assertEqual(dlist.recipients_count, 2)
self.ajax_delete(
"{}?selection={}".format(reverse("admin:alias_delete"), dlist.id)
)
self.assertRaises(Alias.DoesNotExist, Alias.objects.get, address="all@test.com")
def test_forward(self):
values = {"address": "forward2@test.com", "recipients": "rcpt@dest.com"}
self.ajax_post(reverse("admin:alias_add"), values)
fwd = Alias.objects.get(address="forward2@test.com")
self.assertEqual(fwd.recipients_count, 1)
values["recipients"] = "rcpt2@dest.com"
self.ajax_post(reverse("admin:alias_change", args=[fwd.id]), values)
self.assertEqual(fwd.recipients_count, 1)
self.ajax_delete(reverse("admin:alias_delete") + f"?selection={fwd.id}", {})
self.assertRaises(
Alias.DoesNotExist, Alias.objects.get, address="forward2@test.com"
)
def test_forward_and_local_copies(self):
values = {"address": "user@test.com", "recipients": "rcpt@dest.com"}
self.ajax_post(reverse("admin:alias_add"), values)
values = {
"address": "user@test.com",
"recipients": ["rcpt@dest.com"],
"enabled": True,
}
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
fwd = Alias.objects.get(address="user@test.com", internal=False)
self.assertEqual(fwd.recipients_count, 1)
values["recipients"] = "rcpt@dest.com"
values["recipients_1"] = "user@test.com"
self.ajax_post(reverse("admin:alias_change", args=[fwd.id]), values)
values["recipients"] = ["rcpt@dest.com", "user@test.com"]
response = self.client.put(
reverse("v2:alias-detail", args=[fwd.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
fwd = Alias.objects.get(pk=fwd.pk)
self.assertEqual(fwd.aliasrecipient_set.count(), 2)
self.assertEqual(fwd.aliasrecipient_set.filter(r_alias__isnull=True).count(), 2)
@@ -195,26 +130,11 @@ class AliasTestCase(ModoTestCase):
"""Test creation of a wildcard alias."""
values = {
"address": "@test.com",
"recipients": "user@test.com",
"recipients": ["user@test.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
def test_random_alias(self):
"""Test creation of a random alias."""
alias_count = Alias.objects.count()
values = {
"random_address": True,
"domain": Domain.objects.get(name="test.com").pk,
"recipients": "user@test.com",
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
self.assertEqual(Alias.objects.count(), alias_count + 1)
del values["domain"]
content = self.ajax_post(reverse("admin:alias_add"), values, 400)
self.assertIn("domain", content["form_errors"])
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
def test_distribution_list_deletion_on_user_update_bug(self):
"""This test demonstrates an issue with distribution list being
@@ -224,61 +144,45 @@ class AliasTestCase(ModoTestCase):
"""
values = {
"address": "list@test.com",
"recipients": "user@test.com",
"recipients_1": "admin@test.com",
"recipients": ["user@test.com", "admin@test.com"],
"enabled": True,
}
self.ajax_post(reverse("admin:alias_add"), values)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 201)
user = User.objects.get(username="user@test.com")
values = {
"username": user.username,
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"password": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"mailbox": {
"use_domain_quota": True,
},
"is_active": True,
"email": user.email,
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[user.id]), values)
self.assertEqual(Alias.objects.filter(address="list@test.com").count(), 1)
def test_alias_detail_view(self):
"""Test alias detail view."""
account = Alias.objects.get(address="postmaster@test.com")
url = reverse("admin:alias_detail", args=[account.pk])
response = self.client.get(url)
response = self.client.put(
reverse("v2:account-detail", args=[user.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
self.assertIn("Summary", response.content.decode())
self.assertIn("Recipients", response.content.decode())
self.assertTrue(Alias.objects.filter(address="list@test.com").exists())
def test_domainadmin_restrictions(self):
"""Check that restrictions are applied."""
admin = User.objects.get(username="admin@test.com")
self.client.force_login(admin)
self.authenticate_user(admin)
user = User.objects.get(username="user@test.com")
values = {
"username": "user@test.com",
"role": user.role,
"is_active": user.is_active,
"email": "user@test.com",
"aliases": "toto@test.com",
"aliases_1": "titi@test2.com",
"language": "en",
"subject": "subject",
"content": "content",
"address": "titi@test2.com",
"recipients": ["user@test.com"],
"enabled": True,
}
response = self.ajax_post(
reverse("admin:account_change", args=[user.id]), values, 400
)
response = self.client.post(reverse("v2:alias-list"), values, format="json")
self.assertEqual(response.status_code, 400)
self.assertEqual(
response["form_errors"]["aliases_1"][0],
"You don't have access to this domain",
response.json()["address"][0],
"Permission denied.",
)
+44 -376
View File
@@ -3,30 +3,21 @@
import os
import shutil
import tempfile
from unittest import mock
from dateutil.relativedelta import relativedelta
import dns.resolver
from testfixtures import compare
from django.core.management import call_command
from django.urls import reverse
from django.utils import timezone
from django.utils.html import escape
from modoboa.core import factories as core_factories
from modoboa.core.models import User
from modoboa.core.tests.test_views import SETTINGS_SAMPLE
from modoboa.lib.tests import ModoTestCase
from modoboa.maillog import factories as ml_factories
from modoboa.lib.tests import ModoAPITestCase, SETTINGS_SAMPLE
from .. import constants
from . import utils
from .. import factories
from ..models import Alarm, Alias, Domain
class DomainTestCase(ModoTestCase):
class DomainTestCase(ModoAPITestCase):
"""Test case for Domain."""
@classmethod
@@ -35,135 +26,21 @@ class DomainTestCase(ModoTestCase):
super().setUpTestData()
factories.populate_database()
def test_create(self):
"""Test the creation of a domain."""
values = {
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": False,
"type": "domain",
"stepid": "step3",
}
self.ajax_post(reverse("admin:domain_add"), values)
dom = Domain.objects.get(name="pouet.com")
self.assertEqual(dom.name, "pouet.com")
self.assertEqual(dom.quota, 1000)
self.assertEqual(dom.default_mailbox_quota, 100)
self.assertEqual(dom.enabled, False)
self.assertFalse(dom.admins)
def test_create_utf8(self):
"""Test the creation of a domain with non-ASCII characters."""
values = {
"name": "pouét.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": False,
"type": "domain",
"stepid": "step3",
}
self.ajax_post(reverse("admin:domain_add"), values)
dom = Domain.objects.get(name="pouét.com")
self.assertEqual(dom.name, "pouét.com")
self.assertEqual(dom.quota, 1000)
self.assertEqual(dom.default_mailbox_quota, 100)
self.assertEqual(dom.enabled, False)
self.assertFalse(dom.admins)
def test_create_with_template(self):
"""Test the creation of a domain with a template."""
values = {
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": True,
"dom_admin_username": "toto",
"with_mailbox": True,
"create_aliases": True,
"type": "domain",
"stepid": "step3",
}
self.ajax_post(reverse("admin:domain_add"), values)
dom = Domain.objects.get(name="pouet.com")
da = User.objects.get(username="toto@pouet.com")
self.assertIn(da, dom.admins)
al = Alias.objects.get(address="postmaster@pouet.com")
self.assertTrue(al.aliasrecipient_set.filter(r_mailbox=da.mailbox).exists())
self.assertTrue(da.can_access(al))
values = {
"name": "pouet2.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": True,
"dom_admin_username": "postmaster",
"create_aliases": True,
"type": "domain",
"stepid": "step3",
"with_mailbox": True,
}
self.ajax_post(reverse("admin:domain_add"), values)
self.assertTrue(User.objects.filter(username="postmaster@pouet2.com").exists())
self.assertFalse(
Alias.objects.filter(
address="postmaster@pouet2.com", internal=False
).exists()
)
def test_create_with_template_and_random_password(self):
"""Test domain creation with administrator and random password."""
values = {
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": True,
"dom_admin_username": "toto",
"with_mailbox": True,
"create_aliases": True,
"type": "domain",
"stepid": "step3",
"random_password": True,
}
self.ajax_post(reverse("admin:domain_add"), values)
self.assertFalse(
self.client.login(username="admin@pouet.com", password="password")
)
def test_create_with_template_and_no_mailbox(self):
"""Test domain creation with administrator but no mailbox."""
values = {
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": True,
"dom_admin_username": "toto",
"with_mailbox": False,
"create_aliases": True,
"type": "domain",
"stepid": "step3",
}
self.ajax_post(reverse("admin:domain_add"), values)
dom = Domain.objects.get(name="pouet.com")
da = User.objects.get(username="toto@pouet.com")
self.assertIn(da, dom.admins)
self.assertFalse(hasattr(da, "mailbox"))
self.assertFalse(Alias.objects.filter(address="postmaster@pouet.com").exists())
def test_create_with_template_and_empty_quota(self):
"""Test the creation of a domain with a template and no quota"""
values = {
"name": "pouet.com",
"quota": 0,
"default_mailbox_quota": 0,
"create_dom_admin": True,
"dom_admin_username": "toto",
"create_aliases": True,
"domain_admin": {
"username": "toto",
"with_mailbox": True,
"with_aliases": True,
},
"type": "domain",
"stepid": "step3",
"with_mailbox": True,
}
self.ajax_post(reverse("admin:domain_add"), values)
response = self.client.post(reverse("v2:domain-list"), values, format="json")
self.assertEqual(response.status_code, 201)
dom = Domain.objects.get(name="pouet.com")
da = User.objects.get(username="toto@pouet.com")
self.assertIn(da, dom.admins)
@@ -171,45 +48,23 @@ class DomainTestCase(ModoTestCase):
self.assertTrue(al.aliasrecipient_set.filter(r_mailbox=da.mailbox).exists())
self.assertTrue(da.can_access(al))
def test_create_with_template_and_custom_password(self):
"""Test creation of a domain with a template and custom password."""
password = "Toto1000"
self.set_global_parameter("default_password", password, app="core")
values = {
"name": "pouet.com",
"quota": 0,
"default_mailbox_quota": 0,
"create_dom_admin": True,
"dom_admin_username": "toto",
"create_aliases": True,
"type": "domain",
"stepid": "step3",
"with_mailbox": True,
}
self.ajax_post(reverse("admin:domain_add"), values)
dom = Domain.objects.get(name="pouet.com")
da = User.objects.get(username="toto@pouet.com")
self.assertIn(da, dom.admins)
al = Alias.objects.get(address="postmaster@pouet.com")
self.assertTrue(al.aliasrecipient_set.filter(r_mailbox=da.mailbox).exists())
self.assertTrue(da.can_access(al))
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,
"domain_admin": {
"username": "toto",
"with_mailbox": True,
"with_aliases": True,
},
"type": "domain",
"stepid": "step3",
}
response = self.ajax_post(reverse("admin:domain_add"), values, status=400)
response = self.client.post(reverse("v2:domain-list"), values, format="json")
self.assertEqual(response.status_code, 400)
self.assertEqual(
response["form_errors"]["default_mailbox_quota"][0],
response.json()["default_mailbox_quota"][0],
"Cannot be greater than domain quota",
)
@@ -217,91 +72,15 @@ class DomainTestCase(ModoTestCase):
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
response = self.client.put(
reverse("v2:domain-detail", args=[dom.pk]), values, format="json"
)
self.assertEqual(response.status_code, 400)
self.assertEqual(
response["form_errors"]["default_mailbox_quota"][0],
response.json()["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)
self.set_global_parameter("default_mailbox_quota", 50)
response = self.client.get(reverse("admin:domain_add"))
self.assertContains(response, 'value="500"')
self.assertContains(response, 'value="50"')
@mock.patch.object(dns.resolver.Resolver, "resolve")
@mock.patch("socket.getaddrinfo")
def test_create_and_check_mx(self, mock_getaddrinfo, mock_query):
"""Check for authorized MX record."""
mock_query.side_effect = utils.mock_dns_query_result
mock_getaddrinfo.side_effect = utils.mock_ip_query_result
reseller = core_factories.UserFactory(
username="reseller", groups=("Resellers",)
)
self.client.force_login(reseller)
self.set_global_parameter("enable_admin_limits", False, app="limits")
self.set_global_parameter("valid_mxs", "192.0.2.1 2001:db8::1")
self.set_global_parameter("domains_must_have_authorized_mx", True)
values = {
"name": "no-mx.example.com",
"quota": 0,
"default_mailbox_quota": 0,
"create_dom_admin": True,
"dom_admin_username": "toto",
"create_aliases": True,
"type": "domain",
"stepid": "step3",
"with_mailbox": True,
}
self.ajax_post(reverse("admin:domain_add"), values, 400)
self.assertFalse(Domain.objects.filter(name=values["name"]).exists())
values["name"] = "pouet.com"
mock_getaddrinfo.side_effect = utils.mock_ip_query_result
self.ajax_post(reverse("admin:domain_add"), values)
def test_modify(self):
"""Test the modification of a domain
Rename 'test.com' domain to 'pouet.com'
"""
values = {
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"type": "domain",
"enabled": True,
}
dom = Domain.objects.get(name="test.com")
self.ajax_post(reverse("admin:domain_change", args=[dom.id]), values)
dom = Domain.objects.get(name="pouet.com")
self.assertEqual(dom.name, "pouet.com")
self.assertTrue(dom.enabled)
# Check if aliases were renamed too
self.assertTrue(dom.alias_set.filter(address="postmaster@pouet.com").exists())
def test_delete(self):
"""Test the removal of a domain."""
dom = Domain.objects.get(name="test.com")
self.ajax_post(reverse("admin:domain_delete", args=[dom.id]))
with self.assertRaises(Domain.DoesNotExist):
Domain.objects.get(pk=1)
self.assertTrue(User.objects.filter(username="user@test.com").exists())
self.set_global_parameter("auto_account_removal", True)
dom = Domain.objects.get(name="test2.com")
self.ajax_post(reverse("admin:domain_delete", args=[dom.id]))
with self.assertRaises(Domain.DoesNotExist):
Domain.objects.get(pk=1)
self.assertFalse(User.objects.filter(username="admin@test2.com").exists())
def test_domain_counters(self):
"""Check counters at domain level."""
domain = Domain.objects.get(name="test.com")
@@ -310,122 +89,8 @@ class DomainTestCase(ModoTestCase):
self.assertEqual(domain.mbalias_count, 3)
self.assertEqual(domain.identities_count, 5)
def test_domain_flat_list(self):
"""Test the 'domain_flat_list' view."""
response = self.client.get(reverse("admin:domain_flat_list"))
self.assertEqual(response.status_code, 200)
content = response.json()
self.assertIn("test.com", content)
self.assertIn("test2.com", content)
def test_domain_detail_view(self):
"""Test Domain detail view."""
self.set_global_parameter("enable_domain_limits", False, app="limits")
domain = Domain.objects.get(name="test.com")
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Summary", response.content.decode())
self.assertIn("Administrators", response.content.decode())
self.assertIn("Usage", response.content.decode())
self.assertNotIn("Resources usage", response.content.decode())
self.set_global_parameter("enable_domain_limits", True, app="limits")
response = self.client.get(url)
self.assertIn("Resources usage", response.content.decode())
# Try a domain with no quota
domain = Domain.objects.filter(quota=0).first()
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertNotIn("Usage", response.content.decode())
# Try with a fresh domain (see #1174)
domain = factories.DomainFactory(name="simpson.com", quota=100)
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Usage", response.content.decode())
user = User.objects.get(username="user@test.com")
self.client.force_login(user)
domain = Domain.objects.get(name="test2.com")
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertEqual(response.status_code, 403)
def test_domain_quota_list_view(self):
"""Test quota list view."""
factories.DomainFactory(name="test3.com", quota=100)
url = reverse("admin:domain_quota_list")
response = self.ajax_get(url)
self.assertIn("50M", response["rows"])
self.assertIn('title="40% (20 MB) allocated"', response["rows"])
self.assertIn("test.com", response["rows"])
old_rows = response["rows"]
response = self.ajax_get(f"{url}?sort_order=-name")
self.assertNotEqual(old_rows, response["rows"])
response = self.ajax_get(f"{url}?sort_order=allocated_quota")
self.assertNotEqual(old_rows, response["rows"])
def test_domain_logs_list_view(self):
"""Test logs list view."""
domain = Domain.objects.get(name="test.com")
ml_factories.MaillogFactory(from_domain=domain)
ml_factories.MaillogFactory(
to_domain=domain,
status="received",
date=timezone.now() + relativedelta(days=1),
)
ml_factories.MaillogFactory(date=timezone.now() + relativedelta(days=2))
ml_factories.MaillogFactory(date=timezone.now() + relativedelta(days=3))
url = reverse("admin:domain_logs_list")
response = self.ajax_get(url)
self.assertIn("ID1", response["rows"])
old_rows = response["rows"]
response = self.ajax_get(f"{url}?sort_order=-sender")
self.assertNotEqual(old_rows, response["rows"])
response = self.ajax_get(f"{url}?searchquery=ID1")
self.assertNotEqual(old_rows, response["rows"])
admin = User.objects.get(username="admin@test.com")
self.client.force_login(admin)
url = reverse("admin:domain_logs_list")
response = self.ajax_get(url)
self.assertNotEqual(old_rows, response["rows"])
def test_statitics_widget(self):
"""Test statistics display in dashboard."""
url = reverse("core:dashboard")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Global statistics", response.content.decode("utf-8"))
self.client.force_login(User.objects.get(username="admin@test.com"))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
content = response.content.decode("utf-8")
self.assertNotIn("Global statistics", content)
self.assertIn("Per-domain statistics", content)
def test_page_loader(self):
"""Test page loader view."""
factories.AlarmFactory(
domain__name="test.com", mailbox=None, title="Test alarm"
)
url = reverse("admin:domain_page")
response = self.ajax_get(url)
self.assertIn("handle_mailboxes", response)
self.assertIn("listalarms", response["rows"])
response = self.ajax_get(f"{url}?objtype=quota")
self.assertIn("progress-bar", response["rows"])
class DKIMTestCase(ModoTestCase):
class DKIMTestCase(ModoAPITestCase):
"""Test case for DKIM."""
@classmethod
@@ -443,10 +108,10 @@ class DKIMTestCase(ModoTestCase):
def test_global_settings(self):
"""Check validation rules."""
url = reverse("core:parameters")
url = reverse("v2:parameter-global-detail", args=["admin"])
settings = SETTINGS_SAMPLE.copy()
settings["admin-dkim_keys_storage_dir"] = "/wrong"
response = self.client.post(url, settings, format="json")
settings["dkim_keys_storage_dir"] = "/wrong"
response = self.client.put(url, settings, format="json")
self.assertEqual(response.status_code, 400)
compare(
response.json(),
@@ -465,26 +130,27 @@ class DKIMTestCase(ModoTestCase):
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": False,
"type": "domain",
"stepid": "step3",
"enable_dkim": True,
"dkim_key_selector": "",
}
response = self.ajax_post(reverse("admin:domain_add"), values, 400)
url = reverse("v2:domain-list")
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 400)
self.assertEqual(
response["form_errors"]["enable_dkim"][0],
response.json()["enable_dkim"][0],
"DKIM keys storage directory not configured",
)
self.set_global_parameter("dkim_keys_storage_dir", self.workdir)
response = self.ajax_post(reverse("admin:domain_add"), values, 400)
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 400)
self.assertEqual(
response["form_errors"]["dkim_key_selector"][0], "This field is required."
response.json()["dkim_key_selector"][0], "This field is required."
)
values["dkim_key_selector"] = "default"
self.ajax_post(reverse("admin:domain_add"), values)
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 201)
# Try generating a key to a protected directory
self.set_global_parameter("dkim_keys_storage_dir", "/I_DONT_EXIST")
@@ -516,9 +182,6 @@ class DKIMTestCase(ModoTestCase):
self.assertTrue(os.path.exists(key_path))
domain.refresh_from_db()
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertContains(response, escape(domain.bind_format_dkim_public_key))
# Try generating DKIM key for a targetted domain
domain.dkim_private_key_path = ""
@@ -536,7 +199,9 @@ class DKIMTestCase(ModoTestCase):
"default_mailbox_quota": 100,
"type": "domain",
}
self.ajax_post(reverse("admin:domain_change", args=[domain.id]), values)
response = self.client.put(
reverse("v2:domain-detail", args=[domain.id]), values, format="json"
)
domain.refresh_from_db()
self.assertEqual(domain.dkim_private_key_path, "")
@@ -547,19 +212,22 @@ class DKIMTestCase(ModoTestCase):
"name": "pouet.com",
"quota": 1000,
"default_mailbox_quota": 100,
"create_dom_admin": False,
"type": "domain",
"stepid": "step3",
"enable_dkim": True,
"dkim_key_selector": "default",
}
self.ajax_post(reverse("admin:domain_add"), values)
url = reverse("v2:domain-list")
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 201)
call_command("modo", "manage_dkim_keys")
key_path = os.path.join(self.workdir, "{}.pem".format(values["name"]))
self.assertTrue(os.path.exists(key_path))
dom = Domain.objects.get(name="pouet.com")
values["dkim_key_length"] = 4096
self.ajax_post(reverse("admin:domain_change", args=[dom.pk]), values)
response = self.client.put(
reverse("v2:domain-detail", args=[dom.id]), values, format="json"
)
self.assertEqual(response.status_code, 200)
dom.refresh_from_db()
self.assertEqual(dom.dkim_private_key_path, "")
os.unlink(key_path)
-20
View File
@@ -1,5 +1,3 @@
from django.urls import reverse
from modoboa.lib.tests import ModoTestCase
from .. import factories
from ..models import Alias, Domain, DomainAlias
@@ -28,21 +26,3 @@ class DomainAliasTestCase(ModoTestCase):
domal.delete()
self.assertFalse(Alias.objects.filter(address=f"@{domal.name}").exists())
def test_form(self):
dom = Domain.objects.get(name="test.com")
values = {
"name": dom.name,
"quota": dom.quota,
"default_mailbox_quota": dom.default_mailbox_quota,
"enabled": dom.enabled,
"aliases": "domalias.net",
"aliases_1": "domaliasé.com",
"type": "domain",
}
self.ajax_post(reverse("admin:domain_change", args=[dom.id]), values)
self.assertEqual(dom.domainalias_set.count(), 2)
del values["aliases_1"]
self.ajax_post(reverse("admin:domain_change", args=[dom.id]), values)
self.assertEqual(dom.domainalias_set.count(), 1)
+48 -73
View File
@@ -7,11 +7,11 @@ from django.core.management import call_command
from django.urls import reverse
from django.utils.encoding import force_str
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase
from .. import factories, models
class ExportTestCase(ModoTestCase):
class ExportTestCase(ModoAPITestCase):
"""Test case for export operations."""
@classmethod
@@ -21,37 +21,20 @@ class ExportTestCase(ModoTestCase):
factories.populate_database()
def __export_domains(self, domfilter=""):
self.client.get(
"{}?domfilter={}".format(reverse("admin:_domain_list"), domfilter)
)
return self.client.post(
reverse("admin:domain_export"), {"filename": "test.csv"}
)
return self.client.get(reverse("v2:domain-export"))
def __export_identities(self, idtfilter="", grpfilter=""):
self.client.get(
reverse("admin:_identity_list")
+ f"?grpfilter={grpfilter}&idtfilter={idtfilter}"
)
return self.client.post(
reverse("admin:identity_export"), {"filename": "test.csv"}
)
return self.client.get(reverse("v2:identities-export"))
def test_export_domains(self):
def test_export_domains_management_command(self):
"""Check domain export."""
dom = models.Domain.objects.get(name="test.com")
factories.DomainAliasFactory(name="alias.test", target=dom)
response = self.__export_domains()
expected_response = [
"domain;test.com;50;10;True",
"domainalias;alias.test;test.com;True",
"domain;test2.com;0;0;True",
]
self.assertCountEqual(
expected_response, force_str(response.content.strip()).split("\r\n")
)
# Test management command too.
stdout_backup, sys.stdout = sys.stdout, StringIO()
call_command("modo", "export", "domains")
response = sys.stdout.getvalue()
@@ -60,59 +43,51 @@ class ExportTestCase(ModoTestCase):
expected_response, force_str(response.strip()).split("\r\n")
)
def test_export_identities(self):
response = self.__export_identities()
expected_response = "account;admin;;;;True;SuperAdmins;;\r\naccount;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com\r\n" # NOQA:E501
received_content = force_str(response.content.strip()).split("\r\n")
# Empty admin password because it is hashed using SHA512-CRYPT
admin_row = received_content[0].split(";")
admin_row[2] = ""
received_content[0] = ";".join(admin_row)
self.assertCountEqual(expected_response.strip().split("\r\n"), received_content)
# FIXME: filters are not available yet in the API
def test_export_simpleusers(self):
factories.MailboxFactory(
user__username="toto@test.com",
user__first_name="Léon",
user__groups=("SimpleUsers",),
address="toto",
domain__name="test.com",
)
response = self.__export_identities(
idtfilter="account", grpfilter="SimpleUsers"
)
expected_response = "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\naccount;toto@test.com;{PLAIN}toto;Léon;;True;SimpleUsers;toto@test.com;10" # NOQA:E501
self.assertCountEqual(
expected_response.split("\r\n"),
force_str(response.content.strip()).split("\r\n"),
)
# def test_export_simpleusers(self):
# factories.MailboxFactory(
# user__username="toto@test.com",
# user__first_name="Léon",
# user__groups=("SimpleUsers",),
# address="toto",
# domain__name="test.com",
# )
# response = self.__export_identities(
# idtfilter="account", grpfilter="SimpleUsers"
# )
# expected_response = "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\naccount;toto@test.com;{PLAIN}toto;Léon;;True;SimpleUsers;toto@test.com;10" # NOQA:E501
# self.assertCountEqual(
# expected_response.split("\r\n"),
# force_str(response.content.strip()).split("\r\n"),
# )
def test_export_superadmins(self):
"""A test to validate we only export 1 super admin.
# def test_export_superadmins(self):
# """A test to validate we only export 1 super admin.
The password is removed since it is hashed using SHA512-CRYPT.
"""
response = self.__export_identities(
idtfilter="account", grpfilter="SuperAdmins"
)
elements = response.content.decode().strip().split(";")
self.assertEqual(len(elements), 9)
elements[2] = ""
self.assertEqual(";".join(elements), "account;admin;;;;True;SuperAdmins;;")
# The password is removed since it is hashed using SHA512-CRYPT.
# """
# response = self.__export_identities(
# idtfilter="account", grpfilter="SuperAdmins"
# )
# elements = response.content.decode().strip().split(";")
# self.assertEqual(len(elements), 9)
# elements[2] = ""
# self.assertEqual(";".join(elements), "account;admin;;;;True;SuperAdmins;;")
def test_export_domainadmins(self):
response = self.__export_identities(
idtfilter="account", grpfilter="DomainAdmins"
)
expected_response = "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com" # NOQA:E501
self.assertCountEqual(
expected_response.split("\r\n"),
force_str(response.content.strip()).split("\r\n"),
)
# def test_export_domainadmins(self):
# response = self.__export_identities(
# idtfilter="account", grpfilter="DomainAdmins"
# )
# expected_response = "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com" # NOQA:E501
# self.assertCountEqual(
# expected_response.split("\r\n"),
# force_str(response.content.strip()).split("\r\n"),
# )
def test_export_aliases(self):
response = self.__export_identities(idtfilter="alias")
self.assertEqual(
response.content.decode().strip(),
"alias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com", # NOQA:E501
)
# def test_export_aliases(self):
# response = self.__export_identities(idtfilter="alias")
# self.assertEqual(
# response.content.decode().strip(),
# "alias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com", # NOQA:E501
# )
+35 -132
View File
@@ -10,13 +10,13 @@ from django.urls import reverse
from modoboa.core import factories as core_factories
from modoboa.core.models import User
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase
from . import utils
from .. import factories
from ..models import Alias, Domain, DomainAlias
from ..models import Alias, Domain
class ImportTestCase(ModoTestCase):
class ImportTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
@@ -26,37 +26,9 @@ class ImportTestCase(ModoTestCase):
cls.localconfig.save()
factories.populate_database()
def test_domains_import(self):
response = self.client.get(reverse("admin:domain_import"))
self.assertEqual(response.status_code, 200)
self.assertIn("Provide a CSV", response.content.decode())
f = ContentFile(
b"""domain; domain1.com; 1000; 100; True
domain; domain2.com; 1000; 200; False
domainalias; domalias1.com; domain1.com; True
""",
name="domains.csv",
)
self.client.post(reverse("admin:domain_import"), {"sourcefile": f})
admin = User.objects.get(username="admin")
dom = Domain.objects.get(name="domain1.com")
self.assertEqual(dom.quota, 1000)
self.assertEqual(dom.default_mailbox_quota, 100)
self.assertTrue(dom.enabled)
self.assertTrue(admin.is_owner(dom))
domalias = DomainAlias.objects.get(name="domalias1.com")
self.assertEqual(domalias.target, dom)
self.assertTrue(dom.enabled)
self.assertTrue(admin.is_owner(domalias))
dom = Domain.objects.get(name="domain2.com")
self.assertEqual(dom.default_mailbox_quota, 200)
self.assertFalse(dom.enabled)
self.assertTrue(admin.is_owner(dom))
def test_domain_import_bad_syntax(self):
"""Check errors handling."""
url = reverse("admin:domain_import")
url = reverse("v2:domain-import-from-csv")
f = ContentFile("domain; domain1.com; 100; True", name="domains.csv")
response = self.client.post(url, {"sourcefile": f})
self.assertContains(response, "Invalid line")
@@ -82,17 +54,18 @@ domainalias; domalias1.com; domain1.com; True
reseller = core_factories.UserFactory(
username="reseller", groups=("Resellers",)
)
self.client.force_login(reseller)
self.authenticate_user(reseller)
self.set_global_parameter("valid_mxs", "192.0.2.1 2001:db8::1")
self.set_global_parameter("domains_must_have_authorized_mx", True)
url = reverse("v2:domain-import-from-csv")
f = ContentFile(b"domain; test3.com; 100; 1; True", name="domains.csv")
resp = self.client.post(reverse("admin:domain_import"), {"sourcefile": f})
resp = self.client.post(url, {"sourcefile": f})
self.assertContains(resp, "test3.com: no authorized MX record found for domain")
mock_getaddrinfo.side_effect = utils.mock_ip_query_result
f = ContentFile(b"domain; domain1.com; 100; 1; True", name="domains.csv")
resp = self.client.post(reverse("admin:domain_import"), {"sourcefile": f})
resp = self.client.post(url, {"sourcefile": f})
self.assertTrue(Domain.objects.filter(name="domain1.com").exists())
def test_import_domains_with_conflict(self):
@@ -102,76 +75,10 @@ domainalias;test.alias;test.com;True
""",
name="domains.csv",
)
resp = self.client.post(reverse("admin:domain_import"), {"sourcefile": f})
url = reverse("v2:domain-import-from-csv")
resp = self.client.post(url, {"sourcefile": f})
self.assertIn("Object already exists: domainalias", resp.content.decode())
def test_identities_import(self):
response = self.client.get(reverse("admin:identity_import"))
self.assertEqual(response.status_code, 200)
self.assertIn("Provide a CSV", response.content.decode())
f = ContentFile(
"""
account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 0
account; Truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 5; test.com
alias; alias1@test.com; True; user1@test.com
forward; alias2@test.com; True; user1+ext@test.com
forward; fwd1@test.com; True; user@extdomain.com
dlist; dlist@test.com; True; user1@test.com; user@extdomain.com
""",
name="identities.csv",
) # NOQA:E501
self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
)
admin = User.objects.get(username="admin")
u1 = User.objects.get(username="user1@test.com")
mb1 = u1.mailbox
self.assertTrue(admin.is_owner(u1))
self.assertEqual(u1.email, "user1@test.com")
self.assertEqual(u1.first_name, "User")
self.assertEqual(u1.last_name, "One")
self.assertTrue(u1.is_active)
self.assertEqual(u1.role, "SimpleUsers")
self.assertTrue(mb1.use_domain_quota)
self.assertEqual(mb1.quota, 0)
self.assertTrue(admin.is_owner(mb1))
self.assertEqual(mb1.full_address, "user1@test.com")
self.assertTrue(self.client.login(username="user1@test.com", password="toto"))
da = User.objects.get(username="truc@test.com")
damb = da.mailbox
self.assertEqual(da.first_name, "René")
self.assertEqual(da.role, "DomainAdmins")
self.assertEqual(damb.quota, 5)
self.assertFalse(damb.use_domain_quota)
self.assertEqual(damb.full_address, "truc@test.com")
dom = Domain.objects.get(name="test.com")
self.assertIn(da, dom.admins)
u = User.objects.get(username="user@test.com")
self.assertTrue(da.can_access(u))
al = Alias.objects.get(address="alias1@test.com")
self.assertTrue(al.aliasrecipient_set.filter(r_mailbox=u1.mailbox).exists())
self.assertTrue(admin.is_owner(al))
fwd = Alias.objects.get(address="fwd1@test.com")
self.assertTrue(
fwd.aliasrecipient_set.filter(
address="user@extdomain.com",
r_mailbox__isnull=True,
r_alias__isnull=True,
).exists()
)
self.assertTrue(admin.is_owner(fwd))
dlist = Alias.objects.get(address="dlist@test.com")
self.assertTrue(dlist.aliasrecipient_set.filter(r_mailbox=u1.mailbox).exists())
self.assertTrue(
dlist.aliasrecipient_set.filter(address="user@extdomain.com").exists()
)
self.assertTrue(admin.is_owner(dlist))
def test_import_for_nonlocal_domain(self):
"""Try to import an account for nonlocal domain."""
f = ContentFile(
@@ -180,9 +87,8 @@ account; user1@nonlocal.com; toto; User; One; True; SimpleUsers; user1@nonlocal.
""",
name="identities.csv",
) # NOQA:E501
self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
)
url = reverse("v2:identities-import-from-csv")
self.client.post(url, {"sourcefile": f, "crypt_password": True})
self.assertFalse(User.objects.filter(username="user1@nonlocal.com").exists())
def test_import_invalid_quota(self):
@@ -192,24 +98,23 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; ; t
""",
name="identities.csv",
) # NOQA:E501
resp = self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
)
url = reverse("v2:identities-import-from-csv")
resp = self.client.post(url, {"sourcefile": f, "crypt_password": True})
self.assertIn("wrong quota value", resp.content.decode())
def test_import_domain_by_domainadmin(self):
"""Check if a domain admin is not allowed to import a domain."""
self.client.logout()
self.client.login(username="admin@test.com", password="toto")
admin = User.objects.get(username="admin@test.com")
self.authenticate_user(admin)
f = ContentFile(
b"""
domain; domain2.com; 1000; 200; False
""",
name="identities.csv",
)
resp = self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
)
url = reverse("v2:identities-import-from-csv")
resp = self.client.post(url, {"sourcefile": f, "crypt_password": True})
self.assertIn("You are not allowed to import domains", resp.content.decode())
f = ContentFile(
b"""
@@ -217,16 +122,14 @@ domainalias; domalias1.com; test.com; True
""",
name="identities.csv",
)
resp = self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
)
resp = self.client.post(url, {"sourcefile": f, "crypt_password": True})
self.assertIn(
"You are not allowed to import domain aliases", resp.content.decode()
)
def test_import_quota_too_big(self):
self.client.logout()
self.client.login(username="admin@test.com", password="toto")
admin = User.objects.get(username="admin@test.com")
self.authenticate_user(admin)
f = ContentFile(
b"""
account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 40
@@ -234,7 +137,8 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 40
name="identities.csv",
)
resp = self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True},
)
self.assertIn("test.com: domain quota exceeded", resp.content.decode())
@@ -246,7 +150,8 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com
name="identities.csv",
)
self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True},
)
account = User.objects.get(username="user1@test.com")
self.assertEqual(
@@ -262,7 +167,7 @@ account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0;
name="identities.csv",
) # NOQA:E501
self.client.post(
reverse("admin:identity_import"),
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True, "continue_if_exists": True},
)
admin = User.objects.get(username="admin")
@@ -274,8 +179,8 @@ account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0;
Expected result: no
"""
self.client.logout()
self.assertTrue(self.client.login(username="admin@test.com", password="toto"))
admin = User.objects.get(username="admin@test.com")
self.authenticate_user(admin)
f = ContentFile(
b"""
account; sa@test.com; toto; Super; Admin; True; SuperAdmins; superadmin@test.com; 50
@@ -283,7 +188,7 @@ account; sa@test.com; toto; Super; Admin; True; SuperAdmins; superadmin@test.com
name="identities.csv",
) # NOQA:E501
self.client.post(
reverse("admin:identity_import"),
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True, "continue_if_exists": True},
)
with self.assertRaises(User.DoesNotExist):
@@ -297,7 +202,7 @@ alias;user.alias@test.com;True;user@test.com;;;;;;;;;;;;;;;;
name="identities.csv",
)
self.client.post(
reverse("admin:identity_import"),
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True, "continue_if_exists": True},
)
alias = Alias.objects.get(address="user.alias@test.com")
@@ -312,24 +217,21 @@ alias;user@test.com;True;admin@test.com
name="identities.csv",
)
self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True},
)
self.assertTrue(
Alias.objects.filter(address="user@test.com", internal=False).exists()
)
def test_domains_import_utf8(self):
response = self.client.get(reverse("admin:domain_import"))
self.assertEqual(response.status_code, 200)
self.assertIn("Provide a CSV", response.content.decode())
f = ContentFile(
"""domain; dómªin1.com; 1000; 100; True
dómain; dómªin2.com; 1000; 100; True
""".encode(),
name="dómains.csv",
)
self.client.post(reverse("admin:domain_import"), {"sourcefile": f})
self.client.post(reverse("v2:domain-import-from-csv"), {"sourcefile": f})
admin = User.objects.get(username="admin")
dom = Domain.objects.get(name="dómªin1.com")
self.assertEqual(dom.quota, 1000)
@@ -412,7 +314,8 @@ alias; alias1@test.com; True; user1@test.com
name="identities.csv",
) # NOQA:E501
resp = self.client.post(
reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True}
reverse("v2:identities-import-from-csv"),
{"sourcefile": f, "crypt_password": True},
)
self.assertEqual(resp.status_code, 200)
+12 -9
View File
@@ -2,19 +2,18 @@
import os
import shutil
import tempfile
from unittest import mock
from django.core.management import call_command
from django.test import override_settings
from django.urls import reverse
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase
from .. import factories, models
@override_settings(DOVECOT_LOOKUP_PATH=[f"{os.path.dirname(__file__)}/dovecot"])
class MailboxOperationTestCase(ModoTestCase):
class MailboxOperationTestCase(ModoAPITestCase):
"""Test management command."""
@classmethod
@@ -26,7 +25,6 @@ class MailboxOperationTestCase(ModoTestCase):
def setUp(self):
"""Initiate test env."""
super().setUp()
self.workdir = tempfile.mkdtemp()
path = f"{self.workdir}/test.com/admin"
os.makedirs(path)
self.set_global_parameter("handle_mailboxes", True)
@@ -44,7 +42,9 @@ class MailboxOperationTestCase(ModoTestCase):
mb = models.Mailbox.objects.select_related("user").get(
address="admin", domain__name="test.com"
)
self.ajax_post(reverse("admin:account_delete", args=[mb.user.pk]), {})
self.client.post(
reverse("v2:account-delete", args=[mb.user.pk]), {}, format="json"
)
call_command("handle_mailbox_operations")
self.assertFalse(models.MailboxOperation.objects.exists())
self.assertFalse(os.path.exists(mb.mail_home))
@@ -63,10 +63,11 @@ class MailboxOperationTestCase(ModoTestCase):
"is_active": True,
"email": "admin2@test.com",
"language": "en",
"subject": "test",
"content": "content",
"mailbox": {"use_domain_quota": True},
}
self.ajax_post(reverse("admin:account_change", args=[mb.user.pk]), values)
self.client.post(
reverse("v2:account-detail", args=[mb.user.pk]), values, format="json"
)
path = f"{self.workdir}/test.com/admin2"
mail_home_mock.__get__ = mock.Mock(return_value=path)
call_command("handle_mailbox_operations")
@@ -79,7 +80,9 @@ class MailboxOperationTestCase(ModoTestCase):
path = f"{self.workdir}/test.com/admin"
mail_home_mock.__get__ = mock.Mock(return_value=path)
domain = models.Domain.objects.get(name="test.com")
self.ajax_post(reverse("admin:domain_delete", args=[domain.pk]))
self.client.post(
reverse("v2:domain-delete", args=[domain.pk]), {}, format="json"
)
call_command("handle_mailbox_operations")
self.assertFalse(models.MailboxOperation.objects.exists())
self.assertFalse(os.path.exists(path))
-9
View File
@@ -7,7 +7,6 @@ from testfixtures import LogCapture
from django.core import mail, management
from django.test import override_settings
from django.urls import reverse
from django.utils.translation import gettext as _
from modoboa.core import models as core_models, factories as core_factories
@@ -241,10 +240,6 @@ class DNSBLTestCase(ModoTestCase):
self.assertFalse(
models.DNSBLResult.objects.filter(domain=self.domain3).exists()
)
response = self.client.get(
reverse("admin:dnsbl_domain_detail", args=[self.domain.pk])
)
self.assertEqual(response.status_code, 200)
self.assertFalse(self.domain.uses_a_reserved_tld)
self.assertTrue(self.domain2.uses_a_reserved_tld)
@@ -285,10 +280,6 @@ class DNSBLTestCase(ModoTestCase):
self.assertEqual(models.DNSBLResult.objects.count(), 0)
management.call_command("modo", "check_mx", "--no-dnsbl")
self.assertFalse(models.DNSBLResult.objects.filter(domain=self.domain).exists())
response = self.client.get(
reverse("admin:dnsbl_domain_detail", args=[self.domain.pk])
)
self.assertEqual(response.status_code, 200)
class DNSChecksTestCase(ModoTestCase):
+6 -7
View File
@@ -1,11 +1,11 @@
from django.urls import reverse
from modoboa.core.models import User
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase
from .. import factories
class PasswordSchemesTestCase(ModoTestCase):
class PasswordSchemesTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
@@ -18,15 +18,14 @@ class PasswordSchemesTestCase(ModoTestCase):
"username": "tester@test.com",
"first_name": "Tester",
"last_name": "Toto",
"password1": "Toto1234",
"password2": "Toto1234",
"password": "Toto1234",
"role": "SimpleUsers",
"quota_act": True,
"is_active": True,
"email": "tester@test.com",
"stepid": "step2",
"mailbox": {"use_domain_quota": True},
}
self.ajax_post(reverse("admin:account_add"), values)
response = self.client.post(reverse("v2:account-list"), values, format="json")
self.assertEqual(response.status_code, 201)
def _test_scheme(self, name, startpattern):
self.set_global_parameter("password_scheme", name, app="core")
-49
View File
@@ -1,49 +0,0 @@
"""User related tests."""
from django.urls import reverse
from modoboa.core.models import User
from modoboa.lib.tests import ModoTestCase
from ..factories import populate_database
from ..models import Alias
class ForwardTestCase(ModoTestCase):
"""User forward test cases."""
def setUp(self):
super().setUp()
populate_database()
def test_set_forward(self):
self.client.logout()
self.client.login(username="user@test.com", password="toto")
url = reverse("user_forward")
self.ajax_post(url, {"dest": "user@extdomain.com", "keepcopies": True})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
content = response.json()
self.assertIn("user@extdomain.com", content["content"])
self.assertNotIn("user@test.com", content["content"])
forward = Alias.objects.get(address="user@test.com", internal=False)
sadmin = User.objects.get(username="admin")
self.assertTrue(sadmin.can_access(forward))
domadmin = User.objects.get(username="admin@test.com")
self.assertTrue(domadmin.can_access(forward))
selfalias = Alias.objects.get(address="user@test.com", internal=True)
self.assertTrue(selfalias.enabled)
# Deactivate local copies
self.ajax_post(url, {"dest": "user@extdomain.com", "keepcopies": False})
selfalias.refresh_from_db()
self.assertFalse(selfalias.enabled)
# Now, empty forward
self.ajax_post(url, {"dest": "", "keepcopies": False})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
content = response.json()
self.assertNotIn("user@extdomain.com", content["content"])
selfalias.refresh_from_db()
self.assertTrue(selfalias.enabled)
+8 -10
View File
@@ -8,7 +8,7 @@ from django.urls import reverse
from django.utils.functional import cached_property
from modoboa.lib import exceptions
from modoboa.lib.tests import NO_LDAP, ModoTestCase
from modoboa.lib.tests import NO_LDAP, ModoTestCase, ModoAPITestCase
from .. import factories, models
@@ -136,7 +136,7 @@ class LDAPAuthenticationTestCase(LDAPTestCaseMixin, ModoTestCase):
self.check_created_user("mailadmin@example.com", "DomainAdmins", False)
class ProfileTestCase(LDAPTestCaseMixin, ModoTestCase):
class ProfileTestCase(LDAPTestCaseMixin, ModoAPITestCase):
"""Profile related tests."""
@classmethod
@@ -159,14 +159,12 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoTestCase):
self.searchbind_mode()
username = "testuser@example.com"
account = models.User.objects.get(username=username)
self.authenticate(username, "test")
self.ajax_post(
reverse("core:user_profile"),
{
"language": "en",
"oldpassword": "test",
"newpassword": "Toto1234",
"confirmation": "Toto1234",
},
response = self.client.patch(
reverse("v2:account-detail", args=[account.id]),
{"password": "Toto1234"},
format="json",
)
self.assertEqual(response.status_code, 200)
self.authenticate(username, "Toto1234", False)
-51
View File
@@ -3,7 +3,6 @@
from unittest import mock
from django.test import SimpleTestCase
from django.urls import reverse
from django.utils import timezone
from dns.rdtypes.ANY.TXT import TXT
@@ -127,56 +126,6 @@ class LibTestCase(SimpleTestCase):
self.assertEqual(key, "XXX123")
class ViewsTestCase(ModoTestCase):
"""A test case for views."""
@classmethod
def setUpTestData(cls):
"""Create some records."""
super().setUpTestData()
cls.spf_rec = factories.DNSRecordFactory(
type="spf", value="v=SPF1 mx -all", is_valid=True, domain__name="test.com"
)
cls.dmarc_rec = factories.DNSRecordFactory(
type="dmarc",
value="XXX",
is_valid=False,
error="Not a DMARC record",
domain__name="test.com",
)
cls.dkim_rec = factories.DNSRecordFactory(
type="dkim",
value="12345",
is_valid=False,
error="Public key mismatchs",
domain__name="test.com",
)
cls.ac_rec = factories.DNSRecordFactory(
type="autoconfig", value="1.2.3.4", is_valid=True, domain__name="test.com"
)
def test_record_detail_view(self):
url = reverse("dnstools:dns_record_detail", args=[self.spf_rec.pk])
response = self.client.get(url)
self.assertContains(response, "A DNS record has been found and is valid")
url = reverse("dnstools:dns_record_detail", args=[self.dmarc_rec.pk])
response = self.client.get(url)
self.assertContains(response, "Not a DMARC record")
def test_autoconfig_record_status_view(self):
url = reverse(
"dnstools:autoconfig_records_status", args=[self.ac_rec.domain.pk]
)
response = self.client.get(url)
self.assertContains(response, "autoconfig record (Mozilla) found")
self.assertContains(response, "autodiscover record (Microsoft) not found")
def test_domain_dns_configuration(self):
url = reverse("dnstools:domain_dns_configuration", args=[self.ac_rec.domain.pk])
response = self.client.get(url)
self.assertContains(response, "[IP address of your Modoboa server]")
class DomainTestCase(ModoTestCase):
def test_dns_global_status(self):
+116
View File
@@ -30,6 +30,122 @@ except ImportError:
NO_LDAP = True
SETTINGS_SAMPLE = {
"core-check_new_versions": "True",
"core-log_maximum_age": "365",
"core-ldap_auth_method": "searchbind",
"limits-deflt_domain_mailbox_aliases_limit": "0",
"core-send_statistics": "True",
"core-default_top_redirection": "user",
"core-sender_address": "noreply@modoboa.org",
"admin-auto_account_removal": "False",
"core-ldap_server_port": "389",
"core-rounds_number": "70000",
"core-ldap_bind_password": "",
"limits-deflt_domain_domain_aliases_limit": "0",
"core-secret_key": ":?j3]QPWo!.'_c4n",
"limits-deflt_domain_domain_admins_limit": "0",
"limits-enable_admin_limits": "True",
"core-ldap_bind_dn": "",
"core-enable_api_communication": "True",
"limits-deflt_user_domain_admins_limit": "0",
"limits-enable_domain_limits": "False",
"csrfmiddlewaretoken": "SGgMVZsA4TPqoiV786TMST6xgOlhAf4F",
"limits-deflt_user_mailboxes_limit": "0",
"core-password_scheme": "plain",
"core-update_scheme": True,
"core-items_per_page": "30",
"limits-deflt_user_mailbox_aliases_limit": "0",
"limits-deflt_domain_mailboxes_limit": "0",
"core-ldap_is_active_directory": "False",
"core-ldap_group_type": "posixgroup",
"limits-deflt_user_domain_aliases_limit": "0",
"core-top_notifications_check_interval": "30",
"core-ldap_password_attribute": "userPassword",
"admin-auto_create_domain_and_mailbox": "True",
"admin-enable_dnsbl_checks": "True",
"admin-default_domain_quota": "0",
"admin-default_mailbox_quota": "0",
"core-ldap_server_address": "localhost",
"core-authentication_type": "local",
"core-ldap_admin_groups": "",
"core-ldap_groups_search_base": "",
"admin-enable_mx_checks": "True",
"admin-enable_ipv6_mx_checks": "True",
"core-ldap_search_base": "",
"admin-valid_mxs": "",
"limits-deflt_user_domains_limit": "0",
"core-ldap_search_filter": "(mail=%(user)s)",
"core-ldap_secured": "none",
"core-ldap_user_dn_template": "",
"core-default_password": "Toto1000",
"limits-deflt_user_quota_limit": "0",
"core-hide_features_widget": "False",
"core-enable_inactive_accounts": "True",
"core-inactive_account_threshold": "30",
"admin-domains_must_have_authorized_mx": False,
"core-random_password_length": "8",
"admin-create_alias_on_mbox_rename": False,
"admin-dkim_keys_storage_dir": "",
"admin-dkim_default_key_length": 1024,
"admin-custom_dns_server": "193.43.55.67",
"admin-enable_spf_checks": True,
"admin-enable_dkim_checks": True,
"admin-enable_dmarc_checks": True,
"admin-enable_autoconfig_checks": True,
"core-ldap_enable_sync": False,
"core-ldap_sync_bind_dn": "",
"core-ldap_sync_bind_password": "",
"core-ldap_sync_account_dn_template": "",
"core-ldap_sync_delete_remote_account": False,
"core-send_new_versions_email": False,
"core-new_versions_email_rcpt": "postmaster@domain.test",
"core-ldap_enable_secondary_server": False,
"core-ldap_secondary_server_address": "localhost",
"core-ldap_secondary_server_port": 389,
"core-ldap_enable_import": False,
"core-ldap_import_search_base": "",
"core-ldap_import_search_filter": "",
"core-ldap_import_username_attr": "cn",
"core-sms_password_recovery": False,
"core-sms_provider": "",
"core-sms_ovh_endpoint": "ovh-eu",
"core-password_recovery_msg": "",
"core-ldap_dovecot_sync": False,
"maillog-logfile": "/var/log/mail.log",
"maillog-rrd_rootdir": "/tmp",
"maillog-greylist": False,
"pdfcredentials-enabled_pdfcredentials": True,
"pdfcredentials-storage_dir": "./",
"pdfcredentials-delete_first_dl": True,
"pdfcredentials-generate_at_creation": True,
"pdfcredentials-title": "Modoboa",
"pdfcredentials-webpanel_url": "local.host/",
"pdfcredentials-custom_message": "test",
"pdfcredentials-include_connection_settings": False,
"pdfcredentials-smtp_server_address": "127.0.0.1",
"pdfcredentials-smtp_server_port": 666,
"pdfcredentials-smtp_connection_security": "starttls",
"pdfcredentials-imap_server_address": "127.0.0.1",
"pdfcredentials-imap_server_port": 667,
"pdfcredentials-imap_connection_security": "starttls",
"dmarc-enable_rlookups": False,
"imap_migration-enabled_imapmigration": True,
"imap_migration-max_sync_accounts": 2,
"imap_migration-create_folders": True,
"postfix_autoreply-autoreplies_timeout": 86400,
"postfix_autoreply-default_subject": "I'm off",
"postfix_autoreply-default_content": "I'm off",
"sievefilters-server": "127.0.0.1",
"sievefilters-port": 4190,
"sievefilters-starttls": False,
"sievefilters-authentication_mech": "AUTO",
"sievefilters-imap_server": "127.0.0.1",
"sievefilters-imap_secured": False,
"sievefilters-imap_port": 143,
}
class ParametersMixin:
"""Add tools to manage parameters."""
+22 -1
View File
@@ -1,8 +1,13 @@
"""API v2 tests."""
from django.urls import reverse
from dateutil.relativedelta import relativedelta
from django.urls import reverse
from django.utils import timezone
from modoboa.admin import factories as admin_factories, models
from modoboa.lib.tests import ModoAPITestCase
from modoboa.maillog import factories
class StatisticsViewSetTestCase(ModoAPITestCase):
@@ -23,7 +28,23 @@ class StatisticsViewSetTestCase(ModoAPITestCase):
class MaillogViewSetTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls): # NOQA:N802
"""Create test data."""
super().setUpTestData()
admin_factories.populate_database()
domain = models.Domain.objects.get(name="test.com")
factories.MaillogFactory(from_domain=domain)
factories.MaillogFactory(
to_domain=domain,
status="received",
date=timezone.now() + relativedelta(days=1),
)
factories.MaillogFactory(date=timezone.now() + relativedelta(days=2))
factories.MaillogFactory(date=timezone.now() + relativedelta(days=3))
def test_list(self):
url = reverse("v2:maillog-list")
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json()["count"], 4)
+1 -1
View File
@@ -83,7 +83,7 @@ class Registry:
def get_label(self, level: str, app: str) -> str:
return self._registry2[level][app]["label"]
def get_serializer_classes(self, level):
def get_serializers(self, level):
"""Return form instances for all app of the given level."""
sorted_apps = []
first_app = "core"
+2 -21
View File
@@ -11,13 +11,12 @@ import time
from django import db
from django.core.management import call_command
from django.test import TransactionTestCase
from django.urls import reverse
from modoboa.admin import factories as admin_factories
from modoboa.admin import models as admin_models
from modoboa.core import models as core_models
from modoboa.lib.redis import get_redis_connection
from modoboa.lib.tests import ModoTestCase, ParametersMixin
from modoboa.lib.tests import ModoAPITestCase, ParametersMixin
from modoboa.policyd import core as policyd_core
from . import constants
@@ -210,7 +209,7 @@ sasl_username=user@test.com
self.assertEqual(self.rclient.hget(constants.REDIS_HASHNAME, account.email), 10)
class ModelsTestCase(RedisTestCaseMixin, ModoTestCase):
class ModelsTestCase(RedisTestCaseMixin, ModoAPITestCase):
"""Admin models test cases."""
@classmethod
@@ -219,24 +218,6 @@ class ModelsTestCase(RedisTestCaseMixin, ModoTestCase):
super().setUpTestData()
admin_factories.populate_database()
def test_domain_detail_view(self):
domain = admin_models.Domain.objects.get(name="test.com")
domain.message_limit = 10
domain.save()
url = reverse("admin:domain_detail", args=[domain.pk])
response = self.client.get(url)
self.assertContains(response, "Message sending limit")
def test_account_detail_view(self):
account = core_models.User.objects.get(username="user@test.com")
mb = account.mailbox
mb.message_limit = 10
mb.save()
url = reverse("admin:account_detail", args=[account.pk])
response = self.client.get(url)
self.assertContains(response, "Message sending limit")
def test_domain_signal_handler(self):
domain = admin_models.Domain.objects.get(name="test.com")
domain.message_limit = 10