Un peu de ménage dans attributs.py, entres autres

concernant la possibilité de modifier les droits.
This commit is contained in:
Pierre-Elliott Bécue 2013-01-20 18:01:38 +01:00
parent be6b378bf8
commit d65454165f

View file

@ -40,6 +40,30 @@ sys.path.append("/usr/scripts/gestion")
import config, annuaires_pg
from midtools import Mid
### Les droits
# en cas de typo, l'appel d'une variable plante, on préfèrera donc les utiliser en lieu et place
# des chaînes de caractères
nounou = "Nounou"
cableur = "Cableur"
apprenti = "Apprenti"
tresorier = "Tresorier"
bureau = "Bureau"
imprimeur = "Imprimeur"
moderateur = "Moderateur"
multimachines = "Multimachines"
parent = "parent"
soi = "soi"
responsable = "responsable"
TOUS_DROITS = [nounou, apprenti, bureau, tresorier, imprimeur, moderateur, multimachines, cableur]
DROITS_ELEVES = [nounou, bureau]
DROITS_MOYEN = [apprenti, moderateur]
DROITS_FAIBLES = [cableur, imprimeur, multimachines]
DROITS_SUPERVISEUR = { nounou : TOUS_DROITS,
bureau : DROITS_FAIBLES + [bureau, tresorier],
}
def attrify(val, attr, ldif, conn, ctxt_check = True):
"""Transforme un n'importe quoi en Attr.
@ -61,11 +85,12 @@ class Attr(object):
singlevalue = None
optional = None
conn = None
unique = False
can_modify = ['Nounou']
can_modify = [nounou]
can_view = ['Nounou', 'apprenti', 'self', 'parent', 'owner']
"""Qui peut voir l'attribut. Par défaut, les nounous et les apprentis
can_view = [nounou, apprenti, soi, parent, responsable]
"""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."""
@ -121,18 +146,10 @@ class Attr(object):
"""Vérifie l'unicité dans la base de la valeur (mailAlias, chbre,
etc...)"""
attr = self.__class__.__name__
if attr in ["mid", "uid", "cid", "fid", "aid", "ipHostNumber", "uidNumber"]:
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])
if attr in ["mailAlias", "canonicalAlias", 'mail', 'uid']:
res = self.conn.search('(|(mail=%s)(mailAlias=%s)(canonicalAlias=%s))' % ((str(self),)*3))
if res:
raise ValueError("Mail déjà existant", [r.dn for r in res])
if attr in ["host", "hostAlias"]:
res = self.conn.search('(|(host=%s)(hostAlias=%s))' % ((str(self),)*2))
if res:
raise ValueError("Hôte déjà existant", [r.dn for r in res])
def _check_users_restrictions(self, values):
"""Vérifie les restrictions supplémentaires imposées selon les
@ -141,6 +158,11 @@ class Attr(object):
### On l'implémente dans les classes filles !
pass
def is_modifiable(self, liste_droits):
"""
Le droit est-il modifiable par un des droits dans liste_droits ?
"""
return set(liste_droits).isdisjoint(can_modify)
class objectClass(Attr):
singlevalue = False
@ -150,7 +172,7 @@ class objectClass(Attr):
can_modify = []
""" Personne ne doit modifier de classe """
can_view = ['Nounou', 'apprenti']
can_view = [nounou, apprenti]
""" Internal purpose (et à fin pédagogique) """
def parse_value(self, val, ldif):
@ -177,24 +199,26 @@ class aid(intAttr):
optional = True
legend = u"Identifiant de l'adhérent"
category = 'id'
unique = True
can_modify = []
""" Personne ne devrait modifier un attribut d'identification """
can_view = ['Nounou', 'apprenti', 'cableurs']
can_view = [nounou, apprenti, 'Cableurs']
class uid(Attr):
singlevalue = True
option = False
legend = u"L'identifiant canonique de l'adhérent"
category = 'perso'
unique = True
class nom(Attr):
singlevalue = True
optional = False
legend = "Nom"
category = 'perso'
can_modify = ["Nounou", "Cableur"]
can_modify = [nounou, cableur]
def parse_value(self, val, ldif):
if u'club' in ldif['objectClass']:
@ -207,7 +231,7 @@ class prenom(Attr):
optional = False
legend = u"Prénom"
category = 'perso'
can_modify = ["Nounou", "Cableur"]
can_modify = [nounou, cableur]
def parse_value(self, val, ldif):
self.value = validate_name(val)
@ -218,7 +242,7 @@ class tel(Attr):
optional = False
legend = u"Téléphone"
category = 'perso'
can_modify = ["self", "Nounou", "Cableur"]
can_modify = [soi, nounou, cableur]
def parse_value(self, val, ldif):
self.value = format_tel(val)
@ -235,36 +259,39 @@ class yearAttr(intAttr):
raise ValueError("Année invalide (%r)" % val)
self.value = int(val)
class paiement(yearAttr):
legend = u"Paiement"
can_modify = ["Cableur", "Nounou", "tresorier"]
can_modify = [cableur, nounou, tresorier]
category = 'perso'
class carteEtudiant(yearAttr):
legend = u"Carte d'étudiant"
category = 'perso'
can_modify = ["Cableur", "Nounou", "tresorier"]
can_modify = [cableur, nounou, tresorier]
class mailAlias(Attr):
singlevalue = False
optional = True
legend = u"Alias mail"
can_modify = ["self", "Cableur", "Nounou"]
category = 'mail'
def parse_value(self, val, ldif):
val = val.lower()
if not re.match('[a-z][-_.0-9a-z]+', val):
raise ValueError("Alias mail invalide (%r)" % val)
self.value = val
class canonicalAlias(Attr):
class mail(Attr):
singlevalue = True
optional = False
unique = True
legend = "Le mail de l'adhérent"
can_modify = [soi, nounou, cableur]
category = 'mail'
def _check_uniqueness(self):
attr = self.__class__.__name__
if attr in ["mailAlias", "canonicalAlias", 'mail']:
res = self.conn.search('(|(mail=%s)(mailAlias=%s)(canonicalAlias=%s))' % ((str(self),)*3))
if res:
raise ValueError("Mail déjà existant", [r.dn for r in res])
# XXX - to be implemented
#def parse_value(self, mail, ldif):
# pass
class canonicalAlias(mail):
singlevalue = True
optional = False
unique = True
legend = u"Alias mail canonique"
category = 'mail'
@ -274,11 +301,25 @@ class canonicalAlias(Attr):
raise ValueError("Alias mail invalide (%s)" % val)
self.value = val
class mailAlias(mail):
singlevalue = False
optional = True
unique = True
legend = u"Alias mail"
can_modify = [soi, cableur, nounou]
category = 'mail'
def parse_value(self, val, ldif):
val = val.lower()
if not re.match('[a-z][-_.0-9a-z]+', val):
raise ValueError("Alias mail invalide (%r)" % val)
self.value = val
class etudes(Attr):
singlevalue = False
optional = False
legend = u"Études"
can_modify = ["self", "Cableur", "Nounou"]
can_modify = [soi, cableur, nounou]
category = 'perso'
def parse_value(self, val, ldif):
@ -289,8 +330,9 @@ class etudes(Attr):
class chbre(Attr):
singlevalue = True
optional = False
unique = True
legend = u"Chambre sur le campus"
can_modify = ["self", "Cableur", "Nounou"]
can_modify = [soi, cableur, nounou]
category = 'perso'
def parse_value(self, val, ldif):
@ -318,23 +360,30 @@ class droits(Attr):
singlevalue = False
optional = True
legend = u"Droits sur les serveurs"
can_modify = ["Nounou", "Bureau"]
can_modify = [nounou, bureau] #ne sert à rien ici, mais c'est tout à fait exceptionnel
category = 'perso'
def parse_value(self, val, ldif):
if val.lower() not in ['apprenti', 'nounou', 'cableur', 'tresorier', 'bureau',
'webmaster', 'webradio', 'imprimeur', 'multimachines', 'victime', 'moderateur', 'nounours']:
if val.lower() not in [i.lower() for i in TOUS_DROITS]:
raise ValueError("Ces droits n'existent pas (%r)" % val)
if val.lower() == 'webmaster':
self.value = u'WebMaster'
else:
self.value = val.capitalize()
self.value = val.capitalize()
def is_modifiable(self, liste_droits):
"""
Le droit est-il modifiable par un des droits dans liste_droits ?
"""
modifiables = set()
for i in liste_droits:
modifiables.append(DROITS_SUPERVISEUR.get(i, []))
modifiables = list(modifiables)
return self.value in modifiables
class solde(Attr):
singlevalue = True
optional = True
legend = u"Solde d'impression"
can_modify = ["imprimeur", "Nounou", "Tresorier"]
can_modify = [imprimeur, nounou, tresorier]
def parse_value(self, solde, ldif):
# on évite les dépassements, sauf si on nous dit de ne pas vérifier
@ -352,14 +401,25 @@ class dnsAttr(Attr):
raise ValueError("Nom d'hote invalide %r" % dns)
self.value = dns
class host(dnsAttr):
singlevalue = True
optional = False
hname = legend = u"Nom d'hôte"
can_modify = ["parent", "Nounou", "Cableur"]
can_modify = [parent, nounou, cableur]
category = 'base_tech'
def _check_uniqueness(self):
attr = self.__class__.__name__
if attr in ["host", "hostAlias"]:
res = self.conn.search('(|(host=%s)(hostAlias=%s))' % ((str(self),)*2))
if res:
raise ValueError("Hôte déjà existant", [r.dn for r in res])
class hostAlias(host):
singlevalue = False
unique = True
optional = True
legend = u'Alias de nom de machine'
class macAddress(Attr):
singlevalue = True
@ -367,7 +427,7 @@ class macAddress(Attr):
legend = u"Adresse physique de la carte réseau"
hname = "Adresse MAC"
category = 'base_tech'
can_modify = ["parent", "Nounou", "Cableur"]
can_modify = [parent, nounou, cableur]
def parse_value(self, mac, ldif):
self.value = format_mac(mac)
@ -379,6 +439,7 @@ class macAddress(Attr):
class ipHostNumber(Attr):
singlevalue = True
optional = False
unique = True
legend = u"Adresse IPv4 de la machine"
hname = "IPv4"
category = 'base_tech'
@ -395,6 +456,7 @@ class ipHostNumber(Attr):
class mid(Attr):
singlevalue = True
optional = False
unique = True
legend = "Identifiant de machine"
category = 'id'
@ -405,11 +467,6 @@ class mid(Attr):
return unicode(int(self.value))
class hostAlias(dnsAttr):
singlevalue = False
optional = True
legend = u'Alias de nom de machine'
class ipsec(Attr):
singlevalue = False
optional = True
@ -488,6 +545,7 @@ class prise(Attr):
class cid(intAttr):
singlevalue = True
optional = True
unique = True
legend = u"Identifiant du club"
category = 'id'
@ -546,20 +604,20 @@ class info(Attr):
optional = True
legend = u"Quelques informations"
category = 'info'
can_modify = ["Nounou", "Cableur", "Bureau"]
can_modify = [nounou, cableur, bureau]
class homepageAlias(Attr):
singlevalue = True
optional = True
legend = u'Un alias pour la page personnelle'
can_modify = ["Nounou", "Cableur"]
can_modify = [nounou, cableur]
category = 'webpage'
class charteMA(Attr):
singlevalue = True
optional = True
legend= "Signale si l'adhérent a signé la charte de membres actifs"
can_modify = ["Nounou", "Bureau"]
can_modify = [nounou, bureau]
category = 'perso'
def parse_value(self, signed, ldif):
@ -570,6 +628,7 @@ class charteMA(Attr):
class homeDirectory(Attr):
singlevalue=True
optional = True
unique = True
legend="Le chemin du home de l'adhérent"
def parse_value(self, home, ldif):
@ -585,7 +644,7 @@ class loginShell(Attr):
singlevalue = True
optional = True
legend = "Le shell de l'adherent"
can_modify = ["self", "Nounou", "Cableur"]
can_modify = [soi, nounou, cableur]
def parse_value(self, shell, ldif):
#with open('/etc/shells') as f:
@ -620,6 +679,7 @@ class loginShell(Attr):
class uidNumber(intAttr):
singlevalue = True
optional = True
unique = True
legend = "L'uid du compte de l'adherent"
category = 'id'
@ -639,28 +699,19 @@ class gecos(Attr):
a, b, c, d = gecos.split(',')
self.value = gecos
class mail(Attr):
singlevalue = True
optional = False
legend = "Le mail de l'adhérent"
can_modify = ["self", "Nounou", "Cableur"]
category = 'mail'
# XXX - to be implemented
#def parse_value(self, mail, ldif):
# pass
class sshFingerprint(Attr):
singlevalue = False
optional = True
legend = "Clef ssh de la machine"
can_modify = ["parent", "Nounou"]
can_modify = [parent, nounou]
class gpgFingerprint(Attr):
singlevalue = False
optional = True
unique = True
legend = "Clef gpg d'un adhérent"
can_modify = ["self", "Nounou"]
can_modify = [soi, nounou]
class cn(Attr):
singlevalue = True
@ -670,12 +721,13 @@ class cn(Attr):
class dn(Attr):
singlevalue = True
optional = False
unique = True
category = 'id'
class postalAddress(Attr):
singlevalue = False
optional = True
can_modify = ["self", "Cableur", "Nounou", "Bureau"]
can_modify = [soi, cableur, nounou, bureau]
legend = u"Adresse"
category = 'perso'
@ -683,7 +735,7 @@ class controle(Attr):
singlevalue = True
optional = False
legend = u"Contrôle"
can_modify = ["Tresorier", "Nounou"]
can_modify = [tresorier, nounou]
category = 'perso'
def parse_value(self, ctrl, ldif):
@ -694,6 +746,16 @@ class controle(Attr):
else:
self.value = ctrl
### Les classes
ADHERENT_ATTRS = [ nom, prenom, tel, chbre, postalAddress, mail, uid,
canonicalAlias, mailAlias, etudes, paiement,
solde, carteEtudiant, droits, loginShell, blacklist ]
MACHINE_ATTRS = [ host, macAddress, hostAlias, ipHostNumber, portTCPout,
portTCPin, portUDPout, portUDPin ]
CRANS_ATTRIBUTES= {
'objectClass' : objectClass,
'cn' : cn,
@ -745,11 +807,3 @@ CRANS_ATTRIBUTES= {
'gecos': gecos,
'gidNumber': gidNumber
}
ADHERENT_ATTRS = [ nom, prenom, tel, chbre, postalAddress, mail, uid,
canonicalAlias, mailAlias, etudes, paiement,
solde, carteEtudiant, droits, loginShell, blacklist ]
MACHINE_ATTRS = [ host, macAddress, hostAlias, ipHostNumber, portTCPout,
portTCPin, portUDPout, portUDPin ]