319 lines
8.7 KiB
Python
319 lines
8.7 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# ATTRIBUTS.PY-- Description des attributs ldap
|
|
#
|
|
# Copyright (C) 2010 Cr@ns <roots@crans.org>
|
|
# Author: Antoine Durand-Gasselin <adg@crans.org>
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
# * Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# * Neither the name of the Cr@ns nor the names of its contributors may
|
|
# be used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
|
|
# HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
import re
|
|
from unicodedata import normalize
|
|
|
|
def normalize_and_validate(attr, vals, ctxt):
|
|
"""Vérifie que attr peut se voir attribuer les valeurs vals"""
|
|
a = eval('%s()' % attr)
|
|
new_vals = a.normalize(vals, ctxt)
|
|
a.validate(new_vals, ctxt)
|
|
return new_vals
|
|
|
|
def validate_name(value, more_chars=""):
|
|
"""Valide un nom: ie un unicode qui contient lettres, espaces et
|
|
apostrophes, et éventuellement des caractères additionnels"""
|
|
return re.match("[A-Za-z][-' A-Za-z%s]*" % more_chars,
|
|
normalize('NFKD', value).encode('ASCII', 'ignore'))
|
|
|
|
def validate_mac(value):
|
|
"""Vérifie qu'une adresse mac est valide"""
|
|
return True
|
|
|
|
def attrify(val, attr, ldif, ctxt_check = True):
|
|
"""Transforme un n'importe quoi en 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"""
|
|
|
|
return val if isinstance(val, Attr) else CRANS_ATTRIBUTES[attr](val, ldif)
|
|
|
|
class Attr(object):
|
|
legend = "Human-readable description of attribute"
|
|
singlevalue = None
|
|
optional = None
|
|
|
|
def __init__(self, val, ldif):
|
|
assert isinstance(val, unicode)
|
|
self.parse_value(val)
|
|
self.validate(ldif)
|
|
|
|
def parse_value(self, val):
|
|
self.value = val
|
|
|
|
def __str__(self):
|
|
unicode.encode(unicode(self), 'utf-8')
|
|
|
|
def validate(self, ldif):
|
|
"""validates:
|
|
vérifie déjà que ce qu'on a rentré est parsable"""
|
|
self._check_cardinality(ldif)
|
|
self._check_uniqueness(ldif)
|
|
self._check_users_restrictions(ldif)
|
|
|
|
def normalize(self, values, uldif):
|
|
"normalizes"
|
|
return values
|
|
|
|
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(u'%s doit avoir au maximum une valeur (affecte %s)' % self.__class__, values)
|
|
if not self.optional and len(values) == 0:
|
|
raise ValueError('%s doit avoir au moins une valeur' % self.__class__)
|
|
|
|
def _check_type(self, values):
|
|
"""Vérifie que les valeurs ont le bon type (nom est un mot, tel
|
|
est un nombre, etc...)"""
|
|
for v in values:
|
|
assert isinstance(v, unicode)
|
|
|
|
def _check_uniqueness(self, values):
|
|
"""Vérifie l'unicité dans la base de la valeur (mailAlias, chbre,
|
|
etc...)"""
|
|
pass
|
|
|
|
def _check_values(self, values):
|
|
"""Vérifie que les valeurs sont valides (typiquement chbre)"""
|
|
pass
|
|
|
|
def _check_users_restrictions(self, values):
|
|
"""Vérifie les restrictions supplémentaires imposées selon les
|
|
niveaux de droits (<= 3 mailAlias, pas de mac identiques,
|
|
etc...)"""
|
|
pass
|
|
|
|
def can_modify(self):
|
|
"""Vérifie si l'attribut est modifiable"""
|
|
return False
|
|
|
|
|
|
class objectClass(Attr):
|
|
singlevalue = False
|
|
optional = False
|
|
legend = "entité"
|
|
|
|
class nom(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = "Nom"
|
|
def _check_type(self, values):
|
|
return [ validate_name(v) for v in values]
|
|
|
|
def normalize(self, values, uldif):
|
|
return [ v.strip().capitalize() for v in values ]
|
|
|
|
class prenom(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Prénom"
|
|
def _check_type(self, values):
|
|
return [ validate_name(v) for v in values ]
|
|
|
|
def normalize(self, values, uldif):
|
|
return [ values.strip().capitalize() for v in values ]
|
|
|
|
class tel(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Téléphone"
|
|
|
|
def normalize(self, value, uldif):
|
|
return value # XXX - To implement
|
|
|
|
class paiement(Attr):
|
|
singlevallue = False
|
|
optional = True
|
|
legend = u"Paiement"
|
|
|
|
def normalize(self, values, uldif):
|
|
return values # XXX - To implement
|
|
|
|
class carteEtudiant(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Carte d'étudiant"
|
|
|
|
class mailAlias(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Alias mail"
|
|
|
|
class canonicalAlias(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Alias mail canonique"
|
|
|
|
class etudes(Attr):
|
|
singlevalue = False
|
|
optional = False
|
|
legend = u"Études"
|
|
|
|
class chbre(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Chambre sur le campus"
|
|
|
|
class droits(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Droits sur les serveurs"
|
|
|
|
class solde(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u"Solde d'impression"
|
|
|
|
|
|
class host(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
hname = legend = u"Nom d'hôte"
|
|
|
|
class macAddress(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Adresse physique de la carte réseau"
|
|
hname = "Adresse MAC"
|
|
|
|
class ipHostNumber(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = u"Adresse IPv4 de la machine"
|
|
hname = "IPv4"
|
|
|
|
class mid(Attr):
|
|
singlevalue = True
|
|
optional = False
|
|
legend = "Identifiant de machine"
|
|
|
|
class hostAlias(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u'Alias de nom de machine'
|
|
|
|
class ipsec(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u'Clef wifi'
|
|
|
|
class puissance(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u"puissance d'émission pour les bornes wifi"
|
|
|
|
class canal(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u'Canal d\'émission de la borne'
|
|
|
|
class portTCPout(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u'Port TCP ouvert vers l\'extérieur'
|
|
|
|
class portTCPin(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Port TCP ouvert depuis l'extérieur"
|
|
|
|
class portUDPout(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Port UDP ouvert vers l'extérieur"
|
|
|
|
class portUDPin(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Port UDP ouvert depuis l'extérieur"
|
|
|
|
class prise(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u"Prise sur laquelle est branchée la machine"
|
|
|
|
class cid(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u"Identifiant du club"
|
|
|
|
class responsable(Attr):
|
|
singlevalue = True
|
|
optional = True
|
|
legend = u"Responsable du club"
|
|
|
|
|
|
class blacklist(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Blackliste"
|
|
|
|
class historique(Attr):
|
|
singlevalue = False
|
|
optional = True
|
|
legend = u"Historique de l'objet"
|
|
|
|
|
|
CRANS_ATTRIBUTES= {
|
|
'objectClass' : objectClass,
|
|
'nom' : nom,
|
|
'prenom' : prenom,
|
|
'tel' : tel,
|
|
'paiement' : paiement,
|
|
'carteEtudiant' : carteEtudiant,
|
|
'mailAlias' : mailAlias,
|
|
'canonicalAlias' : canonicalAlias,
|
|
'etudes' : etudes,
|
|
'chbre' : chbre,
|
|
'droits' : droits,
|
|
'solde' : solde,
|
|
'mid' : mid,
|
|
'hostAlias' : hostAlias,
|
|
'ipsec' : ipsec,
|
|
'puissance' : puissance,
|
|
'canal' : canal,
|
|
'portTCPout' : portTCPout,
|
|
'portTCPin' : portTCPin,
|
|
'portUDPout' : portUDPout,
|
|
'portUDPin' : portUDPin,
|
|
'prise' : prise,
|
|
'cid' : cid,
|
|
'responsable' : responsable,
|
|
'blacklist' : blacklist,
|
|
'historique' : historique
|
|
}
|
|
|