diff options
Diffstat (limited to 'accounts/backend/user/ldap.py')
-rw-r--r-- | accounts/backend/user/ldap.py | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/accounts/backend/user/ldap.py b/accounts/backend/user/ldap.py index ea1b7fc..0f32530 100644 --- a/accounts/backend/user/ldap.py +++ b/accounts/backend/user/ldap.py @@ -5,7 +5,7 @@ import ldap3 from ldap3.utils.conv import escape_filter_chars from ldap3.utils.dn import escape_attribute_value -from . import Backend, InvalidPasswordError, NoSuchUserError +from . import Backend, InvalidPasswordError, NoSuchUserError, ShouldNotHappen from accounts.models import Account @@ -51,20 +51,23 @@ class LdapBackend(Backend): uid = None mail = None + uidNumber = None services = [] conn.search(user_dn, '(objectClass=*)', - attributes=['objectClass', 'uid', 'mail', 'cn']) + attributes=['objectClass', 'uid', 'mail', 'cn', 'uidNumber']) for entry in conn.entries: - if 'inetOrgPerson' in entry.objectClass.values: + if 'splineAccount' in entry.objectClass.values: uid = entry.uid.value mail = entry.mail.value + uidNumber = entry.uidNumber.value elif 'servicePassword' in entry.objectClass.value: services.append(entry.cn.value) - if uid is None or mail is None: + if uid is None or mail is None or uidNumber is None: raise NoSuchUserError("User not found") - return Account(uid, mail, services, password) + return Account(uid, mail, services, password, + uidNumber=uidNumber) def find(self, filters=None, wildcard=False): """ @@ -73,7 +76,7 @@ class LdapBackend(Backend): if filters is None: filters = dict() - filters['objectClass'] = 'inetOrgPerson' + filters['objectClass'] = 'splineAccount' filter_as_list = ['(%s=%s)' % (attr, _escape(value, wildcard)) for attr, value in filters.items()] filterstr = '(&%s)' % ''.join(filter_as_list) @@ -84,9 +87,10 @@ class LdapBackend(Backend): accounts = [] try: conn.search(base_dn, filterstr, search_scope=ldap3.LEVEL, - attributes=['uid', 'mail']) + attributes=['uid', 'mail', 'uidNumber']) for entry in conn.entries: - accounts.append(Account(entry.uid.value, entry.mail.value)) + accounts.append(Account(entry.uid.value, entry.mail.value, + uidNumber=entry.uidNumber.value)) except ldap3.LDAPException: pass @@ -97,11 +101,12 @@ class LdapBackend(Backend): user_dn = self._format_dn([('uid', account.uid), ('ou', 'users')]) attrs = { - 'objectClass': ['top', 'inetOrgPerson'], + 'objectClass': ['top', 'inetOrgPerson', 'splineAccount'], 'uid': _escape(account.uid), 'sn': 'n/a', 'cn': _escape(account.uid), 'mail': _escape(account.mail), + 'uidNumber': _escape(account.uidNumber), } conn.add(user_dn, attributes=attrs) @@ -195,3 +200,31 @@ class LdapBackend(Backend): del account.new_password_services[service] + def _get_last_uidNumber(self, conn): + uidNumber_dn = self._format_dn([('cn', 'uidMax'), ('ou', 'other')]) + conn.search(uidNumber_dn, '(objectClass=uidNumberMaximum)', + attributes=['uidNumber']) + for entry in conn.entries: + return entry.uidNumber.value + + raise ShouldNotHappen('Last uidNumber not found.') + + def _get_next_uidNumber(self): + conn = self._connect_as_admin() + + uidNumber_dn = self._format_dn([('cn', 'uidMax'), ('ou', 'other')]) + uidNumber = self._get_last_uidNumber(conn) + + # Try to acquire next uidNumber + for i in [0, 1, 2, 3, 4, 5]: + try: + conn.modify(uidNumber_dn, {'uidNumber': [ + (ldap3.MODIFY_DELETE, [uidNumber + i]), + (ldap3.MODIFY_ADD, [uidNumber + i + 1]), + ]) + + if conn.result == ldap3.RESULT_SUCCESS: + return uidNumber + i + 1 + except ldap3.LDAPOperationResult: + pass + raise ShouldNotHappen('Unable to get next uidNumber, try again.') |