diff --git a/modoboa/admin/forms/domain.py b/modoboa/admin/forms/domain.py index a8fc13311..71b1ad208 100644 --- a/modoboa/admin/forms/domain.py +++ b/modoboa/admin/forms/domain.py @@ -142,7 +142,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): q.delete() def save(self, user, commit=True, domalias_post_create=False): - """Custom save method + """Custom save method. Updating a domain may have consequences on other objects (domain alias, mailbox, quota). The most tricky part concerns @@ -150,46 +150,34 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): """ d = super(DomainFormGeneral, self).save(commit=False) - if commit: - old_mail_homes = None - if self.oldname is not None and d.name != self.oldname: - d.name = self.oldname - old_mail_homes = \ - dict((mb.id, mb.mail_home) for mb in d.mailbox_set.all()) - d.name = self.cleaned_data['name'] - d.save() - Mailbox.objects.filter(domain=d, use_domain_quota=True) \ - .update(quota=d.quota) - aliases = [] - for k, v in self.cleaned_data.iteritems(): - if not k.startswith("aliases"): - continue - if v in ["", None]: - continue - aliases.append(v) - for dalias in d.domainalias_set.all(): - if dalias.name not in aliases: - dalias.delete() + if not commit: + return d + d.save() + aliases = [] + for k, v in self.cleaned_data.iteritems(): + if not k.startswith("aliases"): + continue + if v in ["", None]: + continue + aliases.append(v) + for dalias in d.domainalias_set.all(): + if dalias.name not in aliases: + dalias.delete() + else: + aliases.remove(dalias.name) + if aliases: + events.raiseEvent( + "CanCreate", user, "domain_aliases", len(aliases)) + for alias in aliases: + try: + d.domainalias_set.get(name=alias) + except DomainAlias.DoesNotExist: + pass else: - aliases.remove(dalias.name) - if aliases: - events.raiseEvent( - "CanCreate", user, "domain_aliases", len(aliases)) - for alias in aliases: - try: - d.domainalias_set.get(name=alias) - except DomainAlias.DoesNotExist: - pass - else: - continue - al = DomainAlias(name=alias, target=d, enabled=d.enabled) - al.save(creator=user) if domalias_post_create else al.save() - - if old_mail_homes is not None: - self.update_mailbox_quotas(d) - for mb in d.mailbox_set.all(): - mb.rename_dir(old_mail_homes[mb.id]) - + continue + options = {"creator": user} if domalias_post_create else {} + DomainAlias(name=alias, target=d, enabled=d.enabled).save( + **options) return d diff --git a/modoboa/admin/handlers.py b/modoboa/admin/handlers.py index a767b0666..04e3b2175 100644 --- a/modoboa/admin/handlers.py +++ b/modoboa/admin/handlers.py @@ -6,6 +6,29 @@ from django.dispatch import receiver from . import models +@receiver(signals.post_save, sender=models.Domain) +def update_domain_mailboxes(sender, instance, **kwargs): + """Update associated mailboxes.""" + if kwargs.get("created"): + return + instance.mailbox_set.filter(use_domain_quota=True).update( + quota=instance.quota) + if instance.old_mail_homes is None: + return + qset = ( + models.Quota.objects.filter( + username__contains="@{}".format(instance.oldname)) + ) + for q in qset: + username = q.username.replace( + "@{}".format(instance.oldname), "@{}".format(instance.name)) + models.Quota.objects.create( + username=username, bytes=q.bytes, messages=q.messages) + q.delete() + for mb in instance.mailbox_set.all(): + mb.rename_dir(instance.old_mail_homes[mb.pk]) + + @receiver(signals.post_save, sender=models.DomainAlias) def create_alias_for_domainalias(sender, instance, **kwargs): """Create a dedicated alias for domain alias.""" diff --git a/modoboa/admin/models/domain.py b/modoboa/admin/models/domain.py index bbe6928f4..65267a6a9 100644 --- a/modoboa/admin/models/domain.py +++ b/modoboa/admin/models/domain.py @@ -29,7 +29,6 @@ class DomainManager(Manager): @python_2_unicode_compatible class Domain(AdminObject): - """Mail domain.""" name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True, @@ -53,6 +52,12 @@ class Domain(AdminObject): ordering = ["name"] app_label = "admin" + def __init__(self, *args, **kwargs): + """Save name for further use.""" + super(Domain, self).__init__(*args, **kwargs) + self.old_mail_homes = None + self.oldname = self.name + @property def domainalias_count(self): return self.domainalias_set.count() @@ -124,9 +129,16 @@ class Domain(AdminObject): for al in self.alias_set.all(): ungrant_access_to_object(al, account) + def save(self, *args, **kwargs): + """Store current data if domain is renamed.""" + if self.oldname != self.name: + self.old_mail_homes = ( + dict((mb.id, mb.mail_home) for mb in self.mailbox_set.all()) + ) + super(Domain, self).save(*args, **kwargs) + def delete(self, fromuser, keepdir=False): - """Custom delete method. - """ + """Custom delete method.""" from modoboa.lib.permissions import ungrant_access_to_objects from .mailbox import Quota diff --git a/modoboa/admin/tests/api.py b/modoboa/admin/tests/api.py index 7487a2ae6..f319ef24e 100644 --- a/modoboa/admin/tests/api.py +++ b/modoboa/admin/tests/api.py @@ -55,12 +55,17 @@ class APITestCase(ModoAPITestCase): def test_update_domain(self): """Check domain update.""" domain = models.Domain.objects.get(name="test.com") + models.Mailbox.objects.filter( + domain__name="test.com", address="user").update( + use_domain_quota=True) url = reverse("external_api:domain-detail", args=[domain.pk]) response = self.client.put(url, {"name": "test.com", "quota": 1000}) self.assertEqual(response.status_code, 200) domain.refresh_from_db() self.assertEqual(domain.quota, 1000) + mb = models.Mailbox.objects.get( + domain__name="test.com", address="user") + self.assertEqual(mb.quota, 1000) response = self.client.put(url, {"name": "test42.com", "quota": 1000}) self.assertEqual(response.status_code, 200) -