[lc_ldap, attributs] les Attr contiennent aussi les valeurs

This commit is contained in:
Antoine Durand-Gasselin 2010-10-16 15:23:25 +02:00
parent 5f3c3d56fb
commit 85c513a1aa
2 changed files with 95 additions and 58 deletions

View file

@ -50,21 +50,39 @@ def validate_mac(value):
"""Vérifie qu'une adresse mac est valide""" """Vérifie qu'une adresse mac est valide"""
return True 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" legend = "Human-readable description of attribute"
singlevalue = None singlevalue = None
optional = None optional = None
def __init__(self): def __init__(self, val, ldif):
pass assert isinstance(val, unicode)
self.parse_value(val)
self.validate(ldif)
def validate(self, values, uldif): def parse_value(self, val):
"validates" self.value = val
self._check_cardinality(values)
self._check_type(values) def __str__(self):
self._check_uniqueness(values) unicode.encode(unicode(self), 'utf-8')
self._check_values(values)
self._check_users_restrictions(values) 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): def normalize(self, values, uldif):
"normalizes" "normalizes"
@ -271,31 +289,31 @@ class historique(Attr):
CRANS_ATTRIBUTES= { CRANS_ATTRIBUTES= {
'objectClass' : objectClass(), 'objectClass' : objectClass,
'nom' : nom(), 'nom' : nom,
'prenom' : prenom(), 'prenom' : prenom,
'tel' : tel(), 'tel' : tel,
'paiement' : paiement(), 'paiement' : paiement,
'carteEtudiant' : carteEtudiant(), 'carteEtudiant' : carteEtudiant,
'mailAlias' : mailAlias(), 'mailAlias' : mailAlias,
'canonicalAlias' : canonicalAlias(), 'canonicalAlias' : canonicalAlias,
'etudes' : etudes(), 'etudes' : etudes,
'chbre' : chbre(), 'chbre' : chbre,
'droits' : droits(), 'droits' : droits,
'solde' : solde(), 'solde' : solde,
'mid' : mid(), 'mid' : mid,
'hostAlias' : hostAlias(), 'hostAlias' : hostAlias,
'ipsec' : ipsec(), 'ipsec' : ipsec,
'puissance' : puissance(), 'puissance' : puissance,
'canal' : canal(), 'canal' : canal,
'portTCPout' : portTCPout(), 'portTCPout' : portTCPout,
'portTCPin' : portTCPin(), 'portTCPin' : portTCPin,
'portUDPout' : portUDPout(), 'portUDPout' : portUDPout,
'portUDPin' : portUDPin(), 'portUDPin' : portUDPin,
'prise' : prise(), 'prise' : prise,
'cid' : cid(), 'cid' : cid,
'responsable' : responsable(), 'responsable' : responsable,
'blacklist' : blacklist(), 'blacklist' : blacklist,
'historique' : historique() 'historique' : historique
} }

View file

@ -35,7 +35,8 @@ import os, sys, ldap, re, netaddr, datetime, copy, time
from ldap.modlist import addModlist, modifyModlist from ldap.modlist import addModlist, modifyModlist
sys.path.append('/usr/scripts/gestion') sys.path.append('/usr/scripts/gestion')
import config, crans_utils, attributs import config, crans_utils
from attributs import attrify
from ldap_locks import CransLock from ldap_locks import CransLock
uri = 'ldapi:///' #'ldap://ldap.adm.crans.org/' uri = 'ldapi:///' #'ldap://ldap.adm.crans.org/'
@ -55,6 +56,7 @@ def is_actif(sanction):
return debut < now and fin > now return debut < now and fin > now
def uldif_to_ldif(uldif): def uldif_to_ldif(uldif):
## XXX - Kill
"""Prend en argument un dico ldif, et vérifie que toutes les """Prend en argument un dico ldif, et vérifie que toutes les
valeurs sont bien des unicodes, les converti alors en chaînes valeurs sont bien des unicodes, les converti alors en chaînes
utf-8, renvoie un ldif""" utf-8, renvoie un ldif"""
@ -64,12 +66,26 @@ def uldif_to_ldif(uldif):
return ldif return ldif
def ldif_to_uldif(ldif): def ldif_to_uldif(ldif):
## XXX - Kill
'Prend en argument un dico ldif, et décode toutes les chaînes en utf-8' 'Prend en argument un dico ldif, et décode toutes les chaînes en utf-8'
uldif = {} uldif = {}
for attr, vals in ldif.items(): for attr, vals in ldif.items():
uldif[attr] = [ unicode(val, 'utf-8') for val in vals ] uldif[attr] = [ unicode(val, 'utf-8') for val in vals ]
return uldif 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(): def lc_ldap_test():
return lc_ldap(dn='cn=admin,dc=crans,dc=org', cred='75bdb64f32') 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""" """Crée une nouvelle facture"""
raise NotImplementedError() 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: '''Crée une nouvelle entité ldap en dn, avec attributs ldif:
uniquement en unicode''' uniquement en unicode'''
nuldif = {} cldif = ldif_to_cldif(ldif)
for attr, vals in uldif.items() :
nuldif[attr] = attributs.normalize_and_validate(attr, vals, uldif)
#lock = CransLock(self) #lock = CransLock(self)
for item in ['aid', 'uid', 'chbre', 'mailAlias', 'canonicalAlias', for item in ['aid', 'uid', 'chbre', 'mailAlias', 'canonicalAlias',
'fid', 'cid', 'mid', 'macAddress', 'host', 'hostAlias' ]: 'fid', 'cid', 'mid', 'macAddress', 'host', 'hostAlias' ]:
for val in nuldif.get(item, []): for val in cldif.get(item, []):
pass #lock.add(item, val) pass #lock.add(item, val)
#uldif['historique'] = [ self._hist('Création')] #uldif['historique'] = [ self._hist('Création')]
ldif = uldif_to_ldif(nuldif) ldif = cldif_to_ldif(cldif)
modlist = addModlist(ldif) modlist = addModlist(ldif)
#with lock: #with lock:
# print dn, modlist # print dn, modlist
@ -243,20 +257,21 @@ class CransLdapObject:
if not res: if not res:
raise ValueError ('objet inexistant: %s' % dn) raise ValueError ('objet inexistant: %s' % dn)
self.dn, self.attrs = res[0] 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.__class__ = eval(self.attrs['objectClass'][0])
# self._modifs = copy.deepcopy(self.attrs) # self._modifs = copy.deepcopy(self.attrs)
def save(self): def save(self):
"Vérifie que self._modifs contient des valeurs correctes et enregistre les modifications" "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") raise EnvironmentError(u"Objet en lecture seule, réessayer en lecture/écriture")
# Vérifications et Historique # Vérifications et Historique
#histo = self._gen_hist(self._modifs) #histo = self._gen_hist(self._modifs)
#self._modifs['historique'] += histo #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 # On récupère la liste des modifications
modlist = self.get_modlist() modlist = self.get_modlist()
@ -270,8 +285,8 @@ class CransLdapObject:
def get_modlist(self): def get_modlist(self):
"""Renvoie le dico des modifs""" """Renvoie le dico des modifs"""
# unicode -> utf-8 # unicode -> utf-8
ldif = uldif_to_ldif(self._modifs) ldif = cldif_to_ldif(self._modifs)
orig_ldif = uldif_to_ldif(self.attrs) orig_ldif = cldif_to_ldif(self.attrs)
return modifyModlist(orig_ldif, ldif) return modifyModlist(orig_ldif, ldif)
@ -286,16 +301,21 @@ class CransLdapObject:
def set_ldapattr(self, attr, new_vals): def set_ldapattr(self, attr, new_vals):
"""Définit les nouvelles valeurs d'un attribut""" """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): if not isinstance(new_vals, list):
new_vals = [new_vals] new_vals = [new_vals]
for val in new_vals: assert isinstance(val, unicode)
# On vérifie les nouvelles valeurs données à l'attribut # On attrify
new_vals = attributs.normalize_and_validate(attr, new_vals, self._modifs) new_vals = [ attrify(val, attr, self._modifs) for val in new_vals ]
# XXX - Manque un sanity check
# Si ça passe, on effectue les modifications # Si ça passe, on effectue les modifications
old_vals = [ unicode.encode(val, 'utf-8') for val in self.attrs.get(attr, []) ] old_vals = [ str(val) for val in self.attrs.get(attr, []) ]
new_vals = [ unicode.encode(val, 'utf-8') for val in new_vals ] new_vals = [ str(val) for val in new_vals ]
modlist = modifyModlist({attr : old_vals}, {attr : new_vals}) modlist = modifyModlist({attr : old_vals}, {attr : new_vals})
self.conn.modify_s(self.dn, modlist) self.conn.modify_s(self.dn, modlist)
@ -303,10 +323,10 @@ class CransLdapObject:
"""Modifie l'attribut attr ayant la valeur oldVal en newVal. Si """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 l'attribut attr n'a qu'une seule valeur, il n'est pas nécessaire
de préciser oldVal.""" de préciser oldVal."""
assert isinstance(new_val, unicode) new_val = attrify(new_val, attr, self._modifs)
new_vals = self.attrs.get(attr, [])[:] new_vals = self.attrs.get(attr, [])[:]
if old_val: # and oldVal in attrs: 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) new_vals.append(new_val)
elif len(new_vals) == 1: elif len(new_vals) == 1:
new_vals = [ new_val ] new_vals = [ new_val ]
@ -317,12 +337,11 @@ class CransLdapObject:
def del_ldapattr(self, attr, val): def del_ldapattr(self, attr, val):
"""Supprime la valeur val de l'attribut attr""" """Supprime la valeur val de l'attribut attr"""
new_vals = self.attrs.get(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) return self.set_ldapattr(attr, new_vals)
def add_ldapattr(self, attr, new_val): def add_ldapattr(self, attr, new_val):
"""Rajoute la valeur val à l'attribut attr""" """Rajoute la valeur val à l'attribut attr"""
assert isinstance(new_val, unicode)
new_vals = self.attrs.get(attr, [])[:] new_vals = self.attrs.get(attr, [])[:]
new_vals.append(new_val) new_vals.append(new_val)
return self.set_ldapattr(attr, new_vals) return self.set_ldapattr(attr, new_vals)