mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
More tests updated
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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.",
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
# )
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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."""
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user