summaryrefslogtreecommitdiffstats
path: root/PcfAnnuaire.py
blob: 6e97dd1e168c6063475fc61cb3af516bcaf48114 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# -*- coding: UTF-8 -*-

""" PcfAnnuaire Class """

import os
import time
import calendar
import ldap
import urllib

from interfaces import IPcfAnnuaire
from zope.interface import implements
from Products.Archetypes.public import *
from Products.CMFCore.utils import getToolByName
from plone.memoize.volatile import cache, DontCache
from Acquisition import aq_base

schema = BaseSchema

def get_sort_key(x):
    return (getattr(x, 'sn') + getattr(x, 'givenName')).lower()

class PcfAnnuaireEntry:
    def __init__(self, directory, ldap_dn, ldap_entry):
        def get_attr(x):
            try:
                return ldap_entry.get(x)[0].strip()
            except (IndexError, TypeError):
                return None
        self.directory = directory
        self._debug_entry = ldap_entry
        self.debug_entry = ldap_entry
        self.dn = ldap_dn
        self.cn = get_attr('cn')
        self.sn = get_attr('sn')
        self.telephoneNumbers = ldap_entry.get('telephoneNumber')
        if self.telephoneNumbers:
            self.shortTelephoneNumber = self.telephoneNumbers[0][-3:]
        else:
            self.shortTelephoneNumber = None
        self.givenName = get_attr('givenName')
        self.displayName = get_attr('displayName')
        self.mobile = get_attr('mobile')
        self.service = get_attr('department')
        self.building = get_attr('destinationIndicator')
        self.floor = get_attr('extensionAttribute1')
        self.plan_filename = 'unknown.jpg'
        if self.building and self.floor:
            if self.building == 'Hôtel de Ligne':
                bld = 'hdl'
            elif self.building == 'Hôtel du Greffe':
                bld = 'hdg'
            else:
                bld = 'unknown'
            self.plan_filename = '%s%s.jpg' % (bld, self.floor)
        self.office = get_attr('physicalDeliveryOfficeName')
        self.fax = get_attr('facsimileTelephoneNumber')
        self.email = get_attr('mail')
        self.division = get_attr('division')
        self.title = get_attr('title')
        self.company = get_attr('company')
        self.samaccountname = get_attr('sAMAccountName')
        self.manager = get_attr('manager')
        self.manager_name = None
        if self.manager:
            self.manager_url = urllib.quote(self.manager)
            self.manager_name = self.manager.split('=')[1].split(',')[0]

    def __str__(self):
        return urllib.quote(self.dn)

    def has_a_chief(self):
        if not self.manager:
            return False
        if self.service == 'Service du Greffier':
            return True
        sec_gen = self.directory.getSecretaireGeneral()
        if self.manager == sec_gen.dn:
            return False
        return True
    has_a_chief = property(has_a_chief)

class PcfAnnuaireService:
    pass

def cache_key(method, self):
    # append time, so old entries do not get returned forever; (they will still
    # get removed as stale entries are automatically removed after 3 days)
    # (cf plone/memoize/volatile.py)
    return '%s_%s' % (hash(self), (int(time.time()) / 300))

class PcfAnnuaire(BaseContent):

    implements(IPcfAnnuaire)

    schema = schema
    _at_rename_after_creation = True

    def get_ldap_conn(self):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        ldapdir = aq_base(portal.acl_users.ldap)
        luf = ldapdir._getLDAPUserFolder()
        server = luf._delegate.getServers()[0]
        ldap_conn = ldap.initialize('%(protocol)s://%(host)s:%(port)s' % server)
        ldap_conn.simple_bind_s(luf._binduid, luf._bindpwd)
        return ldap_conn

    def get_users_base(self):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        ldapdir = aq_base(portal.acl_users.ldap)
        luf = ldapdir._getLDAPUserFolder()
        users_base = 'OU=ouPCF,' + luf.users_base
        return users_base

    def getObjectEntries(self):
        ldap_conn = self.get_ldap_conn()
        result = ldap_conn.search_s(self.get_users_base(),
                        ldap.SCOPE_SUBTREE, 'objectClass=person')
        return [PcfAnnuaireEntry(self, *x) for x in result]

    @cache(cache_key)
    def getEntries(self):
        t = [x for x in self.getObjectEntries() if \
                x.givenName and x.company == 'Parlement de la Communauté française de Belgique']
        t.sort(key=get_sort_key)
        return t

    def getServices(self):
        entries = self.getObjectEntries()
        services = {}
        for entry in entries:
            if not entry.division:
                continue
            if not entry.division in services:
                service = Service()
                service.name = entry.division
                service.agents = []
                services[division] = service
            service = services.get(entry.division)
            service.agents.append(entry)
        def get_name(x): return getattr(x, 'name')
        services = sorted([x for x in services.values()], key=get_name)
        for service in services:
            services.agents.sort(key=get_sort_key)
        return services

    def getEntriesWithPhone(self):
        return sorted([x for x in self.getEntries() if x.telephoneNumbers], key=get_sort_key)

    def getSecretaireGeneral(self):
        try:
            return [x for x in self.getEntries() if x.title == 'Secrétaire Général'][0]
        except IndexError:
            raise KeyError

    def getServices(self):
        services = {}
        for entry in self.getEntries():
            services[entry.service] = True
        services = sorted(services.keys())
        return services

    def getServiceManager(self, service):
        sec_gen = self.getSecretaireGeneral()
        if service == 'Service du Greffier':
            return sec_gen
        try:
            return [x for x in self.getEntries() if x.service == service and x.manager == sec_gen.dn][0]
        except IndexError:
            return None

    def getServiceNonManagers(self, service):
        service_manager = self.getServiceManager(service)
        entries = [x for x in self.getEntries() if \
                   x.service == service and x.manager == service_manager.dn and x.division in (None, ' ')]
        return sorted(entries, key=get_sort_key)

    def getCellules(self, service):
        service_manager = self.getServiceManager(service)
        entries = [x for x in self.getEntries() if x.manager == service_manager.dn]
        cells = {}
        for entry in entries:
            if entry.division and entry.division != ' ':
                cells[entry.division] = True
        cells = sorted(cells.keys())
        return cells

    def getCelluleManagers(self, service, cellule):
        service_manager = self.getServiceManager(service)
        entries = [x for x in self.getEntries() if \
                   x.service == service and x.division == cellule and x.manager == service_manager.dn]
        return sorted(entries, key=get_sort_key)

    def getCellulePeople(self, service, cellule):
        cellule_managers = [x.dn for x in self.getCelluleManagers(service, cellule)]
        entries = [x for x in self.getEntries() if \
                   x.service == service and x.division == cellule and x.dn not in cellule_managers]
        return sorted(entries, key=get_sort_key)

    def getPerson(self, dn):
        person = [x for x in self.getEntries() if x.dn == dn][0]
        return person

registerType(PcfAnnuaire)