Merge branch 'master' of sila:/git/ldap

This commit is contained in:
Valentin Samir 2011-10-28 20:32:15 +02:00
commit 6d4aad6b00
2 changed files with 87 additions and 41 deletions

View file

@ -69,6 +69,7 @@ class Attr(object):
ldif: objet contenant l'attribut (permet de faire les validations sur l'environnement)
ctxt_check: effectue les validations
"""
self.ctxt_check=ctxt_check
self.value = None
self.conn = conn
assert isinstance(val, unicode)
@ -133,12 +134,14 @@ class objectClass(Attr):
singlevalue = False
optional = False
legend = "entité"
def parse_value(self, val, ldif):
if val not in [ 'top', 'posixAccount', 'shadowAccount', 'proprio',
'adherent', 'club', 'machine', 'machineCrans',
'borneWifi', 'machineWifi', 'machineFixe',
'cransAccount', 'service', 'facture', 'freeMid' ]:
print(val)
raise ValueError("Pourquoi insérer un objectClass=%s ?" % val)
else:
self.value = unicode(val)
@ -254,22 +257,23 @@ class chbre(Attr):
can_modify = ["self", "Cableur", "Nounou"]
def parse_value(self, val, ldif):
if u'club' in ldif['objectClass']:
if val in annuaires_pg.locaux_clubs():
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
return
else:
raise ValueError("Club devrait etre en XclN, pas en %s" % val)
if val in (u"EXT", u"????"):
self.value = val
return
else:
raise ValueError("Club devrait etre en XclN, pas en %s" % val)
if val in (u"EXT", u"????"):
self.value = val
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(val[0], val[1:])
except NameError:
import annuaires_pg_test
annuaires_pg_test.chbre_prises(val[0], val[1:])
self.value = val
@ -295,8 +299,8 @@ class solde(Attr):
can_modify = ["imprimeur", "Nounou", "Tresorier"]
def parse_value(self, solde, ldif):
# on évite les dépassements
if not (float(solde) >= config.impression.decouvert and float(solde) <= 1024.):
# 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.):
raise ValueError("Solde invalide: %s" % solde)
self.value = solde
@ -304,7 +308,7 @@ class dnsAttr(Attr):
def parse_value(self, dns, ldif):
dns = dns.lower()
name, net = dns.split('.', 1)
if (net not in ['crans.org', 'wifi.crans.org'] or
if self.ctxt_check and (net not in ['crans.org', 'wifi.crans.org'] or
not re.match('[a-z][-_a-z0-9]+', name)):
raise ValueError("Nom d'hote invalide '%s'" % dns)
self.value = dns
@ -544,8 +548,12 @@ class loginShell(Attr):
'/usr/bin/rssh',
'/usr/local/bin/disconnect_shell',
'/usr/scripts/surveillance/disconnect_shell',
'/usr/local/bin/badPassSh',
'/usr/bin/passwd',
'/bin/false',
'/bin//zsh'
'']
if (shell not in shells):
if self.ctxt_check and (shell not in shells):
raise ValueError("Shell %s invalide" % shell)
self.value = shell

View file

@ -121,32 +121,53 @@ class lc_ldap(ldap.ldapobject.LDAPObject):
res = self.search_ext_s(dn, scope, filterstr, sizelimit=sizelimit)
return [ new_cransldapobject(self, r[0], mode=mode) for r in res ]
def allMachinesAdherents(self):
"""Renvoie la liste de toutes les machines et de tous les adherents
(club et Association Crans compris). Conçue pour s'éxécuter le plus
rapidement possible. On dumpe malgré tout toute la base."""
res = {}
parent = {}
machines = {}
# (proxying de la base ldap)
for dn, attrs in self.search_s(base_dn, scope=2):
# On crée les listes des machines et propriétaires
if dn.startswith('mid='): # les machines
m = new_cransldapobject(self, dn, ldif = attrs)
parent_dn = dn.split(',', 1)[1]
if not machines.has_key(parent_dn):
machines[parent_dn]=[]
machines[parent_dn].append(m)
elif (dn.startswith('aid=') or dn.startswith('cid=') or dn==base_dn) and not parent.has_key(dn):
# Hélas on refait une recherche ldap dans attributs.py pour trouver les responsables des club
# ce qui prends un temps non négligeable mais est toujours mieux que de le faire pour tous les adherents
parent[dn]=new_cransldapobject(self, dn, ldif = attrs)
allmachines=[]
for dn,mlist in machines.items(): # on associe propriétaires et machines
parent[dn]._machines=mlist
for m in mlist:
m._proprio=parent[dn]
allmachines.append(m)
return allmachines,parent.values() # on renvoie la liste des machines et des adherents (dont club et crans)
def allMachines(self):
"""Renvoie la liste de toutes les machines, Conçue pour
s'éxécuter le plus rapidement possible. On dumpe malgré tout
toute la base, c'est pour pouvoir aussi rajouter à moindre coût
les propriétaires."""
res = {}
parent = {}
machines = []
# On récupère tous les objets ldap et on les met dans un dico
# (proxying de la base ldap)
for dn, attrs in self.search_s(base_dn, scope=2): #on fait tout dans une seule boucle
#~ res[dn] = attrs
# On crée la liste des machines
#~ for dn, attrs in res.items():
if dn.startswith('mid='):
m = new_cransldapobject(self, dn, ldif = attrs)
parent_dn = dn.split(',', 1)[1]
if not parent.has_key(parent_dn):
parent[parent_dn]=adherent(self, dn,machines= [ new_cransldapobject(self, dn,ldif=attrs)]) # on utilise pas new_cransldapobject pour optimiser les appel ldap (on passe la liste des machines)
else:
parent[parent_dn]._machines.append(new_cransldapobject(self, dn,ldif=attrs))
#~ m._proprio = new_cransldapobject(self, parent_dn, res[parent_dn],opt=machine_proprio[parent_dn])
m._proprio = parent[parent_dn]
machines.append(m)
machines,_=self.allMachinesAdherents()
return machines
def allAdherents(self):
"""Renvoie la liste de toutes les adherents, Conçue pour
s'éxécuter le plus rapidement possible. On dumpe malgré tout
toute la base, c'est pour pouvoir aussi rajouter à moindre coût
les machines."""
_,adherents=self.allMachinesAdherents()
return adherents
def newMachine(self, parent, realm, uldif):
"""Crée une nouvelle machine: realm peut être:
fil, fil-v6, wifi, wifi-v6, adm, gratuit, personnel-ens, special"""
@ -241,10 +262,10 @@ def new_cransldapobject(conn, dn, mode='ro', ldif = None):
classe = None
if ldif:
classe = globals()[ldif['objectClass'][0]]
elif dn == base_dn:
if dn == base_dn:
classe = AssociationCrans
elif ldif:
classe = globals()[ldif['objectClass'][0]]
else:
res = conn.search_s(dn, 0)
if not res:
@ -265,7 +286,7 @@ class CransLdapObject(object):
self.mode = mode
self.attrs = None # Contient un dico uldif qui doit représenter ce qui
self.attrs = {} # Contient un dico uldif qui doit représenter ce qui
# est dans la base
self._modifs = None # C'est là qu'on met les modifications
@ -279,6 +300,9 @@ class CransLdapObject(object):
# Vous précisez un ldif, l'objet est 'ro'
self.mode = 'ro'
self.attrs = ldif
if dn != base_dn: # new_cransldapobject ne donne pas de ldif formaté et utilise un ldif non formaté, donc on formate
self.attrs = ldif_to_uldif(self.attrs)
self.attrs = ldif_to_cldif(self.attrs, conn, check_ctxt = False) # on est en read only, donc pas la peine de vérifier la validité
elif dn != base_dn:
res = conn.search_s(dn, 0)
if not res:
@ -395,7 +419,7 @@ class CransLdapObject(object):
# XXX - Proposer de filtrer les blacklistes avec un arg supplémentaire ?
# XXX - Vérifier les blacklistes des machines pour les adhérents ?
attrs = (self.attrs if self.mode not in ["w", "rw"] else self._modifs)
return filter((lambda bl: bl.is_actif()), attrs.get("blacklist"))
return filter((lambda bl: bl.is_actif()), attrs.get("blacklist",[]))
def blacklist(self, sanction, commentaire, debut="now", fin = '-'):
u"""
@ -424,6 +448,20 @@ class proprio(CransLdapObject):
def __init__(self, conn, dn, mode='ro', ldif = None, machines=[]):
super(proprio, self).__init__(conn, dn, mode, ldif)
self._machines = machines
def paiement_ok(self):
"""Renvoie si le propriétaire à payé pour l'année en cours"""
if self.dn == base_dn:
return True
try:
for paiement in self['paiement']:
if paiement.value == config.ann_scol:
return True
except KeyError:
pass
return False
def machines(self):
if not self._machines: