Mise à jour de l'outil de génération de LDIF pour l'annuaire AuF.
[auf-refer.git] / auf-annuaire
CommitLineData
385a99a4
P
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""Outil de gestion d'annuaire LDAP pour l'AuF.
4
5Copyright ©2009-2010 Agence universitaire de la Francophonie
6Licence : GPL version 3
7Auteur : Progfou <jean-christophe.andre@auf.org>
8
9Dépendances Debian : python >= 2.5, python-simplejson, auf-refer
10
11Usage :
12
13 auf-annuaire.py | ldapmodify -x -c -D "cn=admin,o=AUF" -y /etc/ldap.secret
14"""
15
16import os
17import aufrefer
18import simplejson as json
19
20LDAP_HOST = '127.0.0.1'
21LDAP_BASE = 'ou=People,o=AUF'
22LDAP_BINDDN = 'cn=admin,' + LDAP_BASE
23LDAP_PWFILE = ['~/.ldap.secret', '/etc/ldap.secret']
24
25LDAP_INIT_LDIF = u"""dn: ou=People,o=AuF
26changeType: add
27objectClass: top
28objectClass: organizationalUnit
29ou: People
30"""
31
385a99a4
P
32ISO_3166 = aufrefer.get('iso-3166-fr.json')
33NOMS_BUREAU = aufrefer.get('bureaux.json')
a53c1dd3
P
34PAYS_IMPLANT = {'DANANG.VN': 'VN', 'HCMV.VN': 'VN', 'IFI': 'VN',
35 'IFMT': 'LA', 'ITC': 'KH', 'IFAG': 'BG', 'IFE': 'MU'}
36
37PHOTO_FILENAME = "/var/lib/auf-refer-photos/%s.jpg"
385a99a4
P
38
39def noms_bureau(cc):
40 for code, data in NOMS_BUREAU.items():
41 if cc.upper() in data[1]:
42 return code, data[0]
43 return u'### implantation inconnue ###', u'### implantation inconnue ###'
44
385a99a4
P
45class LdapEntry(object):
46 _attributes_order = [
47 'objectClass', 'sn', 'givenName', 'cn', 'ou', 'l', 'mail', 'o',
48 'userPassword', 'telephoneNumber', 'uid',
49 ]
50
51 def __init__(self, dn, d=None, **kv):
52 self.dn = dn
53 if d:
54 self.dict = d
55 else:
56 self.dict = { }
57 self.dict.update(kv)
58
59 def get(self, attribute):
60 return self.dict.get(attribute, None)
61
62 def set(self, attribute, value):
63 old_value = self.dict.get(attribute, None)
64 self.dict[attribute] = value
65 return old_value
66
67 def from_ldif(self, ldif):
68 raise RuntimeError('Note implemented')
69
70 def _to_ldif_line(self, attribute, value):
71 to_encode = False
72 for c in value:
73 if c < ' ' or 'z' < c:
74 to_encode = True
75 break
76 if to_encode:
77 attribute = attribute + ':'
78 if type(value) == unicode:
79 value = value.encode('utf-8')
a53c1dd3 80 value = value.encode('base64').replace('\n', '')
385a99a4
P
81 return u'%s: %s' % (attribute, value)
82
83 def to_ldif(self, changeType=None):
84 ldif = [ ]
85 ldif.append(self._to_ldif_line(u'dn', self.dn))
86 if changeType:
87 ldif.append(u'changeType: %s' % changeType)
88 set_keys = set(self.dict.keys())
89 set_attr_order = set(self._attributes_order)
90 for k in set_keys & set_attr_order:
91 for e in self.dict[k]:
92 ldif.append(self._to_ldif_line(k, e))
93 for k in set_keys - set_attr_order:
94 for e in self.dict[k]:
95 ldif.append(self._to_ldif_line(k, e))
96 ldif.append(u'')
97 return '\n'.join(ldif).encode('utf-8')
98
99
100class AnnuaireAuF(object):
101 _attributes = [
102 'adel', 'redir', 'nom', 'mdp', 'implant', 'coda', 'tel_ext', 'tel_ip',
103 ]
104
105 def __init__(self, ldap_base):
106 self.ldap_base = ldap_base
107 self.data = None
108
109 def json2ldap(self, json_dict):
a53c1dd3
P
110 implant = json_dict['implant'].upper()
111 CC = PAYS_IMPLANT.get(implant, implant)
385a99a4
P
112 nom_bureau_court, nom_bureau_long = noms_bureau(CC)
113 adel = json_dict['adel']
a53c1dd3
P
114 user, domain = adel.rsplit('@', 1)
115 cn = user.title().replace('-De-', '-de-').replace('.', ' ')
385a99a4 116 prenom, nom = cn.rsplit(' ', 1)
a53c1dd3
P
117 login = json_dict['login']
118 nom_affichage = json_dict['nom'] and json_dict['nom'] or cn
385a99a4
P
119
120 ldap_dict = { }
121 ldap_dict['objectClass'] = [
a53c1dd3
P
122 u'top', u'person', u'organizationalPerson', u'inetOrgPerson',
123 u'inetLocalMailRecipient',
385a99a4
P
124 ]
125 ldap_dict['sn'] = [ nom ]
126 ldap_dict['givenName'] = [ prenom ]
127 ldap_dict['cn'] = [ nom_affichage ]
128 ldap_dict['ou'] = [ u'People', nom_bureau_court, nom_bureau_long ]
a53c1dd3 129 ldap_dict['l'] = [ ISO_3166.get(CC, u'### Pays absent de la norme ISO-3166 ###') ]
385a99a4
P
130 ldap_dict['mail'] = [ adel ]
131 ldap_dict['o'] = [ u'AuF', u'Agence universitaire de la Francophonie' ]
132 if json_dict.has_key('mdp') and json_dict['mdp']:
133 ldap_dict['userPassword'] = [ '{CRYPT}' + json_dict['mdp'] ]
134 if json_dict.has_key('tel_ip') and json_dict['tel_ip']:
135 ldap_dict['telephoneNumber'] = [ json_dict['tel_ip'] ]
136 if login is not None and login:
137 ldap_dict['uid'] = [ login ]
a53c1dd3
P
138 else:
139 ldap_dict['uid'] = [ user ]
140 # objectClass: inetLocalMailRecipient
141 ldap_dict['mailLocalAddress'] = [ json_dict['redir'] ]
142 ldap_dict['mailHost'] = [ 'imaps://mail.%s:993' % json_dict['redir'].rsplit('@', 1)[1] ]
143 # photo JPEG
144 photo_filename = PHOTO_FILENAME % adel
145 if os.path.exists(photo_filename):
146 ldap_dict['jpegPhoto'] = [ file(photo_filename, 'rb').read() ]
147 #ldap_dict['photo'] = [ file(photo_filename, 'rb').read() ]
148 # identification unique
385a99a4
P
149 ldap_dn = u'mail=%s,%s' % (adel, self.ldap_base)
150 return ldap_dn, ldap_dict
151
152 def load(self):
153 self.data = [ ]
154 for json_dict in aufrefer.get('annuaire.json'):
155 ldap_dn, ldap_dict = self.json2ldap(json_dict)
156 self.data.append(LdapEntry(ldap_dn, ldap_dict))
157
158 def to_ldif(self):
159 ldif = [ LDAP_INIT_LDIF ]
160 for d in self.data:
161 ldif.append(d.to_ldif(changeType='add'))
162 ldif.append('')
163 return '\n'.join(ldif)
164
165 def search(self, name):
166 return filter(lambda x: x['adel'].find(name) >= 0, self.data)
167
168 def update_ldap(self, base=LDAP_BASE,
169 host=LDAP_HOST, binddn=LDAP_BINDDN, pwfile=LDAP_PWFILE):
170 pass
171
172if __name__ == '__main__':
173 annuaire = AnnuaireAuF(LDAP_BASE)
174 annuaire.load()
175 #print "search('andre'): %s" % \
176 # map(lambda x: x['adel'], annuaire.search('andre'))
177 print annuaire.to_ldif(),
178