<commit_before># Copyright (c) 2009, <NAME>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
LDAP authentication backend

Complete documentation can be found in docs/howto/auth-ldap.txt (or the thing it
compiles to).

Use of this backend requires the python-ldap module. To support unit tests, we
import ldap in a single centralized place (config._LDAPConfig) so that the test
harness can insert a mock object.

A few notes on naming conventions. If an identifier ends in _dn, it is a string
representation of a distinguished name. If it ends in _info, it is a 2-tuple
containing a DN and a dictionary of lists of attributes. ldap.search_s returns a
list of such structures. An identifier that ends in _attrs is the dictionary of
attributes from the _info structure.

A connection is an LDAPObject that has been successfully bound with a DN and
password. The identifier 'user' always refers to a User model object; LDAP user
information will be user_dn or user_info.

Additional classes can be found in the config module next to this one.
"""

import ldap
import sys
import traceback
import pprint
import copy

from django.contrib.auth.models import User, Group, Permission
from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
import django.dispatch
try:
    from django.utils.encoding import force_str
except ImportError:  # Django < 1.5
    from django.utils.encoding import smart_str as force_str

# Django 1.7 Removed custom profiles
try:
    from django.contrib.auth.models import SiteProfileNotAvailable
except ImportError:
    SiteProfileNotAvailable = Exception

# Support Django 1.5's custom user models
try:
    from django.contrib.auth import get_user_model
    get_user_username = lambda u: u.get_username()
except ImportError:
    get_user_model = lambda: User                                        # noqa
    get_user_username = lambda u: u.username

# Small compatibility hack
try:
    basestring
except NameError:
    basestring = str

from django_auth_ldap.config import _LDAPConfig, LDAPSearch


logger = _LDAPConfig.get_logger()


# Signals for populating user objects.
populate_user = django.dispatch.Signal(providing_args=["user", "ldap_user"])
populate_user_profile = django.dispatch.Signal(providing_args=["profile", "ldap_user"])


class LDAPBackend(object):
    """
    The main backend class. This implements the auth backend API, although it
    actually delegates most of its work to _LDAPUser, which is defined next.
    """
    supports_anonymous_user = False
    supports_object_permissions = True
    supports_inactive_user = False

    _settings = None
    _ldap = None  # The cached ldap module (or mock object)

    # This is prepended to our internal setting names to produce the names we
    # expect in Django's settings file. Subclasses can change this in order to
    # support multiple collections of settings.
    settings_prefix = 'AUTH_LDAP_'

    def __getstate__(self):
        """
        Exclude certain cached properties from pickling.
        """
        return dict((k, v) for (k, v) in self.__dict__.items()
                    if k not in ['_settings', '_ldap'])

    def _get_settings(self):
        if self._settings is None:
            self._settings = LDAPSettings(self.settings_prefix)

        return self._settings

    def _set_settings(self, settings):
        self._settings = settings

    settings = property(_get_settings, _set_settings)

    def _get_ldap(self):
        if self._ldap is None:
            from django.conf import settings

            options = getattr(settings, 'AUTH_LDAP_GLOBAL_OPTIONS', None)

            self._ldap = _LDAPConfig.get_ldap(options)

        return self._ldap
    ldap = property(_get_ldap)

    def get_user_model(self):
        """
        By default, this will return the model class configured by
        AUTH_USER_MODEL. Subclasses may wish to override it and return a proxy
        model.
        """
        return get_user_model()

    #
    # The Django auth backend API
    #

    def authenticate(self, username, password):
        if len(password) == 0 and not self.settings.PERMIT_EMPTY_PASSWORD:
            logger.debug('Rejecting empty password for %s' % username)
            return None

        ldap_user = _LDAPUser(self, username=username.strip())
        user = ldap_user.authenticate(password)

        return user

    def get_user(self, user_id):
        user = None

        try:
            user = self.get_user_model().objects.get(pk=user_id)
            _LDAPUser(self, user=user)  # This sets user.ldap_user
        except ObjectDoesNotExist:
            pass

        return user

    def has_perm(self, user, perm, obj=None):
        return perm in self.get_all_permissions(user, obj)

    def has_module_perms(self, user, app_label):
        for perm in self.get_all_permissions(user):<commit_msg>Added **kwargs argument to authenticate method (like in Django ModelBackend)<commit_after># Copyright (c) 2009, <NAME>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
LDAP authentication backend

Complete documentation can be found in docs/howto/auth-ldap.txt (or the thing it
compiles to).

Use of this backend requires the python-ldap module. To support unit tests, we
import ldap in a single centralized place (config._LDAPConfig) so that the test
harness can insert a mock object.

A few notes on naming conventions. If an identifier ends in _dn, it is a string
representation of a distinguished name. If it ends in _info, it is a 2-tuple
containing a DN and a dictionary of lists of attributes. ldap.search_s returns a
list of such structures. An identifier that ends in _attrs is the dictionary of
attributes from the _info structure.

A connection is an LDAPObject that has been successfully bound with a DN and
password. The identifier 'user' always refers to a User model object; LDAP user
information will be user_dn or user_info.

Additional classes can be found in the config module next to this one.
"""

import ldap
import sys
import traceback
import pprint
import copy

from django.contrib.auth.models import User, Group, Permission
from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
import django.dispatch
try:
    from django.utils.encoding import force_str
except ImportError:  # Django < 1.5
    from django.utils.encoding import smart_str as force_str

# Django 1.7 Removed custom profiles
try:
    from django.contrib.auth.models import SiteProfileNotAvailable
except ImportError:
    SiteProfileNotAvailable = Exception

# Support Django 1.5's custom user models
try:
    from django.contrib.auth import get_user_model
    get_user_username = lambda u: u.get_username()
except ImportError:
    get_user_model = lambda: User                                        # noqa
    get_user_username = lambda u: u.username

# Small compatibility hack
try:
    basestring
except NameError:
    basestring = str

from django_auth_ldap.config import _LDAPConfig, LDAPSearch


logger = _LDAPConfig.get_logger()


# Signals for populating user objects.
populate_user = django.dispatch.Signal(providing_args=["user", "ldap_user"])
populate_user_profile = django.dispatch.Signal(providing_args=["profile", "ldap_user"])


class LDAPBackend(object):
    """
    The main backend class. This implements the auth backend API, although it
    actually delegates most of its work to _LDAPUser, which is defined next.
    """
    supports_anonymous_user = False
    supports_object_permissions = True
    supports_inactive_user = False

    _settings = None
    _ldap = None  # The cached ldap module (or mock object)

    # This is prepended to our internal setting names to produce the names we
    # expect in Django's settings file. Subclasses can change this in order to
    # support multiple collections of settings.
    settings_prefix = 'AUTH_LDAP_'

    def __getstate__(self):
        """
        Exclude certain cached properties from pickling.
        """
        return dict((k, v) for (k, v) in self.__dict__.items()
                    if k not in ['_settings', '_ldap'])

    def _get_settings(self):
        if self._settings is None:
            self._settings = LDAPSettings(self.settings_prefix)

        return self._settings

    def _set_settings(self, settings):
        self._settings = settings

    settings = property(_get_settings, _set_settings)

    def _get_ldap(self):
        if self._ldap is None:
            from django.conf import settings

            options = getattr(settings, 'AUTH_LDAP_GLOBAL_OPTIONS', None)

            self._ldap = _LDAPConfig.get_ldap(options)

        return self._ldap
    ldap = property(_get_ldap)

    def get_user_model(self):
        """
        By default, this will return the model class configured by
        AUTH_USER_MODEL. Subclasses may wish to override it and return a proxy
        model.
        """
        return get_user_model()

    #
    # The Django auth backend API
    #

    def authenticate(self, username, password, **kwargs):
        if len(password) == 0 and not self.settings.PERMIT_EMPTY_PASSWORD:
            logger.debug('Rejecting empty password for %s' % username)
            return None

        ldap_user = _LDAPUser(self, username=username.strip())
        user = ldap_user.authenticate(password)

        return user

    def get_user(self, user_id):
        user = None

        try:
            user = self.get_user_model().objects.get(pk=user_id)
            _LDAPUser(self, user=user)  # This sets user.ldap_user
        except ObjectDoesNotExist:
            pass

        return user

    def has_perm(self, user, perm, obj=None):
        return perm in self.get_all_permissions(user, obj)

    def has_module_perms(self, user, app_label):
        for perm in self.get_all_permissions(user):
{'fraction_non_alphanumeric': 0.06185817093878871, 'fraction_numerical': 0.0019406485000404302, 'mean_word_length': 3.412415269354263, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2237890', 'n_tokens_mistral': 3444, 'n_tokens_neox': 3247, 'n_words': 1371}