Merge pull request #2497 from modoboa/refacto/django_3_2

Django 3.2 support
This commit is contained in:
Antoine Nguyen
2022-04-20 15:07:44 +02:00
committed by GitHub
16 changed files with 65 additions and 44 deletions
+19 -17
View File
@@ -313,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
@@ -350,25 +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)
if not creator.can_access(domain):
raise serializers.ValidationError({
"domain": _("Permission denied.")})
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")
+5 -3
View File
@@ -249,7 +249,7 @@ class AccountAPITestCase(ModoAPITestCase):
def setUp(self):
"""Test setup."""
super(AccountAPITestCase, self).setUp()
super().setUp()
self.set_global_parameters({
"enable_admin_limits": False,
"enable_domain_limits": False
@@ -400,15 +400,17 @@ class AccountAPITestCase(ModoAPITestCase):
data["mailbox"]["quota"] = 1000
url = reverse("v1:account-list")
response = self.client.post(url, data, format="json")
# Should fail because domain quota is exceeded
self.assertEqual(response.status_code, 400)
data["username"] = "fromapi@test2.com"
data["mailbox"].update({"full_address": "fromapi@test2.com",
"quota": 10})
url = reverse("v1:account-list")
response = self.client.post(url, data, format="json")
# Should fail because admin has no access to @test2.com domain
self.assertEqual(response.status_code, 400)
errors = response.json()
self.assertIn("domain", errors)
self.assertIn("mailbox", errors)
def test_create_account_bad_master_user(self):
"""Try to create a new account."""
+21
View File
@@ -5,6 +5,7 @@ import os
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core import validators as dj_validators
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from django.contrib.auth import password_validation
@@ -13,6 +14,7 @@ from rest_framework import serializers
from modoboa.admin.api.v1 import serializers as v1_serializers
from modoboa.core import models as core_models, signals as core_signals
from modoboa.lib import email_utils
from modoboa.lib import exceptions as lib_exceptions
from modoboa.lib import fields as lib_fields
from modoboa.lib import validators, web_utils
@@ -402,6 +404,25 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
data["mailbox"] = {
"use_domain_quota": True
}
if "mailbox" in data:
self.address, domain_name = email_utils.split_mailbox(data["username"])
self.domain = get_object_or_404(
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=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)
})
if data.get("password") or not self.partial:
password = data.get("password")
if password:
+1 -1
View File
@@ -6,9 +6,9 @@ from .app_settings import load_admin_settings
class AdminConfig(AppConfig):
"""App configuration."""
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.admin"
verbose_name = "Modoboa admin console"
+1 -2
View File
@@ -4,7 +4,7 @@ from reversion import revisions as reversion
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.utils.encoding import python_2_unicode_compatible, smart_text
from django.utils.encoding import smart_text
from django.utils.translation import ugettext as _, ugettext_lazy
from modoboa.core import models as core_models, signals as core_signals
@@ -26,7 +26,6 @@ class DomainAliasManager(models.Manager):
return self.get_queryset().filter(owners__user=admin)
@python_2_unicode_compatible
class DomainAlias(AdminObject):
"""Domain aliases."""
+1
View File
@@ -26,6 +26,7 @@ def load_core_settings():
class CoreConfig(AppConfig):
"""App configuration."""
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.core"
verbose_name = "Modoboa core"
+1
View File
@@ -2,4 +2,5 @@ from django.apps import AppConfig
class DnstoolsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'modoboa.dnstools'
-2
View File
@@ -4,7 +4,6 @@ import datetime
from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext as _
from . import constants
@@ -35,7 +34,6 @@ class DNSRecordManager(models.Manager):
return record
@python_2_unicode_compatible
class DNSRecord(models.Model):
"""A model to store DNS records for Domain."""
+2 -2
View File
@@ -56,7 +56,7 @@ def render_field(
@register.simple_tag
def render_fields_group(form, pattern):
"""Render a group of fields."""
first = forms.forms.BoundField(form, form.fields[pattern], pattern)
first = forms.BoundField(form, form.fields[pattern], pattern)
configure_field_classes(first)
label = first.label
group = [first]
@@ -66,7 +66,7 @@ def render_fields_group(form, pattern):
fname = "%s_%d" % (pattern, cpt)
if fname not in form.fields:
break
bfield = forms.forms.BoundField(form, form.fields[fname], fname)
bfield = forms.BoundField(form, form.fields[fname], fname)
if len(bfield.errors):
haserror = True
configure_field_classes(bfield)
+1 -1
View File
@@ -18,9 +18,9 @@ def load_limits_settings():
class LimitsConfig(AppConfig):
"""App configuration."""
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.limits"
verbose_name = "Modoboa admin limits"
+1
View File
@@ -8,6 +8,7 @@ from .forms import load_settings
class MaillogConfig(AppConfig):
"""App configuration."""
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.maillog"
verbose_name = "Modoboa graphical statistics"
+1 -1
View File
@@ -2,4 +2,4 @@ from django.apps import AppConfig
class ParametersConfig(AppConfig):
name = "parameters"
name = "modoboa.parameters"
+7 -12
View File
@@ -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,6 +217,7 @@ def get_next_execution_dt():
hour=0, minute=0, second=0)
@sync_to_async
@close_db_connections
def get_domains_to_reset():
"""
@@ -230,9 +232,10 @@ def get_domains_to_reset():
).update(
status=admin_constants.ALARM_CLOSED, closed=timezone.now()
)
return qset
return list(qset)
@sync_to_async
@close_db_connections
def get_mailboxes_to_reset():
"""
@@ -250,25 +253,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()
+1 -1
View File
@@ -4,9 +4,9 @@ from django.apps import AppConfig
class RelayDomainsConfig(AppConfig):
"""App configuration."""
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.relaydomains"
verbose_name = "Modoboa relay domains"
+1
View File
@@ -2,6 +2,7 @@ from django.apps import AppConfig
class TransportConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "modoboa.transport"
def ready(self):
+2 -2
View File
@@ -1,7 +1,7 @@
django>=2.2,<2.3
django<4.0
django-ckeditor==6.3.0
django-phonenumber-field[phonenumbers]==6.1.0
django-reversion==3.0.9
django-reversion==5.0.0
django-xforwardedfor-middleware==2.0
django-otp==1.1.3
django-filter