[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

@ -431,6 +431,13 @@ class blacklist(Attr):
'comm' : bl_comm, 'comm' : bl_comm,
'actif' : int(bl_debut) < now and (bl_fin == '-' or int(bl_fin) > now) } 'actif' : int(bl_debut) < now and (bl_fin == '-' or int(bl_fin) > now) }
def is_actif(self):
return self.value['actif']
def terminer(self):
self.value.fin = max(self.value.debut, time.time() - 60)
self.actif = False
def __unicode__(self): def __unicode__(self):
return u'%(debut)s$%(fin)s$%(type)s$%(comm)s' % self.value return u'%(debut)s$%(fin)s$%(type)s$%(comm)s' % self.value

View file

@ -47,20 +47,6 @@ log_dn = "cn=log"
# Champs à ignorer dans l'historique # Champs à ignorer dans l'historique
HIST_IGNORE_FIELDS = ["modifiersName", "entryCSN", "modifyTimestamp"] 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): def ldif_to_uldif(ldif):
uldif = {} uldif = {}
for attr, vals in ldif.items(): for attr, vals in ldif.items():
@ -325,100 +311,23 @@ class CransLdapObject(object):
return modifyModlist(orig_ldif, ldif) return modifyModlist(orig_ldif, ldif)
def get_values(self, attr): def get(self, attr, default):
"""Renvoie les valeurs d'un attribut ldap de l'objet self""" try:
attrs = self.attrs.get(attr, []) return self[attr]
return attrs except KeyError:
return default
def get_value(self, attr): def __getitem__(self, attr):
"""Renvoie la première valeur d'un attribut ldap de l'objet self""" if self.mode in [ 'w', 'rw' ]:
return self.get_values(attr)[0] return [ unicode(v) for v in self._modifs[attr] ]
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 ]
else: else:
raise ValueError("%s has multiple values, must specify old_val") return [ unicode(v) for v in self.attrs[attr] ]
return self.set_ldapattr(attr, new_vals)
def del_ldapattr(self, attr, val): def __setitem__(self, attr, values):
"""Supprime la valeur val de l'attribut attr""" if not isinstance(values, list):
new_vals = self.attrs.get(attr, [])[:] values = [ values ]
new_vals = [ v for v in new_vals if str(v) != str(val) ] self._modifs[attr] = values
return self.set_ldapattr(attr, new_vals) self._modifs[attr] = [ attrify(val, attr, self._modifs, self.conn) for val in values ]
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 search_historique(self, ign_fields=HIST_IGNORE_FIELDS): def search_historique(self, ign_fields=HIST_IGNORE_FIELDS):
u"""Récupère l'historique u"""Récupère l'historique
@ -445,114 +354,26 @@ class CransLdapObject(object):
for field in fields: for field in fields:
mods = fields[field] mods = fields[field]
mod_list.append("%s %s" %(field, ", ".join(mods))) mod_list.append("%s %s" %(field, ", ".join(mods)))
if mod_list != []: if mod_list != []:
out.append("%s : [%s] %s" % (date, attrs['reqAuthzID'][0], " ; ".join(mod_list))) out.append("%s : [%s] %s" % (date, attrs['reqAuthzID'][0], " ; ".join(mod_list)))
return out return out
def blacklist_actif(self): def blacklist(self, sanction, commentaire, debut=time.time(), fin = '-')
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):
u""" u"""
Blacklistage de la ou de toutes la machines du propriétaire Blacklistage de la ou de toutes la machines du propriétaire
* new est une liste de 4 termes : * debut et fin sont le nombre de secondes depuis epoch
[debut_sanction, fin_sanction, sanction, commentaire]
* début et fin sont le nombre de secondes depuis epoch
* pour un début ou fin immédiate mettre now * pour un début ou fin immédiate mettre now
* pour une fin indéterminée mettre '-' * pour une fin indéterminée mettre '-'
Les données sont stockées dans la base sous la forme : Les données sont stockées dans la base sous la forme :
debut$fin$sanction$commentaire 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 debut == 'now':
if new == None: debut = time.time()
return Blist if fin == 'now':
fin = time.time()
bl = balcklist(u'%s$s$s$s' % (sanction, commentaire, debut, fin), {}, self.conn, False)
if type(new) == tuple: self._modifs.setdefault('blacklist', []).append(bl)
# 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
class proprio(CransLdapObject): class proprio(CransLdapObject):