diff --git a/modoboa/admin/api/v1/serializers.py b/modoboa/admin/api/v1/serializers.py index 6ef08418f..39adde055 100644 --- a/modoboa/admin/api/v1/serializers.py +++ b/modoboa/admin/api/v1/serializers.py @@ -163,14 +163,7 @@ class MailboxSerializer(serializers.ModelSerializer): def validate_full_address(self, value): """Lower case address.""" - value = value.lower() - address, domain_name = email_utils.split_mailbox(value) - domain = get_object_or_404( - admin_models.Domain, name=domain_name) - creator = self.context["request"].user - if not creator.can_access(domain): - raise serializers.ValidationError(_("Permission denied.")) - return value + return value.lower() def validate_quota(self, value): """Convert quota to MB.""" @@ -320,6 +313,24 @@ class WritableAccountSerializer(AccountSerializer): raise serializers.ValidationError({ "username": _("Must be equal to mailbox full_address") }) + if "mailbox" in data: + self.address, domain_name = email_utils.split_mailbox(data["mailbox"]["full_address"]) + self.domain = get_object_or_404( + admin_models.Domain, name=domain_name) + creator = self.context["request"].user + if not creator.can_access(self.domain): + raise serializers.ValidationError({"mailbox": _("Permission denied.")}) + if not self.instance: + try: + core_signals.can_create_object.send( + sender=self.__class__, context=creator, + klass=admin_models.Mailbox) + core_signals.can_create_object.send( + sender=self.__class__, context=self.domain, + object_type="mailboxes") + except lib_exceptions.ModoboaException as inst: + raise serializers.ValidationError({ + "mailbox": force_text(inst)}) condition = ( not data.get("random_password") and ( data.get("password") or @@ -357,22 +368,9 @@ class WritableAccountSerializer(AccountSerializer): def _create_mailbox(self, creator, account, data): """Create a new Mailbox instance.""" full_address = data.pop("full_address") - address, domain_name = email_utils.split_mailbox(full_address) - domain = get_object_or_404( - admin_models.Domain, name=domain_name) - try: - core_signals.can_create_object.send( - sender=self.__class__, context=creator, - klass=admin_models.Mailbox) - core_signals.can_create_object.send( - sender=self.__class__, context=domain, - object_type="mailboxes") - except lib_exceptions.ModoboaException as inst: - raise serializers.ValidationError({ - "domain": force_text(inst)}) quota = data.pop("quota", None) mb = admin_models.Mailbox( - user=account, address=address, domain=domain, **data) + user=account, address=self.address, domain=self.domain, **data) mb.set_quota(quota, creator.has_perm("admin.add_domain")) default_msg_limit = param_tools.get_global_parameter( "default_mailbox_message_limit") diff --git a/modoboa/policyd/core.py b/modoboa/policyd/core.py index 917d98234..23ae7d433 100644 --- a/modoboa/policyd/core.py +++ b/modoboa/policyd/core.py @@ -1,5 +1,6 @@ """Core components of the policy daemon.""" +from asgiref.sync import sync_to_async import asyncio import concurrent.futures from email.message import EmailMessage @@ -216,7 +217,7 @@ def get_next_execution_dt(): hour=0, minute=0, second=0) -@close_db_connections +@sync_to_async def get_domains_to_reset(): """ Return a list of domain to reset. @@ -230,10 +231,10 @@ def get_domains_to_reset(): ).update( status=admin_constants.ALARM_CLOSED, closed=timezone.now() ) - return qset + return list(qset) -@close_db_connections +@sync_to_async def get_mailboxes_to_reset(): """ Return a list of mailboxes to reset. @@ -250,25 +251,17 @@ def get_mailboxes_to_reset(): ).update( status=admin_constants.ALARM_CLOSED, closed=timezone.now() ) - return qset + return list(qset) async def reset_counters(): """Reset all counters.""" rclient = await aioredis.create_redis_pool(settings.REDIS_URL) logger.info("Resetting all counters") - # We're going to execute sync code so we need an executor - executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) - loop = asyncio.get_event_loop() - futures = [ - loop.run_in_executor(executor, get_domains_to_reset), - loop.run_in_executor(executor, get_mailboxes_to_reset) - ] - domains, mboxes = await asyncio.gather(*futures) - for domain in domains: + for domain in await get_domains_to_reset(): rclient.hset( constants.REDIS_HASHNAME, domain.name, domain.message_limit) - for mb in mboxes: + for mb in await get_mailboxes_to_reset(): rclient.hset( constants.REDIS_HASHNAME, mb.full_address, mb.message_limit) rclient.close()