From 85c513a1aa5d9e92c69d6f20aca98dd3f7b35f2d Mon Sep 17 00:00:00 2001 From: Antoine Durand-Gasselin Date: Sat, 16 Oct 2010 15:23:25 +0200 Subject: [PATCH] [lc_ldap, attributs] les Attr contiennent aussi les valeurs --- attributs.py | 90 +++++++++++++++++++++++++++++++--------------------- lc_ldap.py | 63 +++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 58 deletions(-) diff --git a/attributs.py b/attributs.py index 83eddd3..17c08b3 100644 --- a/attributs.py +++ b/attributs.py @@ -50,21 +50,39 @@ def validate_mac(value): """Vérifie qu'une adresse mac est valide""" return True -class Attr: +def attrify(val, attr, ldif, ctxt_check = True): + """Transforme un n'importe quoi en Attr. + + Doit effectuer les normalisations et sanity check si un str ou un + unicode est passé en argument. + Devrait insulter en cas de potentiel problème d'encodage. + Doit effectuer les vérifications de contexte dans le *ldif* si + ctxt_check est vrai""" + + return val if isinstance(val, Attr) else CRANS_ATTRIBUTES[attr](val, ldif) + +class Attr(object): legend = "Human-readable description of attribute" singlevalue = None optional = None - def __init__(self): - pass + def __init__(self, val, ldif): + assert isinstance(val, unicode) + self.parse_value(val) + self.validate(ldif) - def validate(self, values, uldif): - "validates" - self._check_cardinality(values) - self._check_type(values) - self._check_uniqueness(values) - self._check_values(values) - self._check_users_restrictions(values) + def parse_value(self, val): + self.value = val + + def __str__(self): + unicode.encode(unicode(self), 'utf-8') + + def validate(self, ldif): + """validates: + vérifie déjà que ce qu'on a rentré est parsable""" + self._check_cardinality(ldif) + self._check_uniqueness(ldif) + self._check_users_restrictions(ldif) def normalize(self, values, uldif): "normalizes" @@ -271,31 +289,31 @@ class historique(Attr): CRANS_ATTRIBUTES= { -'objectClass' : objectClass(), -'nom' : nom(), -'prenom' : prenom(), -'tel' : tel(), -'paiement' : paiement(), -'carteEtudiant' : carteEtudiant(), -'mailAlias' : mailAlias(), -'canonicalAlias' : canonicalAlias(), -'etudes' : etudes(), -'chbre' : chbre(), -'droits' : droits(), -'solde' : solde(), -'mid' : mid(), -'hostAlias' : hostAlias(), -'ipsec' : ipsec(), -'puissance' : puissance(), -'canal' : canal(), -'portTCPout' : portTCPout(), -'portTCPin' : portTCPin(), -'portUDPout' : portUDPout(), -'portUDPin' : portUDPin(), -'prise' : prise(), -'cid' : cid(), -'responsable' : responsable(), -'blacklist' : blacklist(), -'historique' : historique() +'objectClass' : objectClass, +'nom' : nom, +'prenom' : prenom, +'tel' : tel, +'paiement' : paiement, +'carteEtudiant' : carteEtudiant, +'mailAlias' : mailAlias, +'canonicalAlias' : canonicalAlias, +'etudes' : etudes, +'chbre' : chbre, +'droits' : droits, +'solde' : solde, +'mid' : mid, +'hostAlias' : hostAlias, +'ipsec' : ipsec, +'puissance' : puissance, +'canal' : canal, +'portTCPout' : portTCPout, +'portTCPin' : portTCPin, +'portUDPout' : portUDPout, +'portUDPin' : portUDPin, +'prise' : prise, +'cid' : cid, +'responsable' : responsable, +'blacklist' : blacklist, +'historique' : historique } diff --git a/lc_ldap.py b/lc_ldap.py index a21f020..8df904e 100644 --- a/lc_ldap.py +++ b/lc_ldap.py @@ -35,7 +35,8 @@ import os, sys, ldap, re, netaddr, datetime, copy, time from ldap.modlist import addModlist, modifyModlist sys.path.append('/usr/scripts/gestion') -import config, crans_utils, attributs +import config, crans_utils +from attributs import attrify from ldap_locks import CransLock uri = 'ldapi:///' #'ldap://ldap.adm.crans.org/' @@ -55,6 +56,7 @@ def is_actif(sanction): return debut < now and fin > now def uldif_to_ldif(uldif): + ## XXX - Kill """Prend en argument un dico ldif, et vérifie que toutes les valeurs sont bien des unicodes, les converti alors en chaînes utf-8, renvoie un ldif""" @@ -64,12 +66,26 @@ def uldif_to_ldif(uldif): return ldif def ldif_to_uldif(ldif): + ## XXX - Kill 'Prend en argument un dico ldif, et décode toutes les chaînes en utf-8' uldif = {} for attr, vals in ldif.items(): uldif[attr] = [ unicode(val, 'utf-8') for val in vals ] return uldif +def ldif_to_cldif(ldif): + cldif = {} + for attr, vals in ldif.items(): + cldif[attr] = [ attrify(val, attr, ldif) for val in vals] + return cldif + +def cldif_to_ldif(cldif): + ldif = {} + for attr, vals in cldif.items(): + ldif[attr] = [ str(attr) for attr in vals ] + return ldif + + def lc_ldap_test(): return lc_ldap(dn='cn=admin,dc=crans,dc=org', cred='75bdb64f32') @@ -168,19 +184,17 @@ class lc_ldap(ldap.ldapobject.LDAPObject): """Crée une nouvelle facture""" raise NotImplementedError() - def _create_entity(self, dn, uldif): + def _create_entity(self, dn, ldif): '''Crée une nouvelle entité ldap en dn, avec attributs ldif: uniquement en unicode''' - nuldif = {} - for attr, vals in uldif.items() : - nuldif[attr] = attributs.normalize_and_validate(attr, vals, uldif) + cldif = ldif_to_cldif(ldif) #lock = CransLock(self) for item in ['aid', 'uid', 'chbre', 'mailAlias', 'canonicalAlias', 'fid', 'cid', 'mid', 'macAddress', 'host', 'hostAlias' ]: - for val in nuldif.get(item, []): + for val in cldif.get(item, []): pass #lock.add(item, val) #uldif['historique'] = [ self._hist('Création')] - ldif = uldif_to_ldif(nuldif) + ldif = cldif_to_ldif(cldif) modlist = addModlist(ldif) #with lock: # print dn, modlist @@ -243,20 +257,21 @@ class CransLdapObject: if not res: raise ValueError ('objet inexistant: %s' % dn) self.dn, self.attrs = res[0] - self.attrs = ldif_to_uldif(self.attrs) + if mode in ['w', 'rw']: + self.attrs = ldif_to_cldif(self.attrs) + else: + self.attrs = ldif_to_uldif(self.attrs) self.__class__ = eval(self.attrs['objectClass'][0]) # self._modifs = copy.deepcopy(self.attrs) def save(self): "Vérifie que self._modifs contient des valeurs correctes et enregistre les modifications" - if self.mode != 'w': + if self.mode not in ['w', 'rw']: raise EnvironmentError(u"Objet en lecture seule, réessayer en lecture/écriture") # Vérifications et Historique #histo = self._gen_hist(self._modifs) #self._modifs['historique'] += histo - for attr, vals in self._modifs.items: - self._modifs[attr] = attributs.normalize_and_validate(attr, vals, self._modifs) # On récupère la liste des modifications modlist = self.get_modlist() @@ -270,8 +285,8 @@ class CransLdapObject: def get_modlist(self): """Renvoie le dico des modifs""" # unicode -> utf-8 - ldif = uldif_to_ldif(self._modifs) - orig_ldif = uldif_to_ldif(self.attrs) + ldif = cldif_to_ldif(self._modifs) + orig_ldif = cldif_to_ldif(self.attrs) return modifyModlist(orig_ldif, ldif) @@ -286,16 +301,21 @@ class CransLdapObject: def set_ldapattr(self, attr, new_vals): """Définit les nouvelles valeurs d'un attribut""" + + if self.mode not in ['w', 'rw']: + raise EnvironmentError(u"Objet en lecture seule, réessayer en lecture/écriture") + if not isinstance(new_vals, list): new_vals = [new_vals] - for val in new_vals: assert isinstance(val, unicode) - # On vérifie les nouvelles valeurs données à l'attribut - new_vals = attributs.normalize_and_validate(attr, new_vals, self._modifs) + # On attrify + new_vals = [ attrify(val, attr, self._modifs) for val in new_vals ] + + # XXX - Manque un sanity check # Si ça passe, on effectue les modifications - old_vals = [ unicode.encode(val, 'utf-8') for val in self.attrs.get(attr, []) ] - new_vals = [ unicode.encode(val, 'utf-8') for val in new_vals ] + old_vals = [ str(val) for val in self.attrs.get(attr, []) ] + new_vals = [ str(val) for val in new_vals ] modlist = modifyModlist({attr : old_vals}, {attr : new_vals}) self.conn.modify_s(self.dn, modlist) @@ -303,10 +323,10 @@ class CransLdapObject: """Modifie l'attribut attr ayant la valeur oldVal en newVal. Si l'attribut attr n'a qu'une seule valeur, il n'est pas nécessaire de préciser oldVal.""" - assert isinstance(new_val, unicode) + new_val = attrify(new_val, attr, self._modifs) new_vals = self.attrs.get(attr, [])[:] if old_val: # and oldVal in attrs: - new_vals.remove(old_val) + new_vals = [ val for val in new_vals if str(val) != str(old_val) ] new_vals.append(new_val) elif len(new_vals) == 1: new_vals = [ new_val ] @@ -317,12 +337,11 @@ class CransLdapObject: def del_ldapattr(self, attr, val): """Supprime la valeur val de l'attribut attr""" new_vals = self.attrs.get(attr, [])[:] - new_vals.remove(val) + new_vals = [ v for v in new_vals if str(v) != str(val) ] return self.set_ldapattr(attr, new_vals) def add_ldapattr(self, attr, new_val): """Rajoute la valeur val à l'attribut attr""" - assert isinstance(new_val, unicode) new_vals = self.attrs.get(attr, [])[:] new_vals.append(new_val) return self.set_ldapattr(attr, new_vals)