diff --git a/TODO.md b/TODO.md
index 28461b3c..9ba640e1 100644
--- a/TODO.md
+++ b/TODO.md
@@ -463,4 +463,6 @@ with open(file) as handler:
# Mark transaction process as executed should not override higher transaction states
-# Show password and set password management commands -sam -A|--all --systemuser --account --mailbox vs raw passwords on forms
+# mailbox.addresses get_Queryset SQL contact @ with mailboxes and forwards
+
+# Remove membership fee when changing account.type
diff --git a/orchestra/admin/options.py b/orchestra/admin/options.py
index 3bce46f9..deee5194 100644
--- a/orchestra/admin/options.py
+++ b/orchestra/admin/options.py
@@ -285,8 +285,7 @@ class ChangePasswordAdminMixin(object):
form = self.change_password_form(obj, request.POST, related=related, raw=raw)
if form.is_valid():
form.save()
- change_message = self.construct_change_message(request, form, None)
- self.log_change(request, obj, change_message)
+ self.log_change(request, obj, _("Password changed."))
msg = _('Password changed successfully.')
messages.success(request, msg)
update_session_auth_hash(request, form.user) # This is safe
diff --git a/orchestra/contrib/history/admin.py b/orchestra/contrib/history/admin.py
index 430eb9aa..7d2b86e5 100644
--- a/orchestra/contrib/history/admin.py
+++ b/orchestra/contrib/history/admin.py
@@ -15,6 +15,7 @@ class LogEntryAdmin(admin.ModelAdmin):
)
list_filter = (
'action_flag',
+ ('user', admin.RelatedOnlyFieldListFilter),
('content_type', admin.RelatedOnlyFieldListFilter),
)
date_hierarchy = 'action_time'
diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py
index a3a01fde..7c45e3d8 100644
--- a/orchestra/contrib/mailboxes/admin.py
+++ b/orchestra/contrib/mailboxes/admin.py
@@ -15,6 +15,7 @@ from orchestra.admin.utils import admin_link, change_url
from orchestra.contrib.accounts.actions import list_accounts
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
from orchestra.contrib.accounts.filters import IsActiveListFilter
+from orchestra.core import caches
from . import settings
from .actions import SendMailboxEmail, SendAddressEmail
@@ -82,11 +83,33 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
type(self).actions = self.actions + (SendMailboxEmail(),)
def display_addresses(self, mailbox):
+ # Get from forwards
+ cache = caches.get_request_cache()
+ cached_forwards = cache.get('forwards')
+ if cached_forwards is None:
+ cached_forwards = {}
+ qs = Address.objects.filter(forward__regex=r'(^|.*\s)[^@]+(\s.*|$)')
+ qs = qs.select_related('domain')
+ qs = qs.annotate(email=Concat('name', V('@'), 'domain__name'))
+ qs = qs.values_list('id', 'email', 'forward')
+ for addr_id, email, mbox in qs:
+ url = reverse('admin:mailboxes_address_change', args=(addr_id,))
+ link = '%s' % (url, email)
+ try:
+ cached_forwards[mbox].append(link)
+ except KeyError:
+ cached_forwards[mbox] = [link]
+ cache.set('forwards', cached_forwards)
+ try:
+ forwards = cached_forwards[mailbox.name]
+ except KeyError:
+ forwards = []
+ # Get from mailboxes
addresses = []
for addr in mailbox.addresses.all():
url = change_url(addr)
addresses.append('%s' % (url, addr.email))
- return '
'.join(addresses)
+ return '
'.join(addresses+forwards)
display_addresses.short_description = _("Addresses")
display_addresses.allow_tags = True
diff --git a/orchestra/contrib/mailboxes/backends.py b/orchestra/contrib/mailboxes/backends.py
index 773e7661..ebef95e1 100644
--- a/orchestra/contrib/mailboxes/backends.py
+++ b/orchestra/contrib/mailboxes/backends.py
@@ -70,7 +70,7 @@ class UNIXUserMaildirController(SieveFilteringMixin, ServiceController):
# Update/create %(user)s user state
if id %(user)s ; then
old_password=$(getent shadow %(user)s | cut -d':' -f2)
- usermod %(user)s \\
+ usermod %(user)s \\
--shell %(initial_shell)s \\
--password '%(password)s'
if [[ "$old_password" != '%(password)s' ]]; then
diff --git a/orchestra/contrib/orchestration/managers.py b/orchestra/contrib/orchestration/managers.py
index c91847da..f91ae291 100644
--- a/orchestra/contrib/orchestration/managers.py
+++ b/orchestra/contrib/orchestration/managers.py
@@ -35,6 +35,14 @@ def m2m_collector(sender, *args, **kwargs):
class orchestrate(ContextDecorator):
+ """
+ Context manager for triggering backend operations out of request-response cycle, e.g. shell
+
+ with orchestrate():
+ user = SystemUser.objects.get(username='rata')
+ user.shell = '/dev/null'
+ user.save(update_fields=('shell',))
+ """
thread_locals = local()
thread_locals.pending_operations = None
thread_locals.route_cache = None
diff --git a/orchestra/contrib/orders/admin.py b/orchestra/contrib/orders/admin.py
index 024cbc5f..a2918f11 100644
--- a/orchestra/contrib/orders/admin.py
+++ b/orchestra/contrib/orders/admin.py
@@ -56,7 +56,8 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
'display_metric'
)
list_filter = (
- ActiveOrderListFilter, IgnoreOrderListFilter, BilledOrderListFilter, 'service'
+ ActiveOrderListFilter, IgnoreOrderListFilter, BilledOrderListFilter, 'account__type',
+ 'service',
)
default_changelist_filters = (
('ignore', '0'),
diff --git a/orchestra/contrib/systemusers/actions.py b/orchestra/contrib/systemusers/actions.py
index f896e797..b37780c3 100644
--- a/orchestra/contrib/systemusers/actions.py
+++ b/orchestra/contrib/systemusers/actions.py
@@ -47,7 +47,7 @@ def set_permission(modeladmin, request, queryset):
user.set_perm_perms)
context = {
'action': verbose_action,
- 'perms': verbose_permissions,
+ 'perms': verbose_permissions.lower(),
'to': os.path.join(user.set_perm_base_home, user.set_perm_home_extension),
}
msg = _("%(action)s %(perms)s permission to %(to)s") % context