diff --git a/orchestra/contrib/databases/forms.py b/orchestra/contrib/databases/forms.py index 1504366a..59aa4745 100644 --- a/orchestra/contrib/databases/forms.py +++ b/orchestra/contrib/databases/forms.py @@ -5,7 +5,7 @@ from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ -from orchestra.core.validators import validate_password +from orchestra.core import validators from .models import DatabaseUser, Database @@ -13,7 +13,7 @@ from .models import DatabaseUser, Database class DatabaseUserCreationForm(forms.ModelForm): password1 = forms.CharField(label=_("Password"), required=False, widget=forms.PasswordInput(attrs={'autocomplete': 'off'}), - validators=[validate_password]) + validators=[validators.validate_password]) password2 = forms.CharField(label=_("Password confirmation"), required=False, widget=forms.PasswordInput, help_text=_("Enter the same password as above, for verification.")) @@ -32,12 +32,12 @@ class DatabaseUserCreationForm(forms.ModelForm): class DatabaseCreationForm(DatabaseUserCreationForm): - username = forms.RegexField(label=_("Username"), max_length=30, - required=False, regex=r'^[\w.@+-]+$', - help_text=_("Required. 30 characters or fewer. Letters, digits and " + username = forms.CharField(label=_("Username"), max_length=16, + required=False, validators=[validators.validate_name], + help_text=_("Required. 16 characters or fewer. Letters, digits and " "@/./+/-/_ only."), error_messages={ - 'invalid': _("This value may contain only letters, numbers and " + 'invalid': _("This value may contain 16 characters or fewer, only letters, numbers and " "@/./+/-/_ characters.")}) user = forms.ModelChoiceField(required=False, queryset=DatabaseUser.objects) diff --git a/orchestra/contrib/mailboxes/backends.py b/orchestra/contrib/mailboxes/backends.py index ec766975..26dca795 100644 --- a/orchestra/contrib/mailboxes/backends.py +++ b/orchestra/contrib/mailboxes/backends.py @@ -264,13 +264,18 @@ class PostfixAddressVirtualDomainBackend(ServiceController): def exclude_virtual_alias_domain(self, context): domain = context['domain'] if self.is_last_domain(domain): - self.append(textwrap.dedent(""" - # Delete %(domain)s virtual domain - if grep '^%(domain)s\s*$' %(virtual_alias_domains)s > /dev/null; then - sed -i '/^%(domain)s\s*/d' %(virtual_alias_domains)s - UPDATED_VIRTUAL_ALIAS_DOMAINS=1 - fi""") % context - ) + # Prevent deleting the same domain multiple times on bulk deletes + if not hasattr(self, '_excluded_domains'): + self._excluded_domains = set() + if domain.name not in self._excluded_domains: + self._excluded_domains.add(domain.name) + self.append(textwrap.dedent(""" + # Delete %(domain)s virtual domain + if grep '^%(domain)s\s*$' %(virtual_alias_domains)s > /dev/null; then + sed -i '/^%(domain)s\s*/d' %(virtual_alias_domains)s + UPDATED_VIRTUAL_ALIAS_DOMAINS=1 + fi""") % context + ) def save(self, address): context = self.get_context(address) @@ -378,7 +383,7 @@ class PostfixAddressBackend(PostfixAddressVirtualDomainBackend): self.update_virtual_alias_maps(address, context) def delete(self, address): - context = super().save(address) + context = super().delete(address) self.exclude_virtual_alias_maps(context) def commit(self):