From 4c86b5c05e8103bbb8f6034a32eee1cfed493725 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 20 Aug 2013 16:10:36 +0200 Subject: [PATCH] wip: Big refactoring. --- modoboa/core/models.py | 68 ++----------- modoboa/extensions/admin/__init__.py | 98 ++++++++++++++++++- .../admin/fixtures/initial_data.json | 2 +- .../admin/fixtures/initial_users.json | 2 +- modoboa/extensions/admin/lib.py | 69 ++++++++++++- .../admin/migrations/0001_initial.py | 2 +- .../admin/migrations/0017_set_permissions.py | 2 +- ...8_auto__add_unique_alias_domain_address.py | 2 +- .../migrations/0019_set_default_group.py | 2 +- .../0021_default_superadmin_ownership.py | 2 +- modoboa/extensions/admin/models/alias.py | 1 + modoboa/extensions/admin/models/base.py | 3 + modoboa/extensions/admin/models/domain.py | 24 ++++- .../extensions/admin/models/domain_alias.py | 1 + modoboa/extensions/admin/models/mailbox.py | 39 ++++++++ .../admin/templates/admin/editdomainform.html | 2 +- .../templates/admin/identities_table.html | 2 +- .../admin/templates/admin/logs.html | 20 ---- .../admin/templates/admin/quotas.html | 2 +- .../templates/admin/settings_header.html | 23 ----- .../admin/templatetags/admin_tags.py | 96 +++++++++--------- modoboa/extensions/admin/tests.py | 4 +- modoboa/extensions/admin/urls.py | 1 + modoboa/extensions/admin/views/domain.py | 9 +- modoboa/extensions/admin/views/export.py | 6 +- modoboa/extensions/admin/views/identity.py | 13 ++- modoboa/extensions/sievefilters/forms.py | 2 +- modoboa/extensions/stats/__init__.py | 2 +- modoboa/lib/events.py | 73 ++++++-------- modoboa/lib/permissions.py | 24 ++--- 30 files changed, 367 insertions(+), 229 deletions(-) delete mode 100644 modoboa/extensions/admin/templates/admin/logs.html delete mode 100644 modoboa/extensions/admin/templates/admin/settings_header.html 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 %}
  • {% trans "Administrators" %} diff --git a/modoboa/extensions/admin/templates/admin/identities_table.html b/modoboa/extensions/admin/templates/admin/identities_table.html index af3e32580..98464e498 100644 --- a/modoboa/extensions/admin/templates/admin/identities_table.html +++ b/modoboa/extensions/admin/templates/admin/identities_table.html @@ -1,4 +1,4 @@ -{% load i18n admin_extras libextras %} +{% load i18n admin_tags libextras %} diff --git a/modoboa/extensions/admin/templates/admin/logs.html b/modoboa/extensions/admin/templates/admin/logs.html deleted file mode 100644 index b77458a89..000000000 --- a/modoboa/extensions/admin/templates/admin/logs.html +++ /dev/null @@ -1,20 +0,0 @@ -{% load i18n admin_extras %} -

    {% trans "Logs" %} {% trans "Previously on Modoboa..." %}


    -
    - - - - - - - - - - {% for l in logs %} - - - - - {% endfor %} - -
    {% trans "Date" %}{% trans "Level" %}{% trans "Logger" %}{% trans "Message" %}
    {{ l.date_created }}{{ l.level|colorize_level|safe }}{{ l.logger }}{{ l.message|tohtml|safe }}
    diff --git a/modoboa/extensions/admin/templates/admin/quotas.html b/modoboa/extensions/admin/templates/admin/quotas.html index 6bfa2dd3e..9b0903584 100644 --- a/modoboa/extensions/admin/templates/admin/quotas.html +++ b/modoboa/extensions/admin/templates/admin/quotas.html @@ -1,4 +1,4 @@ -{% load i18n libextras admin_extras %} +{% load i18n libextras admin_tags %} diff --git a/modoboa/extensions/admin/templates/admin/settings_header.html b/modoboa/extensions/admin/templates/admin/settings_header.html deleted file mode 100644 index 9a957a28b..000000000 --- a/modoboa/extensions/admin/templates/admin/settings_header.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "twocols.html" %} -{% load i18n libextras admin_extras %} -{% block pagetitle %}{% trans "Modoboa settings" %}{% endblock %} -{% block html_head %} - - - - - - - -{% endblock %} -{% block leftcol %}{% endblock %} -{% block apparea %}
    {% endblock %} diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py index 3a13c4fe7..2cc789343 100644 --- a/modoboa/extensions/admin/templatetags/admin_tags.py +++ b/modoboa/extensions/admin/templatetags/admin_tags.py @@ -106,19 +106,19 @@ def identities_menu(user): @register.simple_tag def domain_actions(user, domid): - from modoboa.admin.models import Domain + from modoboa.extensions.admin.models import Domain domain = Domain.objects.get(pk=domid) actions = [ {"name": "listidentities", - "url": reverse("modoboa.admin.views.identities") + "#list/?searchquery=@%s" % domain.name, + "url": reverse("modoboa.extensions.admin.views.identity.identities") + "#list/?searchquery=@%s" % domain.name, "title": _("View the domain's identities"), "img": "icon-user"} ] if user.has_perm("admin.delete_domain"): actions.append({ "name": "deldomain", - "url": reverse("modoboa.admin.views.deldomain", args=[domid]), + "url": reverse("modoboa.extensions.admin.views.domain.deldomain", args=[domid]), "title": _("Delete the domain"), "img": "icon-trash" }) @@ -132,72 +132,78 @@ def identity_actions(user, ident): if name == "User": actions = events.raiseQueryEvent("ExtraAccountActions", ident) actions += [ - {"name" : "delaccount", - "url" : reverse("modoboa.admin.views.delaccount", args=[objid]), - "img" : "icon-trash", - "title" : _("Delete this account")}, - ] + {"name": "delaccount", + "url": reverse("modoboa.extensions.admin.views.identity.delaccount", args=[objid]), + "img": "icon-trash", + "title": _("Delete this account")}, + ] else: if ident.get_recipients_count() >= 2: actions = [ - {"name" : "deldlist", - "url" : reverse("modoboa.admin.views.deldlist") + "?selection=%s" % objid, - "img" : "icon-trash", - "title" : _("Delete this distribution list")}, - ] + {"name": "deldlist", + "url": reverse("modoboa.extensions.admin.views.alias.deldlist") + "?selection=%s" % objid, + "img": "icon-trash", + "title": _("Delete this distribution list")}, + ] elif ident.extmboxes != "": actions = [ - {"name" : "delforward", - "url" : reverse("modoboa.admin.views.delforward") + "?selection=%s" % objid, - "img" : "icon-trash", - "title" : _("Delete this forward")}, - ] + {"name": "delforward", + "url": reverse("modoboa.extensions.admin.views.alias.delforward") + "?selection=%s" % objid, + "img": "icon-trash", + "title": _("Delete this forward")}, + ] else: actions = [ - {"name" : "delalias", - "url" : reverse("modoboa.admin.views.delalias") + "?selection=%s" % objid, - "img" : "icon-trash", - "title" : _("Delete this alias")}, - ] + {"name": "delalias", + "url": reverse("modoboa.extensions.admin.views.alias.delalias") + "?selection=%s" % objid, + "img": "icon-trash", + "title": _("Delete this alias")}, + ] return render_actions(actions) @register.simple_tag def identity_modify_link(identity, active_tab='default'): - linkdef = {"label" : identity.identity, "modal" : True} + linkdef = {"label": identity.identity, "modal": True} if identity.__class__.__name__ == "User": - linkdef["url"] = reverse("modoboa.admin.views.editaccount", args=[identity.id]) + linkdef["url"] = reverse( + "modoboa.extensions.admin.views.identity.editaccount", + args=[identity.id] + ) linkdef["url"] += "?active_tab=%s" % active_tab linkdef["modalcb"] = "admin.editaccount_cb" else: - linkdef["url"] = reverse("modoboa.admin.views.editalias", args=[identity.id]) + linkdef["url"] = reverse( + "modoboa.extensions.admin.views.alias.editalias", + args=[identity.id] + ) linkdef["modalcb"] = "admin.aliasform_cb" return render_link(linkdef) @register.simple_tag def domadmin_actions(daid, domid): - actions = [dict( - name="removeperm", - url=reverse("modoboa.admin.views.remove_permission") + "?domid=%s&daid=%s" % (domid, daid), - img="icon-trash", - title=_("Remove this permission") - )] + actions = [{ + "name": "removeperm", + "url": reverse("modoboa.extensions.admin.views.identity.remove_permission") + "?domid=%s&daid=%s" % (domid, daid), + "img": "icon-trash", + "title": _("Remove this permission") + }] return render_actions(actions) @register.simple_tag def loadadminextmenu(user): menu = events.raiseQueryEvent("AdminMenuDisplay", "admin_menu_box", user) - return render_to_string('common/menulist.html', - {"entries" : menu, "user" : user}) + return render_to_string('common/menulist.html', + {"entries": menu, "user": user}) @register.simple_tag def param(app, definition): name = "%s.%s" % (app, definition["name"]) - value = definition.has_key("value") \ - and definition["value"] or definition["deflt"] + value = definition["value"] \ + if "value" in definition else definition["deflt"] if definition["type"] == "separator": return "
    %s
    " % (unicode(definition["label"])) @@ -211,8 +217,7 @@ def param(app, definition): result = """
    """ % (extratags, name, - definition.has_key("label") and _(definition["label"]) - or definition["name"]) + _(definition["label"]) if "label" in definition else definition["name"]) result += "
    " if definition["type"] in ["string", "int"]: @@ -222,7 +227,7 @@ def param(app, definition): if definition["type"] == "text": result += "" \ % (name, name, value) - + if definition["type"] == "list_yesno": for idx, v in enumerate([("yes", _("Yes")), ("no", _("No"))]): checked = "checked" if value == v[0] else "" @@ -230,13 +235,14 @@ def param(app, definition): %(label)s -""" % dict(id="%s_%d" % (name, idx), name=name, value=v[0], label=v[1], checked=checked) +""" % dict(id="%s_%d" % (name, idx), name=name, value=v[0], + label=v[1], checked=checked) if definition["type"] == "list": result += """ """ - if definition.has_key("help"): + if "help" in definition: result += """ """ % (unicode(definition["help"]), _("Help")) @@ -264,7 +270,7 @@ def param(app, definition): @register.filter def gender(value, target): - if genders.has_key(value): + if value in genders: trans = target == "m" and genders[value][0] or genders[value][1] if trans.find("_") == -1: return trans @@ -273,5 +279,7 @@ def gender(value, target): @register.simple_tag def get_extra_admin_content(user, target, currentpage): - res = events.raiseQueryEvent("ExtraAdminContent", user, target, currentpage) + res = events.raiseQueryEvent( + "ExtraAdminContent", user, target, currentpage + ) return "".join(res) diff --git a/modoboa/extensions/admin/tests.py b/modoboa/extensions/admin/tests.py index 60d380a20..514a79f30 100644 --- a/modoboa/extensions/admin/tests.py +++ b/modoboa/extensions/admin/tests.py @@ -15,10 +15,10 @@ from django.test.client import Client from django.utils import simplejson from django.core.urlresolvers import reverse from django.core.files.base import ContentFile -from models import * -from modoboa.admin.lib import * from modoboa.lib import parameters from modoboa.lib.tests import ModoTestCase +from modoboa.extensions.admin.lib import * +from modoboa.extensions.admin.models import * class DomainTestCase(ModoTestCase): diff --git a/modoboa/extensions/admin/urls.py b/modoboa/extensions/admin/urls.py index ccb454700..799d270cf 100644 --- a/modoboa/extensions/admin/urls.py +++ b/modoboa/extensions/admin/urls.py @@ -3,6 +3,7 @@ from django.conf.urls import patterns, url urlpatterns = patterns( 'modoboa.extensions.admin.views.domain', + (r'^$', 'index'), url(r'^domains/$', 'domains', name="domains"), (r'^domains/list/$', '_domains'), (r'^domains/flatlist/$', 'domains_list'), diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py index 65a4bd6b9..70e6824ee 100644 --- a/modoboa/extensions/admin/views/domain.py +++ b/modoboa/extensions/admin/views/domain.py @@ -22,13 +22,18 @@ from modoboa.extensions.admin.forms import ( ) +@login_required +def index(request): + return HttpResponseRedirect(reverse(domains)) + + @login_required @user_passes_test( lambda u: u.has_perm("admin.view_domains") or u.has_perm("admin.view_mailboxes") ) def _domains(request): sort_order, sort_dir = get_sort_order(request.GET, "name") - domains = request.user.get_domains() + domains = Domain.objects.get_for_admin(request.user) squery = request.GET.get("searchquery", None) if squery is not None: q = Q(name__contains=squery) @@ -60,7 +65,7 @@ def domains(request, tplname="admin/domains.html"): @login_required @permission_required("admin.add_user") def domains_list(request): - doms = [dom.name for dom in request.user.get_domains()] + doms = [dom.name for dom in Domain.objects.get_for_admin(request.user)] return ajax_simple_response(doms) diff --git a/modoboa/extensions/admin/views/export.py b/modoboa/extensions/admin/views/export.py index 6c238f78d..437e48173 100644 --- a/modoboa/extensions/admin/views/export.py +++ b/modoboa/extensions/admin/views/export.py @@ -8,6 +8,8 @@ from django.utils.translation import ugettext as _, ungettext from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) +from modoboa.extensions.admin.lib import get_identities +from modoboa.extensions.admin.models import Domain from modoboa.extensions.admin.forms import ( ExportIdentitiesForm, ExportDomainsForm ) @@ -45,7 +47,7 @@ def export_identities(request): form.is_valid() fp = cStringIO.StringIO() csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"]) - for ident in request.user.get_identities(): + for ident in get_identities(request.user): ident.to_csv(csvwriter) content = fp.getvalue() fp.close() @@ -71,7 +73,7 @@ def export_domains(request): form.is_valid() fp = cStringIO.StringIO() csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"]) - for dom in request.user.get_domains(): + for dom in Domain.objects.get_for_admin(request.user): dom.to_csv(csvwriter) for da in dom.domainalias_set.all(): da.to_csv(csvwriter) diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py index edd18d570..8a12954f5 100644 --- a/modoboa/extensions/admin/views/identity.py +++ b/modoboa/extensions/admin/views/identity.py @@ -12,7 +12,10 @@ from modoboa.lib.webutils import ajax_simple_response, _render_to_string from modoboa.lib.formutils import CreationWizard from modoboa.lib.templatetags.libextras import pagination_bar from modoboa.core.models import User -from modoboa.extensions.admin.lib import get_sort_order, get_listing_page +from modoboa.extensions.admin.models import Mailbox +from modoboa.extensions.admin.lib import ( + get_sort_order, get_listing_page, get_identities +) from modoboa.extensions.admin.exceptions import AdminError from modoboa.extensions.admin.forms import ( AccountForm, AccountFormGeneral, AccountFormMail @@ -24,7 +27,7 @@ from modoboa.extensions.admin.forms import ( lambda u: u.has_perm("admin.add_user") or u.has_perm("admin.add_alias") ) def _identities(request): - idents_list = request.user.get_identities(request.GET) + idents_list = get_identities(request.user, request.GET) sort_order, sort_dir = get_sort_order(request.GET, "identity", ["identity", "name_or_rcpt", "tags"]) if sort_order in ["identity", "name_or_rcpt"]: @@ -73,7 +76,9 @@ def list_quotas(request, tplname="admin/quotas.html"): from modoboa.lib.dbutils import db_type sort_order, sort_dir = get_sort_order(request.GET, "address") - mboxes = request.user.get_mailboxes(request.GET.get("searchquery", None)) + mboxes = Mailbox.objects.get_for_admin( + request.user, request.GET.get("searchquery", None) + ) mboxes = mboxes.exclude(quota=0) if sort_order in ["address", "quota", "quota_value__bytes"]: mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order)) @@ -175,7 +180,7 @@ def editaccount(request, accountid, tplname="common/tabforms.html"): if not request.user.can_access(account): raise PermDeniedException mb = None - if account.has_mailbox: + if account.mailbox_set.count(): mb = account.mailbox_set.all()[0] instances = dict(general=account, mail=mb, perms=account) diff --git a/modoboa/extensions/sievefilters/forms.py b/modoboa/extensions/sievefilters/forms.py index 5ee3724bf..41ef3b16a 100644 --- a/modoboa/extensions/sievefilters/forms.py +++ b/modoboa/extensions/sievefilters/forms.py @@ -5,7 +5,7 @@ from django.forms.widgets import RadioFieldRenderer, RadioSelect, RadioInput from django.utils.safestring import mark_safe from django.utils.html import conditional_escape from django.utils.encoding import force_unicode -from modoboa.admin.templatetags.admin_extras import gender +from modoboa.extensions.admin.templatetags.admin_tags import gender class FiltersSetForm(forms.Form): name = forms.CharField() diff --git a/modoboa/extensions/stats/__init__.py b/modoboa/extensions/stats/__init__.py index acaa695ce..61bb62101 100644 --- a/modoboa/extensions/stats/__init__.py +++ b/modoboa/extensions/stats/__init__.py @@ -22,7 +22,7 @@ class Stats(ModoExtension): def load(self): from app_settings import ParametersForm - events.registerEvent("GetGraphSets") + events.declare(["GetGraphSets"]) parameters.register(ParametersForm, ugettext_lazy("Graphical statistics")) def destroy(self): diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index ee3a81b8d..a296374cc 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -16,47 +16,27 @@ from django.conf import settings events = [ "CanCreate", - "CreateDomain", - "DomainModified", - "DeleteDomain", - - "DomainAliasCreated", - "DomainAliasDeleted", - - "CreateMailbox", - "DeleteMailbox", - "ModifyMailbox", - - "MailboxAliasCreated", - "MailboxAliasDeleted", - "AccountCreated", "AccountModified", "AccountDeleted", + "AccountExported", + "AccountImported", "PasswordUpdated", "ExtraAccountActions", - + "RoleChanged", + "GetExtraRoles", "PasswordChange", - + "UserMenuDisplay", "AdminMenuDisplay", "GetStaticContent", - "ExtraAccountForm", - "CheckExtraAccountForm", - "FillAccountInstances", - - "ExtraDomainForm", - "FillDomainInstances", - - "GetExtraRoles", - "ExtEnabled", "ExtDisabled", "UserLogin", "UserLogout", - + "GetAnnouncement", "TopNotifications", @@ -64,17 +44,20 @@ events = [ "ExtraUprefsRoutes", "ExtraUprefsJS" - ] +] callbacks = {} -def registerEvent(name): - """Register a new event - :param name: the event's name +def declare(nevents): + """Declare new events + + :param list nevents: a list of event names """ - if not name in events: - events.append(name) + for evt in nevents: + if not evt in events: + events.append(evt) + def register(event, callback): """Register a plugin callback for a specific event @@ -90,10 +73,11 @@ def register(event, callback): if not event in callbacks.keys(): callbacks[event] = {} fullname = "%s.%s" % (callback.__module__, callback.__name__) - if not callbacks[event].has_key(fullname): + if not fullname in callbacks[event]: callbacks[event][fullname] = callback return 1 + class observe(object): """Event observing decorator @@ -111,7 +95,7 @@ class observe(object): """ def __init__(self, *evtnames, **kwargs): self.evtnames = evtnames - if kwargs.has_key("extname"): + if "extname" in kwargs: self.extname = kwargs["extname"] def __guess_extension_name(self, modname): @@ -123,7 +107,9 @@ class observe(object): def __call__(self, f): modname = inspect.getmodule(inspect.stack()[1][0]).__name__ - extname = self.extname if hasattr(self, "extname") else self.__guess_extension_name(modname) + extname = self.extname if hasattr(self, "extname") \ + else self.__guess_extension_name(modname) + @wraps(f) def wrapped_f(*args): if extname: @@ -140,12 +126,12 @@ class observe(object): return [] elif not modname in settings.MODOBOA_APPS: return [] - return f(*args) - - map(lambda evt: register(evt, wrapped_f), self.evtnames) + for evt in self.evtnames: + register(evt, wrapped_f) return wrapped_f + def unregister(event, callback): """Unregister a callback for a specific event @@ -154,7 +140,7 @@ def unregister(event, callback): """ if not event in events: return False - if not callbacks.has_key(event): + if not event in callbacks: return False fullname = "%s.%s" % (callback.__module__, callback.__name__) try: @@ -162,6 +148,7 @@ def unregister(event, callback): except KeyError: pass + def raiseEvent(event, *args): """Raise a specific event @@ -172,10 +159,11 @@ def raiseEvent(event, *args): """ if not event in events or not event in callbacks.keys(): return 0 - for name, callback in callbacks[event].iteritems(): + for callback in callbacks[event].values(): callback(*args) return 1 + def raiseQueryEvent(event, *args): """Raise a specific event and wait for answers from callbacks @@ -187,10 +175,11 @@ def raiseQueryEvent(event, *args): result = [] if not event in events or not event in callbacks.keys(): return result - for name, callback in callbacks[event].iteritems(): + for callback in callbacks[event].values(): result += callback(*args) return result + def raiseDictEvent(event, *args): """Raise a specific event and return result as a dictionnary @@ -203,7 +192,7 @@ def raiseDictEvent(event, *args): result = {} if not event in events or not event in callbacks.keys(): return result - for name, callback in callbacks[event].iteritems(): + for callback in callbacks[event].values(): tmp = callback(*args) for k, v in tmp.iteritems(): result[k] = v diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py index 0133eb49c..90c0eea9a 100644 --- a/modoboa/lib/permissions.py +++ b/modoboa/lib/permissions.py @@ -7,18 +7,10 @@ from modoboa.core.models import ObjectAccess import events from exceptions import ModoboaException -def get_content_type(obj): - """Simple function that use the right method to retrieve a content type - - :param obj: a django model - :return: a ``ContentType`` object - """ - return obj.get_content_type() if hasattr(obj, "get_content_type") \ - else ContentType.objects.get_for_model(obj) def get_account_roles(user): """Return the list of supported account roles - + This list can be extended by extensions which listen to the ``GetExtraRoles`` event. @@ -32,6 +24,7 @@ def get_account_roles(user): std_roles += events.raiseQueryEvent("GetExtraRoles", user) return sorted(std_roles, key=lambda role: role[1]) + def grant_access_to_object(user, obj, is_owner=False): """Grant access to an object for a given user @@ -48,7 +41,7 @@ def grant_access_to_object(user, obj, is_owner=False): :param obj: an admin. object (Domain, Mailbox, ...) :param is_owner: the user is the unique object's owner """ - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) try: entry = user.objectaccess_set.get(content_type=ct, object_id=obj.id) entry.is_owner = is_owner @@ -62,7 +55,7 @@ def grant_access_to_object(user, obj, is_owner=False): ObjectAccess.objects.create(user=user, content_type=ct, object_id=obj.id, is_owner=is_owner) if is_owner: - from modoboa.admin.models import User + from modoboa.core.models import User for su in User.objects.filter(is_superuser=True): if su == user: continue @@ -74,6 +67,7 @@ def grant_access_to_object(user, obj, is_owner=False): except IntegrityError, e: raise ModoboaException(_("Failed to grant access (%s)" % str(e))) + def grant_access_to_objects(user, objects, ct): """Grant access to a collection of objects @@ -100,7 +94,7 @@ def ungrant_access_to_object(obj, user=None): :param obj: an object inheriting from ``models.Model`` :param user: a ``User`` object """ - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) if user: try: ObjectAccess.objects.get(user=user, content_type=ct, object_id=obj.id).delete() @@ -109,22 +103,24 @@ def ungrant_access_to_object(obj, user=None): else: ObjectAccess.objects.filter(content_type=ct, object_id=obj.id).delete() + def ungrant_access_to_objects(objects): """Cancel all accesses for a given objects list :param objects: a list of objects inheriting from ``model.Model`` """ for obj in objects: - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) ObjectAccess.objects.filter(content_type=ct, object_id=obj.id).delete() + def get_object_owner(obj): """Return the unique owner of this object :param obj: an object inheriting from ``model.Model`` :return: a ``User`` object """ - ct = get_content_type(obj) + ct = ContentType.objects.get_for_model(obj) try: entry = ObjectAccess.objects.get(content_type=ct, object_id=obj.id, is_owner=True) except ObjectAccess.DoesNotExist: