[global] On jette ctxt_check, et les ldifs qui traînent partout, qu'on remplace.
* Les ldifs sont remplacés par un pointeur vers l'objet propriétaire des attributs * Le test de cardinalité est fait lors du setitem dans AttrsDict * Le test d'unicité dans le setitem d'un CransLdapObject. Le setitem vérifie également qu'on affecte pas des attributs non désirés à un objet
This commit is contained in:
parent
60ea18d180
commit
180c17baed
2 changed files with 172 additions and 170 deletions
304
attributs.py
304
attributs.py
|
@ -75,28 +75,34 @@ DROITS_SUPERVISEUR = { nounou : TOUS_DROITS,
|
|||
bureau : DROITS_FAIBLES + [bureau, tresorier],
|
||||
}
|
||||
|
||||
class SingleValueError(ValueError):
|
||||
pass
|
||||
|
||||
def attrify(val, attr, ldif, conn, ctxt_check = True):
|
||||
class UniquenessError(EnvironmentError):
|
||||
pass
|
||||
|
||||
class OptionalError(EnvironmentError):
|
||||
pass
|
||||
|
||||
def attrify(val, attr, conn, Parent=None):
|
||||
"""Transforme un n'importe quoi en :py:class:`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"""
|
||||
"""
|
||||
|
||||
if isinstance(val, Attr):
|
||||
return val
|
||||
else:
|
||||
return CRANS_ATTRIBUTES.get(attr, Attr)(val, ldif, conn, ctxt_check)
|
||||
return CRANS_ATTRIBUTES.get(attr, Attr)(val, conn, Parent)
|
||||
|
||||
|
||||
class AttrsDict(dict) :
|
||||
def __init__(self, conn, ldif = {}, check_ctxt = True):
|
||||
def __init__(self, conn, ldif={}, Parent=None):
|
||||
super(AttrsDict, self).__init__(ldif)
|
||||
self._conn = conn
|
||||
self._ldif = ldif
|
||||
self._check_ctxt = check_ctxt
|
||||
self._parent = Parent
|
||||
|
||||
def __getitem__(self, attr):
|
||||
values = super(AttrsDict, self).__getitem__(attr)
|
||||
|
@ -105,12 +111,23 @@ class AttrsDict(dict) :
|
|||
output = []
|
||||
for val in values:
|
||||
if not isinstance(val, Attr):
|
||||
output.append(attrify(unicode(val, 'utf-8'), attr, self._ldif, self._conn, self._check_ctxt))
|
||||
output.append(attrify(unicode(val, 'utf-8'), attr, self._conn, self._parent))
|
||||
else:
|
||||
output.append(val)
|
||||
self[attr] = output
|
||||
return output
|
||||
|
||||
def __setitem__(self, attr, values):
|
||||
# ne devrait par arriver
|
||||
if not isinstance(values, list):
|
||||
values = [ values ]
|
||||
if self._parent.mode in ['w', 'rw']:
|
||||
if CRANS_ATTRIBUTES.get(attr, Attr).singlevalue and len(values) > 1:
|
||||
raise SingleValueError("L'attribut %s doit être monovalué.")
|
||||
super(AttrsDict, self).__setitem__(attr, values)
|
||||
else:
|
||||
super(AttrsDict, self).__setitem__(attr, values)
|
||||
|
||||
def get(self, value, default_value):
|
||||
try:
|
||||
return self[value]
|
||||
|
@ -124,36 +141,33 @@ class Attr(object):
|
|||
|
||||
* ``val`` : valeur de l'attribut
|
||||
* ``ldif`` : objet contenant l'attribut (permet de faire les validations sur l'environnement)
|
||||
* ``ctxt_check`` : effectue les validations
|
||||
"""
|
||||
legend = "Human-readable description of attribute"
|
||||
singlevalue = None
|
||||
optional = None
|
||||
singlevalue = False
|
||||
optional = True
|
||||
conn = None
|
||||
unique = False
|
||||
|
||||
can_modify = [nounou]
|
||||
"""La liste des droits qui suffisent à avoir le droit de modifier la valeur"""
|
||||
can_modify = [nounou]
|
||||
|
||||
can_view = [nounou, apprenti, soi, parent, respo]
|
||||
"""Qui peut voir l'attribut. Par défaut, les Nounous et les Apprentis
|
||||
peuvent tout voir. Par transparence, et par utilité, on autorise par
|
||||
défaut l'adhérent à voir les données le concernant."""
|
||||
can_view = [nounou, apprenti, soi, parent, respo]
|
||||
|
||||
category = 'other'
|
||||
"""Catégorie de l'attribut (pour affichage futur)"""
|
||||
category = 'other'
|
||||
|
||||
def __init__(self, val, ldif, conn, ctxt_check):
|
||||
def __init__(self, val, conn, Parent):
|
||||
"""Crée un nouvel objet représentant un attribut. """
|
||||
self.ctxt_check=ctxt_check
|
||||
#self.value = None
|
||||
self.value = None
|
||||
self.conn = conn
|
||||
assert isinstance(val, unicode)
|
||||
self.parse_value(val, ldif)
|
||||
if ctxt_check:
|
||||
self.validate(ldif)
|
||||
self.parent = Parent
|
||||
self.parse_value(val)
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, val):
|
||||
"""Transforme l'attribut pour travailler avec notre validateur
|
||||
Le ldif est en dépendance car à certains endroits, il peut servir
|
||||
(par exemple, pour l'ipv6, ou l'ipv4..."""
|
||||
|
@ -167,37 +181,16 @@ class Attr(object):
|
|||
assert isinstance(self.value, unicode)
|
||||
return self.value
|
||||
|
||||
def validate(self, ldif):
|
||||
"""validates:
|
||||
vérifie déjà que ce qu'on a rentré est parsable"""
|
||||
if not self.__class__.__name__ in CRANS_ATTRIBUTES:
|
||||
raise ValueError('Attribut %s inconnu' % self.__class__.__name__)
|
||||
|
||||
# On utilise un ldif parce qu'il faut avoir un contexte
|
||||
# pour savoir si l'attribut qu'on est en train de créer
|
||||
# est légitime.
|
||||
own_values = ldif.get(self.__class__.__name__, [])
|
||||
self._check_cardinality(own_values)
|
||||
self._check_uniqueness()
|
||||
|
||||
def _check_cardinality(self, values):
|
||||
"""Vérifie qu'il y a un nombre correct de valeur =1, <=1, {0,1},
|
||||
etc..."""
|
||||
if self.singlevalue and len(values) > 1:
|
||||
raise ValueError('%s doit avoir au maximum une valeur (affecte %s)' % (self.__class__, values))
|
||||
# A priori, ça sert à rien, on fait du for val in values, si la liste
|
||||
# est vide, le type d'attribut généré n'est pas pris en compte.
|
||||
if not self.optional and len(values) == 0:
|
||||
raise ValueError('%s doit avoir au moins une valeur' % self.__class__)
|
||||
|
||||
def _check_uniqueness(self):
|
||||
def check_uniqueness(self, liste_exclue):
|
||||
"""Vérifie l'unicité dans la base de la valeur (``mailAlias``, ``chbre``,
|
||||
etc...)"""
|
||||
attr = self.__class__.__name__
|
||||
if str(self) in liste_exclue:
|
||||
return
|
||||
if self.unique:
|
||||
res = self.conn.search('%s=%s' % (attr, str(self)))
|
||||
if res:
|
||||
raise ValueError("%s déjà existant" % attr, [r.dn for r in res])
|
||||
raise UniquenessError("%s déjà existant" % attr, [r.dn for r in res])
|
||||
|
||||
def is_modifiable(self, liste_droits):
|
||||
"""
|
||||
|
@ -210,13 +203,13 @@ class objectClass(Attr):
|
|||
optional = False
|
||||
legend = "entité"
|
||||
|
||||
can_modify = []
|
||||
""" Personne ne doit modifier de classe """
|
||||
can_modify = []
|
||||
|
||||
can_view = [nounou, apprenti]
|
||||
""" Internal purpose (et à fin pédagogique) """
|
||||
can_view = [nounou, apprenti]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, val):
|
||||
if val not in [ 'top', 'organizationalUnit', 'posixAccount', 'shadowAccount',
|
||||
'proprio', 'adherent', 'club', 'machine', 'machineCrans',
|
||||
'borneWifi', 'machineWifi', 'machineFixe',
|
||||
|
@ -227,7 +220,7 @@ class objectClass(Attr):
|
|||
|
||||
|
||||
class intAttr(Attr):
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, val):
|
||||
if int(val) <= 0:
|
||||
raise ValueError("Valeur entière invalide : %r" % val)
|
||||
self.value = int(val)
|
||||
|
@ -236,7 +229,7 @@ class intAttr(Attr):
|
|||
return unicode(self.value)
|
||||
|
||||
class boolAttr(Attr):
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, val):
|
||||
if val.lower() in [u'true', u'ok']:
|
||||
self.value = True
|
||||
elif val.lower() == u'false':
|
||||
|
@ -256,13 +249,13 @@ class aid(intAttr):
|
|||
category = 'id'
|
||||
unique = True
|
||||
|
||||
can_modify = []
|
||||
""" Personne ne devrait modifier un attribut d'identification """
|
||||
can_modify = []
|
||||
|
||||
can_view = [nounou, apprenti, 'Cableurs']
|
||||
can_view = [nounou, apprenti, cableur]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
self.value = int(val)
|
||||
def parse_value(self, aid):
|
||||
self.value = int(aid)
|
||||
|
||||
class uid(Attr):
|
||||
singlevalue = True
|
||||
|
@ -278,11 +271,14 @@ class nom(Attr):
|
|||
category = 'perso'
|
||||
can_modify = [nounou, cableur]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
if u'club' in ldif['objectClass']:
|
||||
self.value = validate_name(val,"0123456789\[\]")
|
||||
def parse_value(self, nom):
|
||||
if self.parent != None:
|
||||
if u'club' in self.parent['objectClass']:
|
||||
self.value = validate_name(nom,"0123456789\[\]")
|
||||
else:
|
||||
self.value = validate_name(nom)
|
||||
else:
|
||||
self.value = validate_name(val)
|
||||
self.value = validate_name(nom)
|
||||
|
||||
class prenom(Attr):
|
||||
singlevalue = True
|
||||
|
@ -291,8 +287,8 @@ class prenom(Attr):
|
|||
category = 'perso'
|
||||
can_modify = [nounou, cableur]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
self.value = validate_name(val)
|
||||
def parse_value(self, prenom):
|
||||
self.value = validate_name(prenom)
|
||||
|
||||
class compteWiki(Attr):
|
||||
singlevalue = False
|
||||
|
@ -301,8 +297,8 @@ class compteWiki(Attr):
|
|||
category = 'perso'
|
||||
can_modify = [nounou, cableur, soi]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
self.value = validate_name(val)
|
||||
def parse_value(self, compte):
|
||||
self.value = validate_name(compte)
|
||||
# TODO: validate with mdp for user definition here ?
|
||||
|
||||
class tel(Attr):
|
||||
|
@ -312,19 +308,20 @@ class tel(Attr):
|
|||
category = 'perso'
|
||||
can_modify = [soi, nounou, cableur]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
self.value = format_tel(val)
|
||||
def parse_value(self, tel):
|
||||
self.value = format_tel(tel)
|
||||
if len(self.value) == 0:
|
||||
raise ValueError("Numéro de téléphone invalide (%r)" % val)
|
||||
raise ValueError("Numéro de téléphone invalide (%r)" % tel)
|
||||
|
||||
class yearAttr(intAttr):
|
||||
singlevalue = False
|
||||
optional= True
|
||||
optional = True
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
if int(val) < 1998:
|
||||
raise ValueError("Année invalide (%r)" % val)
|
||||
self.value = int(val)
|
||||
def parse_value(self, annee):
|
||||
annee = int(annee)
|
||||
if annee < 1998:
|
||||
raise ValueError("Année invalide (%r)" % annee)
|
||||
self.value = annee
|
||||
|
||||
class paiement(yearAttr):
|
||||
legend = u"Paiement"
|
||||
|
@ -348,8 +345,10 @@ class mail(Attr):
|
|||
can_modify = [soi, nounou, cableur]
|
||||
category = 'mail'
|
||||
|
||||
def _check_uniqueness(self):
|
||||
def check_uniqueness(self, liste_exclue):
|
||||
attr = self.__class__.__name__
|
||||
if str(self) in liste_exclue:
|
||||
return
|
||||
if attr in ["mailAlias", "canonicalAlias", 'mail']:
|
||||
mail = str(self).split('@', 1)[0]
|
||||
|
||||
|
@ -364,7 +363,7 @@ class mail(Attr):
|
|||
if res:
|
||||
raise ValueError("Le mail %s est déjà pris." % (str(self)))
|
||||
|
||||
def parse_value(self, mail, ldif):
|
||||
def parse_value(self, mail):
|
||||
if not re.match('^[-_.0-9A-Za-z]+@([A-Za-z0-9]{1}[A-Za-z0-9-_]+[.])+[a-z]{2,6}$', mail):
|
||||
raise ValueError("Adresse mail invalide (%s)" % mail)
|
||||
self.value = mail
|
||||
|
@ -377,11 +376,11 @@ class canonicalAlias(mail):
|
|||
legend = u"Alias mail canonique"
|
||||
category = 'mail'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
val = u".".join([ a.capitalize() for a in val.split(u'.', 1) ])
|
||||
if not re.match('^[-_.0-9A-Za-z]+@([A-Za-z0-9]{1}[A-Za-z0-9-_]+[.])+[a-z]{2,6}$', val):
|
||||
raise ValueError("Alias mail invalide (%s)" % val)
|
||||
self.value = val
|
||||
def parse_value(self, mail):
|
||||
mail = u".".join([ a.capitalize() for a in mail.split(u'.', 1) ])
|
||||
if not re.match('^[-_.0-9A-Za-z]+@([A-Za-z0-9]{1}[A-Za-z0-9-_]+[.])+[a-z]{2,6}$', mail):
|
||||
raise ValueError("Alias mail invalide (%s)" % mail)
|
||||
self.value = mail
|
||||
|
||||
class mailAlias(mail):
|
||||
singlevalue = False
|
||||
|
@ -391,11 +390,11 @@ class mailAlias(mail):
|
|||
can_modify = [soi, cableur, nounou]
|
||||
category = 'mail'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
val = val.lower()
|
||||
if not re.match('^[-_.0-9A-Za-z]+@([A-Za-z0-9]{2}[A-Za-z0-9-_]+[.])+[a-z]{2,6}$', val):
|
||||
raise ValueError("Alias mail invalide (%r)" % val)
|
||||
self.value = val
|
||||
def parse_value(self, mail):
|
||||
mail = mail.lower()
|
||||
if not re.match('^[-_.0-9A-Za-z]+@([A-Za-z0-9]{2}[A-Za-z0-9-_]+[.])+[a-z]{2,6}$', mail):
|
||||
raise ValueError("Alias mail invalide (%r)" % mail)
|
||||
self.value = mail
|
||||
|
||||
class mailInvalide(boolAttr):
|
||||
optional = True
|
||||
|
@ -418,10 +417,9 @@ class etudes(Attr):
|
|||
can_modify = [soi, cableur, nounou]
|
||||
category = 'perso'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, etudes):
|
||||
# who cares
|
||||
self.value = val
|
||||
|
||||
self.value = etudes
|
||||
|
||||
class chbre(Attr):
|
||||
singlevalue = True
|
||||
|
@ -431,26 +429,26 @@ class chbre(Attr):
|
|||
can_modify = [soi, cableur, nounou]
|
||||
category = 'perso'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
if self.ctxt_check: # Si ce n'est pas la peine de vérifier, on ne vérifie pas
|
||||
if u'club' in ldif['objectClass']:
|
||||
if val in annuaires_pg.locaux_clubs():
|
||||
self.value = val
|
||||
def parse_value(self, chambre):
|
||||
if self.parent != None:
|
||||
if u'club' in self.parent['objectClass']:
|
||||
if chambre in annuaires_pg.locaux_clubs():
|
||||
self.value = chambre
|
||||
return
|
||||
else:
|
||||
raise ValueError("Club devrait etre en XclN, pas en %r" % val)
|
||||
raise ValueError("Club devrait etre en XclN, pas en %r" % chambre)
|
||||
|
||||
if val in (u"EXT", u"????"):
|
||||
self.value = val
|
||||
return
|
||||
if chambre in (u"EXT", u"????"):
|
||||
self.value = chambre
|
||||
return
|
||||
|
||||
try:
|
||||
annuaires_pg.chbre_prises(val[0], val[1:])
|
||||
except NameError:
|
||||
import annuaires_pg_test
|
||||
annuaires_pg_test.chbre_prises(val[0], val[1:])
|
||||
try:
|
||||
annuaires_pg.chbre_prises(chambre[0], chambre[1:])
|
||||
except NameError:
|
||||
import annuaires_pg_test
|
||||
annuaires_pg_test.chbre_prises(chambre[0], chambre[1:])
|
||||
|
||||
self.value = val
|
||||
self.value = chambre
|
||||
|
||||
class droits(Attr):
|
||||
singlevalue = False
|
||||
|
@ -459,10 +457,10 @@ class droits(Attr):
|
|||
can_modify = [nounou, bureau] #ne sert à rien ici, mais c'est tout à fait exceptionnel
|
||||
category = 'perso'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, droits):
|
||||
# if val.lower() not in [i.lower() for i in TOUS_DROITS]:
|
||||
# raise ValueError("Ces droits n'existent pas (%r)" % val)
|
||||
self.value = val.capitalize()
|
||||
self.value = droits.capitalize()
|
||||
|
||||
def is_modifiable(self, liste_droits):
|
||||
"""
|
||||
|
@ -481,21 +479,21 @@ class solde(Attr):
|
|||
legend = u"Solde d'impression"
|
||||
can_modify = [imprimeur, nounou, tresorier]
|
||||
|
||||
def parse_value(self, solde, ldif):
|
||||
def parse_value(self, solde):
|
||||
# on évite les dépassements, sauf si on nous dit de ne pas vérifier
|
||||
if self.ctxt_check and not (float(solde) >= config.impression.decouvert and float(solde) <= 1024.):
|
||||
if not (float(solde) >= config.impression.decouvert and float(solde) <= 1024.):
|
||||
raise ValueError("Solde invalide: %r" % solde)
|
||||
self.value = solde
|
||||
|
||||
class dnsAttr(Attr):
|
||||
category = 'dns'
|
||||
def parse_value(self, dns, ldif):
|
||||
dns = dns.lower()
|
||||
name, net = dns.split('.', 1)
|
||||
if self.ctxt_check and (net not in ['adm.crans.org', 'crans.org', 'wifi.crans.org'] or
|
||||
def parse_value(self, val):
|
||||
val = val.lower()
|
||||
name, net = val.split('.', 1)
|
||||
if (net not in ['adm.crans.org', 'crans.org', 'wifi.crans.org'] or
|
||||
not re.match('[a-z][-_a-z0-9]+', name)):
|
||||
raise ValueError("Nom d'hote invalide %r" % dns)
|
||||
self.value = dns
|
||||
raise ValueError("Nom d'hote invalide %r" % val)
|
||||
self.value = val
|
||||
|
||||
class host(dnsAttr):
|
||||
singlevalue = True
|
||||
|
@ -504,8 +502,10 @@ class host(dnsAttr):
|
|||
can_modify = [parent, nounou, cableur]
|
||||
category = 'base_tech'
|
||||
|
||||
def _check_uniqueness(self):
|
||||
def check_uniqueness(self, liste_exclue):
|
||||
attr = self.__class__.__name__
|
||||
if str(self) in liste_exclue:
|
||||
return
|
||||
if attr in ["host", "hostAlias"]:
|
||||
res = self.conn.search('(|(host=%s)(hostAlias=%s))' % ((str(self),)*2))
|
||||
if res:
|
||||
|
@ -527,13 +527,13 @@ class macAddress(Attr):
|
|||
category = 'base_tech'
|
||||
can_modify = [parent, nounou, cableur]
|
||||
|
||||
def parse_value(self, mac, ldif):
|
||||
def parse_value(self, mac):
|
||||
self.value = format_mac(mac)
|
||||
# XXX self.parent['ip6HostNumber'] = cequ'ilfaut
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.value).lower()
|
||||
|
||||
|
||||
class ipHostNumber(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
|
@ -543,9 +543,9 @@ class ipHostNumber(Attr):
|
|||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, ip, ldif):
|
||||
def parse_value(self, ip):
|
||||
if ip == '<automatique>':
|
||||
ip = ip4_of_rid(ldif['rid'][0])
|
||||
ip = ip4_of_rid(self.parent['rid'][0])
|
||||
self.value = netaddr.ip.IPAddress(ip)
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -560,8 +560,8 @@ class ip6HostNumber(Attr):
|
|||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
ip = ip6_of_mac(ldif['macAddress'][0], int(ldif['rid'][0]))
|
||||
def parse_value(self, ip6):
|
||||
ip = ip6_of_mac(self.parent['macAddress'][0], int(self.parent['rid'][0]))
|
||||
self.value = netaddr.ip.IPAddress(ip)
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -574,7 +574,7 @@ class mid(Attr):
|
|||
legend = u"Identifiant de machine"
|
||||
category = 'id'
|
||||
|
||||
def parse_value(self, mid, ldif):
|
||||
def parse_value(self, mid):
|
||||
self.value = int(mid)
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -588,7 +588,7 @@ class rid(Attr):
|
|||
category = 'id'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, rid, ldif):
|
||||
def parse_value(self, rid):
|
||||
rid = int(rid)
|
||||
|
||||
# On veut éviter les rid qui recoupent les ipv4 finissant par
|
||||
|
@ -644,11 +644,11 @@ class positionBorne(Attr):
|
|||
singlevalue = True
|
||||
optional = True
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
if val == u'N/A N/A':
|
||||
def parse_value(self, pos):
|
||||
if pos == u'N/A N/A':
|
||||
self.value = u"N/A°N N/A°E"
|
||||
else:
|
||||
lat, lon = val.split(" ")
|
||||
lat, lon = pos.split(" ")
|
||||
self.value = u"%f°N %f°E" % (float(lat), float(lon))
|
||||
|
||||
class nvram(Attr):
|
||||
|
@ -656,8 +656,9 @@ class nvram(Attr):
|
|||
optional = True
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
pass
|
||||
def parse_value(self, nvr):
|
||||
# XXX - on fait quoi ici ?
|
||||
self.value = nvr
|
||||
|
||||
class portAttr(Attr):
|
||||
singlevalue = False
|
||||
|
@ -666,7 +667,7 @@ class portAttr(Attr):
|
|||
category = 'firewall'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, port, ldif):
|
||||
def parse_value(self, port):
|
||||
if ":" in port:
|
||||
a,b = port.split(":", 1)
|
||||
if a:
|
||||
|
@ -694,7 +695,6 @@ class portAttr(Attr):
|
|||
else:
|
||||
return unicode(self.value[0])
|
||||
|
||||
|
||||
class portTCPout(portAttr):
|
||||
legend = u'Port TCP ouvert vers l\'extérieur'
|
||||
|
||||
|
@ -724,8 +724,8 @@ class prise(Attr):
|
|||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, prise, ldif):
|
||||
### Tu es une Nounou, je te fais confiance
|
||||
def parse_value(self, prise):
|
||||
### Tu es Beau, je te fais confiance
|
||||
self.value = prise
|
||||
|
||||
class cid(intAttr):
|
||||
|
@ -735,7 +735,7 @@ class cid(intAttr):
|
|||
legend = u"Identifiant du club"
|
||||
category = 'id'
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
def parse_value(self, val):
|
||||
self.value = int(val)
|
||||
|
||||
class responsable(Attr):
|
||||
|
@ -745,7 +745,7 @@ class responsable(Attr):
|
|||
category = 'perso'
|
||||
can_modify = [cableur, nounou]
|
||||
|
||||
def nonefunction(self, val):
|
||||
def nonefunction(self, resp):
|
||||
"""
|
||||
Just... do... nothing.
|
||||
L'idée est qu'on initialise self.value à None
|
||||
|
@ -755,6 +755,9 @@ class responsable(Attr):
|
|||
pass
|
||||
|
||||
def get_respo(self):
|
||||
"""Méthode spéciale, pour aller avec
|
||||
property. On génère le respo quand
|
||||
c'est nécessaire, pas avant."""
|
||||
if hasattr(self, "_value"):
|
||||
return self._value
|
||||
else:
|
||||
|
@ -765,7 +768,7 @@ class responsable(Attr):
|
|||
self._value = res
|
||||
return res
|
||||
|
||||
def parse_value(self, resp, ldif):
|
||||
def parse_value(self, resp):
|
||||
self.__value = resp
|
||||
|
||||
value = property(get_respo, nonefunction)
|
||||
|
@ -779,7 +782,7 @@ class imprimeurClub(Attr):
|
|||
category = "perso"
|
||||
can_modify = [cableur, nounou]
|
||||
|
||||
def nonefunction(self, val):
|
||||
def nonefunction(self, imprimeur):
|
||||
"""
|
||||
Just... do... nothing.
|
||||
L'idée est qu'on initialise self.value à None
|
||||
|
@ -799,8 +802,8 @@ class imprimeurClub(Attr):
|
|||
self._value = res
|
||||
return res
|
||||
|
||||
def parse_value(self, val, ldif):
|
||||
self.__value = val
|
||||
def parse_value(self, imprimeur):
|
||||
self.__value = imprimeur
|
||||
|
||||
value = property(get_imprimeur, nonefunction)
|
||||
|
||||
|
@ -814,8 +817,8 @@ class blacklist(Attr):
|
|||
category = 'info'
|
||||
can_modify = [nounou]
|
||||
|
||||
def parse_value(self, bl, ldif):
|
||||
bl_debut, bl_fin, bl_type, bl_comm = bl.split('$')
|
||||
def parse_value(self, blacklist):
|
||||
bl_debut, bl_fin, bl_type, bl_comm = blacklist.split('$')
|
||||
now = time.time()
|
||||
self.value = { 'debut' : bl_debut if bl_debut == '-' else int (bl_debut),
|
||||
'fin' : bl_fin if bl_fin == '-' else int(bl_fin),
|
||||
|
@ -860,10 +863,10 @@ class charteMA(Attr):
|
|||
can_modify = [nounou, bureau]
|
||||
category = 'perso'
|
||||
|
||||
def parse_value(self, signed, ldif):
|
||||
if signed.upper() not in ["TRUE", "FALSE"]:
|
||||
raise ValueError("La charte MA est soit TRUE ou FALSE, pas %r" % signed)
|
||||
self.value = signed.upper()
|
||||
def parse_value(self, charteSignee):
|
||||
if charteSignee.upper() not in ["TRUE", "FALSE"]:
|
||||
raise ValueError("La charte MA est soit TRUE ou FALSE, pas %r" % charteSignee)
|
||||
self.value = charteSignee.upper()
|
||||
|
||||
class homeDirectory(Attr):
|
||||
singlevalue=True
|
||||
|
@ -871,13 +874,12 @@ class homeDirectory(Attr):
|
|||
unique = True
|
||||
legend="Le chemin du home de l'adhérent"
|
||||
|
||||
def parse_value(self, home, ldif):
|
||||
uid = ldif['uid'][0]
|
||||
def parse_value(self, home):
|
||||
uid = str(self.parent['uid'][0])
|
||||
if uid.startswith('club-'):
|
||||
uid = uid.split('-',1)[1]
|
||||
if home != u'/home/%s' % uid and home != u'/home/club/%s' % uid:
|
||||
raise ValueError("Le répertoire personnel n'est pas bon: %r (devrait être %r ou %r)" %
|
||||
(home, '/home/%s' % ldif['uid'][0], '/home/club/%s' % ldif['uid'][0]))
|
||||
raise ValueError("Le répertoire personnel n'est pas bon: %r (devrait être %r ou %r)" % (home, '/home/%s' % self.parent['uid'][0], '/home/club/%s' % self.parent['uid'][0]))
|
||||
self.value = home
|
||||
|
||||
class loginShell(Attr):
|
||||
|
@ -886,10 +888,10 @@ class loginShell(Attr):
|
|||
legend = "Le shell de l'adherent"
|
||||
can_modify = [soi, nounou, cableur]
|
||||
|
||||
def parse_value(self, shell, ldif):
|
||||
def parse_value(self, shell):
|
||||
#with open('/etc/shells') as f:
|
||||
# shells = [ l.strip() for l in f.readlines() if not l.startswith('#') ]
|
||||
shells=['/bin/csh',
|
||||
shells = ['/bin/csh',
|
||||
'/bin/sh',
|
||||
'/usr/bin/es',
|
||||
'/usr/bin/ksh',
|
||||
|
@ -912,7 +914,7 @@ class loginShell(Attr):
|
|||
'/bin/false',
|
||||
'/bin//zsh'
|
||||
'']
|
||||
if self.ctxt_check and (shell not in shells):
|
||||
if shell not in shells:
|
||||
raise ValueError("Shell %r invalide" % shell)
|
||||
self.value = shell
|
||||
|
||||
|
@ -935,7 +937,7 @@ class gecos(Attr):
|
|||
legend = "Le gecos"
|
||||
category = 'id'
|
||||
|
||||
def parse_value(self, gecos, ldif):
|
||||
def parse_value(self, gecos):
|
||||
self.value = gecos
|
||||
|
||||
class sshFingerprint(Attr):
|
||||
|
@ -976,7 +978,7 @@ class controle(Attr):
|
|||
can_modify = [tresorier, nounou]
|
||||
category = 'perso'
|
||||
|
||||
def parse_value(self, ctrl, ldif):
|
||||
def parse_value(self, ctrl):
|
||||
if ctrl not in [u"", u"c", u"p", u"cp", u"pc"]:
|
||||
raise ValueError("control peut prendre les valeurs [c][p]")
|
||||
if ctrl == u'cp':
|
||||
|
@ -1008,7 +1010,7 @@ MACHINE_ATTRS = [ host, macAddress, hostAlias, ipHostNumber, portTCPout,
|
|||
portTCPin, portUDPout, portUDPin ]
|
||||
|
||||
|
||||
CRANS_ATTRIBUTES= {
|
||||
CRANS_ATTRIBUTES = {
|
||||
'objectClass' : objectClass,
|
||||
'cn' : cn,
|
||||
'dn' : dn,
|
||||
|
|
38
lc_ldap.py
38
lc_ldap.py
|
@ -104,7 +104,7 @@ def ldif_to_uldif(ldif):
|
|||
uldif[attr] = [ unicode(val, 'utf-8') for val in vals ]
|
||||
return uldif
|
||||
|
||||
def ldif_to_cldif(ldif, conn, check_ctxt = True):
|
||||
def ldif_to_cldif(ldif, conn):
|
||||
"""Transforme un dictionnaire renvoyé par python-ldap, en
|
||||
un dictionnaire dont les valeurs sont des instances de Attr
|
||||
Lorsqu'on récupère le ldif de la base ldap, on n'a pas besoin
|
||||
|
@ -112,7 +112,7 @@ def ldif_to_cldif(ldif, conn, check_ctxt = True):
|
|||
"""
|
||||
cldif = {}
|
||||
for attr, vals in ldif.items():
|
||||
cldif[attr] = [ attributs.attrify(val, attr, ldif, conn, check_ctxt) for val in vals]
|
||||
cldif[attr] = [ attributs.attrify(val, attr, ldif, conn) for val in vals]
|
||||
return cldif
|
||||
|
||||
def cldif_to_ldif(cldif):
|
||||
|
@ -325,7 +325,7 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object):
|
|||
continue
|
||||
else:
|
||||
# On crée l'attribut associé, pour parser sa valeur.
|
||||
my_id = attributs.attrify(unicode(i), attr, {}, self, False)
|
||||
my_id = attributs.attrify(unicode(i), attr, self, False, None)
|
||||
if my_id.value != i:
|
||||
continue
|
||||
else:
|
||||
|
@ -456,20 +456,20 @@ class CransLdapObject(object):
|
|||
raise TypeError("conn doit être une instance de lc_ldap")
|
||||
self.conn = conn
|
||||
|
||||
self.attrs = attributs.AttrsDict(conn) # Contient un dico uldif qui doit représenter ce qui
|
||||
self.attrs = attributs.AttrsDict(conn, Parent=self) # Contient un dico uldif qui doit représenter ce qui
|
||||
# est dans la base. On attrify paresseusement au moment où on utilise un attribut
|
||||
|
||||
self._modifs = None # C'est là qu'on met les modifications
|
||||
|
||||
self._modifs_unchecked = []
|
||||
self.dn = dn
|
||||
|
||||
orig = {}
|
||||
if ldif:
|
||||
if dn != base_dn: # new_cransldapobject ne donne pas de ldif formaté et utilise un ldif non formaté, donc on formate
|
||||
self.attrs = attributs.AttrsDict(self.conn, ldif, check_ctxt = False)
|
||||
self.attrs = attributs.AttrsDict(self.conn, ldif, Parent=self)
|
||||
else:
|
||||
self.attrs = ldif
|
||||
self._modifs = attributs.AttrsDict(self.conn, ldif, check_ctxt = False)
|
||||
self._modifs = attributs.AttrsDict(self.conn, ldif, Parent=self)
|
||||
orig = ldif
|
||||
|
||||
elif dn != base_dn:
|
||||
|
@ -480,12 +480,12 @@ class CransLdapObject(object):
|
|||
|
||||
# L'objet sortant de la base ldap, on ne fait pas de vérifications sur
|
||||
# l'état des données.
|
||||
self.attrs = attributs.AttrsDict(self.conn, res_attrs, check_ctxt = False)
|
||||
self.attrs = attributs.AttrsDict(self.conn, res_attrs, Parent=self)
|
||||
|
||||
# Pour test en cas de mode w ou rw
|
||||
orig = res[0][1]
|
||||
|
||||
self._modifs = attributs.AttrsDict(self.conn, res[0][1], check_ctxt = False)
|
||||
self._modifs = attributs.AttrsDict(self.conn, res[0][1], Parent=self)
|
||||
|
||||
if mode in ['w', 'rw']:
|
||||
if not self.may_be(modified, self.conn.droits + self.conn._check_parent(dn) + self.conn._check_self(dn)):
|
||||
|
@ -550,7 +550,7 @@ class CransLdapObject(object):
|
|||
raise EnvironmentError("Impossible de modifier l'objet, peut-être n'existe-t-il pas ?")
|
||||
|
||||
# Vérification des modifications
|
||||
self.attrs = attributs.AttrsDict(self.conn, self.conn.search_s(self.dn, 0)[0][1], check_ctxt=False)
|
||||
self.attrs = attributs.AttrsDict(self.conn, self.conn.search_s(self.dn, 0)[0][1], Parent=self)
|
||||
differences = []
|
||||
# On fait les différences entre les deux dicos
|
||||
for attr in set(self.attrs.keys()).union(set(self._modifs.keys())):
|
||||
|
@ -607,6 +607,8 @@ class CransLdapObject(object):
|
|||
# Quand on est pas en mode d'écriture, ça plante.
|
||||
if self.mode not in ['w', 'rw']:
|
||||
raise ValueError("Objet en lecture seule")
|
||||
if not self.has_key(attr):
|
||||
raise ValueError("L'objet que vous modifiez n'a pas d'attribut %s" % (attr))
|
||||
# Les valeurs sont nécessairement stockées en liste
|
||||
if not isinstance(values, list):
|
||||
values = [ values ]
|
||||
|
@ -616,12 +618,9 @@ class CransLdapObject(object):
|
|||
# (on peut pas utiliser self._modifs, car il ne faut
|
||||
# faire le changement que si on peut)
|
||||
|
||||
# Sans le dict(), les deux pointent vers le même truc.
|
||||
ldif = dict(self._modifs)
|
||||
# On doit encoder, car _modifs est un ensemble de données brutes
|
||||
# comme tout ldif
|
||||
ldif[attr] = [ value.encode('utf-8') for value in values ]
|
||||
attrs_before_verif = [ attributs.attrify(val, attr, ldif, self.conn) for val in values ]
|
||||
attrs_before_verif = [ attributs.attrify(val, attr, self.conn, Parent=self) for val in values ]
|
||||
for attribut in attrs_before_verif:
|
||||
attribut.check_uniqueness([str(content) for content in self.attrs[attr]])
|
||||
|
||||
# On groupe les attributs précédents, et les nouveaux
|
||||
mixed_attrs = attrs_before_verif + self.attrs[attr]
|
||||
|
@ -950,7 +949,8 @@ class facture(CransLdapObject):
|
|||
}
|
||||
attribs = [attributs.fid, attributs.modePaiement, attributs.recuPaiement]
|
||||
|
||||
class service(CransLdapObject): pass
|
||||
|
||||
class lock(CransLdapObject): pass
|
||||
class service(CransLdapObject):
|
||||
pass
|
||||
|
||||
class lock(CransLdapObject):
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue