From 861cda3cb5256a177845029ddf1900f51271b56c Mon Sep 17 00:00:00 2001 From: "rcritten@redhat.com" Date: Fri, 24 Aug 2007 15:42:56 -0400 Subject: 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 --- ipa-python/entity.py | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 ipa-python/entity.py (limited to 'ipa-python/entity.py') diff --git a/ipa-python/entity.py b/ipa-python/entity.py new file mode 100644 index 000000000..9153c4159 --- /dev/null +++ b/ipa-python/entity.py @@ -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() -- cgit