[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"""
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
}

View file

@ -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)