diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 2906089cc..ccfc3624e 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -1,3 +1,4 @@ +import os import re import hashlib import crypt @@ -15,6 +16,7 @@ from django.contrib.contenttypes import generic from django.contrib.auth.models import ( UserManager, Group, AbstractBaseUser, PermissionsMixin ) +from django.contrib.contenttypes.models import ContentType from modoboa.lib import events, md5crypt, parameters from modoboa.lib.exceptions import PermDeniedException from modoboa.core.extensions import exts_pool @@ -43,6 +45,7 @@ class User(AbstractBaseUser, PermissionsMixin): is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) date_joined = models.DateTimeField(default=timezone.now) + is_local = models.BooleanField(default=True) objects = UserManager() @@ -90,21 +93,6 @@ class User(AbstractBaseUser, PermissionsMixin): ungrant_access_to_object(self) super(User, self).delete(*args, **kwargs) - @staticmethod - def get_content_type(): - """An uggly hack to retrieve the appropriate content_type! - - The explanation is available here: - https://code.djangoproject.com/ticket/11154 - - Quickly, the content_types framework does not retrieve the - appropriate content type for proxy models, it retrieves the - one of the first parent that is not a proxy. - """ - if not hasattr(User, "ct"): - User.ct = ContentType.objects.get(app_label="admin", model="user") - return User.ct - def _crypt_password(self, raw_value): scheme = parameters.get_admin("PASSWORD_SCHEME") if type(raw_value) is unicode: @@ -252,9 +240,7 @@ class User(AbstractBaseUser, PermissionsMixin): :param obj: an object inheriting from ``models.Model`` :return: a boolean """ - from modoboa.lib.permissions import get_content_type - - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) try: ooentry = self.objectaccess_set.get(content_type=ct, object_id=obj.id) except ObjectAccess.DoesNotExist: @@ -271,12 +257,10 @@ class User(AbstractBaseUser, PermissionsMixin): :param obj: a admin object :return: a boolean """ - from modoboa.lib.permissions import get_content_type - if self.is_superuser: return True - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) try: ooentry = self.objectaccess_set.get(content_type=ct, object_id=obj.id) except ObjectAccess.DoesNotExist: @@ -286,25 +270,13 @@ class User(AbstractBaseUser, PermissionsMixin): if ct.model == "user": return False - ct = self.get_content_type() + ct = ContentType.objects.get_for_model(self) qs = self.objectaccess_set.filter(content_type=ct) for ooentry in qs.all(): if ooentry.content_object.is_owner(obj): return True return False - def grant_access_to_all_objects(self): - """Give access to all objects defined in the database - - Must be used when an account is promoted as a super user. - """ - from modoboa.lib.permissions import grant_access_to_objects, get_content_type - grant_access_to_objects(self, User.objects.all(), get_content_type(User)) - grant_access_to_objects(self, Domain.objects.all(), get_content_type(Domain)) - grant_access_to_objects(self, DomainAlias.objects.all(), get_content_type(DomainAlias)) - grant_access_to_objects(self, Mailbox.objects.all(), get_content_type(Mailbox)) - grant_access_to_objects(self, Alias.objects.all(), get_content_type(Alias)) - def set_role(self, role): """Set administrative role for this account @@ -312,10 +284,10 @@ class User(AbstractBaseUser, PermissionsMixin): """ if role is None or self.group == role: return + events.raiseEvent("RoleChanged", self, role) self.groups.clear() if role == "SuperAdmins": self.is_superuser = True - self.grant_access_to_all_objects() else: if self.is_superuser: ObjectAccess.objects.filter(user=self).delete() @@ -372,35 +344,13 @@ class User(AbstractBaseUser, PermissionsMixin): self.is_active = (row[5].strip() == 'True') self.save(creator=user) self.set_role(role) - - self.email = row[7].strip() - if self.email != "": - mailbox, domname = split_mailbox(self.email) - try: - domain = Domain.objects.get(name=domname) - except Domain.DoesNotExist: - raise AdminError( - _("Account import failed (%s): domain does not exist" % self.username) - ) - if not user.can_access(domain): - raise PermDeniedException - mb = Mailbox(address=mailbox, domain=domain, user=self, use_domain_quota=True) - mb.set_quota(override_rules=user.has_perm("admin.change_domain")) - mb.save(creator=user) - if self.group == "DomainAdmins": - for domname in row[8:]: - try: - dom = Domain.objects.get(name=domname.strip()) - except Domain.DoesNotExist: - continue - dom.add_admin(self) + events.raiseEvent("AccountImported", user, self, row[7:]) def to_csv(self, csvwriter): row = ["account", self.username.encode("utf-8"), self.password, self.first_name.encode("utf-8"), self.last_name.encode("utf-8"), self.is_active, self.group, self.email] - if self.group == "DomainAdmins": - row += [dom.name for dom in self.get_domains()] + row += events.raiseQueryEvent("AccountExported", self) csvwriter.writerow(row) reversion.register(User) diff --git a/modoboa/extensions/admin/__init__.py b/modoboa/extensions/admin/__init__.py index fc229ab81..b966c4d75 100644 --- a/modoboa/extensions/admin/__init__.py +++ b/modoboa/extensions/admin/__init__.py @@ -3,6 +3,36 @@ from django.utils.translation import ugettext as _, ugettext_lazy from django.core.urlresolvers import reverse from modoboa.core.extensions import ModoExtension, exts_pool from modoboa.lib import parameters, events +from modoboa.lib.exceptions import PermDeniedException +from modoboa.lib.emailutils import split_mailbox +from modoboa.extensions.admin.exceptions import AdminError +from modoboa.extensions.admin.models import ( + Domain, DomainAlias, Mailbox, Alias +) + + +admin_events = [ + "CreateDomain", + "DomainModified", + "DeleteDomain", + + "DomainAliasCreated", + "DomainAliasDeleted", + + "CreateMailbox", + "DeleteMailbox", + "ModifyMailbox", + + "MailboxAliasCreated", + "MailboxAliasDeleted", + + "ExtraDomainForm", + "FillDomainInstances", + + "ExtraAccountForm", + "CheckExtraAccountForm", + "FillAccountInstances", +] class AdminConsole(ModoExtension): @@ -13,8 +43,9 @@ class AdminConsole(ModoExtension): always_active = True def load(self): - from app_settings import AdminParametersForm + from modoboa.extensions.admin.app_settings import AdminParametersForm parameters.register(AdminParametersForm, ugettext_lazy("Administration")) + events.declare(admin_events) def destroy(self): parameters.unregister() @@ -25,7 +56,6 @@ exts_pool.register_extension(AdminConsole, show=False) @events.observe("AdminMenuDisplay") def menu(target, user): if target != "top_menu": - print "rien" return [] entries = [] if user.has_perm("admin.view_domains"): @@ -40,5 +70,67 @@ def menu(target, user): "url" : reverse("modoboa.extensions.admin.views.identity.identities"), "label" : _("Identities")}, ] - print entries return entries + + +@events.observe("RoleChanged") +def grant_access_to_all_objects(user, role): + from django.contrib.contenttypes.models import ContentType + from modoboa.lib.permissions import grant_access_to_objects + from modoboa.core.models import User + + if role != "SuperAdmins": + return + grant_access_to_objects( + user, User.objects.all(), + ContentType.objects.get_for_model(User) + ) + grant_access_to_objects( + user, Domain.objects.all(), + ContentType.objects.get_for_model(Domain) + ) + grant_access_to_objects( + user, DomainAlias.objects.all(), + ContentType.objects.get_for_model(DomainAlias) + ) + grant_access_to_objects( + user, Mailbox.objects.all(), + ContentType.objects.get_for_model(Mailbox) + ) + grant_access_to_objects( + user, Alias.objects.all(), + ContentType.objects.get_for_model(Alias) + ) + + +@events.observe("AccountExported") +def export_admin_domains(admin): + if admin.group != "DomainAdmins": + return [] + return [dom.name for dom in Domain.objects.get_for_admin(admin)] + + +@events.observe("AccountImported") +def import_account_mailbox(user, account, row): + account.email = row[0].strip() + if account.email != "": + mailbox, domname = split_mailbox(account.email) + try: + domain = Domain.objects.get(name=domname) + except Domain.DoesNotExist: + raise AdminError( + _("Account import failed (%s): domain does not exist" % account.username) + ) + if not user.can_access(domain): + raise PermDeniedException + mb = Mailbox(address=mailbox, domain=domain, + user=account, use_domain_quota=True) + mb.set_quota(override_rules=user.has_perm("admin.change_domain")) + mb.save(creator=user) + if account.group == "DomainAdmins": + for domname in row[1:]: + try: + dom = Domain.objects.get(name=domname.strip()) + except Domain.DoesNotExist: + continue + dom.add_admin(account) diff --git a/modoboa/extensions/admin/fixtures/initial_data.json b/modoboa/extensions/admin/fixtures/initial_data.json index cb8d94e14..9ad462996 100644 --- a/modoboa/extensions/admin/fixtures/initial_data.json +++ b/modoboa/extensions/admin/fixtures/initial_data.json @@ -1 +1 @@ -[{"pk": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["add_user", "admin", "user"], ["change_user", "admin", "user"], ["delete_user", "admin", "user"], ["view_domains", "admin", "domain"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"]]}},{"pk": 2, "model": "auth.group", "fields": {"name": "SimpleUsers", "permissions": []}}] +[{"pk": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["add_user", "core", "user"], ["change_user", "core", "user"], ["delete_user", "core", "user"], ["view_domains", "admin", "domain"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"]]}},{"pk": 2, "model": "auth.group", "fields": {"name": "SimpleUsers", "permissions": []}}] diff --git a/modoboa/extensions/admin/fixtures/initial_users.json b/modoboa/extensions/admin/fixtures/initial_users.json index 3c8921f65..b67729ef2 100644 --- a/modoboa/extensions/admin/fixtures/initial_users.json +++ b/modoboa/extensions/admin/fixtures/initial_users.json @@ -1 +1 @@ -[{"pk": 1, "model": "admin.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "last_login": "2012-01-26 15:19:25", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26 15:19:25"}},{"pk": 1, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "user"], "object_id": 1}}] \ No newline at end of file +[{"pk": 1, "model": "core.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "is_local": true, "last_login": "2012-01-26 15:19:25", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26 15:19:25"}},{"pk": 1, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["core", "user"], "object_id": 1}}] \ No newline at end of file diff --git a/modoboa/extensions/admin/lib.py b/modoboa/extensions/admin/lib.py index 7356a68d7..e6c338228 100644 --- a/modoboa/extensions/admin/lib.py +++ b/modoboa/extensions/admin/lib.py @@ -1,6 +1,11 @@ # coding: utf-8 +from django.db.models import Q from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.contrib.contenttypes.models import ContentType +from modoboa.core.models import User from modoboa.lib import parameters +from modoboa.lib.emailutils import split_mailbox +from modoboa.extensions.admin.models import Alias def get_sort_order(qdict, default, allowed_values=None): @@ -23,9 +28,71 @@ def get_sort_order(qdict, default, allowed_values=None): def get_listing_page(objects, pagenum): - paginator = Paginator(objects, int(parameters.get_admin("ITEMS_PER_PAGE"))) + paginator = Paginator( + objects, int(parameters.get_admin("ITEMS_PER_PAGE", app="core")) + ) try: page = paginator.page(int(pagenum)) except (EmptyPage, PageNotAnInteger, ValueError): page = paginator.page(paginator.num_pages) return page + + +def get_identities(user, args=None): + """Return all the identities owned by a user + + :param user: the desired user + :param args: a args object + :return: a queryset + """ + from itertools import chain + + if args: + squery = args.get("searchquery", None) + idtfilter = args.getlist("idtfilter", None) + grpfilter = args.getlist("grpfilter", None) + else: + squery = None + idtfilter = None + grpfilter = None + + accounts = [] + if not idtfilter or "account" in idtfilter: + ids = user.objectaccess_set \ + .filter(content_type=ContentType.objects.get_for_model(user)) \ + .values_list('object_id', flat=True) + q = Q(pk__in=ids) + if squery: + q &= Q(username__icontains=squery) | Q(email__icontains=squery) + if grpfilter and len(grpfilter): + if "SuperAdmins" in grpfilter: + q &= Q(is_superuser=True) + grpfilter.remove("SuperAdmins") + if len(grpfilter): + q |= Q(groups__name__in=grpfilter) + else: + q &= Q(groups__name__in=grpfilter) + accounts = User.objects.select_related().filter(q) + + aliases = [] + if not idtfilter or ("alias" in idtfilter + or "forward" in idtfilter + or "dlist" in idtfilter): + alct = ContentType.objects.get_for_model(Alias) + ids = user.objectaccess_set.filter(content_type=alct) \ + .values_list('object_id', flat=True) + q = Q(pk__in=ids) + if squery: + if '@' in squery: + local_part, domname = split_mailbox(squery) + if local_part: + q &= Q(address__icontains=local_part) + if domname: + q &= Q(domain__name__icontains=domname) + else: + q &= Q(address__icontains=squery) | Q(domain__name__icontains=squery) + aliases = Alias.objects.select_related().filter(q) + if idtfilter: + aliases = [al for al in aliases if al.type in idtfilter] + + return chain(accounts, aliases) diff --git a/modoboa/extensions/admin/migrations/0001_initial.py b/modoboa/extensions/admin/migrations/0001_initial.py index 2f9302e02..aea35074c 100644 --- a/modoboa/extensions/admin/migrations/0001_initial.py +++ b/modoboa/extensions/admin/migrations/0001_initial.py @@ -142,7 +142,7 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, user_model_name: { - 'Meta': {'object_name': 'User'}, + 'Meta': {'object_name': 'User', 'db_table': "'admin_user'"}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), diff --git a/modoboa/extensions/admin/migrations/0017_set_permissions.py b/modoboa/extensions/admin/migrations/0017_set_permissions.py index ef067116c..0d011f6f6 100644 --- a/modoboa/extensions/admin/migrations/0017_set_permissions.py +++ b/modoboa/extensions/admin/migrations/0017_set_permissions.py @@ -149,7 +149,7 @@ class Migration(DataMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, user_model_name: { - 'Meta': {'object_name': 'User'}, + 'Meta': {'object_name': 'User', 'db_table': "'admin_user'"}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), diff --git a/modoboa/extensions/admin/migrations/0018_auto__add_unique_alias_domain_address.py b/modoboa/extensions/admin/migrations/0018_auto__add_unique_alias_domain_address.py index 90f3d1b42..bdf403947 100644 --- a/modoboa/extensions/admin/migrations/0018_auto__add_unique_alias_domain_address.py +++ b/modoboa/extensions/admin/migrations/0018_auto__add_unique_alias_domain_address.py @@ -93,7 +93,7 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, user_model_name: { - 'Meta': {'object_name': 'User'}, + 'Meta': {'object_name': 'User', 'db_table': "'admin_user'"}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), diff --git a/modoboa/extensions/admin/migrations/0019_set_default_group.py b/modoboa/extensions/admin/migrations/0019_set_default_group.py index e80ada36b..479266596 100644 --- a/modoboa/extensions/admin/migrations/0019_set_default_group.py +++ b/modoboa/extensions/admin/migrations/0019_set_default_group.py @@ -98,7 +98,7 @@ class Migration(DataMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, user_model_name: { - 'Meta': {'object_name': 'User'}, + 'Meta': {'object_name': 'User', 'db_table': "'admin_user'"}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), diff --git a/modoboa/extensions/admin/migrations/0021_default_superadmin_ownership.py b/modoboa/extensions/admin/migrations/0021_default_superadmin_ownership.py index fe26ce3a2..29fc45611 100644 --- a/modoboa/extensions/admin/migrations/0021_default_superadmin_ownership.py +++ b/modoboa/extensions/admin/migrations/0021_default_superadmin_ownership.py @@ -97,7 +97,7 @@ class Migration(DataMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, user_model_name: { - 'Meta': {'object_name': 'User'}, + 'Meta': {'object_name': 'User', 'db_table': "'admin_user'"}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index ee1607cd1..2e83914f6 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -36,6 +36,7 @@ class Alias(DatesAware): ) unique_together = (("address", "domain"),) ordering = ["domain__name", "address"] + app_label = 'admin' def __unicode__(self): return self.full_address diff --git a/modoboa/extensions/admin/models/base.py b/modoboa/extensions/admin/models/base.py index 1f6b0a152..ad94fee92 100644 --- a/modoboa/extensions/admin/models/base.py +++ b/modoboa/extensions/admin/models/base.py @@ -10,6 +10,9 @@ class ObjectDates(models.Model): creation = models.DateTimeField(auto_now_add=True) last_modification = models.DateTimeField(auto_now=True) + class Meta: + app_label = 'admin' + @staticmethod def set_for_object(obj): """Initialize or update dates for a given object. diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py index 559fc7909..99e35f94a 100644 --- a/modoboa/extensions/admin/models/domain.py +++ b/modoboa/extensions/admin/models/domain.py @@ -1,12 +1,27 @@ import reversion from django.db import models +from django.db.models.manager import Manager from django.utils.translation import ugettext as _, ugettext_lazy from django.contrib.contenttypes import generic from modoboa.lib import events, parameters from modoboa.core.models import ObjectAccess +from modoboa.extensions.admin.exceptions import AdminError from .base import DatesAware +class DomainManager(Manager): + + def get_for_admin(self, admin): + """Return the domains belonging to this admin + + The result is a ``QuerySet`` object, so this function can be used + to fill ``ModelChoiceField`` objects. + """ + if admin.is_superuser: + return self.get_query_set() + return self.get_query_set().filter(owners__user=admin) + + class Domain(DatesAware): name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True, help_text=ugettext_lazy("The domain name")) @@ -19,12 +34,15 @@ class Domain(DatesAware): ) owners = generic.GenericRelation(ObjectAccess) + objects = DomainManager() + class Meta: permissions = ( ("view_domain", "View domain"), ("view_domains", "View domains"), ) ordering = ["name"] + app_label = 'admin' @property def domainalias_count(self): @@ -79,6 +97,7 @@ class Domain(DatesAware): def delete(self, fromuser, keepdir=False): from modoboa.lib.permissions import \ ungrant_access_to_object, ungrant_access_to_objects + from .mailbox import Quota if self.domainalias_set.count(): events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all()) @@ -123,7 +142,10 @@ class Domain(DatesAware): if len(row) < 4: raise AdminError(_("Invalid line")) self.name = row[1].strip() - self.quota = int(row[2].strip()) + try: + self.quota = int(row[2].strip()) + except ValueError: + raise AdminError(_("Invalid quota value for domain '%s'" % self.name)) self.enabled = (row[3].strip() == 'True') self.save(creator=user) diff --git a/modoboa/extensions/admin/models/domain_alias.py b/modoboa/extensions/admin/models/domain_alias.py index 0bdf49694..2e7727327 100644 --- a/modoboa/extensions/admin/models/domain_alias.py +++ b/modoboa/extensions/admin/models/domain_alias.py @@ -23,6 +23,7 @@ class DomainAlias(DatesAware): permissions = ( ("view_domaliases", "View domain aliases"), ) + app_label = 'admin' def __unicode__(self): return self.name diff --git a/modoboa/extensions/admin/models/mailbox.py b/modoboa/extensions/admin/models/mailbox.py index 287034216..c254d2106 100644 --- a/modoboa/extensions/admin/models/mailbox.py +++ b/modoboa/extensions/admin/models/mailbox.py @@ -1,6 +1,9 @@ import os import reversion from django.db import models +from django.db.models import Q +from django.db.models.manager import Manager +from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext as _, ugettext_lazy from django.db.models.signals import pre_delete from django.dispatch import receiver @@ -12,6 +15,36 @@ from .base import DatesAware from .domain import Domain +class MailboxManager(Manager): + + def get_for_admin(self, admin, squery=None): + """Return the mailboxes that belong to this admin. + + The result will contain the mailboxes defined for each domain that + user can see. + + :param string squery: a search query + :return: a list of ``Mailbox`` objects + """ + qf = None + if squery is not None: + if '@' in squery: + parts = squery.split('@') + addrfilter = '@'.join(parts[:-1]) + domfilter = parts[-1] + qf = Q(address__contains=addrfilter) & Q(domain__name__contains=domfilter) + else: + qf = Q(address__contains=squery) | Q(domain__name__contains=squery) + ids = admin.objectaccess_set \ + .filter(content_type=ContentType.objects.get_for_model(Mailbox)) \ + .values_list('object_id', flat=True) + if qf is not None: + qf = Q(pk__in=ids) & qf + else: + qf = Q(pk__in=ids) + return self.get_query_set().filter(qf) + + class Mailbox(DatesAware): address = models.CharField( ugettext_lazy('address'), max_length=252, @@ -22,10 +55,13 @@ class Mailbox(DatesAware): domain = models.ForeignKey(Domain) user = models.ForeignKey(User) + objects = MailboxManager() + class Meta: permissions = ( ("view_mailboxes", "View mailboxes"), ) + app_label = 'admin' def __init__(self, *args, **kwargs): super(Mailbox, self).__init__(*args, **kwargs) @@ -211,3 +247,6 @@ class Quota(models.Model): messages = models.IntegerField(default=0) mbox = models.OneToOneField(Mailbox, related_name="quota_value", null=True) + + class Meta: + app_label = 'admin' diff --git a/modoboa/extensions/admin/templates/admin/editdomainform.html b/modoboa/extensions/admin/templates/admin/editdomainform.html index 24c731769..e3c3aad5d 100644 --- a/modoboa/extensions/admin/templates/admin/editdomainform.html +++ b/modoboa/extensions/admin/templates/admin/editdomainform.html @@ -1,4 +1,4 @@ -{% extends "common/tabforms.html" %}{% load i18n libextras admin_extras %} +{% extends "common/tabforms.html" %}{% load i18n libextras admin_tags %} {% block extratabs %}