New tests fixed

This commit is contained in:
Antoine Nguyen
2025-06-08 15:12:48 +02:00
parent abae9bb7c3
commit 7301629207
10 changed files with 191 additions and 171 deletions
+9 -6
View File
@@ -328,9 +328,9 @@ class AccountPasswordSerializer(serializers.ModelSerializer):
class WritableAccountSerializer(AccountSerializer):
"""Serializer to create account."""
random_password = serializers.BooleanField(default=False)
random_password = serializers.BooleanField(default=False, write_only=True)
role = serializers.ChoiceField(choices=core_constants.ROLES)
password = serializers.CharField(required=False)
password = serializers.CharField(required=False, write_only=True)
class Meta(AccountSerializer.Meta):
fields = AccountSerializer.Meta.fields + ("password", "random_password")
@@ -341,10 +341,6 @@ class WritableAccountSerializer(AccountSerializer):
request = self.context.get("request")
if not request:
return
user = self.context["request"].user
self.fields["role"] = serializers.ChoiceField(
choices=permissions.get_account_roles(user)
)
self.fields["domains"] = serializers.ListField(
child=serializers.CharField(), allow_empty=False, required=False
)
@@ -353,6 +349,13 @@ class WritableAccountSerializer(AccountSerializer):
"""Lower case username."""
return value.lower()
def validate_role(self, value):
user = self.context["request"].user
allowed_values = permissions.get_account_roles(user, self.instance)
if value not in [role[0] for role in allowed_values]:
raise serializers.ValidationError("Invalid choice")
return value
def validate(self, data):
"""Check constraints."""
master_user = data.get("master_user", False)
+11
View File
@@ -303,3 +303,14 @@ def get_import_func(sender, objtype, **kwargs):
elif objtype == "dlist":
return lib.import_dlist
return None
@receiver(signals.post_save, sender=core_models.User)
def disable_aliases_on_account_disabled(sender, instance, created, **kwargs):
"""Make sure aliases of a disabled account are also disabled."""
if created or not hasattr(instance, "mailbox"):
return
for alr in instance.mailbox.aliasrecipient_set.all().select_related("alias"):
if alr.alias.recipients_count == 1:
alr.alias.enabled = False
alr.alias.save()
+30 -17
View File
@@ -46,31 +46,42 @@ class AccountTestCase(ModoAPITestCase):
factories.populate_database()
def test_aliases_update_on_disable(self):
"""Check if aliases are updated when account is disabled."""
"""Check if aliases are disabled when account is disabled."""
account = User.objects.get(username="user@test.com")
internal = models.Alias.objects.get(address=account.email, internal=True)
forward = models.Alias.objects.create(address=account.email, internal=False)
factories.AliasRecipientFactory.create(
address=account.mailbox.full_address,
alias=forward,
r_mailbox=account.mailbox,
)
values = {
"username": "user@test.com",
"role": "SimpleUsers",
"quota_act": True,
"mailbox": {
"use_domain_quota": True,
},
"is_active": False,
"email": "user@test.com",
"language": "en",
"subject": "subject",
"content": "content",
}
self.ajax_post(reverse("admin:account_change", args=[account.id]), values)
response = self.client.put(
reverse("v2:account-detail", args=[account.pk]), values, format="json"
)
self.assertEqual(response.status_code, 200)
internal.refresh_from_db()
self.assertFalse(internal.enabled)
forward.refresh_from_db()
self.assertFalse(forward.enabled)
values["is_active"] = True
self.ajax_post(reverse("admin:account_change", args=[account.id]), values)
response = self.client.put(
reverse("v2:account-detail", args=[account.pk]), values, format="json"
)
self.assertEqual(response.status_code, 200)
internal.refresh_from_db()
self.assertTrue(internal.enabled)
self.assertFalse(internal.enabled)
forward.refresh_from_db()
self.assertTrue(forward.enabled)
self.assertFalse(forward.enabled)
@skipIf(NO_LDAP, "No ldap module installed")
@@ -200,6 +211,7 @@ class PermissionsTestCase(ModoAPITestCase):
def test_self_modif(self):
dadmin = User.objects.get(username="admin@test.com")
self.authenticate_user(dadmin)
self.assertTrue(dadmin.can_access(models.Domain.objects.get(name="test.com")))
values = {
"username": "admin@test.com",
@@ -210,11 +222,11 @@ class PermissionsTestCase(ModoAPITestCase):
},
"is_active": True,
"language": "en",
"domains": ["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")))
@@ -223,9 +235,8 @@ class PermissionsTestCase(ModoAPITestCase):
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.assertEqual(response.status_code, 400)
self.assertEqual(response.json()["role"][0], "Invalid choice")
self.authenticate_user(self.reseller)
self.assertTrue(self.reseller.can_access(self.reseller))
@@ -234,6 +245,7 @@ class PermissionsTestCase(ModoAPITestCase):
"first_name": "Reseller",
"is_active": True,
"language": "en",
"role": "Resellers",
}
response = self.client.put(
reverse("v2:account-detail", args=[self.reseller.id]), values, format="json"
@@ -244,8 +256,8 @@ class PermissionsTestCase(ModoAPITestCase):
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")
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()["role"][0], "Invalid choice")
def test_domainadmin_deletes_superadmin(self):
"""Check domain admins restrictions about super admins
@@ -306,7 +318,7 @@ class PermissionsTestCase(ModoAPITestCase):
def test_domadmins_permissions(self):
"""
Check that two domain admins in the same domains see the same
Check that two domain admins in the same domain see the same
content.
"""
dom = models.Domain.objects.get(name="test.com")
@@ -327,7 +339,8 @@ class PermissionsTestCase(ModoAPITestCase):
"mailbox": {"use_domain_quota": True},
"is_active": True,
}
self.client.post(reverse("v2:account-list"), values, format="json")
response = self.client.post(reverse("v2:account-list"), values, format="json")
self.assertEqual(response.status_code, 201)
new_mb = models.Mailbox.objects.get(user__username="new@test.com")
new_mb = models.Mailbox.objects.get(user__username=values["username"])
self.assertTrue(mb.user.can_access(new_mb))
+2 -14
View File
@@ -109,17 +109,11 @@ class DKIMTestCase(ModoAPITestCase):
def test_global_settings(self):
"""Check validation rules."""
url = reverse("v2:parameter-global-detail", args=["admin"])
settings = SETTINGS_SAMPLE.copy()
settings = SETTINGS_SAMPLE["admin"].copy()
settings["dkim_keys_storage_dir"] = "/wrong"
response = self.client.put(url, settings, format="json")
self.assertEqual(response.status_code, 400)
compare(
response.json(),
{
"form_errors": {"dkim_keys_storage_dir": ["Directory not found."]},
"prefix": "admin",
},
)
compare(response.json(), {"dkim_keys_storage_dir": ["Directory not found."]})
settings["admin-dkim_keys_storage_dir"] = self.workdir
response = self.client.post(url, settings, format="json")
self.assertEqual(response.status_code, 200)
@@ -142,12 +136,6 @@ class DKIMTestCase(ModoAPITestCase):
)
self.set_global_parameter("dkim_keys_storage_dir", self.workdir)
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 400)
self.assertEqual(
response.json()["dkim_key_selector"][0], "This field is required."
)
values["dkim_key_selector"] = "default"
response = self.client.post(url, values, format="json")
self.assertEqual(response.status_code, 201)
@@ -2,18 +2,15 @@
import os
import shutil
import tempfile
from django.core.management import call_command
from django.urls import reverse
from modoboa.core.tests.test_views import SETTINGS_SAMPLE
from modoboa.lib.tests import ModoTestCase
from modoboa.lib.tests import ModoAPITestCase, SETTINGS_SAMPLE
from .. import factories
class NeedDovecotUpdateTestCase(ModoTestCase):
class NeedDovecotUpdateTestCase(ModoAPITestCase):
"""Test need dovecot ldap update command."""
@classmethod
@@ -25,7 +22,6 @@ class NeedDovecotUpdateTestCase(ModoTestCase):
def setUp(self):
"""Initiate initial env."""
super().setUp()
self.workdir = tempfile.mkdtemp()
self.localconfig.need_dovecot_update = False
self.localconfig.save()
@@ -34,11 +30,10 @@ class NeedDovecotUpdateTestCase(ModoTestCase):
shutil.rmtree(self.workdir)
def test_update_dovecot_update_state_valid_form(self):
url = reverse("core:parameters")
settings = SETTINGS_SAMPLE.copy()
response = self.client.post(url, settings, format="json")
url = reverse("v2:parameter-global-detail", args=["core"])
settings = SETTINGS_SAMPLE["core"].copy()
response = self.client.put(url, settings, format="json")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), "Parameters saved")
self.localconfig.refresh_from_db()
self.assertTrue(self.localconfig.need_dovecot_update)
+1 -1
View File
@@ -428,7 +428,7 @@ class SMTPAuthenticationTestCase(ModoTestCase):
data = {"username": username, "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, "/")
mock_smtp.return_value.login.assert_called_once_with(username, password)
self.assertTrue(models.User.objects.filter(username=username).exists())
+1 -1
View File
@@ -159,8 +159,8 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoAPITestCase):
self.searchbind_mode()
username = "testuser@example.com"
account = models.User.objects.get(username=username)
self.authenticate(username, "test")
account = models.User.objects.get(username=username)
response = self.client.patch(
reverse("v2:account-detail", args=[account.id]),
{"password": "Toto1234"},
+3
View File
@@ -18,6 +18,9 @@ def get_account_roles(user, account=None):
:param ``User`` account: account beeing modified (None on creation)
:return: list of strings
"""
if account and user == account:
# Special case to ensure a user cannot change its own role
return [(user.role, "")]
result = [core_constants.SIMPLEUSERS_ROLE]
filters = core_signals.user_can_set_role.send(
sender="get_account_roles", user=user, role="DomainAdmins", account=account
+128 -112
View File
@@ -31,118 +31,134 @@ except ImportError:
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,
"core": {
"check_new_versions": "True",
"log_maximum_age": "365",
"ldap_auth_method": "searchbind",
"send_statistics": "True",
"default_top_redirection": "user",
"sender_address": "noreply@modoboa.org",
"ldap_server_port": "389",
"rounds_number": "70000",
"ldap_bind_password": "",
"secret_key": ":?j3]QPWo!.'_c4n",
"ldap_bind_dn": "",
"enable_api_communication": "True",
"password_scheme": "plain",
"update_scheme": True,
"items_per_page": "30",
"ldap_is_active_directory": "False",
"ldap_group_type": "posixgroup",
"top_notifications_check_interval": "30",
"ldap_password_attribute": "userPassword",
"ldap_server_address": "localhost",
"authentication_type": "local",
"ldap_admin_groups": "",
"ldap_groups_search_base": "",
"ldap_search_base": "",
"ldap_enable_sync": False,
"ldap_sync_bind_dn": "",
"ldap_sync_bind_password": "",
"ldap_sync_account_dn_template": "",
"ldap_sync_delete_remote_account": False,
"send_new_versions_email": False,
"new_versions_email_rcpt": "postmaster@domain.test",
"ldap_enable_secondary_server": False,
"ldap_secondary_server_address": "localhost",
"ldap_secondary_server_port": 389,
"ldap_enable_import": False,
"ldap_import_search_base": "",
"ldap_import_username_attr": "cn",
"sms_password_recovery": False,
"sms_provider": "",
"sms_ovh_endpoint": "ovh-eu",
"password_recovery_msg": "",
"ldap_dovecot_sync": False,
"hide_features_widget": "False",
"enable_inactive_accounts": "True",
"inactive_account_threshold": "30",
"ldap_search_filter": "(mail=%(user)s)",
"ldap_secured": "none",
"ldap_user_dn_template": "",
"default_password": "Toto1000",
"random_password_length": "8",
},
"limits": {
"deflt_domain_mailbox_aliases_limit": "0",
"deflt_domain_domain_aliases_limit": "0",
"deflt_domain_domain_admins_limit": "0",
"enable_domain_limits": "False",
"enable_admin_limits": "True",
"deflt_user_domain_admins_limit": "0",
"deflt_user_mailboxes_limit": "0",
"deflt_user_mailbox_aliases_limit": "0",
"deflt_domain_mailboxes_limit": "0",
"deflt_user_domain_aliases_limit": "0",
"deflt_user_domains_limit": "0",
"deflt_user_quota_limit": "0",
},
"admin": {
"auto_account_removal": "False",
"auto_create_domain_and_mailbox": "True",
"enable_dnsbl_checks": "True",
"default_domain_quota": "0",
"default_mailbox_quota": "0",
"enable_mx_checks": "True",
"enable_ipv6_mx_checks": "True",
"create_alias_on_mbox_rename": False,
"dkim_keys_storage_dir": "",
"dkim_default_key_length": 1024,
"custom_dns_server": "193.43.55.67",
"enable_spf_checks": True,
"enable_dkim_checks": True,
"enable_dmarc_checks": True,
"enable_autoconfig_checks": True,
"valid_mxs": "",
"domains_must_have_authorized_mx": False,
},
"maillog": {
"logfile": "/var/log/mail.log",
"rrd_rootdir": "/tmp",
"greylist": False,
},
"pdfcredentials": {
"enabled_pdfcredentials": True,
"storage_dir": "./",
"delete_first_dl": True,
"generate_at_creation": True,
"title": "Modoboa",
"webpanel_url": "local.host/",
"custom_message": "test",
"include_connection_settings": False,
"smtp_server_address": "127.0.0.1",
"smtp_server_port": 666,
"smtp_connection_security": "starttls",
"imap_server_address": "127.0.0.1",
"imap_server_port": 667,
"imap_connection_security": "starttls",
},
"dmarc": {
"enable_rlookups": False,
},
"imap_migration": {
"enabled_imapmigration": True,
"max_sync_accounts": 2,
"create_folders": True,
},
"postfix_autoreply": {
"autoreplies_timeout": 86400,
"default_subject": "I'm off",
"default_content": "I'm off",
},
"sievefilters": {
"server": "127.0.0.1",
"port": 4190,
"starttls": False,
"authentication_mech": "AUTO",
"imap_server": "127.0.0.1",
"imap_secured": False,
"imap_port": 143,
},
}
+1 -10
View File
@@ -29,17 +29,8 @@ class Registry:
def __init__(self):
"""Constructor."""
self._registry = {"global": {}, "user": {}}
self._registry2 = {"global": {}, "user": {}}
def add(self, level, formclass, label):
"""Add a new class containing parameters."""
self._registry[level][formclass.app] = {
"label": label,
"formclass": formclass,
"defaults": {},
}
def add2(
self,
level: str,
@@ -91,7 +82,7 @@ class Registry:
sorted_apps.append(first_app)
sorted_apps += sorted(
(a for a in self._registry2[level] if a != first_app),
key=lambda a: self._registry[level][a]["label"],
key=lambda a: self._registry2[level][a]["label"],
)
result = []
for app in sorted_apps: