LDAP improvements:
- Better logging - Better error messages - Add unit tests - Clean up the setup tool for LDAP
This commit is contained in:
parent
3e1abba284
commit
efab02ae47
5 changed files with 173 additions and 28 deletions
|
@ -11,12 +11,23 @@ from util.validation import generate_valid_usernames
|
|||
from data import model
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
if os.environ.get('LDAP_DEBUG') == '1':
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.DEBUG)
|
||||
|
||||
logger.addHandler(ch)
|
||||
|
||||
class DatabaseUsers(object):
|
||||
def verify_user(self, username_or_email, password):
|
||||
""" Simply delegate to the model implementation. """
|
||||
return model.verify_user(username_or_email, password)
|
||||
result = model.verify_user(username_or_email, password)
|
||||
if not result:
|
||||
return (None, 'Invalid Username or Password')
|
||||
|
||||
return (result, None)
|
||||
|
||||
|
||||
def user_exists(self, username):
|
||||
return model.get_user(username) is not None
|
||||
|
@ -30,9 +41,10 @@ class LDAPConnection(object):
|
|||
self._conn = None
|
||||
|
||||
def __enter__(self):
|
||||
trace_level = 2 if os.environ.get('LDAP_DEBUG') else 0
|
||||
trace_level = 2 if os.environ.get('LDAP_DEBUG') == '1' else 0
|
||||
self._conn = ldap.initialize(self._ldap_uri, trace_level=trace_level)
|
||||
self._conn.simple_bind_s(self._user_dn, self._user_pw)
|
||||
|
||||
return self._conn
|
||||
|
||||
def __exit__(self, exc_type, value, tb):
|
||||
|
@ -55,7 +67,7 @@ class LDAPUsers(object):
|
|||
query = u'(|({0}={2})({1}={2}))'.format(self._uid_attr, self._email_attr,
|
||||
username_or_email)
|
||||
|
||||
logger.debug('Conducting user search: %s => %s', user_search_dn, query)
|
||||
logger.debug('Conducting user search: %s under %s', query, user_search_dn)
|
||||
try:
|
||||
user = conn.search_s(user_search_dn, ldap.SCOPE_SUBTREE, query.encode('utf-8'))
|
||||
except ldap.LDAPError:
|
||||
|
@ -75,12 +87,12 @@ class LDAPUsers(object):
|
|||
|
||||
# Make sure that even if the server supports anonymous binds, we don't allow it
|
||||
if not password:
|
||||
return None
|
||||
return (None, 'Anonymous binding not allowed')
|
||||
|
||||
found_user = self._ldap_user_search(username_or_email)
|
||||
|
||||
if found_user is None:
|
||||
return None
|
||||
return (None, 'Username not found')
|
||||
|
||||
found_dn, found_response = found_user
|
||||
|
||||
|
@ -91,9 +103,15 @@ class LDAPUsers(object):
|
|||
pass
|
||||
except ldap.INVALID_CREDENTIALS:
|
||||
logger.exception('Invalid LDAP credentials')
|
||||
return None
|
||||
return (None, 'Invalid password')
|
||||
|
||||
# Now check if we have a federated login for this user
|
||||
if not found_response.get(self._uid_attr):
|
||||
return (None, 'Missing uid field "%s" in user record' % self._uid_attr)
|
||||
|
||||
if not found_response.get(self._email_attr):
|
||||
return (None, 'Missing mail field "%s" in user record' % self._email_attr)
|
||||
|
||||
username = found_response[self._uid_attr][0].decode('utf-8')
|
||||
email = found_response[self._email_attr][0]
|
||||
db_user = model.verify_federated_login('ldap', username)
|
||||
|
@ -107,7 +125,7 @@ class LDAPUsers(object):
|
|||
|
||||
if not valid_username:
|
||||
logger.error('Unable to pick a username for user: %s', username)
|
||||
return None
|
||||
return (None, 'Unable to pick a username. Please report this to your administrator.')
|
||||
|
||||
db_user = model.create_federated_user(valid_username, email, 'ldap', username,
|
||||
set_password_notification=False)
|
||||
|
@ -116,7 +134,7 @@ class LDAPUsers(object):
|
|||
db_user.email = email
|
||||
db_user.save()
|
||||
|
||||
return db_user
|
||||
return (db_user, None)
|
||||
|
||||
def user_exists(self, username):
|
||||
found_user = self._ldap_user_search(username)
|
||||
|
@ -225,12 +243,7 @@ class UserAuthentication(object):
|
|||
else:
|
||||
password = decrypted
|
||||
|
||||
result = self.state.verify_user(username_or_email, password)
|
||||
if result:
|
||||
return (result, '')
|
||||
else:
|
||||
return (result, 'Invalid password.')
|
||||
|
||||
return self.state.verify_user(username_or_email, password)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.state, name, None)
|
||||
|
|
Reference in a new issue