[lc_ldap,attributs] nettoyage bl & set_ldapattr

This commit is contained in:
Antoine Durand-Gasselin 2010-11-11 17:49:07 +01:00
parent 222a2a9a4d
commit adfa070db5
2 changed files with 29 additions and 201 deletions

View file

@ -47,20 +47,6 @@ log_dn = "cn=log"
# Champs à ignorer dans l'historique
HIST_IGNORE_FIELDS = ["modifiersName", "entryCSN", "modifyTimestamp"]
def is_actif(sanction):
"""Retourne True ou False suivant si la sanction fournie (chaîne
venant de blacklist) est active ou non.
La blacklist est de la forme "debut$fin$..."
"""
bl_debut, bl_fin, _ = sanction.split('$', 3)
now = time.time()
debut = int(bl_debut)
if bl_fin == '-':
fin = now + 1
else:
fin = int(bl_fin)
return debut < now and fin > now
def ldif_to_uldif(ldif):
uldif = {}
for attr, vals in ldif.items():
@ -325,100 +311,23 @@ class CransLdapObject(object):
return modifyModlist(orig_ldif, ldif)
def get_values(self, attr):
"""Renvoie les valeurs d'un attribut ldap de l'objet self"""
attrs = self.attrs.get(attr, [])
return attrs
def get(self, attr, default):
try:
return self[attr]
except KeyError:
return default
def get_value(self, attr):
"""Renvoie la première valeur d'un attribut ldap de l'objet self"""
return self.get_values(attr)[0]
def set_ldapattr(self, attr, new_vals):
"""Définit les nouvelles valeurs d'un attribut"""
if self.mode not in ['w', 'rw']:
raise EnvironmentError("Objet en lecture seule, réessayer en lecture/écriture")
if not isinstance(new_vals, list):
new_vals = [new_vals]
# On attrify
cldif = self.attrs.copy()
cldif[attr] = new_vals
new_vals = [ attrify(val, attr, cldif, self.conn) for val in new_vals ]
# Si ça passe, on effectue les modifications
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)
def mod_ldapattr(self, attr, new_val, old_val = None):
"""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."""
new_vals = self.attrs.get(attr, [])[:]
if old_val: # and oldVal in attrs:
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 ]
def __getitem__(self, attr):
if self.mode in [ 'w', 'rw' ]:
return [ unicode(v) for v in self._modifs[attr] ]
else:
raise ValueError("%s has multiple values, must specify old_val")
return self.set_ldapattr(attr, new_vals)
return [ unicode(v) for v in self.attrs[attr] ]
def del_ldapattr(self, attr, val):
"""Supprime la valeur val de l'attribut attr"""
new_vals = self.attrs.get(attr, [])[:]
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"""
new_vals = self.attrs.get(attr, [])[:]
new_vals.append(new_val)
return self.set_ldapattr(attr, new_vals)
def _gen_hist(self, modifs):
# XXX - Kill it! l'historique devrait être généré par ldap
"""Genère l'historique des modifications apportées. Cette
fonction n'est là que pour de la rétro-compatibilité,
normalement les modifications sont automatiquement loggées."""
histo = []
for field in self.ofields:
if modifs.get(field, []) != self.attrs.get(field, []):
if modifs.get(field, []) == []:
msg = u"[%s] %s -> RESET" % (field, self.attrs[field][0])
elif self.attrs.get(field, []) == []:
msg = u"[%s] := %s" % (field, modifs[field][0])
else:
msg = u"[%s] %s -> %s" % (field, self.attrs[field][0], modifs[field][0])
histo.append(self.conn._hist(msg))
for field in self.xfields + self.ufields:
if modifs.get(field, []) != self.attrs.get(field, []):
msg = u"[%s] %s -> %s" % (field, u'; '.join(self.attrs[field]), u'; '.join(modifs[field]))
histo.append(self.conn._hist(msg))
for field in self.mfields:
oldvals = self.attrs.get(field, [])
newvals = modifs.get(field, [])
olds = set(oldvals)
news = set(newvals)
if oldvals == newvals:
continue
elif olds != news:
adds = ''.join([ '+' + val for val in news - olds])
diff = ''.join([ '-' + val for val in olds - news])
msg = u'[%s]%s%s' % ( field, adds, diff)
elif olds == news and len(oldvals) == len(newvals) == len(olds):
msg = u"[%s].shuffle()" % field
else:
raise ValueError("Les valeurs pour %s : %s -> %s ne semblent pas différentes" % (field, oldvals, newvals))
histo.append(self.conn._hist(msg))
return histo
def __setitem__(self, attr, values):
if not isinstance(values, list):
values = [ values ]
self._modifs[attr] = values
self._modifs[attr] = [ attrify(val, attr, self._modifs, self.conn) for val in values ]
def search_historique(self, ign_fields=HIST_IGNORE_FIELDS):
u"""Récupère l'historique
@ -445,114 +354,26 @@ class CransLdapObject(object):
for field in fields:
mods = fields[field]
mod_list.append("%s %s" %(field, ", ".join(mods)))
if mod_list != []:
out.append("%s : [%s] %s" % (date, attrs['reqAuthzID'][0], " ; ".join(mod_list)))
return out
def blacklist_actif(self):
u"""Vérifie si l'instance courante est blacklistée.
Retourne les sanctions en cours (liste).
Retourne une liste vide si aucune sanction en cours.
"""
return self.blacklist_all()[0].keys()
def blacklist_all(self):
u"""Vérifie si l'instance courante est blacklistée ou a été
blacklistée. Retourne les sanctions en cours sous la forme
d'un couple de deux dictionnaires (l'un pour les sanctions
actives, l'autre pour les inactive), chacun ayant comme
clef la sanction et comme valeur une liste de couple de
dates (en secondes depuis epoch) correspondant aux
différentes périodes de sanctions.
ex: {'upload': [(1143336210, 1143509010), ...]}
"""
bl_liste = self.attrs.get('blacklist', [])
if isinstance(self, machine): # Blist du propriétaire
bl_liste += proprio().blacklist()
actifs = {}; inactifs = {}
for sanction in bl_liste:
f = sanction.split('$')
if is_actif(sanction):
actifs.setdefault(f[2], []).append((f[0], f[1]))
else:
inactifs.setdefault(f[2], []).append((f[0], f[1]))
return (actifs, inactifs)
def blacklist(self, new=None):
def blacklist(self, sanction, commentaire, debut=time.time(), fin = '-')
u"""
Blacklistage de la ou de toutes la machines du propriétaire
* new est une liste de 4 termes :
[debut_sanction, fin_sanction, sanction, commentaire]
* début et fin sont le nombre de secondes depuis epoch
* debut et fin sont le nombre de secondes depuis epoch
* pour un début ou fin immédiate mettre now
* pour une fin indéterminée mettre '-'
Les données sont stockées dans la base sous la forme :
debut$fin$sanction$commentaire
Pour modifier une entrée donner un tuple de deux termes :
(index dans blacklist à modifier, nouvelle liste),
l'index étant celui dans la liste retournée par blacklist().
"""
Blist = self.attrs.setdefault('blacklist', [])[:]
if new == None:
return Blist
if debut == 'now':
debut = time.time()
if fin == 'now':
fin = time.time()
bl = balcklist(u'%s$s$s$s' % (sanction, commentaire, debut, fin), {}, self.conn, False)
if type(new) == tuple:
# Modification
index = new[0]
new = new[1]
if new == '':
Blist.pop(index)
return Blist
else:
index = -1
if type(new) != list or len(new) != 4:
raise TypeError
# Verification que les dates sont OK
if new[0] == 'now':
debut = new[0] = int(time.time())
else:
try: debut = new[0] = int(new[0])
except: raise ValueError('Date de début blacklist invalide')
if new[1] == 'now':
fin = new[1] = int(time.time())
elif new[1] == '-':
fin = -1
else:
try: fin = new[1] = int(new[1])
except: raise ValueError('Date de fin blacklist invalide')
if debut == fin:
raise ValueError('Dates de début et de fin identiques')
elif fin != -1 and debut > fin:
raise ValueError('Date de fin avant date de début')
# On dépasse la fin de sanction d'1min pour être sûr qu'elle est périmée.
fin = fin + 60
new_c = u'$'.join(map(str, new))
if index != -1:
Blist[index] = new_c
else:
Blist.append(new_c)
if Blist != self.attrs.get('blacklist'):
self.set_ldapattr('blacklist', Blist)
if not hasattr(self, "_blacklist_restart"):
self._blacklist_restart = {}
restart = self._blacklist_restart.setdefault(new[2], [])
if debut not in restart:
restart.append(debut)
if fin != -1 and fin not in restart:
restart.append(fin)
return Blist
self._modifs.setdefault('blacklist', []).append(bl)
class proprio(CransLdapObject):