mirror of https://github.com/zulip/zulip.git
Fix support for LDAP Authentication mechanism.
This addresses a few issues: * The LDAP authentication integration now creates an account a new Zulip account if the user authenticated correctly but didn't have a Zulip account. * The previous code didn't correctly disable the LDAP group permissions functionality. We're not using groups support from the Django LDAP extension and not doing so can cause errors trying to fetch data from LDAP. Huge thanks to @toaomatis for the initial implementation of this. Fixes #72.
This commit is contained in:
parent
90e61d3b61
commit
784ba7e066
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue