From 2eeba77c476fe2f4c7f3206e3ed89180df83d3cd Mon Sep 17 00:00:00 2001 From: Carlos Ramos Date: Mon, 6 Oct 2014 00:39:34 -0600 Subject: [PATCH 1/7] Improve the postfixadmin migration code: - Assign right permissions to domain administrators and superadministrator. - Correctly prepend the password schema to all admins. - Update model classes with the correct varchar length and other useful relations. --- .../commands/migrate_from_postfixadmin.py | 82 ++++++++++--------- modoboa/tools/pfxadmin_migrate/models.py | 63 +++++++------- 2 files changed, 75 insertions(+), 70 deletions(-) diff --git a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py index 757d1a9ba..bd453ed3c 100644 --- a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py +++ b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py @@ -55,6 +55,7 @@ from django.db.models import Q import modoboa.core.models as core_models import modoboa.extensions.admin.models as admin_models from modoboa.lib.emailutils import split_mailbox +from modoboa.extensions.admin import grant_access_to_all_objects from modoboa.tools.pfxadmin_migrate import models as pf_models @@ -208,74 +209,74 @@ class Command(BaseCommand): options["mboxes_path"], domain.name, old_mb.maildir) new_mb.rename_dir(oldpath) - def _migrate_domain(self, old_dom, options, creator): + def _migrate_domain(self, pf_domain, options, creator): """Single domain migration.""" - print "Migrating domain %s" % old_dom.domain + print "\nMigrating domain %s" % pf_domain.domain newdom = admin_models.Domain() - newdom.name = old_dom.domain - newdom.enabled = old_dom.active - newdom.quota = old_dom.maxquota - newdom.dates = self._migrate_dates(old_dom) + newdom.name = pf_domain.domain + newdom.enabled = pf_domain.active + newdom.quota = pf_domain.maxquota + newdom.dates = self._migrate_dates(pf_domain) newdom.save(creator=creator, using=options["_to"]) + self._migrate_domain_aliases(newdom, options, creator) self._migrate_mailboxes(newdom, options, creator) self._migrate_mailbox_aliases(newdom, options, creator) - self._migrate_domain_aliases(newdom, options, creator) + self._migrate_admins(options, creator, pf_domain, newdom) - def _migrate_admins(self, options, creator): - """Administrators migration.""" - print "Migrating administrators" + def _migrate_admins(self, options, creator, pf_domain, newdom=None): + """Administrators migration. + + :param pf_domain: The ``pf_models.Domain`` to get the admins to migrate. + :param newdom: If None the admins will not be linked to any domain and + they will be SuperAdmins. Otherwise link them to this domain and make them + DomainAdmins. + """ + + if (newdom is None): + print "\nMigrating super administrators" + else: + print "\tMigrating administrators" dagroup = Group.objects.using(options["_to"]).get(name="DomainAdmins") - for old_admin in pf_models.Admin.objects.using(options["_from"]).all(): - local_part, domname = split_mailbox(old_admin.username) - try: - query = Q(username=old_admin.username) & \ - (Q(domain="ALL") | Q(domain=domname)) - creds = pf_models.DomainAdmins.objects \ - .using(options["_from"]).get(query) - except pf_models.DomainAdmins.DoesNotExist: - print ( - "Warning: skipping useless admin %s" % (old_admin.username) - ) - continue - try: - domain = admin_models.Domain.objects \ - .using(options["_to"]).get(name=domname) - except admin_models.Domain.DoesNotExist: - print ( - "Warning: skipping domain admin %s, domain not found" - % old_admin.username - ) - continue + for old_admin in pf_domain.admins.all(): + if (newdom is None): + print "\tMigrating %s" % old_admin.username + + #In postfixadmin, it's possible to have an admin account and a user account with the same username but they are completely different entities, so they do not have a common password. In Modoboa this does not makes sense, so we actually merge these two entities into a single user if both are found. Question is, which password should we use?. The admin password is used to be on the secure side. try: user = core_models.User.objects \ .using(options["_to"]).get(username=old_admin.username) + + if ("SimpleUsers" == user.group): + print "Warning: Found an admin account with the same username as normal user '%s'. The existing user will be promoted to admin and it's password changed to the admin's account password. " % user.username + except core_models.User.DoesNotExist: user = core_models.User() user.username = old_admin.username user.email = old_admin.username - user.password = old_admin.password user.is_active = old_admin.active user.save(creator=creator, using=options["_to"]) user.date_joined = old_admin.modified - if creds.domain == "ALL": + user.password = "{%s}%s" % \ + (options["passwords_scheme"].upper(), old_admin.password) + + if (newdom is None): + grant_access_to_all_objects(user, "SuperAdmins") user.is_superuser = True else: user.groups.add(dagroup) - domain.add_admin(user) + newdom.add_admin(user) + user.save(using=options["_to"]) def _do_migration(self, options, creator_username='admin'): """Run the complete migration.""" - pf_domains = pf_models.Domain.objects.using(options["_from"]).all() + pf_domains = pf_models.Domain.objects.using(options["_from"]).exclude(domain = 'ALL') creator = core_models.User.objects.using(options["_to"]).get( username=creator_username) for pf_domain in pf_domains: - if pf_domain.domain == "ALL": - continue - try: # Skip this domain if it's an alias is_domain_alias = pf_models.AliasDomain.objects \ @@ -285,7 +286,10 @@ class Command(BaseCommand): continue except pf_models.AliasDomain.DoesNotExist: self._migrate_domain(pf_domain, options, creator) - self._migrate_admins(options, creator) + + #Handle the ALL domain + pf_domain = pf_models.Domain.objects.using(options["_from"]).get(domain = 'ALL') + self._migrate_admins(options, creator, pf_domain) def handle(self, *args, **options): """Command entry point.""" diff --git a/modoboa/tools/pfxadmin_migrate/models.py b/modoboa/tools/pfxadmin_migrate/models.py index cbb86ac92..94f143ce2 100755 --- a/modoboa/tools/pfxadmin_migrate/models.py +++ b/modoboa/tools/pfxadmin_migrate/models.py @@ -11,8 +11,8 @@ from django.db import models class Admin(models.Model): - username = models.CharField(max_length=765, primary_key=True) - password = models.CharField(max_length=765) + username = models.CharField(max_length=255, primary_key=True) + password = models.CharField(max_length=255) created = models.DateTimeField() modified = models.DateTimeField() active = models.IntegerField() @@ -24,9 +24,9 @@ class Admin(models.Model): class Alias(models.Model): - address = models.CharField(max_length=765, primary_key=True) + address = models.CharField(max_length=255, primary_key=True) goto = models.TextField() - domain = models.CharField(max_length=765) + domain = models.CharField(max_length=255) created = models.DateTimeField() modified = models.DateTimeField() active = models.IntegerField() @@ -38,8 +38,8 @@ class Alias(models.Model): class AliasDomain(models.Model): - alias_domain = models.CharField(max_length=765, primary_key=True) - target_domain = models.CharField(max_length=765) + alias_domain = models.CharField(max_length=255, primary_key=True) + target_domain = models.CharField(max_length=255) created = models.DateTimeField() modified = models.DateTimeField() active = models.IntegerField() @@ -62,17 +62,18 @@ class Config(models.Model): class Domain(models.Model): - domain = models.CharField(max_length=765, primary_key=True) - description = models.CharField(max_length=765) + domain = models.CharField(max_length=255, primary_key=True) + description = models.CharField(max_length=255) aliases = models.IntegerField() mailboxes = models.IntegerField() maxquota = models.BigIntegerField() quota = models.BigIntegerField() - transport = models.CharField(max_length=765) + transport = models.CharField(max_length=255) backupmx = models.IntegerField() created = models.DateTimeField() modified = models.DateTimeField() active = models.IntegerField() + admins = models.ManyToManyField(Admin, through='DomainAdmins') class Meta: db_table = u'domain' @@ -81,8 +82,8 @@ class Domain(models.Model): class DomainAdmins(models.Model): - username = models.CharField(max_length=765) - domain = models.CharField(max_length=765) + username = models.ForeignKey(Admin, db_column='username') + domain = models.ForeignKey(Domain, db_column='domain') created = models.DateTimeField(primary_key=True) active = models.IntegerField() @@ -94,12 +95,12 @@ class DomainAdmins(models.Model): class Fetchmail(models.Model): id = models.IntegerField(primary_key=True) - mailbox = models.CharField(max_length=765) - src_server = models.CharField(max_length=765) + mailbox = models.CharField(max_length=255) + src_server = models.CharField(max_length=255) src_auth = models.CharField(max_length=33, blank=True) - src_user = models.CharField(max_length=765) - src_password = models.CharField(max_length=765) - src_folder = models.CharField(max_length=765) + src_user = models.CharField(max_length=255) + src_password = models.CharField(max_length=255) + src_folder = models.CharField(max_length=255) poll_time = models.IntegerField() fetchall = models.IntegerField() keep = models.IntegerField() @@ -107,7 +108,7 @@ class Fetchmail(models.Model): usessl = models.IntegerField() extra_options = models.TextField(blank=True) returned_text = models.TextField(blank=True) - mda = models.CharField(max_length=765) + mda = models.CharField(max_length=255) date = models.DateTimeField() class Meta: @@ -118,9 +119,9 @@ class Fetchmail(models.Model): class Log(models.Model): timestamp = models.DateTimeField() - username = models.CharField(max_length=765) - domain = models.CharField(max_length=765) - action = models.CharField(max_length=765) + username = models.CharField(max_length=255) + domain = models.CharField(max_length=255) + action = models.CharField(max_length=255) data = models.TextField() class Meta: @@ -130,13 +131,13 @@ class Log(models.Model): class Mailbox(models.Model): - username = models.CharField(max_length=765, primary_key=True) - password = models.CharField(max_length=765) - name = models.CharField(max_length=765) - maildir = models.CharField(max_length=765) + username = models.CharField(max_length=255, primary_key=True) + password = models.CharField(max_length=255) + name = models.CharField(max_length=255) + maildir = models.CharField(max_length=255) quota = models.BigIntegerField() - local_part = models.CharField(max_length=765) - domain = models.CharField(max_length=765) + local_part = models.CharField(max_length=255) + domain = models.CharField(max_length=255) created = models.DateTimeField() modified = models.DateTimeField() active = models.IntegerField() @@ -148,7 +149,7 @@ class Mailbox(models.Model): class Quota(models.Model): - username = models.CharField(max_length=765, primary_key=True) + username = models.CharField(max_length=255, primary_key=True) path = models.CharField(max_length=300, primary_key=True) current = models.BigIntegerField(null=True, blank=True) @@ -170,11 +171,11 @@ class Quota2(models.Model): class Vacation(models.Model): - email = models.CharField(max_length=765) - subject = models.CharField(max_length=765) + email = models.CharField(max_length=255) + subject = models.CharField(max_length=255) body = models.TextField() cache = models.TextField() - domain = models.CharField(max_length=765) + domain = models.CharField(max_length=255) created = models.DateTimeField() active = models.IntegerField() @@ -186,7 +187,7 @@ class Vacation(models.Model): class VacationNotification(models.Model): on_vacation = models.ForeignKey(Vacation, db_column='on_vacation') - notified = models.CharField(max_length=765, primary_key=True) + notified = models.CharField(max_length=255, primary_key=True) notified_at = models.DateTimeField() class Meta: From 534b21c896ec4b772d25e487edc8d8bff78609a7 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 8 Oct 2014 09:57:43 +0200 Subject: [PATCH 2/7] Last fixes. see #609 --- .../commands/migrate_from_postfixadmin.py | 61 +++++++++++++------ modoboa/tools/pfxadmin_migrate/models.py | 4 +- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py index bd453ed3c..aacab4111 100644 --- a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py +++ b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py @@ -45,12 +45,12 @@ used by PostfixAdmin. """ from optparse import make_option import os +import re import sys from django.contrib.auth.models import Group from django.core.management.base import BaseCommand from django.db import transaction -from django.db.models import Q import modoboa.core.models as core_models import modoboa.extensions.admin.models as admin_models @@ -60,6 +60,19 @@ from modoboa.extensions.admin import grant_access_to_all_objects from modoboa.tools.pfxadmin_migrate import models as pf_models +def set_account_password(account, password, scheme): + """Correclty format the password before storing it. + + It seems postfixadmin sometimes prepend the scheme... but not + always :p + + """ + if re.search(r"\{[\w-]+\}", password): + account.password = password + else: + account.password = "{%s}%s" % (scheme.upper(), password) + + class Command(BaseCommand): """Migration from postfixadmin.""" @@ -190,8 +203,8 @@ class Command(BaseCommand): new_user.email = old_mb.username new_user.is_active = old_mb.active new_user.date_joined = old_mb.created - new_user.password = "{%s}%s" % \ - (options["passwords_scheme"].upper(), old_mb.password) + set_account_password( + new_user, old_mb.password, options["passwords_scheme"]) new_user.dates = self._migrate_dates(old_mb) new_user.save(creator=creator, using=options["_to"]) new_user.set_role("SimpleUsers") @@ -226,29 +239,41 @@ class Command(BaseCommand): def _migrate_admins(self, options, creator, pf_domain, newdom=None): """Administrators migration. - :param pf_domain: The ``pf_models.Domain`` to get the admins to migrate. - :param newdom: If None the admins will not be linked to any domain and - they will be SuperAdmins. Otherwise link them to this domain and make them - DomainAdmins. + :param pf_domain: The ``pf_models.Domain`` to get the admins to migrate. + :param newdom: If None the admins will not be linked to any domain + and they will be SuperAdmins. Otherwise link them to + this domain and make them DomainAdmins. """ - if (newdom is None): + if newdom is None: print "\nMigrating super administrators" else: print "\tMigrating administrators" dagroup = Group.objects.using(options["_to"]).get(name="DomainAdmins") for old_admin in pf_domain.admins.all(): - if (newdom is None): + if newdom is None: print "\tMigrating %s" % old_admin.username - #In postfixadmin, it's possible to have an admin account and a user account with the same username but they are completely different entities, so they do not have a common password. In Modoboa this does not makes sense, so we actually merge these two entities into a single user if both are found. Question is, which password should we use?. The admin password is used to be on the secure side. + # In postfixadmin, it's possible to have an admin account + # and a user account with the same username but they are + # completely different entities, so they do not have a + # common password. In Modoboa this does not makes sense, so + # we actually merge these two entities into a single user + # if both are found. Question is, which password should we + # use?. The admin password is used to be on the secure + # side. try: user = core_models.User.objects \ .using(options["_to"]).get(username=old_admin.username) - if ("SimpleUsers" == user.group): - print "Warning: Found an admin account with the same username as normal user '%s'. The existing user will be promoted to admin and it's password changed to the admin's account password. " % user.username + if "SimpleUsers" == user.group: + print ( + "Warning: Found an admin account with the same " + "username as normal user '%s'. The existing user will " + "be promoted to admin and it's password changed to the " + "admin's account password. " % user.username + ) except core_models.User.DoesNotExist: user = core_models.User() @@ -258,10 +283,10 @@ class Command(BaseCommand): user.save(creator=creator, using=options["_to"]) user.date_joined = old_admin.modified - user.password = "{%s}%s" % \ - (options["passwords_scheme"].upper(), old_admin.password) + set_account_password( + user, old_admin.password, options["passwords_scheme"]) - if (newdom is None): + if newdom is None: grant_access_to_all_objects(user, "SuperAdmins") user.is_superuser = True else: @@ -272,7 +297,8 @@ class Command(BaseCommand): def _do_migration(self, options, creator_username='admin'): """Run the complete migration.""" - pf_domains = pf_models.Domain.objects.using(options["_from"]).exclude(domain = 'ALL') + pf_domains = pf_models.Domain.objects.using( + options["_from"]).exclude(domain='ALL') creator = core_models.User.objects.using(options["_to"]).get( username=creator_username) for pf_domain in pf_domains: @@ -288,7 +314,8 @@ class Command(BaseCommand): self._migrate_domain(pf_domain, options, creator) #Handle the ALL domain - pf_domain = pf_models.Domain.objects.using(options["_from"]).get(domain = 'ALL') + pf_domain = pf_models.Domain.objects.using( + options["_from"]).get(domain='ALL') self._migrate_admins(options, creator, pf_domain) def handle(self, *args, **options): diff --git a/modoboa/tools/pfxadmin_migrate/models.py b/modoboa/tools/pfxadmin_migrate/models.py index 94f143ce2..c95f46216 100755 --- a/modoboa/tools/pfxadmin_migrate/models.py +++ b/modoboa/tools/pfxadmin_migrate/models.py @@ -150,7 +150,7 @@ class Mailbox(models.Model): class Quota(models.Model): username = models.CharField(max_length=255, primary_key=True) - path = models.CharField(max_length=300, primary_key=True) + path = models.CharField(max_length=100, primary_key=True) current = models.BigIntegerField(null=True, blank=True) class Meta: @@ -160,7 +160,7 @@ class Quota(models.Model): class Quota2(models.Model): - username = models.CharField(max_length=300, primary_key=True) + username = models.CharField(max_length=100, primary_key=True) bytes = models.BigIntegerField() messages = models.IntegerField() From ce2b04723fe6249cbd8fbd0146f7949c8fb632e6 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 8 Oct 2014 10:09:14 +0200 Subject: [PATCH 3/7] Documentation update. see #609 --- doc/additional/migrating.rst | 13 +++--- .../commands/migrate_from_postfixadmin.py | 41 +------------------ 2 files changed, 7 insertions(+), 47 deletions(-) diff --git a/doc/additional/migrating.rst b/doc/additional/migrating.rst index 4f1e8f71c..22acee28b 100644 --- a/doc/additional/migrating.rst +++ b/doc/additional/migrating.rst @@ -42,23 +42,20 @@ variable and save your changes. You are now ready to start the migration so run the following commands:: $ cd - $ python manage.py migrate_from_postfixadmin -r -p + $ python manage.py migrate_from_postfixadmin -s + +```` must be replaced by the scheme used within +postfixadmin (``crypt`` most of the time). Depending on how many domains/mailboxes your existing setup contains, the migration can be long. Just wait for the script's ending. -.. note:: - - The rename operation is not synchronous. If you choose this option, - you must enable **Handle mailboxes on filesystem** option. See - :ref:`fs_operations`. - The procedure is over, edit the :file:`settings.py` file and: * remove the ``pfxadmin`` database connection from the ``DATABASES`` variable * remove the ``'modoboa.tools.pfxadmin_migrate',`` from the - ``INSTALLED_APPS`` variable + ``MODOBOA_APPS`` variable You should be able to connect to Modoboa using the same credentials you were using to connect to PostfixAdmin. diff --git a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py index aacab4111..7b40d5461 100644 --- a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py +++ b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py @@ -12,17 +12,6 @@ will be lost on the new database. Here is the list: * Logs * Fetchmail table -Mailboxes organisation on the filesystem will change. PostfixAdmin -uses the following layout:: - - /domain.tld/user@domain.tld/ - -Whereas Modoboa uses the following:: - - /domain.tld/user/ - -To rename directories, you'll need the appropriate permissions. - Domain administrators that manage more than one domain will not be completly restored. They will only be administrator of the domain that corresponds to their username. @@ -44,9 +33,7 @@ used by PostfixAdmin. """ from optparse import make_option -import os import re -import sys from django.contrib.auth.models import Group from django.core.management.base import BaseCommand @@ -89,15 +76,6 @@ class Command(BaseCommand): help="Name of the Modoboa db connection declared in settings.py" " (default is default)" ), - make_option( - "-r", "--rename-dirs", action="store_true", default=False, - help="Rename mailbox directories (default is no)" - ), - make_option( - "-p", "--mboxes-path", default=None, - help="Path where directories are stored on the filesystem" - "(used only if --rename-dirs)" - ), make_option( "-s", "--passwords-scheme", default="crypt", help="Scheme used to crypt user passwords" @@ -184,14 +162,7 @@ class Command(BaseCommand): ) def _migrate_mailboxes(self, domain, options, creator): - """Migrate mailboxes of a single domain. - - .. note:: - - Mailboxes rename will be done later by the - handle_mailboxes_operation script. - - """ + """Migrate mailboxes of a single domain.""" print "\tMigrating mailboxes" old_mboxes = pf_models.Mailbox.objects \ .using(options["_from"]).filter(domain=domain.name) @@ -217,11 +188,6 @@ class Command(BaseCommand): new_mb.set_quota(old_mb.quota / 1024000, override_rules=True) new_mb.save(creator=creator, using=options["_to"]) - if options["rename_dirs"]: - oldpath = os.path.join( - options["mboxes_path"], domain.name, old_mb.maildir) - new_mb.rename_dir(oldpath) - def _migrate_domain(self, pf_domain, options, creator): """Single domain migration.""" print "\nMigrating domain %s" % pf_domain.domain @@ -313,15 +279,12 @@ class Command(BaseCommand): except pf_models.AliasDomain.DoesNotExist: self._migrate_domain(pf_domain, options, creator) - #Handle the ALL domain + # Handle the ALL domain pf_domain = pf_models.Domain.objects.using( options["_from"]).get(domain='ALL') self._migrate_admins(options, creator, pf_domain) def handle(self, *args, **options): """Command entry point.""" - if options["rename_dirs"] and options["mboxes_path"] is None: - print "Error: you must provide the --mboxes-path option" - sys.exit(1) with transaction.commit_on_success(): self._do_migration(options) From 243ee9c5743b02b764d3b8fee8322962ebc23cf9 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 8 Oct 2014 10:23:16 +0200 Subject: [PATCH 4/7] Amavis configuration update. see #608 --- doc/getting_started/plugins.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/getting_started/plugins.rst b/doc/getting_started/plugins.rst index ad1ce99c4..3662c6ffe 100644 --- a/doc/getting_started/plugins.rst +++ b/doc/getting_started/plugins.rst @@ -118,6 +118,11 @@ quarantined messages storing. Here is a working configuration sample:: @storage_sql_dsn = (['DBI::database=;host=;port=', '', ']']); + # PostgreSQL users NEED this parameter! + # MySQL users only need this parameter is email addresses are stored + # using the VARBINARY type. + $sql_allow_8bit_address = 1; + $virus_quarantine_method = 'sql:'; $spam_quarantine_method = 'sql:'; $banned_files_quarantine_method = 'sql:'; From e69cf5bf59dbe4080cd5634735757b0f3700db66 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 8 Oct 2014 10:33:36 +0200 Subject: [PATCH 5/7] Amavis configuration update. --- doc/plugins/amavis.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/plugins/amavis.rst b/doc/plugins/amavis.rst index 8bc7f74e3..8f6f37bca 100644 --- a/doc/plugins/amavis.rst +++ b/doc/plugins/amavis.rst @@ -43,6 +43,11 @@ quarantined messages storing. Here is a working configuration sample:: @storage_sql_dsn = (['DBI::database=;host=;port=', '', ']']); + # PostgreSQL users NEED this parameter! + # MySQL users only need this parameter is email addresses are stored + # using the VARBINARY type. + $sql_allow_8bit_address = 1; + $virus_quarantine_method = 'sql:'; $spam_quarantine_method = 'sql:'; $banned_files_quarantine_method = 'sql:'; From 7f58bbd3e91448492510ae66d73c3c4184056525 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 13 Oct 2014 21:58:36 +0200 Subject: [PATCH 6/7] Fix attempt. see #610 --- .../extensions/stats/static/stats/js/stats.js | 20 +++++++++++++++++-- .../stats/templates/stats/index.html | 7 +------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/modoboa/extensions/stats/static/stats/js/stats.js b/modoboa/extensions/stats/static/stats/js/stats.js index 0e9d54f12..753224782 100644 --- a/modoboa/extensions/stats/static/stats/js/stats.js +++ b/modoboa/extensions/stats/static/stats/js/stats.js @@ -7,7 +7,8 @@ Stats.prototype = { defaults: { deflocation: "graphs/", - language: "en" + language: "en", + domain_list_url: null }, initialize: function(options) { @@ -52,7 +53,7 @@ Stats.prototype = { language: this.options.language }); $("#searchquery").autocompleter({ - choices: get_domains_list, + choices: $.proxy(this.get_domain_list, this), choice_selected: $.proxy(this.search_domain, this), empty_choice: $.proxy(this.reset_search, this) }); @@ -71,6 +72,21 @@ Stats.prototype = { $.proxy(this.graphs_cb, this)); }, + /** + * Retrieve a list of domain from the server. + */ + get_domain_list: function() { + var result; + $.ajax({ + url: this.options.domain_list_url, + dataType: "json", + async: false + }).done(function(data) { + result = data; + }); + return result; + }, + change_period: function(e) { e.preventDefault(); var $link = $(e.target); diff --git a/modoboa/extensions/stats/templates/stats/index.html b/modoboa/extensions/stats/templates/stats/index.html index 9aec1d1ef..6df360da5 100644 --- a/modoboa/extensions/stats/templates/stats/index.html +++ b/modoboa/extensions/stats/templates/stats/index.html @@ -6,15 +6,10 @@ {% extra_static_content "identities" user %} diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py index 8834a5cfe..84a2cdd5d 100644 --- a/modoboa/lib/permissions.py +++ b/modoboa/lib/permissions.py @@ -4,7 +4,6 @@ from django.utils.translation import ugettext as _ from django.db import IntegrityError from modoboa.core.models import ObjectAccess, User from modoboa.lib import events -from modoboa.lib.exceptions import ModoboaException def get_account_roles(user, account=None): @@ -19,7 +18,7 @@ def get_account_roles(user, account=None): """ std_roles = [("SimpleUsers", _("Simple user"))] if user.is_superuser: - std_roles += [("SuperAdmins", _("Super administrator"))] + std_roles += [("SuperAdmins", _("Super administrator"))] filters = events.raiseQueryEvent( 'UserCanSetRole', user, 'DomainAdmins', account ) diff --git a/modoboa/static/js/autocompleter.js b/modoboa/static/js/autocompleter.js index c726ba256..c5b63b62d 100644 --- a/modoboa/static/js/autocompleter.js +++ b/modoboa/static/js/autocompleter.js @@ -9,13 +9,10 @@ initialize: function(element, options) { this.$element = $(element); this.options = $.extend({}, $.fn.autocompleter.defaults, options); - this.choices = { - value: null - }; if (typeof this.options.choices === "function") { - this.options.choices(this.choices); + this.choices = this.options.choices(); } else { - this.choices.value = this.options.choices(); + this.choices = this.options.choices; } this.$menu = $('