Phonebook

Summary: Integrate LDAP information in the Profiles pages and use it as a corporate phonebook
Version: 0.3
Prerequisites: pmwiki 2.1
Status: Production
Maintainer: TjeerdVanDerLaan

Questions answered by this recipe

In our network we use an LDAP directory (or Active Directory) as a central repository for user information. After I've implemented single sign-on for my PmWiki based intranet I would like to integrate our LDAP directory information in PmWiki so that it adds some kind of corporate phonebook to PmWiki.

Description

This recipe synchronizes the Profiles pages with users in the LDAP directory. When new users are added the Profiles pages are automatically added. Information like telephone numbers is automatically refreshed in existing pages. Finally when users are deleted the Profiles pages are accordingly deleted. Additionally some page variables are added to be able to use the LDAP information in pages (or the Profiles.GroupHeader? page).

Installation

Put phonebook.phpΔ in your cookbook directory.

Add the following lines to your local/config.php and specify the variables according to your environment. Note that a valid username and password are needed:

SDV($Phonebook_GroupName, 'Profiles'); 
SDV($Phonebook_LdapServer,'ldap://dc.internal.services');
SDV($Phonebook_LdapUser,'username@internal.services');
SDV($Phonebook_LdapPass,'password');
SDV($Phonebook_BaseDn,'dc=internal,dc=services');
SDV($Phonebook_Filter,'(&(objectClass=user)(objectClass=person)
        (telephonenumber=*)(|(homeMDB=*)(msExchHomeServerName=*))
        (!(objectClass=computer))(!(description=Disabled*)))');
SDV($Phonebook_Title,'cn'); 
SDV($Phonebook_Fields, Array('cn','sn','givenname','description','title',
        'initials','department','mail','telephonenumber',
        'physicaldeliveryofficename','samaccountname','mobile'));
SDV($Phonebook_Interval,3600); // cleanup pages every hour
include_once("$FarmD/cookbook/phonebook.php");

For each of the fields specified a page variable is created like $ldap_sn or $ldap_givenname. These variables can be used in the pages. Although users can add all kind of information to their profile page, initially there are only empty pages created so the phonebook information is not automatically shown. Therefore create a Profiles.GroupHeader page so that each page shows the directory information. Note that a reference to photo is part of the generic information:

(:title {$ldap_cn}:)

%rframe height=140px% Attach:{$ldap_samaccountname}.jpg
||width:40%
||Title:||{$ldap_title} ||
||Name:||{$ldap_sn} ||
||First name:||{$ldap_givenname} ||
||Job title:||{$ldap_description} ||
||Department:||{$ldap_department} ||
||Telephone:||{$ldap_telephonenumber} ||
||Room:||{$ldap_physicaldeliveryofficename} ||
||Mobile:||{$ldap_mobile} ||

----

By standard PmWiki only searches the target and text fields of the pages. This recipe adds a phonebook field to all Profiles pages. In order to allow to search for phonebook data the following line has to be changed in the pagelist.php (written in diff format for version 2.1.26):

356c356
>  $text = $fold($pn."\n".@$page['targets']."\n"..@$page['phonebook']."\n".@$page['text']);

If you are using the PageListExtensions cookbook change the following line in this cookbook:

230c230
>  $text = $pn."\n".@$page['targets']."\n".@$page['phonebook']."\n".@$page['text'];

Now that the phonebook information can be searched a separate Profiles.Search? page can be created. First this file should suppress the GroupHeader. Also the result list of a phonebook needs a different layout:

(:nogroupheader:)
(:title Employee search:)
(:searchbox group=Profiles list=normal fmt=#phonebook:)

----

(:searchresults:)

For the layout of the phonebook search results add the following template to the Site.LocalTemplates page:

[[#phonebook]]
(:if equal {<$Group}:)
(:table class=phonebook width="90%" :)
(:cell style="background:#e5e5ff;padding-left:5px" :)'''Name'''
(:cell style="background:#e5e5ff;padding-left:5px" :)%thd%'''Telephone''' 
(:cell style="background:#e5e5ff;padding-left:5px" :)%thd%'''Room''' (:if:)
(:cellnr style="background:#eeeeff;padding-left:5px" :)[[{=$FullName}|{=$Title}]] 
(:cell style="background:#eeeeff;padding-left:5px" :){=$ldap_telephonenumber}
(:cell style="background:#eeeeff;padding-left:5px" :){=$ldap_physicaldeliveryofficename} 
(:if equal {>$Group}:)
(:tableend:)(:if:)
[[#phonebookend]]

Finally finish the complete phonebook functionality by creating the home-page Profles.Profiles?. This page can present a search box like the Profiles.Search? screen, but for a somewhat smaller organization also the complete list of employees can be shown:

(:nogroupheader:)

(:title All employees:)
(:pagelist group=Profiles list=normal:)

Release Notes

Version 0.1

This is my first attempt. Although the low number (I always start there) this first attempt now works quite well for some weeks now.

This cookbook defines a new PageStore class in which the ls() function is used to browse through an LDAP directory for entries. For each entry returned by the LDAP directory a profile page with the SAMAccountName is updated with a phonebook value which contains an array of LDAP fields and values. If the page does not exist, it is created as an empty page. All pages that exist but are not in the LDAP directory are deleted using the delete action (so the information remains in the background on the server).

Because a refresh of all Profiles pages at every pagelist action would create too much overhead, this is only done once in a while. The interval is by default once per hour. Therefore a timestamp has to be kept (the file wiki.d/.phonebook.timestamp acts as such). This recipe is used in organization with up to 200 users in the LDAP directory without any performance problems. There is up to now no experience with larger sets of Profiles pages.

If the specification of the fields is changed, delete the wiki.d/.phonebook.timestamp file and request a pagelist of the Profiles pages. All phonebook information in the pages is refreshed.

Although I do not like altering the source of other scripts in order to make the recipe working, I did not find another way to let Pmwiki search for the phonebook information. Maybe the search fields can be made configurable in an upcoming version?

Version 0.2

Repaired a bug in the deletion of pages. A variable is used to configure pages to be kept and not deleted.

Version 0.3

The title of the pages is now refreshed as well.

Contributors

Tjeerd van der Laan

Comments

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.