Commit 84777603 authored by Valentin Samir's avatar Valentin Samir

[attributs, objets] Une fonction pour générer automatiquement une ligne d'historique

Elle s'appelle history_gen.
Il faut l'appeler explicitement pour le moment, pour éviter de mettre des lignes
en double vu que jusqu'à maintenant, historique était fait à la main.

Il y a 4 niveaux d'historique pour les attributs :
  * full on loggue toutes les modifications
      pour un singlevalue : nom (Durant -> Dupond")
      pour les autres : mailAlias+toto@free.fr-titi@orange.com
  * partial, comme full sauf qu'on limite la longeur de chaque valeur d'attribut
    à au plus 15 caractères
  * info, on signalute juste que l'attribut attribut a été créer, supprimer ou modifier:
  * None, on n'ajoute pas de ligne (par exemple pour l'historique lui même, on le loggue pas
     ses modifications)

Ajoutez en d'autre si vous pensez à des trucs cools
parent f6fe2f78
......@@ -256,6 +256,7 @@ class Attr(object):
conn = None
unique = False
concurrent = True
historique = "full" # valeurs possibles "full", "partial", "info", None
unique_exclue = []
#: Le nom de l'attribut dans le schéma LDAP
ldap_name = None
......@@ -1022,6 +1023,7 @@ class ipsec(Attr):
category = 'wifi'
ldap_name = "ipsec"
can_modify = [nounou, parent]
historique = "info"
default = u'auto'
def parse_value(self, val):
......@@ -1313,6 +1315,7 @@ class historique(Attr):
ldap_name = "historique"
# Il faudrait faire quelque chose pour que soi, parent, cableur ne puissent que ajouter de nouvelles lignes
can_modify = [nounou, soi, parent, cableur]
historique = None
# Thanks to 20-100, on va devoir gérer deux cas
FORMAT = "%d/%m/%Y %H:%M:%S"
......@@ -1334,6 +1337,7 @@ class info(Attr):
category = 'info'
can_modify = [nounou, cableur, bureau]
ldap_name = "info"
historique = "info"
@crans_attribute
class homepageAlias(Attr):
......@@ -1427,6 +1431,7 @@ class userPassword(Attr):
category = ''
ldap_name = "userPassword"
can_modify = [nounou, bureau, cableur]
historique = "info"
def is_modifiable(self, liste_droits):
"""
......@@ -1452,6 +1457,7 @@ class sshFingerprint(Attr):
can_modify = [parent, nounou]
ldap_name = "sshFingerprint"
python_type = dict
historique = "partial"
def parse_value(self, key):
if isinstance(key, self.python_type):
......@@ -1692,6 +1698,7 @@ class privatekey(Attr):
python_type = str
can_modify = [parent, nounou]
legend = "Clef privée"
historique = "info"
@crans_attribute
class csr(Attr):
......@@ -1699,6 +1706,7 @@ class csr(Attr):
python_type = str
can_modify = [parent, nounou]
legend = "requête de signature de certificat"
historique = "info"
def _format_cert(self, csr):
import OpenSSL
......@@ -1728,6 +1736,7 @@ class certificat(Attr):
python_type = str
can_modify = [parent, nounou]
legend = "Certificat"
historique = "info"
def __init__(self, *args, **kwargs):
super(certificat, self).__init__(*args, **kwargs)
......
......@@ -299,9 +299,91 @@ class CransLdapObject(object):
assert isinstance(chain, unicode)
new_line = u"%s, %s : %s" % (time.strftime(attributs.historique.FORMAT), login, chain)
# Attention, le __setitem__ est surchargé, mais pas .append sur l'historique
self["historique"] = self.get("historique", []) + [new_line]
def history_gen(self, attr=None, login=None):
"Génère une ligne d'historique pour l'arribut attr ou une ligne par attributs pour l'objet courant"
if attr is None:
for attr in self.attrs.keys():
self.history_gen(attr)
def partial_name(name, max_len=14, start=7, end=7):
if len(name) > max_len:
return "%s…%s" % (name[:start], name[-end:])
else:
return name
if login is None:
login = self.conn.current_login
if isinstance(attr, str) or isinstance(attr, unicode):
attr = attributs.AttributeFactory.get(attr)
elif isinstance(attr, Attr):
attr = type(attr)
elif issubclass(attr, Attr):
pass
else:
raise ValueError("%r ne correspont pas a un attribut" % attr)
if not attr.historique:
return
if attr.historique not in ["full", "partial", "info"]:
raise ValueError("Format d'historique %s inconnu" % attr.historique)
old_values = self.attrs[attr.ldap_name]
new_values = self._modifs[attr.ldap_name]
if old_values == new_values:
return
comm = None
if attr.singlevalue:
# modification
if old_values and new_values:
if attr.historique == "full":
comm = u"%s (%s -> %s)" % (attr.ldap_name, old_values[0], new_values[0])
elif attr.historique == "partial":
old = partial_name(str(old_values[0]))
new = partial_name(str(new_values[0]))
comm = u"%s (%s -> %s)" % (attr.ldap_name, old, new)
elif attr.historique == "info":
comm = u"%s" % attr.ldap_name
# création
elif not old_values and new_values:
if attr.historique == "info":
comm = u"+%s" % attr.ldap_name
elif attr.historique in ["full", "partial"]:
new = str(new_values[0])
if attr.historique == "partial":
new = partial_name(new)
comm = u"%s+%s" % (attr.ldap_name, new)
# suppréssion
elif not new_values and old_values:
if attr.historique == "info":
comm = u"-%s" % attr.ldap_name
elif attr.historique in ["full", "partial"]:
old = str(old_values[0])
if attr.historique == "partial":
old = partial_name(old)
comm = u"%s-%s" % (attr.ldap_name, old)
else:
added = []
deleted = []
if attr.historique == "partial":
append = lambda x: partial_name(str(x))
else:
append = lambda x: str(x)
for a in new_values:
if not a in old_values:
added.append(append(a))
for a in old_values:
if not a in new_values:
deleted.append(append(a))
if attr.historique == "info":
comm = u"%s%s%s" % ('+' if added else "", '-' if deleted else "", attr.ldap_name)
elif attr.historique in ["full", "partial"]:
comm = u"%s%s%s%s%s" % (attr.ldap_name, '+' if added else "", '+'.join(added), '-' if deleted else "", '-'.join(deleted))
if comm:
new_line = u"%s, %s : %s" % (time.strftime(attributs.historique.FORMAT), login, comm)
if not new_line in self["historique"]:
self["historique"].append(new_line)
else:
raise ValueError("impossible de générer l'historique pour %s %s %s" % (attr, old_values, new_values))
def _check_optionnal(self, comment):
"""Vérifie que les attributs qui ne sont pas optionnels sont effectivement peuplés."""
objet = self.ldap_name
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment