diff --git a/zproject/backends.py b/zproject/backends.py index 7c39e43e09..b1368774c1 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -5,9 +5,11 @@ from django.conf import settings import django.contrib.auth from django_auth_ldap.backend import LDAPBackend +from zerver.lib.actions import do_create_user -from zerver.models import UserProfile, get_user_profile_by_id, \ - get_user_profile_by_email, remote_user_to_email, email_to_username +from zerver.models import UserProfile, Realm, get_user_profile_by_id, \ + get_user_profile_by_email, remote_user_to_email, email_to_username, \ + resolve_email_to_domain, get_realm from apiclient.sample_tools import client as googleapiclient from oauth2client.crypt import AppIdentityError @@ -128,26 +130,59 @@ class ZulipRemoteUserBackend(RemoteUserBackend): return user_profile -class ZulipLDAPAuthBackend(ZulipAuthMixin, LDAPBackend): +class ZulipLDAPException(Exception): + pass + +class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): + # Don't use Django LDAP's permissions functions + def has_perm(self, user, perm, obj=None): + return False + def has_module_perms(self, user, app_label): + return False + def get_all_permissions(self, user, obj=None): + return set() + def get_group_permissions(self, user, obj=None): + return set() + def django_to_ldap_username(self, username): if settings.LDAP_APPEND_DOMAIN is not None: + if not username.endswith("@" + settings.LDAP_APPEND_DOMAIN): + raise ZulipLDAPException("Username does not match LDAP domain.") return email_to_username(username) return username - def ldap_to_django_username(self, username): if settings.LDAP_APPEND_DOMAIN is not None: return "@".join((username, settings.LDAP_APPEND_DOMAIN)) return username +class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): + def authenticate(self, username, password): + try: + username = self.django_to_ldap_username(username) + return ZulipLDAPAuthBackendBase.authenticate(self, username, password) + except Realm.DoesNotExist: + return None + except ZulipLDAPException: + return None + def get_or_create_user(self, username, ldap_user): try: return get_user_profile_by_email(username), False except UserProfile.DoesNotExist: - return UserProfile(), False + domain = resolve_email_to_domain(username) + realm = get_realm(domain) -class ZulipLDAPUserPopulator(ZulipLDAPAuthBackend): - # Just like ZulipLDAPAuthBackend, but doesn't let you log in. + full_name_attr = settings.AUTH_LDAP_USER_ATTR_MAP["full_name"] + short_name = full_name = ldap_user.attrs[full_name_attr] + if "short_name" in settings.AUTH_LDAP_USER_ATTR_MAP: + short_name_attr = settings.AUTH_LDAP_USER_ATTR_MAP["short_name"] + short_name = ldap_user.attrs[short_name_attr] + user_profile = do_create_user(username, None, realm, full_name, short_name) + return user_profile, False + +# Just like ZulipLDAPAuthBackend, but doesn't let you log in. +class ZulipLDAPUserPopulator(ZulipLDAPAuthBackendBase): def authenticate(self, username, password): return None