From a8b5c86c8a09cfad7ff837bf18adbcaf7820c440 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 2 Feb 2015 14:21:39 +0100 Subject: [PATCH] Unit tests fixed. --- modoboa/core/__init__.py | 2 + modoboa/core/factories.py | 20 ++++++-- .../management/commands/load_initial_data.py | 7 ++- modoboa/extensions/admin/factories.py | 18 +++++-- modoboa/extensions/admin/forms/account.py | 9 +++- modoboa/extensions/admin/forms/alias.py | 7 ++- .../commands/handle_mailbox_operations.py | 2 - modoboa/extensions/admin/modo_extension.py | 2 +- .../extensions/amavis/general_callbacks.py | 23 +++++++++ .../amavis/management/commands/amnotify.py | 2 - .../amavis/management/commands/qcleanup.py | 3 -- .../migrations/0002_load_initial_data.py | 51 ------------------- modoboa/extensions/amavis/modo_extension.py | 24 ++++++++- .../migrations/0002_load_initial_data.py | 29 ----------- modoboa/extensions/limits/modo_extension.py | 13 ++--- modoboa/extensions/limits/tests.py | 8 ++- modoboa/extensions/postfix_autoreply/forms.py | 9 ++-- .../postfix_autoreply/general_callbacks.py | 1 + .../management/commands/autoreply.py | 2 - .../migrations/0002_load_initial_data.py | 40 --------------- .../postfix_autoreply/modo_extension.py | 20 +++++++- modoboa/extensions/postfix_autoreply/tests.py | 8 ++- .../general_callbacks.py | 2 +- .../postfix_relay_domains/limits_callbacks.py | 20 +++++++- .../migrations/0002_load_initial_data.py | 22 -------- .../postfix_relay_domains/modo_extension.py | 11 ++++ .../extensions/postfix_relay_domains/tests.py | 15 +++--- modoboa/extensions/radicale/factories.py | 12 +++-- .../management/commands/generate_rights.py | 7 +-- modoboa/extensions/radicale/tests.py | 12 ++--- .../stats/management/commands/logparser.py | 2 - modoboa/lib/form_utils.py | 7 ++- modoboa/lib/tests.py | 26 +++------- tests/install_from_scratch.py | 2 +- 34 files changed, 198 insertions(+), 240 deletions(-) delete mode 100644 modoboa/extensions/amavis/migrations/0002_load_initial_data.py delete mode 100644 modoboa/extensions/limits/migrations/0002_load_initial_data.py delete mode 100644 modoboa/extensions/postfix_autoreply/migrations/0002_load_initial_data.py delete mode 100644 modoboa/extensions/postfix_relay_domains/migrations/0002_load_initial_data.py diff --git a/modoboa/core/__init__.py b/modoboa/core/__init__.py index e31c299f1..cc91ec6c1 100644 --- a/modoboa/core/__init__.py +++ b/modoboa/core/__init__.py @@ -22,6 +22,8 @@ BASE_EVENTS = [ "PasswordChange", "UserCanSetRole", + "InitialDataLoaded", + "UserMenuDisplay", "AdminMenuDisplay", "GetStaticContent", diff --git a/modoboa/core/factories.py b/modoboa/core/factories.py index d4dd9d6ad..768ca8546 100644 --- a/modoboa/core/factories.py +++ b/modoboa/core/factories.py @@ -1,27 +1,37 @@ +"""Factories for core application.""" + import factory + from django.contrib.auth.models import Group + from . import models class PermissionFactory(factory.DjangoModelFactory): - ABSTRACT_FACTORY = True + + class Meta: + abstract = True @factory.post_generation def set_permission(self, create, extracted, **kwargs): if not create: return - self.post_create(models.User.objects.get(pk=1)) + self.post_create(models.User.objects.filter(is_superuser=True).first()) class GroupFactory(factory.DjangoModelFactory): - FACTORY_FOR = Group + + class Meta: + model = Group name = 'DefaultGroup' class UserFactory(PermissionFactory): - FACTORY_FOR = models.User - FACTORY_DJANGO_GET_OR_CREATE = ("username", ) + + class Meta: + model = models.User + django_get_or_create = ("username", ) email = factory.LazyAttribute(lambda a: a.username) password = '{PLAIN}toto' diff --git a/modoboa/core/management/commands/load_initial_data.py b/modoboa/core/management/commands/load_initial_data.py index a42a99ef3..148c57cc6 100644 --- a/modoboa/core/management/commands/load_initial_data.py +++ b/modoboa/core/management/commands/load_initial_data.py @@ -25,15 +25,17 @@ class Command(BaseCommand, CloseConnectionMixin): def handle(self, *args, **options): """Command entry point.""" - if not User.objects.filter(pk=1, username="admin").exists(): + if not User.objects.filter(is_superuser=True).count(): admin = User(username="admin", is_superuser=True) admin.set_password("password") admin.save() ObjectAccess.objects.create( user=admin, content_object=admin, is_owner=True) + superadmin = User.objects.filter(is_superuser=True).first() groups = PERMISSIONS.keys() + [ - role[0] for role in events.raiseQueryEvent("GetExtraRoles") + role[0] for role + in events.raiseQueryEvent("GetExtraRoles", superadmin) ] for groupname in groups: group, created = Group.objects.get_or_create(name=groupname) @@ -49,3 +51,4 @@ class Command(BaseCommand, CloseConnectionMixin): for extname in exts_pool.extensions.keys(): extension = exts_pool.get_extension(extname) extension.load_initial_data() + events.raiseEvent("InitialDataLoaded", extname) diff --git a/modoboa/extensions/admin/factories.py b/modoboa/extensions/admin/factories.py index b4399e0cd..e49956e83 100644 --- a/modoboa/extensions/admin/factories.py +++ b/modoboa/extensions/admin/factories.py @@ -8,15 +8,21 @@ from . import models class DomainFactory(PermissionFactory): - FACTORY_FOR = models.Domain - FACTORY_DJANGO_GET_OR_CREATE = ("name", ) + + """Factory to create Domains.""" + + class Meta: + model = models.Domain + django_get_or_create = ("name", ) quota = 10 enabled = True class MailboxFactory(PermissionFactory): - FACTORY_FOR = models.Mailbox + + class Meta: + model = models.Mailbox domain = factory.SubFactory(DomainFactory) user = factory.SubFactory(UserFactory) @@ -25,7 +31,9 @@ class MailboxFactory(PermissionFactory): class AliasFactory(PermissionFactory): - FACTORY_FOR = models.Alias + + class Meta: + model = models.Alias enabled = True @@ -35,7 +43,7 @@ def populate_database(): 2 domains, 1 domain admin, 2 users """ - dom = DomainFactory.create(name="test.com") + dom = DomainFactory(name="test.com") admin = UserFactory( username="admin@test.com", groups=('DomainAdmins', ), password='{PLAIN}toto' diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index dcda56951..37d70964b 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -1,5 +1,7 @@ """Forms related to accounts management.""" +from collections import OrderedDict + from django import forms from django.core.urlresolvers import reverse from django.http import QueryDict @@ -49,8 +51,11 @@ class AccountFormGeneral(forms.ModelForm): def __init__(self, user, *args, **kwargs): super(AccountFormGeneral, self).__init__(*args, **kwargs) - self.fields.keyOrder = ['role', 'username', 'first_name', 'last_name', - 'password1', 'password2', 'is_active'] + self.fields = OrderedDict( + (key, self.fields[key]) for key in + ['role', 'username', 'first_name', 'last_name', 'password1', + 'password2', 'is_active'] + ) self.fields["is_active"].label = _("Enabled") self.user = user if user.group == "DomainAdmins": diff --git a/modoboa/extensions/admin/forms/alias.py b/modoboa/extensions/admin/forms/alias.py index d54dad929..1a999fe49 100644 --- a/modoboa/extensions/admin/forms/alias.py +++ b/modoboa/extensions/admin/forms/alias.py @@ -1,5 +1,7 @@ """Forms related to aliases management.""" +from collections import OrderedDict + from django import forms from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy @@ -39,7 +41,10 @@ class AliasForm(forms.ModelForm, DynamicForm): def __init__(self, user, *args, **kwargs): self.user = user super(AliasForm, self).__init__(*args, **kwargs) - self.fields.keyOrder = ['email', 'recipients', 'enabled'] + self.fields = OrderedDict( + (key, self.fields[key]) for key in + ['email', 'recipients', 'enabled'] + ) if len(args) and isinstance(args[0], QueryDict): if "instance" in kwargs: diff --git a/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py b/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py index 49607b4fe..b0cea9d46 100644 --- a/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py +++ b/modoboa/extensions/admin/management/commands/handle_mailbox_operations.py @@ -9,7 +9,6 @@ from modoboa.core.management.commands import CloseConnectionMixin from modoboa.lib import parameters from modoboa.lib.sysutils import exec_cmd from modoboa.lib.exceptions import InternalError -from modoboa.extensions.admin import AdminConsole from modoboa.extensions.admin.models import MailboxOperation @@ -75,7 +74,6 @@ class Command(BaseCommand, CloseConnectionMixin): return True def handle(self, *args, **options): - AdminConsole().load() try: if parameters.get_admin("HANDLE_MAILBOXES") == 'no': return diff --git a/modoboa/extensions/admin/modo_extension.py b/modoboa/extensions/admin/modo_extension.py index 0b5687508..15d64de5b 100644 --- a/modoboa/extensions/admin/modo_extension.py +++ b/modoboa/extensions/admin/modo_extension.py @@ -56,7 +56,7 @@ PERMISSIONS = { ["admin", "alias", "delete_alias"], ["admin", "mailbox", "view_mailboxes"], ["admin", "alias", "view_aliases"], - ["admin", "domainalias", "view_domainaliases"], + ["admin", "domainalias", "view_domaliases"], ["admin", "domainalias", "add_domainalias"], ["admin", "domainalias", "change_domainalias"], ["admin", "domainalias", "delete_domainalias"] diff --git a/modoboa/extensions/amavis/general_callbacks.py b/modoboa/extensions/amavis/general_callbacks.py index 32e42cb01..1e1c9b9d5 100644 --- a/modoboa/extensions/amavis/general_callbacks.py +++ b/modoboa/extensions/amavis/general_callbacks.py @@ -12,6 +12,29 @@ from .lib import manual_learning_enabled from .models import Policy, Users +def create_relay_domains_records(): + """Create records for existing relay domains.""" + from modoboa.extensions.postfix_relay_domains.models import RelayDomain + + for dom in RelayDomain.objects.all(): + name = "@{0}".format(dom.name) + policy, created = Policy.objects.get_or_create(policy_name=name[:32]) + Users.objects.get_or_create( + email=name, fullname=name, priority=7, policy=policy) + for rdalias in dom.relaydomainalias_set.all(): + name = "@{0}".format(rdalias.name) + Users.objects.get_or_create( + email=name, fullname=name, priority=7, policy=policy) + + +@events.observe("InitialDataLoaded") +def load_relay_domains_dependant_data(name): + """Load relay domains dependant data.""" + if name != "postfix_relay_domains": + return + create_relay_domains_records() + + @events.observe("UserMenuDisplay") def menu(target, user): if target == "top_menu": diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py index 82c5f62f0..209350da3 100644 --- a/modoboa/extensions/amavis/management/commands/amnotify.py +++ b/modoboa/extensions/amavis/management/commands/amnotify.py @@ -13,7 +13,6 @@ from modoboa.lib import parameters from modoboa.lib.email_utils import sendmail_simple from modoboa.extensions.admin.models import Domain -from modoboa.extensions.amavis import Amavis from modoboa.extensions.amavis.models import ( Msgrcpt ) @@ -42,7 +41,6 @@ class Command(BaseCommand, CloseConnectionMixin): if options["baseurl"] is None: raise CommandError("You must provide the --baseurl option") self.options = options - Amavis().load() self.notify_admins_pending_requests() def send_pr_notification(self, rcpt, reqs): diff --git a/modoboa/extensions/amavis/management/commands/qcleanup.py b/modoboa/extensions/amavis/management/commands/qcleanup.py index d81b9645a..47e2d6dce 100644 --- a/modoboa/extensions/amavis/management/commands/qcleanup.py +++ b/modoboa/extensions/amavis/management/commands/qcleanup.py @@ -7,7 +7,6 @@ from optparse import make_option from django.core.management.base import BaseCommand from modoboa.core.management.commands import CloseConnectionMixin -from modoboa.extensions.amavis import Amavis from modoboa.extensions.amavis.models import ( Msgrcpt, Msgs, Maddr ) @@ -42,8 +41,6 @@ class Command(BaseCommand, CloseConnectionMixin): l.addHandler(logging.StreamHandler()) self.verbose = options["verbose"] - Amavis().load() - max_messages_age = int(parameters.get_admin("MAX_MESSAGES_AGE", app="amavis")) diff --git a/modoboa/extensions/amavis/migrations/0002_load_initial_data.py b/modoboa/extensions/amavis/migrations/0002_load_initial_data.py deleted file mode 100644 index 398696173..000000000 --- a/modoboa/extensions/amavis/migrations/0002_load_initial_data.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - -from modoboa.core.extensions import exts_pool - - -def load_initial_data(apps, schema_editor): - """Load initial data.""" - Domain = apps.get_model("admin", "Domain") - Policy = apps.get_model("amavis", "Policy") - Users = apps.get_model("amavis", "Users") - - for dom in Domain.objects.all(): - name = "@{0}".format(dom.name) - policy, created = Policy.objects.get_or_create(policy_name=name[:32]) - Users.objects.get_or_create( - email=name, fullname=name, priority=7, policy=policy) - for dalias in dom.domainalias_set.all(): - name = "@{0}".format(dalias.name) - Users.objects.get_or_create( - email=name, fullname=name, priority=7, policy=policy) - - if not exts_pool.is_extension_installed( - "modoboa.extensions.postfix_relay_domains"): - return - - RelayDomain = apps.get_model("postfix_relay_domains", "RelayDomain") - - for dom in RelayDomain.objects.all(): - name = "@{0}".format(dom.name) - policy, created = Policy.objects.get_or_create(policy_name=name[:32]) - Users.objects.get_or_create( - email=name, fullname=name, priority=7, policy=policy) - for rdalias in dom.relaydomainalias_set.all(): - name = "@{0}".format(rdalias.name) - Users.objects.get_or_create( - email=name, fullname=name, priority=7, policy=policy) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('amavis', '0001_initial'), - ] - - operations = [ - migrations.RunPython(load_initial_data) - ] diff --git a/modoboa/extensions/amavis/modo_extension.py b/modoboa/extensions/amavis/modo_extension.py index 3919be8e4..55f73ba3e 100644 --- a/modoboa/extensions/amavis/modo_extension.py +++ b/modoboa/extensions/amavis/modo_extension.py @@ -8,13 +8,16 @@ Provides: * Per-domain settings """ -import sys from django.utils.translation import ugettext_lazy from modoboa.core.extensions import ModoExtension, exts_pool +from modoboa.extensions.admin.models import Domain from modoboa.lib import parameters +from . import general_callbacks +from .models import Policy, Users + class Amavis(ModoExtension): name = "amavis" @@ -29,6 +32,23 @@ class Amavis(ModoExtension): parameters.register(ParametersForm, "Amavis") parameters.register(UserSettings, ugettext_lazy("Quarantine")) - from modoboa.extensions.amavis import general_callbacks + + def load_initial_data(self): + """Create records for existing domains and co.""" + for dom in Domain.objects.all(): + name = "@{0}".format(dom.name) + policy, created = Policy.objects.get_or_create( + policy_name=name[:32]) + Users.objects.get_or_create( + email=name, fullname=name, priority=7, policy=policy) + for dalias in dom.domainalias_set.all(): + name = "@{0}".format(dalias.name) + Users.objects.get_or_create( + email=name, fullname=name, priority=7, policy=policy) + + if not exts_pool.is_extension_installed( + "modoboa.extensions.postfix_relay_domains"): + return + general_callbacks.create_relay_domains_records() exts_pool.register_extension(Amavis) diff --git a/modoboa/extensions/limits/migrations/0002_load_initial_data.py b/modoboa/extensions/limits/migrations/0002_load_initial_data.py deleted file mode 100644 index eb51dcd1d..000000000 --- a/modoboa/extensions/limits/migrations/0002_load_initial_data.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - -from modoboa.extensions.limits.models import LimitTemplates - - -def load_initial_data(apps, schema_editor): - """Load initial data.""" - User = apps.get_model("core", "User") - LimitsPool = apps.get_model("limits", "LimitsPool") - Limit = apps.get_model("limits", "Limit") - - for user in User.objects.filter(groups__name="DomainAdmins"): - pool, created = LimitsPool.objects.get_or_create(user=user) - for tpl in LimitTemplates().templates: - Limit.objects.create(name=tpl[0], pool=pool, maxvalue=0) - - -class Migration(migrations.Migration): - - dependencies = [ - ('limits', '0001_initial'), - ] - - operations = [ - migrations.RunPython(load_initial_data) - ] diff --git a/modoboa/extensions/limits/modo_extension.py b/modoboa/extensions/limits/modo_extension.py index 2f1253ee2..45a8659a6 100644 --- a/modoboa/extensions/limits/modo_extension.py +++ b/modoboa/extensions/limits/modo_extension.py @@ -7,8 +7,9 @@ The *limits* extension from django.utils.translation import ugettext_lazy from modoboa.core.extensions import ModoExtension, exts_pool +from modoboa.core.models import User from modoboa.lib import events, parameters -from .models import LimitsPool, Limit +from .models import LimitTemplates, LimitsPool, Limit EVENTS = [ @@ -34,10 +35,10 @@ class Limits(ModoExtension): from modoboa.extensions.limits import general_callbacks def load_initial_data(self): - """Complete existing pools with new limits.""" - new_limits = ["relay_domains_limit", "relay_domain_aliases_limit"] - for pool in LimitsPool.objects.all(): - for lname in new_limits: - Limit.objects.get_or_create(name=lname, pool=pool, maxvalue=0) + """Create pools for existing accounts.""" + for user in User.objects.filter(groups__name="DomainAdmins"): + pool, created = LimitsPool.objects.get_or_create(user=user) + for tpl in LimitTemplates().templates: + Limit.objects.get_or_create(name=tpl[0], pool=pool, maxvalue=0) exts_pool.register_extension(Limits) diff --git a/modoboa/extensions/limits/tests.py b/modoboa/extensions/limits/tests.py index 893417ea0..69b737714 100644 --- a/modoboa/extensions/limits/tests.py +++ b/modoboa/extensions/limits/tests.py @@ -10,15 +10,14 @@ from modoboa.extensions.admin.factories import ( from modoboa.extensions.admin.models import Alias, Domain from modoboa.extensions.limits.models import LimitTemplates from modoboa.lib import parameters -from modoboa.lib.tests import ExtTestCase +from modoboa.lib.tests import ModoTestCase -class PermissionsTestCase(ExtTestCase): +class PermissionsTestCase(ModoTestCase): fixtures = ["initial_users.json"] def setUp(self): super(PermissionsTestCase, self).setUp() - self.activate_extensions('limits') populate_database() def test_domainadmin_deletes_reseller(self): @@ -42,7 +41,7 @@ class PermissionsTestCase(ExtTestCase): self.assertEqual(resp, "Permission denied") -class ResourceTestCase(ExtTestCase): +class ResourceTestCase(ModoTestCase): fixtures = ["initial_users.json"] def setUp(self): @@ -52,7 +51,6 @@ class ResourceTestCase(ExtTestCase): provided by 'postfix_relay_domains' are properly received. """ super(ResourceTestCase, self).setUp() - self.activate_extensions('limits') for tpl in LimitTemplates().templates: parameters.save_admin('DEFLT_%s' % tpl[0].upper(), 2, app='limits') populate_database() diff --git a/modoboa/extensions/postfix_autoreply/forms.py b/modoboa/extensions/postfix_autoreply/forms.py index 9e159343e..0e32ebf0d 100644 --- a/modoboa/extensions/postfix_autoreply/forms.py +++ b/modoboa/extensions/postfix_autoreply/forms.py @@ -2,6 +2,8 @@ """Custom forms.""" +from collections import OrderedDict + from django import forms from django.utils import timezone from django.utils.translation import ugettext as _, ugettext_lazy @@ -44,9 +46,10 @@ class ARmessageForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(ARmessageForm, self).__init__(*args, **kwargs) - self.fields.keyOrder = [ - 'subject', 'content', 'fromdate', 'untildate', 'enabled' - ] + self.fields = OrderedDict( + (key, self.fields[key]) for key in + ['subject', 'content', 'fromdate', 'untildate', 'enabled'] + ) if 'instance' in kwargs and kwargs['instance'] is not None: self.fields['fromdate'].initial = \ kwargs['instance'].fromdate.replace(second=0, microsecond=0) diff --git a/modoboa/extensions/postfix_autoreply/general_callbacks.py b/modoboa/extensions/postfix_autoreply/general_callbacks.py index caff6b845..450cf0b42 100644 --- a/modoboa/extensions/postfix_autoreply/general_callbacks.py +++ b/modoboa/extensions/postfix_autoreply/general_callbacks.py @@ -120,6 +120,7 @@ def extra_mailform_fields(form_name, mailbox=None): ('autoreply', YesNoField( label=ugettext_lazy("Enable auto-reply"), initial="yes" if status else "no", + required=False, help_text=ugettext_lazy("Enable or disable Postfix auto-reply") )) ] diff --git a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py index 82f0c3064..09482185c 100644 --- a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py +++ b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py @@ -10,7 +10,6 @@ from modoboa.core.management.commands import CloseConnectionMixin from modoboa.lib import parameters from modoboa.lib.email_utils import split_mailbox, sendmail_simple from modoboa.extensions.admin.models import Mailbox -from modoboa.extensions.postfix_autoreply import PostfixAutoreply from modoboa.extensions.postfix_autoreply.models import ARmessage, ARhistoric @@ -25,7 +24,6 @@ def send_autoreply(sender, mailbox, armessage): try: lastar = ARhistoric.objects.get(armessage=armessage.id, sender=sender) - PostfixAutoreply().load() timeout = parameters.get_admin("AUTOREPLIES_TIMEOUT", app="postfix_autoreply") delta = datetime.timedelta(seconds=int(timeout)) diff --git a/modoboa/extensions/postfix_autoreply/migrations/0002_load_initial_data.py b/modoboa/extensions/postfix_autoreply/migrations/0002_load_initial_data.py deleted file mode 100644 index d98c2b720..000000000 --- a/modoboa/extensions/postfix_autoreply/migrations/0002_load_initial_data.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - -from modoboa.extensions.postfix_autoreply.general_callbacks import ( - onDomainCreated, onMailboxCreated -) - - -def load_initial_data(apps, schema_editor): - """Load initial data.""" - Domain = apps.get_model("admin", "Domain") - Transport = apps.get_model("postfix_autoreply", "Transport") - Alias = apps.get_model("postfix_autoreply", "Alias") - - for dom in Domain.objects.all(): - try: - Transport.objects.get(domain="autoreply.%s" % dom.name) - except Transport.DoesNotExist: - onDomainCreated(None, dom) - else: - continue - - for mb in dom.mailbox_set.all(): - try: - Alias.objects.get(full_address=mb.full_address) - except Alias.DoesNotExist: - onMailboxCreated(None, mb) - - -class Migration(migrations.Migration): - - dependencies = [ - ('postfix_autoreply', '0001_initial'), - ] - - operations = [ - migrations.RunPython(load_initial_data) - ] diff --git a/modoboa/extensions/postfix_autoreply/modo_extension.py b/modoboa/extensions/postfix_autoreply/modo_extension.py index fa38fd894..90e861cde 100644 --- a/modoboa/extensions/postfix_autoreply/modo_extension.py +++ b/modoboa/extensions/postfix_autoreply/modo_extension.py @@ -10,7 +10,10 @@ functionality into Postfix. from django.utils.translation import ugettext_lazy from modoboa.core.extensions import ModoExtension, exts_pool +from modoboa.extensions.admin.models import Domain from modoboa.lib import events, parameters +from . import general_callbacks +from .models import Transport, Alias class PostfixAutoreply(ModoExtension): @@ -31,7 +34,22 @@ class PostfixAutoreply(ModoExtension): ) parameters.register( ParametersForm, ugettext_lazy("Automatic replies")) - from modoboa.extensions.postfix_autoreply import general_callbacks + + def load_initial_data(self): + """Create records for existing domains.""" + for dom in Domain.objects.all(): + try: + Transport.objects.get(domain="autoreply.%s" % dom.name) + except Transport.DoesNotExist: + general_callbacks.onDomainCreated(None, dom) + else: + continue + + for mb in dom.mailbox_set.all(): + try: + Alias.objects.get(full_address=mb.full_address) + except Alias.DoesNotExist: + general_callbacks.onMailboxCreated(None, mb) exts_pool.register_extension(PostfixAutoreply) diff --git a/modoboa/extensions/postfix_autoreply/tests.py b/modoboa/extensions/postfix_autoreply/tests.py index e021e2929..3e1dd172e 100644 --- a/modoboa/extensions/postfix_autoreply/tests.py +++ b/modoboa/extensions/postfix_autoreply/tests.py @@ -1,6 +1,6 @@ from django.core.urlresolvers import reverse from modoboa.core.models import User -from modoboa.lib.tests import ExtTestCase +from modoboa.lib.tests import ModoTestCase from modoboa.extensions.admin import factories from modoboa.extensions.admin.models import ( Domain @@ -10,12 +10,11 @@ from modoboa.extensions.postfix_autoreply.models import ( ) -class EventsTestCase(ExtTestCase): +class EventsTestCase(ModoTestCase): fixtures = ['initial_users.json'] def setUp(self): super(EventsTestCase, self).setUp() - self.activate_extensions('postfix_autoreply') factories.populate_database() def test_domain_created_event(self): @@ -100,12 +99,11 @@ class EventsTestCase(ExtTestCase): al = Alias.objects.get(full_address='leon@test.com') -class FormTestCase(ExtTestCase): +class FormTestCase(ModoTestCase): fixtures = ['initial_users.json'] def setUp(self): super(FormTestCase, self).setUp() - self.activate_extensions('postfix_autoreply') factories.populate_database() # def test_set_autoreply(self): diff --git a/modoboa/extensions/postfix_relay_domains/general_callbacks.py b/modoboa/extensions/postfix_relay_domains/general_callbacks.py index 34422c156..2dd319956 100644 --- a/modoboa/extensions/postfix_relay_domains/general_callbacks.py +++ b/modoboa/extensions/postfix_relay_domains/general_callbacks.py @@ -30,7 +30,7 @@ PERMISSIONS = { @events.observe("GetExtraRolePermissions") def extra_permissions(rolename): """Return extra permissions for Resellers.""" - if not exts_pool.is_extension_installed("modoboa.extensions.limit"): + if not exts_pool.is_extension_installed("modoboa.extensions.limits"): return [] return PERMISSIONS.get(rolename, []) diff --git a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py b/modoboa/extensions/postfix_relay_domains/limits_callbacks.py index 8b1ce5d81..7a7b362cf 100644 --- a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py +++ b/modoboa/extensions/postfix_relay_domains/limits_callbacks.py @@ -2,10 +2,28 @@ from django.utils.translation import ugettext_lazy -from .models import RelayDomainAlias from modoboa.extensions.limits.lib import inc_limit_usage, dec_limit_usage +from modoboa.extensions.limits.models import LimitsPool, Limit from modoboa.lib import events from modoboa.lib.permissions import get_object_owner +from .models import RelayDomainAlias + + +def create_new_limits(): + """Create relay domains limits.""" + + new_limits = ["relay_domains_limit", "relay_domain_aliases_limit"] + for pool in LimitsPool.objects.all(): + for lname in new_limits: + Limit.objects.get_or_create(name=lname, pool=pool, maxvalue=0) + + +@events.observe("InitialDataLoaded") +def load_limits_dependant_data(name): + """Complete existing pools with new limits.""" + if name != "limits": + return + create_new_limits() @events.observe('GetExtraParameters') diff --git a/modoboa/extensions/postfix_relay_domains/migrations/0002_load_initial_data.py b/modoboa/extensions/postfix_relay_domains/migrations/0002_load_initial_data.py deleted file mode 100644 index cec56af50..000000000 --- a/modoboa/extensions/postfix_relay_domains/migrations/0002_load_initial_data.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -def load_initial_data(apps, schema_editor): - """Load initial data.""" - Service = apps.get_model("postfix_relay_domains", "Service") - for service_name in ['relay', 'smtp']: - Service.objects.get_or_create(name=service_name) - - -class Migration(migrations.Migration): - - dependencies = [ - ('postfix_relay_domains', '0001_initial'), - ] - - operations = [ - migrations.RunPython(load_initial_data) - ] diff --git a/modoboa/extensions/postfix_relay_domains/modo_extension.py b/modoboa/extensions/postfix_relay_domains/modo_extension.py index 2fe412608..4694f801a 100644 --- a/modoboa/extensions/postfix_relay_domains/modo_extension.py +++ b/modoboa/extensions/postfix_relay_domains/modo_extension.py @@ -41,4 +41,15 @@ class PostfixRelayDomains(ModoExtension): if exts_pool.is_extension_installed("modoboa.extensions.amavis"): import amavis_callbacks + def load_initial_data(self): + """Create extension data.""" + from .models import Service + for service_name in ['relay', 'smtp']: + Service.objects.get_or_create(name=service_name) + + if not exts_pool.is_extension_installed("modoboa.extensions.limits"): + return + from .limits_callbacks import create_new_limits + create_new_limits() + exts_pool.register_extension(PostfixRelayDomains) diff --git a/modoboa/extensions/postfix_relay_domains/tests.py b/modoboa/extensions/postfix_relay_domains/tests.py index f1d28a001..0a725161d 100644 --- a/modoboa/extensions/postfix_relay_domains/tests.py +++ b/modoboa/extensions/postfix_relay_domains/tests.py @@ -1,11 +1,11 @@ from django.core.urlresolvers import reverse + from modoboa.core.factories import UserFactory -from modoboa.lib import parameters -from modoboa.lib.tests import ExtTestCase from modoboa.extensions.admin import factories -from modoboa.extensions.limits.tests import ResourceTestCase -from .models import RelayDomain, RelayDomainAlias, Service +from modoboa.lib import parameters +from modoboa.lib.tests import ModoTestCase from .factories import RelayDomainFactory, RelayDomainAliasFactory +from .models import RelayDomain, RelayDomainAlias, Service class Operations(object): @@ -47,12 +47,11 @@ class Operations(object): self.assertEqual(l.maxvalue, maxvalue) -class RelayDomainsTestCase(ExtTestCase, Operations): +class RelayDomainsTestCase(ModoTestCase, Operations): fixtures = ['initial_users.json'] def setUp(self): super(RelayDomainsTestCase, self).setUp() - self.activate_extensions('postfix_relay_domains') factories.populate_database() self.rdom = RelayDomainFactory(name='relaydomain.tld') RelayDomainAliasFactory(name='relaydomainalias.tld', target=self.rdom) @@ -162,14 +161,12 @@ class RelayDomainsTestCase(ExtTestCase, Operations): RelayDomain.objects.get(name='relaydomainalias.tld') -class LimitsTestCase(ExtTestCase, Operations): - fixtures = ['initial_users.json'] +class LimitsTestCase(ModoTestCase, Operations): def setUp(self): super(LimitsTestCase, self).setUp() from modoboa.extensions.limits.models import LimitTemplates - self.activate_extensions('limits', 'postfix_relay_domains') for tpl in LimitTemplates().templates: parameters.save_admin('DEFLT_%s' % tpl[0].upper(), 2, app='limits') self.user = UserFactory.create( diff --git a/modoboa/extensions/radicale/factories.py b/modoboa/extensions/radicale/factories.py index a164df7db..278cc3232 100644 --- a/modoboa/extensions/radicale/factories.py +++ b/modoboa/extensions/radicale/factories.py @@ -11,21 +11,27 @@ from . import models class UserCalendarFactory(factory.DjangoModelFactory): - FACTORY_FOR = models.UserCalendar + + class Meta: + model = models.UserCalendar name = factory.Sequence(lambda n: 'User calendar %s' % n) mailbox = factory.SubFactory(MailboxFactory) class SharedCalendarFactory(factory.DjangoModelFactory): - FACTORY_FOR = models.SharedCalendar + + class Meta: + model = models.SharedCalendar name = factory.Sequence(lambda n: 'Shared calendar %s' % n) domain = factory.SubFactory(DomainFactory) class AccessRuleFactory(factory.DjangoModelFactory): - FACTORY_FOR = models.AccessRule + + class Meta: + model = models.AccessRule mailbox = factory.SubFactory(MailboxFactory) calendar = factory.SubFactory(UserCalendarFactory) diff --git a/modoboa/extensions/radicale/management/commands/generate_rights.py b/modoboa/extensions/radicale/management/commands/generate_rights.py index 9d6c3d722..3dd857c97 100644 --- a/modoboa/extensions/radicale/management/commands/generate_rights.py +++ b/modoboa/extensions/radicale/management/commands/generate_rights.py @@ -7,8 +7,7 @@ from django.core.management.base import BaseCommand from modoboa.core.management.commands import CloseConnectionMixin from modoboa.core.models import User from modoboa.lib import parameters -from modoboa.extensions.admin import Domain -from modoboa.extensions.radicale import Radicale +from modoboa.extensions.admin.models import Domain from modoboa.extensions.radicale.models import ( AccessRule ) @@ -102,9 +101,7 @@ permission = %s self._cfgfile.close() def handle(self, *args, **options): - """Command entry point. - """ - Radicale().load() + """Command entry point.""" path = parameters.get_admin("RIGHTS_FILE_PATH", app="radicale") if not options["force"]: try: diff --git a/modoboa/extensions/radicale/tests.py b/modoboa/extensions/radicale/tests.py index 955eac766..749364d3c 100644 --- a/modoboa/extensions/radicale/tests.py +++ b/modoboa/extensions/radicale/tests.py @@ -10,7 +10,7 @@ from django.core.urlresolvers import reverse from django.core import management from modoboa.lib import parameters -from modoboa.lib.tests import ExtTestCase +from modoboa.lib.tests import ModoTestCase from modoboa.extensions.admin.factories import ( MailboxFactory, populate_database ) @@ -24,12 +24,10 @@ from .factories import ( from .models import UserCalendar, SharedCalendar, AccessRule -class UserCalendarTestCase(ExtTestCase): - fixtures = ["initial_users.json"] +class UserCalendarTestCase(ModoTestCase): def setUp(self): super(UserCalendarTestCase, self).setUp() - self.activate_extensions('radicale') populate_database() def assertRuleEqual(self, calname, username, read=False, write=False): @@ -137,12 +135,11 @@ class UserCalendarTestCase(ExtTestCase): reverse("radicale:user_calendar_add"), values, status=400) -class SharedCalendarTestCase(ExtTestCase): +class SharedCalendarTestCase(ModoTestCase): fixtures = ["initial_users.json"] def setUp(self): super(SharedCalendarTestCase, self).setUp() - self.activate_extensions('radicale') populate_database() def test_add_calendar(self): @@ -205,12 +202,11 @@ class SharedCalendarTestCase(ExtTestCase): ) -class AccessRuleTestCase(ExtTestCase): +class AccessRuleTestCase(ModoTestCase): fixtures = ["initial_users.json"] def setUp(self): super(AccessRuleTestCase, self).setUp() - self.activate_extensions('radicale') populate_database() self.rights_file_path = tempfile.mktemp() parameters.save_admin( diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py index bdcb11bc7..1f38ff6fa 100644 --- a/modoboa/extensions/stats/management/commands/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -31,7 +31,6 @@ from django.core.management.base import BaseCommand from modoboa.core.extensions import exts_pool from modoboa.core.management.commands import CloseConnectionMixin from modoboa.extensions.admin.models import Domain -from modoboa.extensions.stats import Stats from modoboa.extensions.stats.lib import date_to_timestamp from modoboa.lib import parameters @@ -373,7 +372,6 @@ class Command(BaseCommand, CloseConnectionMixin): ) def handle(self, *args, **options): - Stats().load() if options["logfile"] is None: options["logfile"] = parameters.get_admin("LOGFILE", app="stats") p = LogParser(options, parameters.get_admin("RRD_ROOTDIR", app="stats")) diff --git a/modoboa/lib/form_utils.py b/modoboa/lib/form_utils.py index ef90c7ff4..5686532fc 100644 --- a/modoboa/lib/form_utils.py +++ b/modoboa/lib/form_utils.py @@ -3,6 +3,7 @@ """Form management utilities.""" import abc +from collections import OrderedDict import re from django.core.exceptions import ValidationError @@ -180,8 +181,10 @@ class DynamicForm(object): if value is not None: self.fields[name].initial = value if pos: - self.fields.keyOrder.remove(name) - self.fields.keyOrder.insert(pos, name) + order = self.fields.keys() + order.remove(name) + order.insert(post, name) + self.fields = OrderedDict((key, self.fields[key]) for key in order) def _load_from_qdict(self, qdict, pattern, typ): """Load all instances of a field from a ``QueryDict`` object. diff --git a/modoboa/lib/tests.py b/modoboa/lib/tests.py index 5eee3edbd..ade238400 100644 --- a/modoboa/lib/tests.py +++ b/modoboa/lib/tests.py @@ -1,15 +1,20 @@ # coding: utf-8 +"""Testing utilities.""" + import json + +from django import forms +from django.core import management from django.test import TestCase from django.test.client import Client -from django import forms -from django.core.urlresolvers import reverse + from modoboa.lib import parameters class ModoTestCase(TestCase): def setUp(self, username="admin", password="password"): + management.call_command("load_initial_data") self.clt = Client() self.assertEqual( self.clt.login(username=username, password=password), True) @@ -35,23 +40,6 @@ class ModoTestCase(TestCase): return self.ajax_request('get', *args, **kwargs) -class ExtTestCase(ModoTestCase): - - def setUp(self, *args, **kwargs): - super(ExtTestCase, self).setUp(*args, **kwargs) - self.clt.get(reverse("core:extension_list")) - - def activate_extensions(self, *names): - from modoboa.core.extensions import exts_pool - - self.ajax_post( - reverse("core:extension_save"), - dict(("select_%s" % name, "1") for name in names) - ) - for name in names: - exts_pool.get_extension(name).load() - - class TestParams(parameters.AdminParametersForm): app = "test" diff --git a/tests/install_from_scratch.py b/tests/install_from_scratch.py index 9fafbb56c..3f0f7c3f4 100644 --- a/tests/install_from_scratch.py +++ b/tests/install_from_scratch.py @@ -66,7 +66,7 @@ class DeployTest(unittest.TestCase): self.dbhost, self.projname) cmd = ( "modoboa-admin.py deploy --dbaction install --collectstatic " - "--dburl %s --extensions all --domain %s %s" + "--dburl %s --domain %s %s" % (dburl, 'localhost', self.projname) ) code, output = exec_cmd(cmd, cwd=self.workdir)