56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
from typing import Union, List
|
|
|
|
import ldap3
|
|
from zope import component
|
|
from zope.interface import implementer
|
|
|
|
from .UWLDAPRecord import UWLDAPRecord
|
|
from ceo_common.interfaces import IUWLDAPService, IConfig
|
|
|
|
|
|
@implementer(IUWLDAPService)
|
|
class UWLDAPService:
|
|
def __init__(self):
|
|
cfg = component.getUtility(IConfig)
|
|
self.uwldap_server_url = cfg.get('uwldap_server_url')
|
|
self.uwldap_base = cfg.get('uwldap_base')
|
|
|
|
def _get_conn(self) -> ldap3.Connection:
|
|
return ldap3.Connection(
|
|
self.uwldap_server_url, auto_bind=True, read_only=True,
|
|
raise_exceptions=True)
|
|
|
|
def get_user(self, username: str) -> Union[UWLDAPRecord, None]:
|
|
conn = self._get_conn()
|
|
conn.search(
|
|
self.uwldap_base, f'(uid={username})',
|
|
attributes=UWLDAPRecord.ldap_attributes, size_limit=1)
|
|
if not conn.entries:
|
|
return None
|
|
return UWLDAPRecord.deserialize_from_ldap(conn.entries[0])
|
|
|
|
def get_programs_for_users(self, usernames: List[str]) -> List[Union[str, None]]:
|
|
filter_str = '(|' + ''.join([f'(uid={uid})' for uid in usernames]) + ')'
|
|
programs = [None] * len(usernames)
|
|
user_indices = {uid: i for i, uid in enumerate(usernames)}
|
|
|
|
conn = self._get_conn()
|
|
conn.search(
|
|
self.uwldap_base, filter_str, attributes=['ou', 'uid'],
|
|
size_limit=len(usernames))
|
|
for entry in conn.entries:
|
|
# some records in UWLDAP have two UIDs because UIDs
|
|
# were historically limited to 8 characters
|
|
uid = None
|
|
for uw_uid in entry.uid.values:
|
|
if uw_uid in user_indices:
|
|
uid = uw_uid
|
|
break
|
|
# sanity check
|
|
assert uid is not None
|
|
idx = user_indices[uid]
|
|
program = entry.ou.value
|
|
if program:
|
|
programs[idx] = program
|
|
return programs
|