Initial support for Groups
Create separate object for Users and Groups (using same base class) Check for uniqueness before adding new users and groups Remove user_container from everything but add operations Abstract out a number of functions that are common across users and groups Make sure all strings passed in to be in a filter are checked Add new error message: No modifications specified
This commit is contained in:
1 parent
240a99b6f3
commit
861cda3cb5
16 files changed
+1012
-229
No files matched your search
@@ -0,0 +1,153 @@
|
||||
import ldap
|
||||
import ldif
|
||||
import re
|
||||
import cStringIO
|
||||
|
||||
def utf8_encode_value(value):
|
||||
if isinstance(value,unicode):
|
||||
return value.encode('utf-8')
|
||||
return value
|
||||
|
||||
def utf8_encode_values(values):
|
||||
if isinstance(values,list) or isinstance(values,tuple):
|
||||
return map(utf8_encode_value, values)
|
||||
else:
|
||||
return utf8_encode_value(values)
|
||||
|
||||
class Entity:
|
||||
"""This class represents an IPA user. An LDAP entry consists of a DN
|
||||
and a list of attributes. Each attribute consists of a name and a list of
|
||||
values. For the time being I will maintain this.
|
||||
|
||||
In python-ldap, entries are returned as a list of 2-tuples.
|
||||
Instance variables:
|
||||
dn - string - the string DN of the entry
|
||||
data - cidict - case insensitive dict of the attributes and values
|
||||
orig_data - cidict - case insentiive dict of the original attributes and values"""
|
||||
|
||||
def __init__(self,entrydata=None):
|
||||
"""data is the raw data returned from the python-ldap result method,
|
||||
which is a search result entry or a reference or None.
|
||||
If creating a new empty entry, data is the string DN."""
|
||||
if entrydata:
|
||||
if isinstance(entrydata,tuple):
|
||||
self.dn = entrydata[0]
|
||||
self.data = ldap.cidict.cidict(entrydata[1])
|
||||
elif isinstance(entrydata,str) or isinstance(entrydata,unicode):
|
||||
self.dn = entrydata
|
||||
self.data = ldap.cidict.cidict()
|
||||
elif isinstance(entrydata,dict):
|
||||
self.dn = entrydata['dn']
|
||||
del entrydata['dn']
|
||||
self.data = ldap.cidict.cidict(entrydata)
|
||||
else:
|
||||
self.dn = ''
|
||||
self.data = ldap.cidict.cidict()
|
||||
|
||||
self.orig_data = dict(self.data)
|
||||
|
||||
def __nonzero__(self):
|
||||
"""This allows us to do tests like if entry: returns false if there is no data,
|
||||
true otherwise"""
|
||||
return self.data != None and len(self.data) > 0
|
||||
|
||||
def hasAttr(self,name):
|
||||
"""Return True if this entry has an attribute named name, False otherwise"""
|
||||
return self.data and self.data.has_key(name)
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
"""One should use setValue() or setValues() to set values except for
|
||||
dn and data which are special."""
|
||||
if name != 'dn' and name != 'data' and name != 'orig_data':
|
||||
raise KeyError, 'use setValue() or setValues()'
|
||||
else:
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __getattr__(self,name):
|
||||
"""If name is the name of an LDAP attribute, return the first value for that
|
||||
attribute - equivalent to getValue - this allows the use of
|
||||
entry.cn
|
||||
instead of
|
||||
entry.getValue('cn')
|
||||
This also allows us to return None if an attribute is not found rather than
|
||||
throwing an exception"""
|
||||
return self.getValue(name)
|
||||
|
||||
def getValues(self,name):
|
||||
"""Get the list (array) of values for the attribute named name"""
|
||||
return self.data.get(name)
|
||||
|
||||
def getValue(self,name):
|
||||
"""Get the first value for the attribute named name"""
|
||||
value = self.data.get(name,[None])
|
||||
if isinstance(value,list) or isinstance(value,tuple):
|
||||
return value[0]
|
||||
else:
|
||||
return value
|
||||
|
||||
def setValue(self,name,*value):
|
||||
"""Value passed in may be a single value, several values, or a single sequence.
|
||||
For example:
|
||||
ent.setValue('name', 'value')
|
||||
ent.setValue('name', 'value1', 'value2', ..., 'valueN')
|
||||
ent.setValue('name', ['value1', 'value2', ..., 'valueN'])
|
||||
ent.setValue('name', ('value1', 'value2', ..., 'valueN'))
|
||||
Since *value is a tuple, we may have to extract a list or tuple from that
|
||||
tuple as in the last two examples above"""
|
||||
if (len(value) < 1):
|
||||
return
|
||||
if (len(value) == 1):
|
||||
self.data[name] = utf8_encode_values(value[0])
|
||||
else:
|
||||
self.data[name] = utf8_encode_values(value)
|
||||
|
||||
setValues = setValue
|
||||
|
||||
def toTupleList(self):
|
||||
"""Convert the attrs and values to a list of 2-tuples. The first element
|
||||
of the tuple is the attribute name. The second element is either a
|
||||
single value or a list of values."""
|
||||
return self.data.items()
|
||||
|
||||
def toDict(self):
|
||||
"""Convert the attrs and values to a dict. The dict is keyed on the
|
||||
attribute name. The value is either single value or a list of values."""
|
||||
result = {}
|
||||
for k in self.data.keys():
|
||||
result[k] = self.data[k]
|
||||
result['dn'] = self.dn
|
||||
return result
|
||||
|
||||
def attrList(self):
|
||||
"""Return a list of all attributes in the entry"""
|
||||
return self.data.keys()
|
||||
|
||||
def origDataDict(self):
|
||||
"""Returns a dict of the original values of the user. Used for updates."""
|
||||
result = {}
|
||||
for k in self.orig_data.keys():
|
||||
result[k] = self.orig_data[k]
|
||||
result['dn'] = self.dn
|
||||
return result
|
||||
|
||||
# def __str__(self):
|
||||
# """Convert the Entry to its LDIF representation"""
|
||||
# return self.__repr__()
|
||||
#
|
||||
# # the ldif class base64 encodes some attrs which I would rather see in raw form - to
|
||||
# # encode specific attrs as base64, add them to the list below
|
||||
# ldif.safe_string_re = re.compile('^$')
|
||||
# base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData']
|
||||
#
|
||||
# def __repr__(self):
|
||||
# """Convert the Entry to its LDIF representation"""
|
||||
# sio = cStringIO.StringIO()
|
||||
# # what's all this then? the unparse method will currently only accept
|
||||
# # a list or a dict, not a class derived from them. self.data is a
|
||||
# # cidict, so unparse barfs on it. I've filed a bug against python-ldap,
|
||||
# # but in the meantime, we have to convert to a plain old dict for printing
|
||||
# # I also don't want to see wrapping, so set the line width really high (1000)
|
||||
# newdata = {}
|
||||
# newdata.update(self.data)
|
||||
# ldif.LDIFWriter(sio,User.base64_attrs,1000).unparse(self.dn,newdata)
|
||||
# return sio.getvalue()
|
||||
@@ -0,0 +1,7 @@
|
||||
from ipa.entity import Entity
|
||||
|
||||
class Group(Entity):
|
||||
|
||||
def __init2__(self):
|
||||
pass
|
||||
|
||||
+96
-6
@@ -26,6 +26,7 @@ sys.path.append("/usr/share/ipa")
|
||||
from ipaserver import funcs
|
||||
import ipa.rpcclient as rpcclient
|
||||
import user
|
||||
import group
|
||||
import ipa
|
||||
import config
|
||||
|
||||
@@ -54,20 +55,23 @@ class IPAClient:
|
||||
if self.local:
|
||||
self.transport.set_principal(princ)
|
||||
|
||||
# User support
|
||||
def get_user_by_uid(self,uid,sattrs=None):
|
||||
"""Get a specific user by uid. If sattrs is set then only those
|
||||
attributes will be returned."""
|
||||
attributes will be returned, otherwise all available attributes
|
||||
are returned."""
|
||||
result = self.transport.get_user_by_uid(uid,sattrs)
|
||||
return user.User(result)
|
||||
|
||||
def get_user_by_dn(self,dn,sattrs=None):
|
||||
"""Get a specific user by uid. If sattrs is set then only those
|
||||
attributes will be returned."""
|
||||
"""Get a specific user by dn. If sattrs is set then only those
|
||||
attributes will be returned, otherwise all available attributes
|
||||
are returned."""
|
||||
result = self.transport.get_user_by_dn(dn,sattrs)
|
||||
return user.User(result)
|
||||
|
||||
def add_user(self,user,user_container=None):
|
||||
"""Add a user. user is a ipa.user object"""
|
||||
"""Add a user. user is a ipa.user.User object"""
|
||||
|
||||
realm = config.config.get_realm()
|
||||
|
||||
@@ -97,10 +101,10 @@ class IPAClient:
|
||||
result = self.transport.get_add_schema()
|
||||
return result
|
||||
|
||||
def find_users(self, criteria, sattrs=None, user_container=None):
|
||||
def find_users(self, criteria, sattrs=None):
|
||||
"""Find users whose uid matches the criteria. Wildcards are
|
||||
acceptable. Returns a list of User objects."""
|
||||
result = self.transport.find_users(criteria, sattrs, user_container)
|
||||
result = self.transport.find_users(criteria, sattrs)
|
||||
|
||||
users = []
|
||||
for (attrs) in result:
|
||||
@@ -124,3 +128,89 @@ class IPAClient:
|
||||
|
||||
result = self.transport.mark_user_deleted(uid)
|
||||
return result
|
||||
|
||||
# Groups support
|
||||
|
||||
def get_group_by_cn(self,cn,sattrs=None):
|
||||
"""Get a specific group by cn. If sattrs is set then only those
|
||||
attributes will be returned, otherwise all available attributes
|
||||
are returned."""
|
||||
result = self.transport.get_group_by_cn(cn,sattrs)
|
||||
return group.Group(result)
|
||||
|
||||
def get_group_by_dn(self,dn,sattrs=None):
|
||||
"""Get a specific group by cn. If sattrs is set then only those
|
||||
attributes will be returned, otherwise all available attributes
|
||||
are returned."""
|
||||
result = self.transport.get_group_by_dn(dn,sattrs)
|
||||
return group.Group(result)
|
||||
|
||||
def add_group(self,group,group_container=None):
|
||||
"""Add a group. group is a ipa.group.Group object"""
|
||||
|
||||
realm = config.config.get_realm()
|
||||
|
||||
group_dict = group.toDict()
|
||||
|
||||
# dn is set on the server-side
|
||||
del group_dict['dn']
|
||||
|
||||
# convert to a regular dict before sending
|
||||
result = self.transport.add_group(group_dict, group_container)
|
||||
return result
|
||||
|
||||
def find_groups(self, criteria, sattrs=None):
|
||||
"""Find groups whose cn matches the criteria. Wildcards are
|
||||
acceptable. Returns a list of Group objects."""
|
||||
result = self.transport.find_groups(criteria, sattrs)
|
||||
|
||||
groups = []
|
||||
for (attrs) in result:
|
||||
if attrs is not None:
|
||||
groups.append(group.Group(attrs))
|
||||
|
||||
return groups
|
||||
|
||||
def add_user_to_group(self, user, group):
|
||||
"""Add a user to an existing group.
|
||||
user is a uid of the user to add
|
||||
group is the cn of the group to be added to
|
||||
"""
|
||||
|
||||
return self.transport.add_user_to_group(user, group)
|
||||
|
||||
def add_users_to_group(self, users, group):
|
||||
"""Add several users to an existing group.
|
||||
user is a list of uids of the users to add
|
||||
group is the cn of the group to be added to
|
||||
|
||||
Returns a list of the users that were not added.
|
||||
"""
|
||||
|
||||
return self.transport.add_users_to_group(users, group)
|
||||
|
||||
def remove_user_from_group(self, user, group):
|
||||
"""Remove a user from an existing group.
|
||||
user is a uid of the user to remove
|
||||
group is the cn of the group to be removed from
|
||||
"""
|
||||
|
||||
return self.transport.remove_user_from_group(user, group)
|
||||
|
||||
def remove_users_from_group(self, users, group):
|
||||
"""Remove several users from an existing group.
|
||||
user is a list of uids of the users to remove
|
||||
group is the cn of the group to be removed from
|
||||
|
||||
Returns a list of the users that were not removed.
|
||||
"""
|
||||
|
||||
return self.transport.remove_users_from_group(users, group)
|
||||
|
||||
def update_group(self,group):
|
||||
"""Update a group entry."""
|
||||
|
||||
realm = config.config.get_realm()
|
||||
|
||||
result = self.transport.update_group(group.origDataDict(), group.toDict())
|
||||
return result
|
||||
@@ -115,6 +115,11 @@ LDAP_MISSING_DN = gen_error_code(
|
||||
0x0005,
|
||||
"Entry missing dn")
|
||||
|
||||
LDAP_EMPTY_MODLIST = gen_error_code(
|
||||
LDAP_CATEGORY,
|
||||
0x0006,
|
||||
"No modifications to be performed")
|
||||
|
||||
#
|
||||
# Input errors (sample - replace me)
|
||||
#
|
||||
|
||||
+162
-16
@@ -51,25 +51,28 @@ class RPCClient:
|
||||
def convert_entry(self,ent):
|
||||
# Convert into a dict. We need to handle multi-valued attributes as well
|
||||
# so we'll convert those into lists.
|
||||
user={}
|
||||
obj={}
|
||||
for (k) in ent:
|
||||
k = k.lower()
|
||||
if user.get(k) is not None:
|
||||
if isinstance(user[k],list):
|
||||
user[k].append(ent[k].strip())
|
||||
if obj.get(k) is not None:
|
||||
if isinstance(obj[k],list):
|
||||
obj[k].append(ent[k].strip())
|
||||
else:
|
||||
first = user[k]
|
||||
user[k] = ()
|
||||
user[k].append(first)
|
||||
user[k].append(ent[k].strip())
|
||||
first = obj[k]
|
||||
obj[k] = ()
|
||||
obj[k].append(first)
|
||||
obj[k].append(ent[k].strip())
|
||||
else:
|
||||
user[k] = ent[k]
|
||||
obj[k] = ent[k]
|
||||
|
||||
return user
|
||||
return obj
|
||||
|
||||
# User support
|
||||
|
||||
def get_user_by_uid(self,uid,sattrs=None):
|
||||
"""Get a specific user. If sattrs is not None then only those
|
||||
attributes will be returned. The result is a dict."""
|
||||
attributes will be returned, otherwise all available
|
||||
attributes are returned. The result is a dict."""
|
||||
server = self.setup_server()
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
@@ -84,7 +87,8 @@ class RPCClient:
|
||||
|
||||
def get_user_by_dn(self,dn,sattrs=None):
|
||||
"""Get a specific user. If sattrs is not None then only those
|
||||
attributes will be returned. The result is a dict."""
|
||||
attributes will be returned, otherwise all available
|
||||
attributes are returned. The result is a dict."""
|
||||
server = self.setup_server()
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
@@ -145,7 +149,7 @@ class RPCClient:
|
||||
|
||||
return result
|
||||
|
||||
def find_users (self, criteria, sattrs=None, user_container=None):
|
||||
def find_users (self, criteria, sattrs=None):
|
||||
"""Return a list containing a User object for each user that matches
|
||||
the criteria."""
|
||||
|
||||
@@ -154,9 +158,7 @@ class RPCClient:
|
||||
# None values are not allowed in XML-RPC
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
if user_container is None:
|
||||
user_container = "__NONE__"
|
||||
result = server.find_users(criteria, sattrs, user_container)
|
||||
result = server.find_users(criteria, sattrs)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
@@ -189,3 +191,147 @@ class RPCClient:
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
# Group support
|
||||
|
||||
def get_group_by_cn(self,cn,sattrs=None):
|
||||
"""Get a specific group. If sattrs is not None then only those
|
||||
attributes will be returned, otherwise all available
|
||||
attributes are returned. The result is a dict."""
|
||||
server = self.setup_server()
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
try:
|
||||
result = server.get_group_by_cn(cn, sattrs)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def get_group_by_dn(self,dn,sattrs=None):
|
||||
"""Get a specific group. If sattrs is not None then only those
|
||||
attributes will be returned, otherwise all available
|
||||
attributes are returned. The result is a dict."""
|
||||
server = self.setup_server()
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
try:
|
||||
result = server.get_group_by_dn(dn, sattrs)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def add_group(self,group,group_container=None):
|
||||
"""Add a new group. Takes as input a dict where the key is the
|
||||
attribute name and the value is either a string or in the case
|
||||
of a multi-valued field a list of values"""
|
||||
server = self.setup_server()
|
||||
|
||||
if group_container is None:
|
||||
group_container = "__NONE__"
|
||||
|
||||
try:
|
||||
result = server.add_group(group, group_container)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
def find_groups (self, criteria, sattrs=None):
|
||||
"""Return a list containing a Group object for each group that matches
|
||||
the criteria."""
|
||||
|
||||
server = self.setup_server()
|
||||
try:
|
||||
# None values are not allowed in XML-RPC
|
||||
if sattrs is None:
|
||||
sattrs = "__NONE__"
|
||||
result = server.find_groups(criteria, sattrs)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def add_user_to_group(self, user, group):
|
||||
"""Add a user to an existing group.
|
||||
user is a uid of the user to add
|
||||
group is the cn of the group to be added to
|
||||
"""
|
||||
server = self.setup_server()
|
||||
try:
|
||||
result = server.add_user_to_group(user, group)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def add_users_to_group(self, users, group):
|
||||
"""Add several users to an existing group.
|
||||
user is a list of the uids of the users to add
|
||||
group is the cn of the group to be added to
|
||||
|
||||
Returns a list of the users that were not added.
|
||||
"""
|
||||
server = self.setup_server()
|
||||
try:
|
||||
result = server.add_users_to_group(users, group)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def remove_user_from_group(self, user, group):
|
||||
"""Remove a user from an existing group.
|
||||
user is a uid of the user to remove
|
||||
group is the cn of the group to be removed from
|
||||
"""
|
||||
server = self.setup_server()
|
||||
try:
|
||||
result = server.remove_user_from_group(user, group)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def remove_users_from_group(self, users, group):
|
||||
"""Remove several users from an existing group.
|
||||
user is a list of the uids of the users to remove
|
||||
group is the cn of the group to be removed from
|
||||
|
||||
Returns a list of the users that were not removed.
|
||||
"""
|
||||
server = self.setup_server()
|
||||
try:
|
||||
result = server.remove_users_from_group(users, group)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
|
||||
def update_group(self,oldgroup,newgroup):
|
||||
"""Update an existing group. oldgroup and newgroup are dicts of attributes"""
|
||||
server = self.setup_server()
|
||||
|
||||
try:
|
||||
result = server.update_group(oldgroup, newgroup)
|
||||
except xmlrpclib.Fault, fault:
|
||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||
except socket.error, (value, msg):
|
||||
raise xmlrpclib.Fault(value, msg)
|
||||
|
||||
return result
|
||||
+5
-151
@@ -1,153 +1,7 @@
|
||||
import ldap
|
||||
import ldif
|
||||
import re
|
||||
import cStringIO
|
||||
from ipa.entity import Entity
|
||||
|
||||
def utf8_encode_value(value):
|
||||
if isinstance(value,unicode):
|
||||
return value.encode('utf-8')
|
||||
return value
|
||||
class User(Entity):
|
||||
|
||||
def utf8_encode_values(values):
|
||||
if isinstance(values,list) or isinstance(values,tuple):
|
||||
return map(utf8_encode_value, values)
|
||||
else:
|
||||
return utf8_encode_value(values)
|
||||
|
||||
class User:
|
||||
"""This class represents an IPA user. An LDAP entry consists of a DN
|
||||
and a list of attributes. Each attribute consists of a name and a list of
|
||||
values. For the time being I will maintain this.
|
||||
|
||||
In python-ldap, entries are returned as a list of 2-tuples.
|
||||
Instance variables:
|
||||
dn - string - the string DN of the entry
|
||||
data - cidict - case insensitive dict of the attributes and values
|
||||
orig_data - cidict - case insentiive dict of the original attributes and values"""
|
||||
|
||||
def __init__(self,entrydata=None):
|
||||
"""data is the raw data returned from the python-ldap result method,
|
||||
which is a search result entry or a reference or None.
|
||||
If creating a new empty entry, data is the string DN."""
|
||||
if entrydata:
|
||||
if isinstance(entrydata,tuple):
|
||||
self.dn = entrydata[0]
|
||||
self.data = ldap.cidict.cidict(entrydata[1])
|
||||
elif isinstance(entrydata,str) or isinstance(entrydata,unicode):
|
||||
self.dn = entrydata
|
||||
self.data = ldap.cidict.cidict()
|
||||
elif isinstance(entrydata,dict):
|
||||
self.dn = entrydata['dn']
|
||||
del entrydata['dn']
|
||||
self.data = ldap.cidict.cidict(entrydata)
|
||||
else:
|
||||
self.dn = ''
|
||||
self.data = ldap.cidict.cidict()
|
||||
|
||||
self.orig_data = dict(self.data)
|
||||
|
||||
def __nonzero__(self):
|
||||
"""This allows us to do tests like if entry: returns false if there is no data,
|
||||
true otherwise"""
|
||||
return self.data != None and len(self.data) > 0
|
||||
|
||||
def hasAttr(self,name):
|
||||
"""Return True if this entry has an attribute named name, False otherwise"""
|
||||
return self.data and self.data.has_key(name)
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
"""One should use setValue() or setValues() to set values except for
|
||||
dn and data which are special."""
|
||||
if name != 'dn' and name != 'data' and name != 'orig_data':
|
||||
raise KeyError, 'use setValue() or setValues()'
|
||||
else:
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __getattr__(self,name):
|
||||
"""If name is the name of an LDAP attribute, return the first value for that
|
||||
attribute - equivalent to getValue - this allows the use of
|
||||
entry.cn
|
||||
instead of
|
||||
entry.getValue('cn')
|
||||
This also allows us to return None if an attribute is not found rather than
|
||||
throwing an exception"""
|
||||
return self.getValue(name)
|
||||
|
||||
def getValues(self,name):
|
||||
"""Get the list (array) of values for the attribute named name"""
|
||||
return self.data.get(name)
|
||||
|
||||
def getValue(self,name):
|
||||
"""Get the first value for the attribute named name"""
|
||||
value = self.data.get(name,[None])
|
||||
if isinstance(value,list) or isinstance(value,tuple):
|
||||
return value[0]
|
||||
else:
|
||||
return value
|
||||
|
||||
def setValue(self,name,*value):
|
||||
"""Value passed in may be a single value, several values, or a single sequence.
|
||||
For example:
|
||||
ent.setValue('name', 'value')
|
||||
ent.setValue('name', 'value1', 'value2', ..., 'valueN')
|
||||
ent.setValue('name', ['value1', 'value2', ..., 'valueN'])
|
||||
ent.setValue('name', ('value1', 'value2', ..., 'valueN'))
|
||||
Since *value is a tuple, we may have to extract a list or tuple from that
|
||||
tuple as in the last two examples above"""
|
||||
if (len(value) < 1):
|
||||
return
|
||||
if (len(value) == 1):
|
||||
self.data[name] = utf8_encode_values(value[0])
|
||||
else:
|
||||
self.data[name] = utf8_encode_values(value)
|
||||
|
||||
setValues = setValue
|
||||
|
||||
def toTupleList(self):
|
||||
"""Convert the attrs and values to a list of 2-tuples. The first element
|
||||
of the tuple is the attribute name. The second element is either a
|
||||
single value or a list of values."""
|
||||
return self.data.items()
|
||||
|
||||
def toDict(self):
|
||||
"""Convert the attrs and values to a dict. The dict is keyed on the
|
||||
attribute name. The value is either single value or a list of values."""
|
||||
result = {}
|
||||
for k in self.data.keys():
|
||||
result[k] = self.data[k]
|
||||
result['dn'] = self.dn
|
||||
return result
|
||||
|
||||
def attrList(self):
|
||||
"""Return a list of all attributes in the entry"""
|
||||
return self.data.keys()
|
||||
|
||||
def origDataDict(self):
|
||||
"""Returns a dict of the original values of the user. Used for updates."""
|
||||
result = {}
|
||||
for k in self.orig_data.keys():
|
||||
result[k] = self.orig_data[k]
|
||||
result['dn'] = self.dn
|
||||
return result
|
||||
|
||||
# def __str__(self):
|
||||
# """Convert the Entry to its LDIF representation"""
|
||||
# return self.__repr__()
|
||||
#
|
||||
# # the ldif class base64 encodes some attrs which I would rather see in raw form - to
|
||||
# # encode specific attrs as base64, add them to the list below
|
||||
# ldif.safe_string_re = re.compile('^$')
|
||||
# base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData']
|
||||
#
|
||||
# def __repr__(self):
|
||||
# """Convert the Entry to its LDIF representation"""
|
||||
# sio = cStringIO.StringIO()
|
||||
# # what's all this then? the unparse method will currently only accept
|
||||
# # a list or a dict, not a class derived from them. self.data is a
|
||||
# # cidict, so unparse barfs on it. I've filed a bug against python-ldap,
|
||||
# # but in the meantime, we have to convert to a plain old dict for printing
|
||||
# # I also don't want to see wrapping, so set the line width really high (1000)
|
||||
# newdata = {}
|
||||
# newdata.update(self.data)
|
||||
# ldif.LDIFWriter(sio,User.base64_attrs,1000).unparse(self.dn,newdata)
|
||||
# return sio.getvalue()
|
||||
def __init2__(self):
|
||||
pass
|
||||
|
||||
Reference in new issue
Block a user