diff --git a/modoboa/admin/__init__.py b/modoboa/admin/__init__.py index eead1b284..1f904eb1d 100644 --- a/modoboa/admin/__init__.py +++ b/modoboa/admin/__init__.py @@ -240,7 +240,13 @@ class GeneralParametersForm(parameters.AdminParametersForm): values = self.get_current_values() if not ldap_available or values["authentication_type"] != "ldap": return - ldap_uri = 'ldap://' if values["ldap_secured"] == "yes" else "ldaps://" + if not hasattr(settings, "AUTH_LDAP_USER_ATTR_MAP"): + setattr(settings, "AUTH_LDAP_USER_ATTR_MAP", { + "first_name": "givenName", + "email": "mail", + "last_name": "sn" + }) + ldap_uri = 'ldaps://' if values["ldap_secured"] == "yes" else "ldap://" ldap_uri += "%s:%s" % (values["ldap_server_address"], values["ldap_server_port"]) setattr(settings, "AUTH_LDAP_SERVER_URI", ldap_uri) if values["ldap_auth_method"] == "searchbind": @@ -254,6 +260,14 @@ class GeneralParametersForm(parameters.AdminParametersForm): else: setattr(settings, "AUTH_LDAP_USER_DN_TEMPLATE", values["ldap_user_dn_template"]) + if values["ldap_is_active_directory"] == "yes": + if not hasattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS"): + setattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS", { + ldap.OPT_REFERRALS: False + }) + else: + settings.AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_REFERRALS] = False + parameters.register(GeneralParametersForm, ugettext_lazy("General")) diff --git a/modoboa/admin/models.py b/modoboa/admin/models.py index 4659e3a46..6deebe21c 100644 --- a/modoboa/admin/models.py +++ b/modoboa/admin/models.py @@ -555,6 +555,7 @@ class Domain(DatesAware): events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all()) ungrant_access_to_objects(self.domainalias_set.all()) if self.mailbox_set.count(): + Quota.objects.filter(username__contains='@%s' % self.name).delete() events.raiseEvent("DeleteMailbox", self.mailbox_set.all()) ungrant_access_to_objects(self.mailbox_set.all()) hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False) @@ -724,8 +725,10 @@ class Mailbox(DatesAware): self.quota = value def get_cur_quota(self): + if not self.quota: + return 0 q = Quota.objects.get(username=self.full_address) - return q.bytes / (self.quota * 1048576) * 100 + return int(q.bytes / float(self.quota * 1048576) * 100) def save_from_user(self, localpart, domain, user, quota=None, owner=None): """Simple save method called for automatic creations @@ -743,8 +746,19 @@ class Mailbox(DatesAware): Quota.objects.create(username=self.full_address) def delete(self, keepdir=False): - q = Quota.objects.get(username=self.full_address) - q.delete() + """Custom delete method + + We try to delete the associated quota in the same time (it may + has already been removed if we're deleting a domain). + + :param bool keepdir: delete the mailbox home dir on the filesystem or not + """ + try: + q = Quota.objects.get(username=self.full_address) + except Quota.DoesNotExist: + pass + else: + q.delete() super(Mailbox, self).delete() if not keepdir: self.delete_dir() @@ -964,24 +978,18 @@ class Extension(models.Model): events.raiseEvent("ExtDisabled", self) -def populate_callback(sender, user=None, **kwargs): - """Populate signal callback +def populate_callback(user): + """Populate callback If the LDAP authentication backend is in use, this callback will be called each time a new user authenticates succesfuly to Modoboa. This function is in charge of creating the mailbox associated to the provided ``User`` object. - :param sender: ?? :param user: a ``User`` instance """ from modoboa.lib.permissions import grant_access_to_object - if parameters.get_admin("AUTHENTICATION_TYPE") != "ldap": - return - if user is None: - return - sadmins = User.objects.filter(is_superuser=True) user.groups.add(Group.objects.get(name="SimpleUsers")) @@ -1013,11 +1021,3 @@ def populate_callback(sender, user=None, **kwargs): grant_access_to_object(sadmins[0], mb, True) for su in sadmins[1:]: grant_access_to_object(su, domain) - - -try: - from django_auth_ldap.backend import populate_user -except ImportError, inst: - pass -else: - populate_user.connect(populate_callback, dispatch_uid="myuid") diff --git a/modoboa/admin/static/admin/js/admin.js b/modoboa/admin/static/admin/js/admin.js index 3db113d36..72dfb7383 100644 --- a/modoboa/admin/static/admin/js/admin.js +++ b/modoboa/admin/static/admin/js/admin.js @@ -122,13 +122,13 @@ Domains.prototype = { var deloptions = (data.handle_mailboxes) ? {keepdir: gettext("Do not delete domain directory")} : {}; - var warnmsg = (data.auto_account_removal) + var warnmsg = (data.auto_account_removal && data.auto_account_removal == "yes") ? gettext("This operation will remove ALL data associated to this domain.") : gettext("This operation will remove all data associated to this domain, excepting accounts."); $("a[name=deldomain]").confirm({ question: gettext("Delete this domain?"), - warning: gettext("This operation will remove ALL data associated to this domain."), + warning: warnmsg, checkboxes: deloptions, success_cb: $.proxy(this.reload_listing, this) }); diff --git a/modoboa/admin/views.py b/modoboa/admin/views.py index 99a808b88..407088eac 100644 --- a/modoboa/admin/views.py +++ b/modoboa/admin/views.py @@ -505,6 +505,7 @@ def saveparameters(request): form = formdef["form"] if form.is_valid(): form.save() + form.to_django_settings() continue return ajax_simple_response({"status": "ko", "prefix": form.app, "errors": form.errors}) return ajax_simple_response(dict(status="ok", respmsg=_("Parameters saved"))) diff --git a/modoboa/lib/authbackends.py b/modoboa/lib/authbackends.py index b27a05ccd..db5ec34e1 100644 --- a/modoboa/lib/authbackends.py +++ b/modoboa/lib/authbackends.py @@ -1,5 +1,6 @@ from django.contrib.auth.backends import ModelBackend from modoboa.admin.models import User +from modoboa.lib import parameters class SimpleBackend(ModelBackend): @@ -20,6 +21,8 @@ class SimpleBackend(ModelBackend): try: from django_auth_ldap.backend import LDAPBackend as orig_LDAPBackend, _LDAPUser + from modoboa.admin.models import populate_callback + class LDAPBackend(orig_LDAPBackend): @@ -29,10 +32,13 @@ try: username is the Django-friendly username of the user. ldap_user.dn is the user's DN and ldap_user.attrs contains all of their LDAP attributes. """ - return User.objects.get_or_create( + user, created = User.objects.get_or_create( username__iexact=username, defaults={'username': username.lower()} - ) + ) + if created: + populate_callback(user) + return user, created def get_user(self, user_id): user = None @@ -43,5 +49,11 @@ try: pass return user + def authenticate(self, username, password): + auth_type = parameters.get_admin("AUTHENTICATION_TYPE", app="admin") + if auth_type == "ldap": + return super(LDAPBackend, self).authenticate(username, password) + return None + except ImportError: pass