summaryrefslogtreecommitdiffstats
path: root/accounts/backend/user/ldap.py
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/backend/user/ldap.py')
-rw-r--r--accounts/backend/user/ldap.py51
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.')