diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py index 471949b8..a3a01fde 100644 --- a/orchestra/contrib/mailboxes/admin.py +++ b/orchestra/contrib/mailboxes/admin.py @@ -4,7 +4,7 @@ from urllib.parse import parse_qs from django import forms from django.contrib import admin, messages from django.core.urlresolvers import reverse -from django.db.models import F, Value as V +from django.db.models import F, Count, Value as V from django.db.models.functions import Concat from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -96,7 +96,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo url = change_url(addr) forwards.append('%s' % (url, addr.email)) return '
'.join(forwards) - display_forwards.short_description = _("Forwards") + display_forwards.short_description = _("Forward from") display_forwards.allow_tags = True def display_filtering(self, mailbox): @@ -203,13 +203,13 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): 'display_email', 'account_link', 'domain_link', 'display_mailboxes', 'display_forward', ) list_filter = (HasMailboxListFilter, HasForwardListFilter) - fields = ('account_link', 'email_link', 'mailboxes', 'forward') + fields = ('account_link', 'email_link', 'mailboxes', 'forward', 'display_all_mailboxes') add_fields = ('account_link', ('name', 'domain'), 'mailboxes', 'forward') # inlines = [AutoresponseInline] search_fields = ( 'forward', 'mailboxes__name', 'account__username', 'computed_email', 'domain__name' ) - readonly_fields = ('account_link', 'domain_link', 'email_link') + readonly_fields = ('account_link', 'domain_link', 'email_link', 'display_all_mailboxes') actions = (SendAddressEmail(),) filter_by_account_fields = ('domain', 'mailboxes') filter_horizontal = ['mailboxes'] @@ -237,6 +237,16 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): return '
'.join(boxes) display_mailboxes.short_description = _("Mailboxes") display_mailboxes.allow_tags = True + display_mailboxes.admin_order_field = 'mailboxes__count' + + def display_all_mailboxes(self, address): + boxes = [] + for mailbox in address.get_mailboxes(): + url = change_url(mailbox) + boxes.append('%s' % (url, mailbox.name)) + return '
'.join(boxes) + display_all_mailboxes.short_description = _("Mailboxes links") + display_all_mailboxes.allow_tags = True def display_forward(self, address): forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()} @@ -268,7 +278,8 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): def get_queryset(self, request): qs = super(AddressAdmin, self).get_queryset(request) - return qs.annotate(computed_email=Concat(F('name'), V('@'), F('domain__name'))) + qs = qs.annotate(computed_email=Concat(F('name'), V('@'), F('domain__name'))) + return qs.annotate(Count('mailboxes')) def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): if not add: diff --git a/orchestra/contrib/mailboxes/models.py b/orchestra/contrib/mailboxes/models.py index 7caf240a..0c609107 100644 --- a/orchestra/contrib/mailboxes/models.py +++ b/orchestra/contrib/mailboxes/models.py @@ -151,13 +151,12 @@ class Address(models.Model): def get_forward_mailboxes(self): rm_local_domain = re.compile(r'@%s$' % settings.MAILBOXES_LOCAL_DOMAIN) + mailboxes = [] for forward in self.forward.split(): forward = rm_local_domain.sub('', forward) if '@' not in forward: - try: - yield Mailbox.objects.get(name=forward) - except Mailbox.DoesNotExist: - pass + mailboxes.append(forward) + return Mailbox.objects.filter(name__in=mailboxes) def get_mailboxes(self): for mailbox in self.mailboxes.all(): diff --git a/orchestra/contrib/mailboxes/signals.py b/orchestra/contrib/mailboxes/signals.py index 4330a1d1..8bb45533 100644 --- a/orchestra/contrib/mailboxes/signals.py +++ b/orchestra/contrib/mailboxes/signals.py @@ -12,7 +12,7 @@ from .models import Mailbox, Address def delete_forwards(sender, *args, **kwargs): # Cleanup related addresses instance = kwargs['instance'] - for address in Address.objects.filter(forward__regex=r'.*(^|\s)+%s($|\s)+.*' % instance.name): + for address in instance.get_forwards(): forward = address.forward.split() forward.remove(instance.name) address.forward = ' '.join(forward) diff --git a/orchestra/contrib/systemusers/backends.py b/orchestra/contrib/systemusers/backends.py index 83c15b77..9b1d5099 100644 --- a/orchestra/contrib/systemusers/backends.py +++ b/orchestra/contrib/systemusers/backends.py @@ -28,59 +28,60 @@ class UNIXUserController(ServiceController): context = self.get_context(user) if not context['user']: return - groups = ','.join(self.get_groups(user)) - context['groups_arg'] = '--groups %s' % groups if groups else '' # TODO userd add will fail if %(user)s group already exists self.append(textwrap.dedent(""" # Update/create user state for %(user)s if id %(user)s ; then - usermod %(user)s --home %(home)s \\ + usermod %(user)s --home '%(home)s' \\ --password '%(password)s' \\ - --shell %(shell)s %(groups_arg)s + --shell '%(shell)s' \\ + --groups '%(groups)s' else useradd_code=0 - useradd %(user)s --home %(home)s \\ + useradd %(user)s --home '%(home)s' \\ --password '%(password)s' \\ - --shell %(shell)s %(groups_arg)s || useradd_code=$? + --shell '%(shell)s' \\ + --groups '%(groups)s' || useradd_code=$? if [[ $useradd_code -eq 8 ]]; then # User is logged in, kill and retry pkill -u %(user)s; sleep 2 pkill -9 -u %(user)s; sleep 1 - useradd %(user)s --home %(home)s \\ + useradd %(user)s --home '%(home)s' \\ --password '%(password)s' \\ - --shell %(shell)s %(groups_arg)s + --shell '%(shell)s' \\ + --groups '%(groups)s' elif [[ $useradd_code -ne 0 ]]; then exit $useradd_code fi fi - mkdir -p %(base_home)s - chmod 750 %(base_home)s + mkdir -p '%(base_home)s' + chmod 750 '%(base_home)s' """) % context ) if context['home'] != context['base_home']: - self.append(textwrap.dedent(""" + self.append(textwrap.dedent("""\ # Set extra permissions: %(user)s home is inside %(mainuser)s home if mount | grep "^$(df %(home)s|grep '^/'|cut -d' ' -f1)\s" | grep acl > /dev/null; then # Account group as the owner - chown %(mainuser)s:%(mainuser)s %(home)s - chmod g+s %(home)s + chown %(mainuser)s:%(mainuser)s '%(home)s' + chmod g+s '%(home)s' # Home access setfacl -m u:%(user)s:--x '%(mainuser_home)s' # Grant perms to future files within the directory - setfacl -m d:u:%(user)s:rwx %(home)s + setfacl -m d:u:%(user)s:rwx '%(home)s' # Grant access to main user - setfacl -m d:u:%(mainuser)s:rwx %(home)s + setfacl -m d:u:%(mainuser)s:rwx '%(home)s' else chmod g+rxw %(home)s fi""") % context ) else: self.append(textwrap.dedent("""\ - chown %(user)s:%(group)s %(home)s + chown %(user)s:%(group)s '%(home)s' ls -A /etc/skel/ | while read line; do - if [[ ! -e %(home)s/${line} ]]; then - cp -a /etc/skel/${line} %(home)s/${line} && \\ - chown -R %(user)s:%(group)s %(home)s/${line} + if [[ ! -e "%(home)s/${line}" ]]; then + cp -a "/etc/skel/${line}" "%(home)s/${line}" && \\ + chown -R %(user)s:%(group)s "%(home)s/${line}" fi done """) % context @@ -107,14 +108,14 @@ class UNIXUserController(ServiceController): self.append(textwrap.dedent("""\ # Move home into SYSTEMUSERS_MOVE_ON_DELETE_PATH, nesting if exists. deleted_home="%(deleted_home)s" - while [[ -e $deleted_home ]]; do + while [[ -e "$deleted_home" ]]; do deleted_home="${deleted_home}/$(basename ${deleted_home})" done - mv %(base_home)s $deleted_home || exit_code=$? + mv '%(base_home)s' "$deleted_home" || exit_code=$? """) % context ) else: - self.append("rm -fr %(base_home)s" % context) + self.append("rm -fr '%(base_home)s'" % context) def grant_permissions(self, user, context): context['perms'] = user.set_perm_perms @@ -206,8 +207,8 @@ class UNIXUserController(ServiceController): self.append(textwrap.dedent("""\ # Create link su %(user)s --shell /bin/bash << 'EOF' || exit_code=1 - if [[ ! -e %(link_name)s ]]; then - ln -s %(link_target)s %(link_name)s + if [[ ! -e '%(link_name)s' ]]; then + ln -s '%(link_target)s' '%(link_name)s' else echo "%(link_name)s already exists, doing nothing." >&2 exit 1 @@ -236,6 +237,7 @@ class UNIXUserController(ServiceController): 'object_id': user.pk, 'user': user.username, 'group': user.username, + 'groups': ','.join(self.get_groups(user)), 'password': user.password if user.active else '*%s' % user.password, 'shell': user.shell, 'mainuser': user.username if user.is_main else user.account.username,