diff --git a/attributs.py b/attributs.py index 14f38c4..3e5fcb8 100644 --- a/attributs.py +++ b/attributs.py @@ -104,7 +104,7 @@ 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"]: #... etc + if attr in [ "mid", "uid", "cid", "fid", "aid"]: #... etc assert not self.conn.search('%s=%s' % (attr, str(self))) if attr in [ "mailAlias", "canonicalAlias"]: assert not self.conn.search('|(mailAlias=%s)(canonicalAlias=%s)' % ((str(self),)*2)) diff --git a/crans_utils.py b/crans_utils.py index 035dd23..add9bca 100644 --- a/crans_utils.py +++ b/crans_utils.py @@ -46,7 +46,13 @@ def ip_of_mid(mid): def strip_accents(a): """ Supression des accents de la chaîne fournie""" res = normalize('NFKD', a).encode('ASCII', 'ignore') - return res.replace(' ', '_').replace("'", '') + return res + +def strip_spaces(a): + """ Suppression des espaces et des apostrophes""" + res = a.copy() + res.replace(' ', '_').replace("'", '') + return res def mailexist(mail): """Vérifie si une adresse mail existe ou non grace à la commande diff --git a/lc_ldap.py b/lc_ldap.py index f9256d6..4363819 100644 --- a/lc_ldap.py +++ b/lc_ldap.py @@ -33,6 +33,7 @@ from __future__ import with_statement import os, sys, ldap, re, netaddr, datetime, copy, time from ldap.modlist import addModlist, modifyModlist +from Levenshtein import jaro sys.path.append('/usr/scripts/gestion') import config, crans_utils @@ -161,7 +162,10 @@ class lc_ldap(ldap.ldapobject.LDAPObject): else: raise ValueError("Realm inconnu: %s" % realm) - plage = xrange( *(config.mid[realm])) + if realm == 'fil': + plage = xrange(256, 2047) + else: + plage = xrange( *(config.mid[realm])) mid = uldif.setdefault('mid', [ unicode(self._find_id('mid', plage)) ]) uldif['ipHostNumber'] = [ unicode(crans_utils.ip_of_mid(int (mid[0]))) ] return self._create_entity('mid=%s,%s' % (mid[0], parent), uldif) @@ -571,6 +575,72 @@ class adherent(proprio): mfields = proprio.mfields + ['carteEtudiant', 'mailAlias', 'droits' ] xfields = ['etudes', 'postalAddress'] + def compte(self,login = None, uidNumber=0, hash_pass = '', shell=config.login_shell): + """Renvoie le nom du compte crans, s'il n'existe pas, et que uid + est précisé, le crée""" + + if u'posixAccount' in self.attrs['objectClass']: + return self.attrs['uid'][0] + elif login: + nom = strip_accents(self.attrs['nom'][0]).lower() + login = strip_accents(login).lower() + if jaro(nom, login) < 0.75: + raise ValueError("L'uid est trop différent du nom (%s -> %s)" % (uid, self.attrs['nom'][0])) + if not re.match('[a-z][-a-z]{1,15}'): + raise ValueError("Seules les lettres non accentuées et le - sont acceptés pour le login") + if mailexist(login): + raise ValueError(u"Login existant ou correspondant à un alias mail.", 1) + + home = '/home/' + login + if os.path.exists(home): + raise ValueError(u'Création du compte impossible : home existant', 1) + + if os.path.exists("/var/mail/" + login): + raise ValueError(u'Création du compte impossible : /var/mail/%s existant' % login, 1) + + self._modifs['homeDirectory'] = [home] + self._modifs['mail'] = [login] + self._modifs['uid' ] = [login] + fn = strip_accents(self.attrs['prenom'].capitalize()) + ln = strip_accents(self.attrs['nom'].capitalize())) + calias = strip_spaces(fn) + '.' + strip_spaces(ln) + if mailexists(calias): + calias = login + self._modifs['canonicalAlias'] = [calias] + self._modifs['objectClass'] = ['adherent', 'cransAccount', 'posixAccount', 'shadowAccount'] + self._modifs['cn'] = fn + ' ' + ln + self._modifs['loginShell'] = [ shel] + self._modifs['userPassword'] = [hash_pass] + + if uidNumber: + if self.conn.search('(uidNumber=%s)' % uidNumber): + raise ValueError(u'uidNumber pris') + else: + pool_uid = range(1001, 9999) + random.shuffle(pool_uid) + while len(pool_uid) > 0: + uidNumber = pool_uid.pop() # On choisit un uid + if not self.conn.search('(uidNumber=%s)' % uidNumber): + break + if not len(pool_uid): + raise ValueError(u"Plus d'uid disponibles !") + + ## try: + ## self.lock('uidNumber', str(uidNumber)) + ## except: + ## # Quelqu'un nous a piqué l'uid que l'on venait de choisir ! + ## return self.compte(login, uidNumber, hash_pass, shell) + + self._modifs['uidNumber'] = [str(uidNumber)] + self._modifs['gidNumber'] = [str(config.gid)] + self._modifs['gecos'] = cn + ',,,' + + self.save() + + else: + raise EnvironmentError("L'adhérent n'a pas de compte crans") + + class club(proprio): ufields = ['cid', 'responsable'] mfields = ['imprimeurClub']