From e21c2df217adcae4b2f2d7996dfe8e807a8c0eaa Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 5 Jan 2016 07:39:45 +0100 Subject: [PATCH 1/7] Fix #819 --- modoboa/core/commands/templates/settings.py.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index f09474086..0a4781432 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -36,7 +36,7 @@ SITE_ID = 1 # Security settings -X_FRAME_OPTIONS = "DENY" +X_FRAME_OPTIONS = "SAMEORIGIN" # Application definition From e1d73a8e70bcb7e4270abec07a7c238133552298 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 5 Jan 2016 08:51:14 +0100 Subject: [PATCH 2/7] Refactor applications loading. --- modoboa/core/apps.py | 68 ++++++++++++++++++++++++++++++++++++++++++ modoboa/limits/apps.py | 31 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 modoboa/core/apps.py create mode 100644 modoboa/limits/apps.py diff --git a/modoboa/core/apps.py b/modoboa/core/apps.py new file mode 100644 index 000000000..70d611fb5 --- /dev/null +++ b/modoboa/core/apps.py @@ -0,0 +1,68 @@ +"""Core config for admin.""" + +from django.apps import AppConfig + + +BASE_EVENTS = [ + "CanCreate", + + "AccountCreated", + "AccountAutoCreated", + "AccountModified", + "AccountDeleted", + "AccountExported", + "AccountImported", + "PasswordUpdated", + "ExtraAccountActions", + "RoleChanged", + "GetExtraRoles", + "GetExtraRolePermissions", + "PasswordChange", + "UserCanSetRole", + + "InitialDataLoaded", + + "UserMenuDisplay", + "AdminMenuDisplay", + "GetStaticContent", + + "UserLogin", + "UserLogout", + + "GetAnnouncement", + + "TopNotifications", + "ExtraAdminContent", + + "ExtraUprefsRoutes", + "ExtraUprefsJS", + + "GetExtraParameters", + "ExtraFormFields", + "SaveExtraFormFields", +] + + +def load_core_settings(): + """Load core settings. + + This function must be manually called (see :file:`urls.py`) in + order to load base settings. + """ + from django.utils.translation import ugettext_lazy + from modoboa.lib import parameters, events + from .app_settings import GeneralParametersForm + + parameters.register(GeneralParametersForm, ugettext_lazy("General")) + events.declare(BASE_EVENTS) + + +class CoreConfig(AppConfig): + + """App configuration.""" + + name = "modoboa.core" + verbose_name = "Modoboa core" + + def ready(self): + load_core_settings() diff --git a/modoboa/limits/apps.py b/modoboa/limits/apps.py new file mode 100644 index 000000000..f6401a959 --- /dev/null +++ b/modoboa/limits/apps.py @@ -0,0 +1,31 @@ +"""App config for limits.""" + +from django.apps import AppConfig + + +EVENTS = [ + 'GetExtraLimitTemplates' +] + + +def load_limits_settings(): + """Load settings.""" + from django.utils.translation import ugettext as _ + from modoboa.lib import events, parameters + from .app_settings import ParametersForm + + parameters.register(ParametersForm, _("Limits")) + events.declare(EVENTS) + from . import controls + from . import general_callbacks + + +class LimitsConfig(AppConfig): + + """App configuration.""" + + name = "modoboa.limits" + verbose_name = "Modoboa admin limits" + + def ready(self): + load_limits_settings() From 6f75875ad2d33816966d307bde6cede8c5651bf7 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 5 Jan 2016 08:56:25 +0100 Subject: [PATCH 3/7] Refactor applications loading (wip). --- modoboa/admin/apps.py | 4 ++ modoboa/admin/callbacks.py | 10 ---- .../management/commands/export_domains.py | 3 - .../management/commands/export_identities.py | 4 +- .../management/commands/import_domains.py | 4 -- .../management/commands/import_identities.py | 3 - modoboa/admin/tests/password_schemes.py | 6 -- modoboa/core/__init__.py | 56 ++----------------- modoboa/core/management/commands/cleanlogs.py | 2 - .../management/commands/load_initial_data.py | 8 +-- modoboa/core/models.py | 2 +- modoboa/lib/parameters.py | 6 ++ modoboa/limits/__init__.py | 1 + modoboa/limits/app_settings.py | 13 ----- modoboa/relaydomains/app_settings.py | 22 +------- modoboa/relaydomains/apps.py | 23 ++++++++ modoboa/relaydomains/urls.py | 2 +- modoboa/urls.py | 16 ++---- 18 files changed, 48 insertions(+), 137 deletions(-) diff --git a/modoboa/admin/apps.py b/modoboa/admin/apps.py index 92a55ff2d..281d2d5ba 100644 --- a/modoboa/admin/apps.py +++ b/modoboa/admin/apps.py @@ -2,6 +2,8 @@ from django.apps import AppConfig +from .app_settings import load_admin_settings + class AdminConfig(AppConfig): @@ -11,4 +13,6 @@ class AdminConfig(AppConfig): verbose_name = "Modoboa admin console" def ready(self): + load_admin_settings() + from . import handlers diff --git a/modoboa/admin/callbacks.py b/modoboa/admin/callbacks.py index 3e6d6ef1a..f0983c875 100644 --- a/modoboa/admin/callbacks.py +++ b/modoboa/admin/callbacks.py @@ -49,16 +49,6 @@ def extra_permissions(rolename): return PERMISSIONS.get(rolename, []) -@events.observe("ExtraUprefsRoutes") -def extra_routes(): - from django.conf.urls import url - return [ - url(r'^user/forward/', - 'modoboa.admin.views.user.forward', - name="user_forward"), - ] - - @events.observe("AdminMenuDisplay") def admin_menu(target, user): if target != "top_menu": diff --git a/modoboa/admin/management/commands/export_domains.py b/modoboa/admin/management/commands/export_domains.py index c4fc5edc6..6af70c586 100644 --- a/modoboa/admin/management/commands/export_domains.py +++ b/modoboa/admin/management/commands/export_domains.py @@ -4,7 +4,6 @@ from optparse import make_option from django.core.management.base import BaseCommand -from modoboa.core import load_core_settings from modoboa.core.extensions import exts_pool from ...models import Domain @@ -20,8 +19,6 @@ class Command(BaseCommand): def handle(self, *args, **kwargs): exts_pool.load_all() - load_core_settings() - csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar']) for dom in Domain.objects.all(): dom.to_csv(csvwriter) diff --git a/modoboa/admin/management/commands/export_identities.py b/modoboa/admin/management/commands/export_identities.py index 6d3bb1f46..020e948c6 100644 --- a/modoboa/admin/management/commands/export_identities.py +++ b/modoboa/admin/management/commands/export_identities.py @@ -4,7 +4,6 @@ from optparse import make_option from django.core.management.base import BaseCommand -from modoboa.core import load_core_settings from modoboa.core.models import User from modoboa.core.extensions import exts_pool from ...models import Alias @@ -21,11 +20,10 @@ class Command(BaseCommand): def handle(self, *args, **kwargs): exts_pool.load_all() - load_core_settings() csvwriter = csv.writer(sys.stdout, delimiter=kwargs['sepchar']) for u in User.objects.all(): u.to_csv(csvwriter) - for a in Alias.objects.prefetch_related('mboxes', 'aliases'): + for a in Alias.objects.prefetch_related('aliasrecipient_set'): a.to_csv(csvwriter) diff --git a/modoboa/admin/management/commands/import_domains.py b/modoboa/admin/management/commands/import_domains.py index aafbbe2ef..562a9b6f2 100644 --- a/modoboa/admin/management/commands/import_domains.py +++ b/modoboa/admin/management/commands/import_domains.py @@ -2,8 +2,6 @@ from optparse import make_option from django.core.management.base import BaseCommand - -from modoboa.core import load_core_settings from modoboa.core.extensions import exts_pool from ._import import import_csv @@ -25,7 +23,5 @@ class Command(BaseCommand): def handle(self, *args, **kwargs): exts_pool.load_all() - load_core_settings() - for filename in args: import_csv(filename, kwargs) diff --git a/modoboa/admin/management/commands/import_identities.py b/modoboa/admin/management/commands/import_identities.py index 28487bc61..43e35a01f 100644 --- a/modoboa/admin/management/commands/import_identities.py +++ b/modoboa/admin/management/commands/import_identities.py @@ -2,7 +2,6 @@ from optparse import make_option from django.core.management.base import BaseCommand -from modoboa.core import load_core_settings from modoboa.core.extensions import exts_pool from ._import import import_csv @@ -28,7 +27,5 @@ class Command(BaseCommand): def handle(self, *args, **kwargs): exts_pool.load_all() - load_core_settings() - for filename in args: import_csv(filename, kwargs) diff --git a/modoboa/admin/tests/password_schemes.py b/modoboa/admin/tests/password_schemes.py index 5d3fc5a71..28b1331b7 100644 --- a/modoboa/admin/tests/password_schemes.py +++ b/modoboa/admin/tests/password_schemes.py @@ -1,6 +1,5 @@ from django.core.urlresolvers import reverse -from modoboa.core import load_core_settings from modoboa.core.models import User from modoboa.lib.tests import ModoTestCase from modoboa.lib import parameters @@ -16,11 +15,6 @@ class PasswordSchemesTestCase(ModoTestCase): super(PasswordSchemesTestCase, cls).setUpTestData() factories.populate_database() - def setUp(self): - """Test initialization.""" - super(PasswordSchemesTestCase, self).setUp() - load_core_settings() - def _create_account(self): values = dict( username="tester@test.com", first_name="Tester", last_name="Toto", diff --git a/modoboa/core/__init__.py b/modoboa/core/__init__.py index 641809b03..b345b0939 100644 --- a/modoboa/core/__init__.py +++ b/modoboa/core/__init__.py @@ -1,65 +1,15 @@ from django.core.urlresolvers import reverse -from django.utils.translation import ugettext as _, ugettext_lazy +from django.utils.translation import ugettext as _ -from modoboa.lib import parameters, events +from modoboa.lib import events -BASE_EVENTS = [ - "CanCreate", - - "AccountCreated", - "AccountAutoCreated", - "AccountModified", - "AccountDeleted", - "AccountExported", - "AccountImported", - "PasswordUpdated", - "ExtraAccountActions", - "RoleChanged", - "GetExtraRoles", - "GetExtraRolePermissions", - "PasswordChange", - "UserCanSetRole", - - "InitialDataLoaded", - - "UserMenuDisplay", - "AdminMenuDisplay", - "GetStaticContent", - - "UserLogin", - "UserLogout", - - "GetAnnouncement", - - "TopNotifications", - "ExtraAdminContent", - - "ExtraUprefsRoutes", - "ExtraUprefsJS", - - "GetExtraParameters", - "ExtraFormFields", - "SaveExtraFormFields", -] PERMISSIONS = { "SimpleUsers": [] } -def load_core_settings(): - """Load core settings. - - This function must be manually called (see :file:`urls.py`) in - order to load base settings. - """ - from modoboa.core.app_settings import GeneralParametersForm - - parameters.register(GeneralParametersForm, ugettext_lazy("General")) - events.declare(BASE_EVENTS) - - @events.observe("TopNotifications") def check_for_new_version(request, include_all): """ @@ -78,3 +28,5 @@ def check_for_new_version(request, include_all): "text": _("One or more updates are available"), "level": "info", }] + +default_app_config = "modoboa.core.apps.CoreConfig" diff --git a/modoboa/core/management/commands/cleanlogs.py b/modoboa/core/management/commands/cleanlogs.py index 7840615f1..5cb7147a7 100644 --- a/modoboa/core/management/commands/cleanlogs.py +++ b/modoboa/core/management/commands/cleanlogs.py @@ -6,7 +6,6 @@ from optparse import make_option from django.core.management.base import BaseCommand from django.utils import timezone -from modoboa.core import load_core_settings from modoboa.core.models import Log from modoboa.lib import parameters @@ -39,7 +38,6 @@ class Command(BaseCommand): l.addHandler(logging.StreamHandler()) self.verbose = options["verbose"] - load_core_settings() log_maximum_age = int(parameters.get_admin("LOG_MAXIMUM_AGE")) self.__vprint("Deleting logs older than %d days..." % log_maximum_age) limit = timezone.now() - datetime.timedelta(log_maximum_age) diff --git a/modoboa/core/management/commands/load_initial_data.py b/modoboa/core/management/commands/load_initial_data.py index 1bf92aa23..88f47117a 100644 --- a/modoboa/core/management/commands/load_initial_data.py +++ b/modoboa/core/management/commands/load_initial_data.py @@ -8,15 +8,13 @@ from django.contrib.auth.models import Group from django.core.management.base import BaseCommand -from modoboa.admin.app_settings import load_admin_settings -from modoboa.core import load_core_settings, PERMISSIONS +from modoboa.core import PERMISSIONS from modoboa.core.extensions import exts_pool from modoboa.core.models import User, ObjectAccess from modoboa.lib.cryptutils import random_key from modoboa.lib import events from modoboa.lib import models as lib_models from modoboa.lib.permissions import add_permissions_to_group -from modoboa.limits.app_settings import load_limits_settings import modoboa.relaydomains.models as relay_models @@ -28,10 +26,6 @@ class Command(BaseCommand): def handle(self, *args, **options): """Command entry point.""" - load_core_settings() - load_admin_settings() - load_limits_settings() - if not User.objects.filter(is_superuser=True).count(): admin = User(username="admin", is_superuser=True) admin.set_password("password") diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 68bca8dff..519546806 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -135,7 +135,7 @@ class User(PermissionsMixin): try: scheme = parameters.get_admin("PASSWORD_SCHEME") except parameters.NotDefined: - from modoboa.core import load_core_settings + from modoboa.core.apps import load_core_settings load_core_settings() scheme = parameters.get_admin("PASSWORD_SCHEME") diff --git a/modoboa/lib/parameters.py b/modoboa/lib/parameters.py index 2cb780b3b..dc23d4538 100644 --- a/modoboa/lib/parameters.py +++ b/modoboa/lib/parameters.py @@ -16,6 +16,8 @@ from modoboa.lib import events from modoboa.lib.exceptions import ModoboaException from modoboa.lib.sysutils import guess_extension_name +from . import db_utils + _params = {'A': {}, 'U': {}} @@ -91,6 +93,8 @@ class AdminParametersForm(GenericParametersForm): def _load_initial_values(self): from .models import Parameter + if not db_utils.db_table_exists("lib_parameter"): + return names = [ "%s.%s" % (self.app, name.upper()) for name in self.fields.keys() ] @@ -132,6 +136,8 @@ class UserParametersForm(GenericParametersForm): super(UserParametersForm, self).__init__(*args, **kwargs) def _load_initial_values(self): + if not db_utils.db_table_exists("lib_userparameter"): + return if self.user is None: return from .models import UserParameter diff --git a/modoboa/limits/__init__.py b/modoboa/limits/__init__.py index e69de29bb..1816137f6 100644 --- a/modoboa/limits/__init__.py +++ b/modoboa/limits/__init__.py @@ -0,0 +1 @@ +default_app_config = "modoboa.limits.apps.LimitsConfig" diff --git a/modoboa/limits/app_settings.py b/modoboa/limits/app_settings.py index ce16d2e55..8c2129ccb 100644 --- a/modoboa/limits/app_settings.py +++ b/modoboa/limits/app_settings.py @@ -3,14 +3,9 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from modoboa.lib import events, parameters from modoboa.lib.form_utils import SeparatorField from modoboa.lib.parameters import AdminParametersForm -EVENTS = [ - 'GetExtraLimitTemplates' -] - class ParametersForm(AdminParametersForm): app = "limits" @@ -73,11 +68,3 @@ class ParametersForm(AdminParametersForm): def __init__(self, *args, **kwargs): super(AdminParametersForm, self).__init__(*args, **kwargs) self._load_extra_parameters('A') - - -def load_limits_settings(): - """Load settings.""" - parameters.register(ParametersForm, _("Limits")) - events.declare(EVENTS) - from . import controls - from . import general_callbacks diff --git a/modoboa/relaydomains/app_settings.py b/modoboa/relaydomains/app_settings.py index 300f10983..cb308249f 100644 --- a/modoboa/relaydomains/app_settings.py +++ b/modoboa/relaydomains/app_settings.py @@ -5,21 +5,10 @@ Relay domains settings definition. from django import forms from django.utils.translation import ugettext_lazy -from modoboa.lib import events, parameters +from modoboa.lib import parameters from modoboa.lib.form_utils import SeparatorField -EVENTS = [ - "RelayDomainCreated", - "RelayDomainDeleted", - "RelayDomainModified", - "RelayDomainAliasCreated", - "RelayDomainAliasDeleted", - "ExtraRelayDomainForm", - "FillRelayDomainInstances" -] - - class AdminParametersForm(parameters.AdminParametersForm): """Admin parameters definition.""" @@ -34,12 +23,3 @@ class AdminParametersForm(parameters.AdminParametersForm): help_text=ugettext_lazy('Path to the master.cf configuration file'), widget=forms.TextInput(attrs={"class": "form-control"}) ) - - -def load_relaydomains_settings(): - """Load application settings.""" - parameters.register( - AdminParametersForm, ugettext_lazy("Relay domains") - ) - events.declare(EVENTS) - from . import general_callbacks diff --git a/modoboa/relaydomains/apps.py b/modoboa/relaydomains/apps.py index 32c76cb2c..2a8895b46 100644 --- a/modoboa/relaydomains/apps.py +++ b/modoboa/relaydomains/apps.py @@ -3,6 +3,28 @@ from django.apps import AppConfig +EVENTS = [ + "RelayDomainCreated", + "RelayDomainDeleted", + "RelayDomainModified", + "RelayDomainAliasCreated", + "RelayDomainAliasDeleted", + "ExtraRelayDomainForm", + "FillRelayDomainInstances" +] + + +def load_relaydomains_settings(): + """Load application settings.""" + from django.utils.translation import ugettext as _ + from modoboa.lib import events, parameters + from .app_settings import AdminParametersForm + + parameters.register(AdminParametersForm, _("Relay domains")) + events.declare(EVENTS) + from . import general_callbacks + + class RelayDomainsConfig(AppConfig): """App configuration.""" @@ -11,4 +33,5 @@ class RelayDomainsConfig(AppConfig): verbose_name = "Modoboa relay domains" def ready(self): + load_relaydomains_settings() from . import handlers diff --git a/modoboa/relaydomains/urls.py b/modoboa/relaydomains/urls.py index 73352afee..8e4c5b10f 100644 --- a/modoboa/relaydomains/urls.py +++ b/modoboa/relaydomains/urls.py @@ -3,6 +3,6 @@ from django.conf.urls import patterns, url urlpatterns = patterns( 'modoboa.relaydomains.views', - url(r'^relaydomains/scan_services/$', 'scan_for_services', + url(r'^scan_services/$', 'scan_for_services', name="service_scan"), ) diff --git a/modoboa/urls.py b/modoboa/urls.py index 86fe5b038..484552ecd 100644 --- a/modoboa/urls.py +++ b/modoboa/urls.py @@ -1,27 +1,21 @@ from django.conf import settings from django.conf.urls import patterns, include, url -from modoboa.admin.app_settings import load_admin_settings -from modoboa.core import load_core_settings from modoboa.core.extensions import exts_pool from modoboa.lib import parameters, events -from modoboa.limits.app_settings import load_limits_settings -from modoboa.relaydomains.app_settings import load_relaydomains_settings -load_core_settings() -load_admin_settings() -load_limits_settings() -load_relaydomains_settings() - urlpatterns = patterns( '', url(r'^$', 'modoboa.lib.web_utils.topredirection', name="topredirection"), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': ('modoboa', ), }), ('', include('modoboa.core.urls', namespace="core")), - ('', include('modoboa.admin.urls', namespace="admin")), - ('', include('modoboa.relaydomains.urls', namespace="relaydomains")), + url('^user/forward/', 'modoboa.admin.views.user.forward', + name='user_forward'), + ('admin/', include('modoboa.admin.urls', namespace="admin")), + ('relaydomains/', + include('modoboa.relaydomains.urls', namespace="relaydomains")), ) urlpatterns += patterns( From 3e14f882826ae561efe0f7dbed25e4a7e1f02bb9 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 13 Jan 2016 16:34:31 +0100 Subject: [PATCH 4/7] Fix #826 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index dfdb14156..cab74df2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django==1.8.7 +django<=1.8.99 django-reversion==1.9.3 dj-database-url pycrypto From 695b7dbe3c47b5bbbea7a98dd2a29c642349a4e0 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 18 Jan 2016 09:03:06 +0100 Subject: [PATCH 5/7] Django 1.8. --- .../management/commands/import_identities.py | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/modoboa/admin/management/commands/import_identities.py b/modoboa/admin/management/commands/import_identities.py index 43e35a01f..4cce81e83 100644 --- a/modoboa/admin/management/commands/import_identities.py +++ b/modoboa/admin/management/commands/import_identities.py @@ -11,21 +11,20 @@ class Command(BaseCommand): args = 'csvfile' help = 'Import identities from a csv file' - option_list = BaseCommand.option_list + ( - make_option( - '--sepchar', action='store_true', dest='sepchar', default=';' - ), - make_option( - '--continue-if-exists', action='store_true', - dest='continue_if_exists', default=True - ), - make_option( - '--crypt-password', action='store_true', dest='crypt_password', - default=False - ) - ) + def add_arguments(self, parser): + """Add extra arguments to command.""" + parser.add_argument( + "--sepchar", type=str, default=";", + help="Separator used in file.") + parser.add_argument( + "--continue-if-exists", action="store_true", + dest='continue_if_exists', default=True, + help="Continue even if an entry already exists.") + parser.add_argument( + "--crypt-password", action="store_true", dest="crypt_password", + default=False, help="Encrypt provided passwords.") - def handle(self, *args, **kwargs): + def handle(self, *args, **options): exts_pool.load_all() for filename in args: - import_csv(filename, kwargs) + import_csv(filename, options) From b3bbda39df35fad92aa084084a3ce586977e92bd Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 18 Jan 2016 09:46:59 +0100 Subject: [PATCH 6/7] Assign permissions when a domain admin creates a mailbox. fix #825 --- modoboa/admin/models/mailbox.py | 2 +- modoboa/admin/tests/account.py | 32 ++++++++++++++++++++++++++++++++ modoboa/limits/controls.py | 1 - 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/models/mailbox.py b/modoboa/admin/models/mailbox.py index c1d249069..27c39c138 100644 --- a/modoboa/admin/models/mailbox.py +++ b/modoboa/admin/models/mailbox.py @@ -262,7 +262,7 @@ class Mailbox(AdminObject): from modoboa.lib.permissions import grant_access_to_object super(Mailbox, self).post_create(creator) conditions = ( - creator.is_superuser, + creator.has_perm("admin.add_mailbox"), not self.user.has_perm("admin.add_domain") ) if all(conditions): diff --git a/modoboa/admin/tests/account.py b/modoboa/admin/tests/account.py index 12137d305..c05b6e856 100644 --- a/modoboa/admin/tests/account.py +++ b/modoboa/admin/tests/account.py @@ -132,7 +132,15 @@ class PermissionsTestCase(ModoTestCase): @classmethod def setUpTestData(cls): """Create test data.""" + from modoboa.lib import parameters + from modoboa.limits.models import LimitTemplates + super(PermissionsTestCase, cls).setUpTestData() + for tpl in LimitTemplates().templates: + parameters.save_admin( + "DEFLT_{0}".format(tpl[0].upper()), 2, + app="limits" + ) factories.populate_database() cls.user = User.objects.get(username='user@test.com') cls.values = dict( @@ -263,3 +271,27 @@ class PermissionsTestCase(ModoTestCase): reverse("admin:account_add"), values, status=400 ) + + def test_domadmins_permissions(self): + """ + Check that two domain admins in the same domains see the same + content. + """ + dom = models.Domain.objects.get(name="test.com") + mb = factories.MailboxFactory( + domain=dom, address="admin2", + user__username="admin2@test.com", user__groups=('DomainAdmins', ), + user__password="{PLAIN}toto") + dom.add_admin(mb.user) + self.client.logout() + self.assertTrue( + self.client.login(username="admin@test.com", password="toto")) + values = { + "username": "new@test.com", "password1": "Toto1234", + "password2": "Toto1234", "role": "SimpleUsers", "quota_act": True, + "is_active": True, "email": "new@test.com", "stepid": "step2" + } + self.ajax_post(reverse("admin:account_add"), values) + + new_mb = models.Mailbox.objects.get(user__username="new@test.com") + self.assertTrue(mb.user.can_access(new_mb)) diff --git a/modoboa/limits/controls.py b/modoboa/limits/controls.py index 28cba46b0..4239c0bd6 100644 --- a/modoboa/limits/controls.py +++ b/modoboa/limits/controls.py @@ -122,7 +122,6 @@ def create_pool(user): owner = get_object_owner(user) if owner.group not in ['SuperAdmins', 'Resellers']: return - if user.group == 'DomainAdmins': check_limit(owner, 'domain_admins_limit') inc_limit_usage(owner, 'domain_admins_limit') From d44c843e669c962d852a2b5b8904d27ec26582ad Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 19 Jan 2016 18:09:35 +0100 Subject: [PATCH 7/7] Fix unit tests. see #825 --- modoboa/admin/models/mailbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modoboa/admin/models/mailbox.py b/modoboa/admin/models/mailbox.py index 27c39c138..5388ab3b2 100644 --- a/modoboa/admin/models/mailbox.py +++ b/modoboa/admin/models/mailbox.py @@ -266,12 +266,14 @@ class Mailbox(AdminObject): not self.user.has_perm("admin.add_domain") ) if all(conditions): - # A super user is creating a new mailbox. Give + # An admin is creating a new mailbox. Give # access to that mailbox (and the associated # account) to the appropriate domain admins, # except if the new account has a more important # role (SuperAdmin, Reseller) for admin in self.domain.admins: + if admin == creator: + continue grant_access_to_object(admin, self) grant_access_to_object(admin, self.user)