mirror of https://github.com/zulip/zulip.git
ldap: Use a workaround instead of forking django-auth-ldap.
Till now, we've been forking django-auth-ldap at https://github.com/zulip/django-auth-ldap to put the LDAPReverseEmailSearch feature in it, hoping to get it merged upstream in https://github.com/django-auth-ldap/django-auth-ldap/pull/150 The efforts to get it merged have stalled for now however and we don't want to be on the fork forever, so this commit puts the email search feature as a clumsy workaround inside our codebase and switches to using the latest upstream release instead of the fork.
This commit is contained in:
parent
6c15df68e8
commit
78297efefd
|
@ -42,10 +42,7 @@ mypy-boto3-s3
|
|||
defusedxml
|
||||
|
||||
# Needed for LDAP support
|
||||
# Using our fork for the feature of searching users by email.
|
||||
# https://github.com/django-auth-ldap/django-auth-ldap/pull/150 for monitoring
|
||||
# progress on merging this upstream.
|
||||
https://github.com/zulip/django-auth-ldap/archive/e26d0ef2a7ff77ab3fdd7b6578a76081f780778c.zip#egg=django-auth-ldap==2.0.0zulip1
|
||||
django-auth-ldap
|
||||
|
||||
# Django extension providing bitfield support
|
||||
django-bitfield
|
||||
|
|
|
@ -391,8 +391,9 @@ django[argon2]==3.2.6 \
|
|||
# django-phonenumber-field
|
||||
# django-sendfile2
|
||||
# django-two-factor-auth
|
||||
https://github.com/zulip/django-auth-ldap/archive/e26d0ef2a7ff77ab3fdd7b6578a76081f780778c.zip#egg=django-auth-ldap==2.0.0zulip1 \
|
||||
--hash=sha256:1a104fdb5085ef9340996ae82d4b302f99c39c5d9d60d4ae55bcc7c1f58cb65e
|
||||
django-auth-ldap==3.0.0 \
|
||||
--hash=sha256:19ee19034f344d9efd07ed88d3187e256ec33ae39d6a47222083b89f7d35c5f6 \
|
||||
--hash=sha256:1f2d5c562d9ba9a5e9a64099ae9798e1a63840a11afe4d1c4a9c74121f066eaa
|
||||
# via -r requirements/common.in
|
||||
django-bitfield==2.1.0 \
|
||||
--hash=sha256:158f1056e22cce450d0a49633ea77bfd84b85a2294b1ef03faa775a485f4065d \
|
||||
|
|
|
@ -242,8 +242,9 @@ django[argon2]==3.2.6 \
|
|||
# django-phonenumber-field
|
||||
# django-sendfile2
|
||||
# django-two-factor-auth
|
||||
https://github.com/zulip/django-auth-ldap/archive/e26d0ef2a7ff77ab3fdd7b6578a76081f780778c.zip#egg=django-auth-ldap==2.0.0zulip1 \
|
||||
--hash=sha256:1a104fdb5085ef9340996ae82d4b302f99c39c5d9d60d4ae55bcc7c1f58cb65e
|
||||
django-auth-ldap==3.0.0 \
|
||||
--hash=sha256:19ee19034f344d9efd07ed88d3187e256ec33ae39d6a47222083b89f7d35c5f6 \
|
||||
--hash=sha256:1f2d5c562d9ba9a5e9a64099ae9798e1a63840a11afe4d1c4a9c74121f066eaa
|
||||
# via -r requirements/common.in
|
||||
django-bitfield==2.1.0 \
|
||||
--hash=sha256:158f1056e22cce450d0a49633ea77bfd84b85a2294b1ef03faa775a485f4065d \
|
||||
|
|
|
@ -48,4 +48,4 @@ API_FEATURE_LEVEL = 93
|
|||
# historical commits sharing the same major version, in which case a
|
||||
# minor version bump suffices.
|
||||
|
||||
PROVISION_VERSION = "155.1"
|
||||
PROVISION_VERSION = "156.0"
|
||||
|
|
|
@ -31,7 +31,7 @@ from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
|||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django_auth_ldap.backend import LDAPBackend, LDAPReverseEmailSearch, _LDAPUser, ldap_error
|
||||
from django_auth_ldap.backend import LDAPBackend, _LDAPUser, ldap_error
|
||||
from lxml.etree import XMLSyntaxError
|
||||
from onelogin.saml2.errors import OneLogin_Saml2_Error
|
||||
from onelogin.saml2.response import OneLogin_Saml2_Response
|
||||
|
@ -434,13 +434,11 @@ def check_ldap_config() -> None:
|
|||
assert settings.AUTH_LDAP_USERNAME_ATTR and settings.AUTH_LDAP_REVERSE_EMAIL_SEARCH
|
||||
|
||||
|
||||
def find_ldap_users_by_email(email: str) -> Optional[List[_LDAPUser]]:
|
||||
def find_ldap_users_by_email(email: str) -> List[_LDAPUser]:
|
||||
"""
|
||||
Returns list of _LDAPUsers matching the email search,
|
||||
or None if no matches are found.
|
||||
Returns list of _LDAPUsers matching the email search
|
||||
"""
|
||||
email_search = LDAPReverseEmailSearch(LDAPBackend(), email)
|
||||
return email_search.search_for_users(should_populate=False)
|
||||
return LDAPReverseEmailSearch().search_for_users(email)
|
||||
|
||||
|
||||
def email_belongs_to_ldap(realm: Realm, email: str) -> bool:
|
||||
|
@ -469,6 +467,46 @@ def email_belongs_to_ldap(realm: Realm, email: str) -> bool:
|
|||
ldap_logger = logging.getLogger("zulip.ldap")
|
||||
|
||||
|
||||
class LDAPReverseEmailSearch(_LDAPUser):
|
||||
"""
|
||||
This class is a workaround - we want to use
|
||||
django-auth-ldap to query the ldap directory for
|
||||
users with the specified email address, but it doesn't
|
||||
provide an API for that or an isolated class for handling
|
||||
the connection. Because connection-handling is tightly integrated
|
||||
into the _LDAPUser class, we have to make this strange inheritance here,
|
||||
in order to be able to comfortably have an ldap connection and make search
|
||||
queries.
|
||||
|
||||
We may be able to get rid of this in the future if we can get
|
||||
https://github.com/django-auth-ldap/django-auth-ldap/pull/150 merged upstream.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# Superclass __init__ requires a username argument - it doesn't actually
|
||||
# impact anything for us in this class, given its very limited use
|
||||
# for only making a search query, so we pass an empty string.
|
||||
super().__init__(LDAPBackend(), username="")
|
||||
|
||||
def search_for_users(self, email: str) -> List[_LDAPUser]:
|
||||
search = settings.AUTH_LDAP_REVERSE_EMAIL_SEARCH
|
||||
USERNAME_ATTR = settings.AUTH_LDAP_USERNAME_ATTR
|
||||
|
||||
results = search.execute(self.connection, {"email": email})
|
||||
|
||||
ldap_users = []
|
||||
for result in results:
|
||||
user_dn, user_attrs = result
|
||||
username = user_attrs[USERNAME_ATTR][0]
|
||||
ldap_user = _LDAPUser(self.backend, username=username)
|
||||
ldap_user._user_dn = user_dn
|
||||
ldap_user._user_attrs = user_attrs
|
||||
|
||||
ldap_users.append(ldap_user)
|
||||
|
||||
return ldap_users
|
||||
|
||||
|
||||
class ZulipLDAPException(_LDAPUser.AuthenticationFailed):
|
||||
"""Since this inherits from _LDAPUser.AuthenticationFailed, these will
|
||||
be caught and logged at debug level inside django-auth-ldap's authenticate()"""
|
||||
|
@ -544,7 +582,7 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend):
|
|||
# We can use find_ldap_users_by_email
|
||||
if is_valid_email(username):
|
||||
email_search_result = find_ldap_users_by_email(username)
|
||||
if email_search_result is None:
|
||||
if not email_search_result:
|
||||
result = username
|
||||
elif len(email_search_result) == 1:
|
||||
return email_search_result[0]._username
|
||||
|
|
Loading…
Reference in New Issue