class AccountPermissionsForm(forms.Form, DynamicForm): domains = DomainNameField( label=ugettext_lazy("Domain(s)"), required=False, help_text=ugettext_lazy("Domain(s) that user administrates")) def __init__(self, *args, **kwargs): if "instance" in kwargs: self.account = kwargs["instance"] del kwargs["instance"] super(AccountPermissionsForm, self).__init__(*args, **kwargs) if not hasattr(self, "account") or self.account is None: return for pos, dom in enumerate(Domain.objects.get_for_admin(self.account)): name = "domains_%d" % (pos + 1) self._create_field(DomainNameField, name, dom.name) if len(args) and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "domains", DomainNameField) def save(self): current_domains = [ dom.name for dom in Domain.objects.get_for_admin(self.account) ] for name, value in self.cleaned_data.items(): if not name.startswith("domains"): continue if value in ["", None]: continue if value not in current_domains: domain = Domain.objects.get(name=value) domain.add_admin(self.account) for domain in Domain.objects.get_for_admin(self.account): if not filter(lambda name: self.cleaned_data[name] == domain.name, self.cleaned_data.keys()): domain.remove_admin(self.account)
class RelayDomainFormGeneral(forms.ModelForm): """RelayDomain form.""" name = DomainNameField(label=ugettext_lazy("Name"), help_text=ugettext_lazy("The relay domain name")) class Meta: model = RelayDomain exclude = ["domain", "dates"] widgets = {"service": forms.Select(attrs={"class": "form-control"})} def __init__(self, *args, **kwargs): super(RelayDomainFormGeneral, self).__init__(*args, **kwargs) self.field_widths = {"service": 3} def save(self, *args, **kwargs): """Custom save method.""" domain = kwargs.get("domain") instance = super(RelayDomainFormGeneral, self).save(commit=False) if domain: instance.domain = domain instance.save() return instance
class RelayDomainFormGeneral(forms.ModelForm, DynamicForm): aliases = DomainNameField( label=ugettext_lazy("Alias(es)"), required=False, help_text=ugettext_lazy( "Alias(es) of this relay domain. Indicate only one name per input" ", press ENTER to add a new input.")) class Meta: model = RelayDomain exclude = ['dates'] widgets = {"service": forms.Select(attrs={"class": "form-control"})} def __init__(self, *args, **kwargs): self.oldname = None if "instance" in kwargs: self.oldname = kwargs["instance"].name super(RelayDomainFormGeneral, self).__init__(*args, **kwargs) self.field_widths = {"service": 3} if args and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "aliases", DomainNameField) elif 'instance' in kwargs: rd = kwargs['instance'] for pos, rdalias in enumerate(rd.relaydomainalias_set.all()): name = "aliases_%d" % (pos + 1) self._create_field(forms.CharField, name, rdalias.name, 3) def clean(self): """Custom fields validaton. We want to prevent duplicate names between domains, relay domains, domain aliases and relay domain aliases. The validation way is not very smart... """ super(RelayDomainFormGeneral, self).clean() cleaned_data = self.cleaned_data for dtype, label in [(Domain, _('domain')), (DomainAlias, _('domain alias')), (RelayDomainAlias, _('relay domain alias'))]: try: dtype.objects.get(name=cleaned_data['name']) except dtype.DoesNotExist: pass else: self.add_error("name", _("A %s with this name already exists") % label) break for k in cleaned_data.keys(): if not k.startswith("aliases"): continue if not cleaned_data[k]: del cleaned_data[k] continue for dtype, name in [(RelayDomain, _('relay domain')), (DomainAlias, _('domain alias')), (Domain, _('domain'))]: try: dtype.objects.get(name=cleaned_data[k]) except dtype.DoesNotExist: pass else: self.add_error( k, _("A %s with this name already exists") % name) break return cleaned_data def save(self, user, commit=True, rdomalias_post_create=False): """Custom save method. As relay domain aliases are defined using the same form as relay domains, we need to save them manually. :param ``User`` user: connected user """ rd = super(RelayDomainFormGeneral, self).save(commit=False) if commit: rd.oldname = self.oldname rd.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 rdalias in rd.relaydomainalias_set.all(): if rdalias.name not in aliases: rdalias.delete() else: aliases.remove(rdalias.name) if aliases: events.raiseEvent("CanCreate", user, "relay_domain_aliases", len(aliases)) for alias in aliases: try: rd.relaydomainalias_set.get(name=alias) except RelayDomainAlias.DoesNotExist: pass else: continue al = RelayDomainAlias(name=alias, target=rd, enabled=rd.enabled) al.save(creator=user) \ if rdomalias_post_create else al.save() return rd
class DomainFormGeneral(forms.ModelForm, DynamicForm): quota = forms.IntegerField( label=ugettext_lazy("Quota"), required=False, help_text=ugettext_lazy( "Default quota in MB applied to mailboxes. Leave empty to use the " "default value.")) aliases = DomainNameField( label=ugettext_lazy("Alias(es)"), required=False, help_text=ugettext_lazy( "Alias(es) of this domain. Indicate only one name per input, " "press ENTER to add a new input.")) name = DomainNameField(widget=forms.TextInput()) class Meta: model = Domain fields = ("name", "quota", "aliases", "enabled") def __init__(self, *args, **kwargs): self.oldname = None if "instance" in kwargs: self.oldname = kwargs["instance"].name super(DomainFormGeneral, self).__init__(*args, **kwargs) self.field_widths = {"quota": 3} if len(args) and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "aliases", DomainNameField) elif "instance" in kwargs: d = kwargs["instance"] for pos, dalias in enumerate(d.domainalias_set.all()): name = "aliases_%d" % (pos + 1) self._create_field(forms.CharField, name, dalias.name, 3) def clean_quota(self): if self.cleaned_data['quota'] is None: return int(parameters.get_admin('DEFAULT_DOMAIN_QUOTA')) if self.cleaned_data['quota'] < 0: raise forms.ValidationError(_("Must be a positive integer")) return self.cleaned_data['quota'] def clean(self): """Custom fields validation. We want to prevent duplicate names between domains and domain aliases. Extensions have the possibility to declare other objects (see *CheckDomainName* event). The validation way is not very smart... """ super(DomainFormGeneral, self).clean() if self._errors: raise forms.ValidationError(self._errors) cleaned_data = self.cleaned_data name = cleaned_data["name"] label = check_if_domain_exists(name, [(DomainAlias, _('domain alias'))]) if label is not None: self._errors["name"] = self.error_class( [_("A %s with this name already exists" % unicode(label))]) del cleaned_data["name"] for k in cleaned_data.keys(): if not k.startswith("aliases"): continue if cleaned_data[k] == "": del cleaned_data[k] continue if cleaned_data[k] == name: self._errors[k] = self.error_class( [_("A %s with this name already exists") % _("domain")]) del cleaned_data[k] continue label = check_if_domain_exists(cleaned_data[k], [(Domain, _("domain"))]) if label is not None: self._errors[k] = self.error_class( [_("A %s with this name already exists" % unicode(label))]) del cleaned_data[k] return cleaned_data def update_mailbox_quotas(self, domain): """Update all quota records associated to this domain. This method must be called only when a domain gets renamed. As the primary key used for a quota is an email address, rename a domain will change all associated email addresses, so it will change the primary keys used for quotas. The consequence is we can't issue regular UPDATE queries using the .save() method of a Quota instance (it will trigger an INSERT as the primary key has changed). So, we use this ugly hack to bypass this behaviour. It is not perfomant at all as it will generate one query per quota record to update. """ for q in Quota.objects.filter(username__contains="@%s" % self.oldname): username = q.username.replace('@%s' % self.oldname, '@%s' % domain.name) newq = Quota.objects.create(username=username, bytes=q.bytes, messages=q.messages) q.delete() def save(self, user, commit=True, domalias_post_create=False): """Custom save method Updating a domain may have consequences on other objects (domain alias, mailbox, quota). The most tricky part concerns quotas update. """ 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() 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]) return d