Use python-ldap directly in members
This leaves only utility functions in ldapi.
This commit is contained in:
parent
b8be0f8149
commit
217c9806f1
405
ceo/ldapi.py
405
ceo/ldapi.py
|
@ -1,365 +1,114 @@
|
||||||
"""
|
"""
|
||||||
LDAP Backend Interface
|
LDAP Utilities
|
||||||
|
|
||||||
This module is intended to be a thin wrapper around LDAP operations.
|
|
||||||
Methods on the connection object correspond in a straightforward way
|
|
||||||
to LDAP queries and updates.
|
|
||||||
|
|
||||||
A LDAP entry is the most important component of a CSC UNIX account.
|
|
||||||
The entry contains the username, user id number, real name, shell,
|
|
||||||
and other important information. All non-local UNIX accounts must
|
|
||||||
have an LDAP entry, even if the account does not log in directly.
|
|
||||||
|
|
||||||
This module makes use of python-ldap, a Python module with bindings
|
This module makes use of python-ldap, a Python module with bindings
|
||||||
to libldap, OpenLDAP's native C client library.
|
to libldap, OpenLDAP's native C client library.
|
||||||
"""
|
"""
|
||||||
import ldap.modlist
|
import ldap.modlist
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
|
|
||||||
|
|
||||||
class LDAPException(Exception):
|
def connect_sasl(uri, mech, realm):
|
||||||
"""Exception class for LDAP-related errors."""
|
|
||||||
|
# open the connection
|
||||||
|
ld = ldap.initialize(uri)
|
||||||
|
|
||||||
|
# authenticate
|
||||||
|
sasl = Sasl(mech, realm)
|
||||||
|
ld.sasl_interactive_bind_s('', sasl)
|
||||||
|
|
||||||
|
return ld
|
||||||
|
|
||||||
|
|
||||||
class LDAPConnection(object):
|
def abslookup(ld, dn, objectclass=None):
|
||||||
"""
|
|
||||||
Connection to the LDAP directory. All directory
|
|
||||||
queries and updates are made via this class.
|
|
||||||
|
|
||||||
Exceptions: (all methods)
|
# search for the specified dn
|
||||||
LDAPException - on directory query failure
|
try:
|
||||||
|
if objectclass:
|
||||||
Example:
|
search_filter = '(objectclass=%s)' % escape(objectclass)
|
||||||
connection = LDAPConnection()
|
matches = ld.search_s(dn, ldap.SCOPE_BASE, search_filter)
|
||||||
connection.connect(...)
|
else:
|
||||||
|
matches = ld.search_s(dn, ldap.SCOPE_BASE)
|
||||||
# make queries and updates, e.g.
|
except ldap.NO_SUCH_OBJECT:
|
||||||
connection.user_delete('mspang')
|
return None
|
||||||
|
|
||||||
connection.disconnect()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.ldap = None
|
|
||||||
|
|
||||||
|
|
||||||
def connect_anon(self, uri, user_base, group_base):
|
|
||||||
"""
|
|
||||||
Establish a connection to the LDAP Server.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
uri - connection string (e.g. ldap://foo.com, ldaps://bar.com)
|
|
||||||
user_base - base of the users subtree
|
|
||||||
group_base - baes of the group subtree
|
|
||||||
|
|
||||||
Example: connect('ldaps:///', 'cn=ceo,dc=csclub,dc=uwaterloo,dc=ca',
|
|
||||||
'secret', 'ou=People,dc=csclub,dc=uwaterloo,dc=ca',
|
|
||||||
'ou=Group,dc=csclub,dc=uwaterloo,dc=ca')
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# open the connection
|
|
||||||
self.ldap = ldap.initialize(uri)
|
|
||||||
|
|
||||||
# authenticate
|
|
||||||
self.ldap.simple_bind_s('', '')
|
|
||||||
|
|
||||||
self.user_base = user_base
|
|
||||||
self.group_base = group_base
|
|
||||||
|
|
||||||
|
|
||||||
def connect_sasl(self, uri, mech, realm, user_base, group_base):
|
|
||||||
|
|
||||||
# open the connection
|
|
||||||
self.ldap = ldap.initialize(uri)
|
|
||||||
|
|
||||||
# authenticate
|
|
||||||
sasl = Sasl(mech, realm)
|
|
||||||
self.ldap.sasl_interactive_bind_s('', sasl)
|
|
||||||
|
|
||||||
self.user_base = user_base
|
|
||||||
self.group_base = group_base
|
|
||||||
|
|
||||||
|
|
||||||
def disconnect(self):
|
|
||||||
"""Close the connection to the LDAP server."""
|
|
||||||
|
|
||||||
if self.ldap:
|
|
||||||
|
|
||||||
# close connection
|
|
||||||
try:
|
|
||||||
self.ldap.unbind_s()
|
|
||||||
self.ldap = None
|
|
||||||
except ldap.LDAPError, e:
|
|
||||||
raise LDAPException("unable to disconnect: %s" % e)
|
|
||||||
|
|
||||||
|
|
||||||
def connected(self):
|
|
||||||
"""Determine whether the connection has been established."""
|
|
||||||
|
|
||||||
return self.ldap is not None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Helper Methods ###
|
|
||||||
|
|
||||||
def lookup(self, dn, objectClass=None):
|
|
||||||
"""
|
|
||||||
Helper method to retrieve the attributes of an entry.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
dn - the distinguished name of the directory entry
|
|
||||||
|
|
||||||
Returns: a dictionary of attributes of the matched dn, or
|
|
||||||
None of the dn does not exist in the directory
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self.connected(): raise LDAPException("Not connected!")
|
|
||||||
|
|
||||||
# search for the specified dn
|
|
||||||
try:
|
|
||||||
if objectClass:
|
|
||||||
search_filter = '(objectClass=%s)' % self.escape(objectClass)
|
|
||||||
matches = self.ldap.search_s(dn, ldap.SCOPE_BASE, search_filter)
|
|
||||||
else:
|
|
||||||
matches = self.ldap.search_s(dn, ldap.SCOPE_BASE)
|
|
||||||
except ldap.NO_SUCH_OBJECT:
|
|
||||||
return None
|
|
||||||
except ldap.LDAPError, e:
|
|
||||||
raise LDAPException("unable to lookup dn %s: %s" % (dn, e))
|
|
||||||
|
|
||||||
# this should never happen due to the nature of DNs
|
# dn was found, but didn't match the objectclass filter
|
||||||
if len(matches) > 1:
|
if len(matches) < 1:
|
||||||
raise LDAPException("duplicate dn in ldap: " + dn)
|
return None
|
||||||
|
|
||||||
# dn was found, but didn't match the objectClass filter
|
# return the attributes of the single successful match
|
||||||
elif len(matches) < 1:
|
match = matches[0]
|
||||||
return None
|
match_dn, match_attributes = match
|
||||||
|
return match_attributes
|
||||||
|
|
||||||
# return the attributes of the single successful match
|
|
||||||
match = matches[0]
|
|
||||||
match_dn, match_attributes = match
|
|
||||||
return match_attributes
|
|
||||||
|
|
||||||
|
def lookup(ld, rdntype, rdnval, base, objectclass=None):
|
||||||
|
dn = '%s=%s,%s' % (rdntype, escape(rdnval), base)
|
||||||
|
return abslookup(ld, dn, objectclass)
|
||||||
|
|
||||||
|
|
||||||
### User-related Methods ###
|
def search(ld, base, search_filter, params, scope=ldap.SCOPE_SUBTREE, attrlist=None, attrsonly=0):
|
||||||
|
|
||||||
def user_lookup(self, uid, objectClass=None):
|
real_filter = search_filter % tuple(escape(x) for x in params)
|
||||||
"""
|
|
||||||
Retrieve the attributes of a user.
|
|
||||||
|
|
||||||
Parameters:
|
# search for entries that match the filter
|
||||||
uid - the uid to look up
|
matches = ld.search_s(base, scope, real_filter, attrlist, attrsonly)
|
||||||
|
return matches
|
||||||
|
|
||||||
Returns: attributes of user with uid
|
|
||||||
"""
|
|
||||||
|
|
||||||
dn = 'uid=' + uid + ',' + self.user_base
|
def modify(ld, rdntype, rdnval, base, mlist):
|
||||||
return self.lookup(dn, objectClass)
|
dn = '%s=%s,%s' % (rdntype, escape(rdnval), base)
|
||||||
|
ld.modify_s(dn, mlist)
|
||||||
|
|
||||||
|
|
||||||
def user_search(self, search_filter, params):
|
def modify_attrs(ld, rdntype, rdnval, base, old, attrs):
|
||||||
"""
|
dn = '%s=%s,%s' % (rdntype, escape(rdnval), base)
|
||||||
Search for users with a filter.
|
|
||||||
|
|
||||||
Parameters:
|
# build list of modifications to make
|
||||||
search_filter - LDAP filter string to match users against
|
changes = ldap.modlist.modifyModlist(old, attrs)
|
||||||
|
|
||||||
Returns: a dictionary mapping uids to attributes
|
# apply changes
|
||||||
"""
|
ld.modify_s(dn, changes)
|
||||||
|
|
||||||
if not self.connected(): raise LDAPException("Not connected!")
|
|
||||||
|
|
||||||
search_filter = search_filter % tuple(self.escape(x) for x in params)
|
def modify_diff(ld, rdntype, rdnval, base, old, new):
|
||||||
|
dn = '%s=%s,%s' % (rdntype, escape(rdnval), base)
|
||||||
|
|
||||||
# search for entries that match the filter
|
# build list of modifications to make
|
||||||
try:
|
changes = make_modlist(old, new)
|
||||||
matches = self.ldap.search_s(self.user_base, ldap.SCOPE_SUBTREE, search_filter)
|
|
||||||
except ldap.LDAPError, e:
|
|
||||||
raise LDAPException("user search failed: %s" % e)
|
|
||||||
|
|
||||||
results = {}
|
# apply changes
|
||||||
for match in matches:
|
ld.modify_s(dn, changes)
|
||||||
dn, attrs = match
|
|
||||||
uid = attrs['uid'][0]
|
|
||||||
results[uid] = attrs
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
def escape(value):
|
||||||
|
"""
|
||||||
|
Escapes special characters in a value so that it may be safely inserted
|
||||||
|
into an LDAP search filter.
|
||||||
|
"""
|
||||||
|
|
||||||
def user_modify(self, uid, attrs):
|
value = str(value)
|
||||||
"""
|
value = value.replace('\\', '\\5c').replace('*', '\\2a')
|
||||||
Update user attributes in the directory.
|
value = value.replace('(', '\\28').replace(')', '\\29')
|
||||||
|
value = value.replace('\x00', '\\00')
|
||||||
|
return value
|
||||||
|
|
||||||
Parameters:
|
|
||||||
uid - username of the user to modify
|
|
||||||
attrs - dictionary as returned by user_lookup() with changes to make.
|
|
||||||
omitted attributes are DELETED.
|
|
||||||
|
|
||||||
Example: user = user_lookup('mspang')
|
def make_modlist(old, new):
|
||||||
user['uidNumber'] = [ '0' ]
|
keys = set(old.keys()).union(set(new))
|
||||||
connection.user_modify('mspang', user)
|
mlist = []
|
||||||
"""
|
for key in keys:
|
||||||
|
if key in old and not key in new:
|
||||||
# distinguished name of the entry to modify
|
mlist.append((ldap.MOD_DELETE, key, list(set(old[key]))))
|
||||||
dn = 'uid=' + uid + ',' + self.user_base
|
elif key in new and not key in old:
|
||||||
|
mlist.append((ldap.MOD_ADD, key, list(set(new[key]))))
|
||||||
# retrieve current state of user
|
else:
|
||||||
old_user = self.user_lookup(uid)
|
to_add = list(set(new[key]) - set(old[key]))
|
||||||
|
if len(to_add) > 0:
|
||||||
try:
|
mlist.append((ldap.MOD_ADD, key, to_add))
|
||||||
|
to_del = list(set(old[key]) - set(new[key]))
|
||||||
# build list of modifications to make
|
if len(to_del) > 0:
|
||||||
changes = ldap.modlist.modifyModlist(old_user, attrs)
|
mlist.append((ldap.MOD_DELETE, key, to_del))
|
||||||
|
return mlist
|
||||||
# apply changes
|
|
||||||
self.ldap.modify_s(dn, changes)
|
|
||||||
|
|
||||||
except ldap.LDAPError, e:
|
|
||||||
raise LDAPException("unable to modify: %s" % e)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Group-related Methods ###
|
|
||||||
|
|
||||||
def group_lookup(self, cn):
|
|
||||||
"""
|
|
||||||
Retrieves the attributes of a group.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
cn - the UNIX group name to lookup
|
|
||||||
|
|
||||||
Returns: attributes of the group's LDAP entry
|
|
||||||
|
|
||||||
Example: connection.group_lookup('office') -> {
|
|
||||||
'cn': 'office',
|
|
||||||
'gidNumber', '1001',
|
|
||||||
...
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
dn = 'cn=' + cn + ',' + self.group_base
|
|
||||||
return self.lookup(dn, 'posixGroup')
|
|
||||||
|
|
||||||
|
|
||||||
### Member-related Methods ###
|
|
||||||
|
|
||||||
def member_lookup(self, uid):
|
|
||||||
"""
|
|
||||||
Retrieve the attributes of a member. This method will only return
|
|
||||||
results that have the objectClass 'member'.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
uid - the username to look up
|
|
||||||
|
|
||||||
Returns: attributes of member with uid
|
|
||||||
|
|
||||||
Example: connection.member_lookup('mspang') ->
|
|
||||||
{ 'uid': 'mspang', 'uidNumber': 21292 ...}
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self.connected(): raise LDAPException("Not connected!")
|
|
||||||
|
|
||||||
dn = 'uid=' + uid + ',' + self.user_base
|
|
||||||
return self.lookup(dn, 'member')
|
|
||||||
|
|
||||||
|
|
||||||
def member_search_name(self, name):
|
|
||||||
"""
|
|
||||||
Retrieves a list of members with the specified name (fuzzy).
|
|
||||||
|
|
||||||
Returns: a dictionary mapping uids to attributes
|
|
||||||
"""
|
|
||||||
|
|
||||||
search_filter = '(&(objectClass=member)(cn~=%s))'
|
|
||||||
return self.user_search(search_filter, [ name ] )
|
|
||||||
|
|
||||||
|
|
||||||
def member_search_term(self, term):
|
|
||||||
"""
|
|
||||||
Retrieves a list of members who were registered in a certain term.
|
|
||||||
|
|
||||||
Returns: a dictionary mapping uids to attributes
|
|
||||||
"""
|
|
||||||
|
|
||||||
search_filter = '(&(objectClass=member)(term=%s))'
|
|
||||||
return self.user_search(search_filter, [ term ])
|
|
||||||
|
|
||||||
|
|
||||||
def member_search_program(self, program):
|
|
||||||
"""
|
|
||||||
Retrieves a list of members in a certain program (fuzzy).
|
|
||||||
|
|
||||||
Returns: a dictionary mapping uids to attributes
|
|
||||||
"""
|
|
||||||
|
|
||||||
search_filter = '(&(objectClass=member)(program~=%s))'
|
|
||||||
return self.user_search(search_filter, [ program ])
|
|
||||||
|
|
||||||
|
|
||||||
def member_add(self, uid, cn, program=None, description=None):
|
|
||||||
"""
|
|
||||||
Adds a member to the directory.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
uid - the UNIX username for the member
|
|
||||||
cn - the real name of the member
|
|
||||||
program - the member's program of study
|
|
||||||
description - a description for the entry
|
|
||||||
"""
|
|
||||||
|
|
||||||
dn = 'uid=' + uid + ',' + self.user_base
|
|
||||||
attrs = {
|
|
||||||
'objectClass': [ 'top', 'account', 'member' ],
|
|
||||||
'uid': [ uid ],
|
|
||||||
'cn': [ cn ],
|
|
||||||
}
|
|
||||||
|
|
||||||
if program:
|
|
||||||
attrs['program'] = [ program ]
|
|
||||||
if description:
|
|
||||||
attrs['description'] = [ description ]
|
|
||||||
|
|
||||||
try:
|
|
||||||
modlist = ldap.modlist.addModlist(attrs)
|
|
||||||
self.ldap.add_s(dn, modlist)
|
|
||||||
except ldap.LDAPError, e:
|
|
||||||
raise LDAPException("unable to add: %s" % e)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Miscellaneous Methods ###
|
|
||||||
|
|
||||||
def escape(self, value):
|
|
||||||
"""
|
|
||||||
Escapes special characters in a value so that it may be safely inserted
|
|
||||||
into an LDAP search filter.
|
|
||||||
"""
|
|
||||||
|
|
||||||
value = str(value)
|
|
||||||
value = value.replace('\\', '\\5c').replace('*', '\\2a')
|
|
||||||
value = value.replace('(', '\\28').replace(')', '\\29')
|
|
||||||
value = value.replace('\x00', '\\00')
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
def make_modlist(self, old, new):
|
|
||||||
keys = set(old.keys()).union(set(new))
|
|
||||||
mlist = []
|
|
||||||
for key in keys:
|
|
||||||
if key in old and not key in new:
|
|
||||||
mlist.append((ldap.MOD_DELETE, key, list(set(old[key]))))
|
|
||||||
elif key in new and not key in old:
|
|
||||||
mlist.append((ldap.MOD_ADD, key, list(set(new[key]))))
|
|
||||||
else:
|
|
||||||
to_add = list(set(new[key]) - set(old[key]))
|
|
||||||
if len(to_add) > 0:
|
|
||||||
mlist.append((ldap.MOD_ADD, key, to_add))
|
|
||||||
to_del = list(set(old[key]) - set(new[key]))
|
|
||||||
if len(to_del) > 0:
|
|
||||||
mlist.append((ldap.MOD_DELETE, key, to_del))
|
|
||||||
return mlist
|
|
||||||
|
|
||||||
|
|
||||||
class Sasl:
|
class Sasl:
|
||||||
|
|
|
@ -10,7 +10,7 @@ Future changes to the members database that need to be atomic
|
||||||
must also be moved into this module.
|
must also be moved into this module.
|
||||||
"""
|
"""
|
||||||
import re, subprocess, ldap
|
import re, subprocess, ldap
|
||||||
from ceo import conf, excep, ldapi
|
from ceo import conf, ldapi
|
||||||
from ceo.excep import InvalidArgument
|
from ceo.excep import InvalidArgument
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ def configure():
|
||||||
|
|
||||||
### Exceptions ###
|
### Exceptions ###
|
||||||
|
|
||||||
|
LDAPException = ldap.LDAPError
|
||||||
ConfigurationException = conf.ConfigurationException
|
ConfigurationException = conf.ConfigurationException
|
||||||
LDAPException = ldapi.LDAPException
|
|
||||||
|
|
||||||
class MemberException(Exception):
|
class MemberException(Exception):
|
||||||
"""Base exception class for member-related errors."""
|
"""Base exception class for member-related errors."""
|
||||||
|
@ -76,26 +76,30 @@ class ChildFailed(MemberException):
|
||||||
### Connection Management ###
|
### Connection Management ###
|
||||||
|
|
||||||
# global directory connection
|
# global directory connection
|
||||||
ldap_connection = ldapi.LDAPConnection()
|
ld = None
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
"""Connect to LDAP."""
|
"""Connect to LDAP."""
|
||||||
|
|
||||||
configure()
|
configure()
|
||||||
|
|
||||||
ldap_connection.connect_sasl(cfg['server_url'], cfg['sasl_mech'],
|
global ld
|
||||||
cfg['sasl_realm'], cfg['users_base'], cfg['groups_base'])
|
ld = ldapi.connect_sasl(cfg['server_url'],
|
||||||
|
cfg['sasl_mech'], cfg['sasl_realm'])
|
||||||
|
|
||||||
|
|
||||||
def disconnect():
|
def disconnect():
|
||||||
"""Disconnect from LDAP."""
|
"""Disconnect from LDAP."""
|
||||||
|
|
||||||
ldap_connection.disconnect()
|
global ld
|
||||||
|
ld.unbind_s()
|
||||||
|
ld = None
|
||||||
|
|
||||||
|
|
||||||
def connected():
|
def connected():
|
||||||
"""Determine whether the connection has been established."""
|
"""Determine whether the connection has been established."""
|
||||||
|
|
||||||
return ldap_connection.connected()
|
return ld and ld.connected()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +153,7 @@ def get(userid):
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return ldap_connection.user_lookup(userid)
|
return ldapi.lookup(ld, 'uid', userid, cfg['users_base'])
|
||||||
|
|
||||||
|
|
||||||
def list_term(term):
|
def list_term(term):
|
||||||
|
@ -168,7 +172,10 @@ def list_term(term):
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return ldap_connection.member_search_term(term)
|
members = ldapi.search(ld, cfg['users_base'],
|
||||||
|
'(&(objectClass=member)(term=%s))', [ term ])
|
||||||
|
|
||||||
|
return dict([(member['uid'], member) for member in members])
|
||||||
|
|
||||||
|
|
||||||
def list_name(name):
|
def list_name(name):
|
||||||
|
@ -177,7 +184,8 @@ def list_name(name):
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
name - the name to match members against
|
name - the name to match members against
|
||||||
Returns: a list of member dictionaries
|
|
||||||
|
Returns: a list of member dictionaries
|
||||||
|
|
||||||
Example: list_name('Spang'): -> {
|
Example: list_name('Spang'): -> {
|
||||||
'mspang': { 'cn': 'Michael Spang', ... },
|
'mspang': { 'cn': 'Michael Spang', ... },
|
||||||
|
@ -185,7 +193,10 @@ Returns: a list of member dictionaries
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return ldap_connection.member_search_name(name)
|
members = ldapi.search(ld, cfg['users_base'],
|
||||||
|
'(&(objectClass=member)(cn~=%s))', [ name ])
|
||||||
|
|
||||||
|
return dict([(member['uid'], member) for member in members])
|
||||||
|
|
||||||
|
|
||||||
def list_group(group):
|
def list_group(group):
|
||||||
|
@ -225,10 +236,7 @@ def list_positions():
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ceo_ldap = ldap_connection.ldap
|
members = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE, '(position=*)')
|
||||||
user_base = ldap_connection.user_base
|
|
||||||
|
|
||||||
members = ceo_ldap.search_s(user_base, ldap.SCOPE_SUBTREE, '(position=*)')
|
|
||||||
positions = {}
|
positions = {}
|
||||||
for (_, member) in members:
|
for (_, member) in members:
|
||||||
for position in member['position']:
|
for position in member['position']:
|
||||||
|
@ -237,6 +245,7 @@ def list_positions():
|
||||||
positions[position][member['uid'][0]] = member
|
positions[position][member['uid'][0]] = member
|
||||||
return positions
|
return positions
|
||||||
|
|
||||||
|
|
||||||
def set_position(position, members):
|
def set_position(position, members):
|
||||||
"""
|
"""
|
||||||
Sets a position
|
Sets a position
|
||||||
|
@ -248,12 +257,8 @@ def set_position(position, members):
|
||||||
Example: set_position('president', ['dtbartle'])
|
Example: set_position('president', ['dtbartle'])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ceo_ldap = ldap_connection.ldap
|
res = ld.search_s(cfg['users_base'], ldap.SCOPE_SUBTREE,
|
||||||
user_base = ldap_connection.user_base
|
'(&(objectClass=member)(position=%s))' % ldapi.escape(position))
|
||||||
escape = ldap_connection.escape
|
|
||||||
|
|
||||||
res = ceo_ldap.search_s(user_base, ldap.SCOPE_SUBTREE,
|
|
||||||
'(&(objectClass=member)(position=%s))' % escape(position))
|
|
||||||
old = set([ member['uid'][0] for (_, member) in res ])
|
old = set([ member['uid'][0] for (_, member) in res ])
|
||||||
new = set(members)
|
new = set(members)
|
||||||
mods = {
|
mods = {
|
||||||
|
@ -265,7 +270,7 @@ def set_position(position, members):
|
||||||
|
|
||||||
for action in ['del', 'add']:
|
for action in ['del', 'add']:
|
||||||
for userid in mods[action]:
|
for userid in mods[action]:
|
||||||
dn = 'uid=%s,%s' % (escape(userid), user_base)
|
dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||||
entry1 = {'position' : [position]}
|
entry1 = {'position' : [position]}
|
||||||
entry2 = {} #{'position' : []}
|
entry2 = {} #{'position' : []}
|
||||||
entry = ()
|
entry = ()
|
||||||
|
@ -273,19 +278,13 @@ def set_position(position, members):
|
||||||
entry = (entry1, entry2)
|
entry = (entry1, entry2)
|
||||||
elif action == 'add':
|
elif action == 'add':
|
||||||
entry = (entry2, entry1)
|
entry = (entry2, entry1)
|
||||||
mlist = ldap_connection.make_modlist(entry[0], entry[1])
|
mlist = ldapi.make_modlist(entry[0], entry[1])
|
||||||
ceo_ldap.modify_s(dn, mlist)
|
ld.modify_s(dn, mlist)
|
||||||
|
|
||||||
|
|
||||||
def change_group_member(action, group, userid):
|
def change_group_member(action, group, userid):
|
||||||
|
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||||
ceo_ldap = ldap_connection.ldap
|
group_dn = 'cn=%s,%s' % (ldapi.escape(group), cfg['groups_base'])
|
||||||
user_base = ldap_connection.user_base
|
|
||||||
group_base = ldap_connection.group_base
|
|
||||||
escape = ldap_connection.escape
|
|
||||||
|
|
||||||
user_dn = 'uid=%s,%s' % (escape(userid), user_base)
|
|
||||||
group_dn = 'cn=%s,%s' % (escape(group), group_base)
|
|
||||||
entry1 = {'uniqueMember' : []}
|
entry1 = {'uniqueMember' : []}
|
||||||
entry2 = {'uniqueMember' : [user_dn]}
|
entry2 = {'uniqueMember' : [user_dn]}
|
||||||
entry = []
|
entry = []
|
||||||
|
@ -295,8 +294,8 @@ def change_group_member(action, group, userid):
|
||||||
entry = (entry2, entry1)
|
entry = (entry2, entry1)
|
||||||
else:
|
else:
|
||||||
raise InvalidArgument("action", action, "invalid action")
|
raise InvalidArgument("action", action, "invalid action")
|
||||||
mlist = ldap_connection.make_modlist(entry[0], entry[1])
|
mlist = ldapi.make_modlist(entry[0], entry[1])
|
||||||
ceo_ldap.modify_s(group_dn, mlist)
|
ld.modify_s(group_dn, mlist)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -350,15 +349,12 @@ def register(userid, term_list):
|
||||||
Example: register(3349, ["w2007", "s2007"])
|
Example: register(3349, ["w2007", "s2007"])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ceo_ldap = ldap_connection.ldap
|
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
|
||||||
user_base = ldap_connection.user_base
|
|
||||||
escape = ldap_connection.escape
|
|
||||||
user_dn = 'uid=%s,%s' % (escape(userid), user_base)
|
|
||||||
|
|
||||||
if type(term_list) in (str, unicode):
|
if type(term_list) in (str, unicode):
|
||||||
term_list = [ term_list ]
|
term_list = [ term_list ]
|
||||||
|
|
||||||
ldap_member = ldap_connection.member_lookup(userid)
|
ldap_member = get(userid)
|
||||||
if ldap_member and 'term' not in ldap_member:
|
if ldap_member and 'term' not in ldap_member:
|
||||||
ldap_member['term'] = []
|
ldap_member['term'] = []
|
||||||
|
|
||||||
|
@ -378,8 +374,8 @@ def register(userid, term_list):
|
||||||
if not term in ldap_member['term']:
|
if not term in ldap_member['term']:
|
||||||
new_member['term'].append(term)
|
new_member['term'].append(term)
|
||||||
|
|
||||||
mlist = ldap_connection.make_modlist(ldap_member, new_member)
|
mlist = ldapi.make_modlist(ldap_member, new_member)
|
||||||
ceo_ldap.modify_s(user_dn, mlist)
|
ld.modify_s(user_dn, mlist)
|
||||||
|
|
||||||
|
|
||||||
def registered(userid, term):
|
def registered(userid, term):
|
||||||
|
@ -396,7 +392,7 @@ def registered(userid, term):
|
||||||
Example: registered("mspang", "f2006") -> True
|
Example: registered("mspang", "f2006") -> True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
member = ldap_connection.member_lookup(userid)
|
member = get(userid)
|
||||||
return 'term' in member and term in member['term']
|
return 'term' in member and term in member['term']
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,7 +402,8 @@ def group_members(group):
|
||||||
Returns a list of group members
|
Returns a list of group members
|
||||||
"""
|
"""
|
||||||
|
|
||||||
group = ldap_connection.group_lookup(group)
|
group = ldapi.lookup(ld, 'cn', group, cfg['groups_base'])
|
||||||
|
|
||||||
if group:
|
if group:
|
||||||
if 'uniqueMember' in group:
|
if 'uniqueMember' in group:
|
||||||
r = re.compile('^uid=([^,]*)')
|
r = re.compile('^uid=([^,]*)')
|
||||||
|
|
Loading…
Reference in New Issue