diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 7b8bb7a..54e8eee 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -4,6 +4,9 @@ import random import ldap3 from django.conf import settings +import logging + +logger = logging.getLogger(__name__) class LdapManager: @@ -67,38 +70,53 @@ class LdapManager: return passwd - def create_user(self, loginname, displayname, mail, password): - """ - Create a new user in the LDAP storage. - - *loginname* must be a unique, valid user id. It is generally safe to - pass lower-case ascii letters here. The *loginname* of an account - cannot be changed. - - *displayname* is the name which is shown to other users. This can be - changed in the future. - - *mail* is a valid mail address of the user. - - *password* is the initial plain text password for the user. - """ - + def create_user(self, user, password, firstname, lastname, email): conn = self.get_admin_conn() + uidNumber = self._get_max_uid() + 1 + logger.debug("uidNumber={uidNumber}".format(uidNumber=uidNumber)) + results = True + while results: + results = self.check_user_exists( + "", + True, + '(&(objectClass=inetOrgPerson)(objectClass=posixAccount)' + '(objectClass=top)(uidNumber={uidNumber}))'.format( + uidNumber=uidNumber + ) + ) + if results: + logger.debug( + "{uid} exists. Trying next.".format(uid=uidNumber) + ) + uidNumber += 1 + logger.debug("{uid} does not exist. Using it".format(uid=uidNumber)) + self._set_max_uid(uidNumber) try: conn.add( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=loginname), - ["inetOrgPerson"], + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + ["inetOrgPerson", "posixAccount", "ldapPublickey"], { - "uid": [loginname], - "cn": [displayname], - "sn": ["XXX"], - "givenName": ["XXX"], - "mail": [mail], - "userpassword": [self._ssha_password( + "uid": [user.encode("utf-8")], + "sn": [lastname.encode("utf-8")], + "givenName": [firstname.encode("utf-8")], + "cn": ["{} {}".format(firstname, lastname).encode("utf-8")], + "displayName": ["{} {}".format(firstname, lastname).encode("utf-8")], + "uidNumber": [str(uidNumber)], + "gidNumber": [str(settings.LDAP_CUSTOMER_GROUP_ID)], + "loginShell": ["/bin/bash"], + "homeDirectory": ["/home/{}".format(user).encode("utf-8")], + "mail": email.encode("utf-8"), + "userPassword": [self._ssha_password( password.encode("utf-8") )] } ) + logger.debug('Created user %s %s' % (user.encode('utf-8'), + uidNumber)) + except Exception as ex: + logger.debug('Could not create user %s' % user.encode('utf-8')) + logger.error("Exception: " + str(ex)) + raise Exception(ex) finally: conn.unbind() @@ -124,21 +142,63 @@ class LdapManager: conn.unbind() return return_val - def check_user_exists(self, uid, is_customer=True): + def check_user_exists(self, uid, is_customer=True, search_filter=""): """ Check if the user with the given uid exists in the customer group. :param uid: str representing the user :param is_customer: bool representing whether the current user is a customer. By default, the user is a customer (assume) + :param search_filter: str representing the filter condition to find + users. If its empty, the search finds the user with + the given uid. :return: True if the user exists otherwise return False """ conn = self.get_admin_conn() try: result = conn.search( settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, - search_filter='(uid={uid})'.format(uid=uid) + search_filter=search_filter if len(search_filter)> 0 else + '(uid={uid})'.format(uid=uid) ) finally: conn.unbind() return result + + def _set_max_uid(self, max_uid): + """ + a utility function to save max_uid value to a file + + :param max_uid: an integer representing the max uid + :return: + """ + with open(settings.LDAP_MAX_UID_FILE_PATH, 'w+') as handler: + handler.write(str(max_uid)) + + def _get_max_uid(self): + """ + A utility function to read the max uid value that was previously set + + :return: An integer representing the max uid value that was previously + set + """ + try: + with open(settings.LDAP_MAX_UID_FILE_PATH, 'r+') as handler: + try: + return_value = int(handler.read()) + except ValueError as ve: + logger.error( + "Error reading int value from {}. {}" + "Returning default value {} instead".format( + settings.LDAP_MAX_UID_PATH, + str(ve), + settings.LDAP_DEFAULT_START_UID + ) + ) + return_value = settings.LDAP_DEFAULT_START_UID + return return_value + except FileNotFoundError as fnfe: + logger.error("File not found : " + str(fnfe)) + return_value = settings.LDAP_DEFAULT_START_UID + logger.error("So, returning UID={}".format(return_value)) + return return_value