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