diff --git a/attributs.py b/attributs.py index c44dabb..45e77b4 100644 --- a/attributs.py +++ b/attributs.py @@ -431,6 +431,13 @@ class blacklist(Attr): 'comm' : bl_comm, '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): return u'%(debut)s$%(fin)s$%(type)s$%(comm)s' % self.value diff --git a/lc_ldap.py b/lc_ldap.py index 28bf119..6f3283d 100644 --- a/lc_ldap.py +++ b/lc_ldap.py @@ -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):