ldapweb/webapp/ldaputils.py

67 lines
1.7 KiB
Python

import re
import ldap
from webapp import config
def is_valid_name(name):
"""`true` if `name` is a safe ldap uid/cn"""
return re.match(r'^[a-zA-Z_][a-zA-Z0-9-_\.]*\Z', name) is not None
def validate_name(name):
"""Raises `RuntimeError` if `name` is not a safe ldap uid/cn"""
if not is_valid_name(name):
raise RuntimeError('Invalid name')
def user_dn(uid):
validate_name(uid)
return config.ldap_user_dn_format.format(uid)
def group_dn(cn):
validate_name(cn)
return config.ldap_group_dn_format.format(cn)
def wrap(filter):
if len(filter) and filter[0] == '(' and filter[-1] == ')':
return filter
else:
return f'({filter})'
def _or(*filters):
wrapped = ''.join(wrap(f) for f in filters)
return f'(|{wrapped})'
def _and(*filters):
wrapped = ''.join(wrap(f) for f in filters)
return f'(&{wrapped})'
def _not(filter):
wrapped = wrap(filter)
return f'(!{wrapped})'
def member_of_any(groups):
"""Returns a filter that matches users that are a member of any of the given group names"""
return _or(*(f'memberOf={group_dn(group)}' for group in groups))
def groups_of_user(uid):
"""Returns a filter that matches groups that have the given user as a member"""
return f'(&(objectClass=groupOfUniqueNames)(uniqueMember={user_dn(uid)}))'
def normalized_entries(entries):
"""
Converts ldap entries from python-ldap format into a more convenient
List[Tuple[
dn,
List[tuple[attr_name, attr_value]]
]]
"""
normalized = []
for dn, attrs in entries:
normalized_attrs = []
for attr, values in attrs.items():
for value in values:
normalized_attrs.append((attr, value.decode()))
normalized.append((dn, normalized_attrs))
return normalized