LDAP Data Source now with full CRUD !

April 26, 2008

So I was making a site up and had to use LDAP as the backend. CakePHP is my favourite PHP framework and a quick Google search returned a link to a CakePHP bakery article which gave me a great starting point. The class basically allows you to read from LDAP, but that’s it. It was good enough to play with, but I quickly got to a point where I really needed to write to LDAP.

I started investigating how I could get a list of attribute types and object classes from LDAP (without parsing the schema files or something hacky like that). I thought I could look into the phpldapadmin project to see how they did it. I’m glad I did! It was just what I was looking for. They saved me a bit of code!

Credits go out to the original author of the class, euphrate aka “euphrate_ylb”, and to the phpldapadmin guys for some of the code in the class.

Anyway, enough rambling. Onto the good stuff:

  • Download the LDAP data source class and save it as /path/to/cakephp/app/models/datasources/ldap_source.php.
  • You’ll need a model. Mine is in /path/to/cakephp/app/models/ldap_user.php. The most important parts are:
var $useDbConfig = 'ldap';
var $primaryKey = 'uid';

Primary Key is an important one (specially when updating & deleting records). In my LDAP tree, I know for a fact that no 2 users will have the same uid, so I used this field. Feel free to choose another unique field (if, for example, you have an Employee ID field and it is unique).

var $defaultObjectClass = 'inetOrgPerson';

The above variable is used to further strict searching when updating/deleting records to an object class too. If you don’t set the above variable, when you update/delete a user it will search for the $primaryKey field in the entire tree. By restricting to an object class of my liking I ensure I’m not going to get any unwanted matches.

Special note when CREATING records

Since there isn’t any easy way to automagically determine what Distinguished Name (DN) a new record will take, I made it so that one of the fields that you have to submit as part of $this->data is ‘_DN_’. For example, in my beforeSave() function of my ldap_user.php model, I have the following:

function beforeSave() {
        $this->data[$this->name]['_DN_'] = 'cn=' . $user[$this->name]['uid'] . ',ou=Some Department,dc=example,dc=com';
}

When deleting or updating a user, remember to set the $this->Model->id field to be the value that you want to match on (based on $primaryKey). In my case, if I set $this->Model->id = ‘foo’, it will search LDAP for (&(objectclass=inetOrgPerson)(uid=foo)) and based on that match, it will update or delete (depending on what action I’m taking).

It’s now 4AM so there’s a good chance most of what I wrote doesn’t make sense. If you don’t know your way around LDAP, this probably didn’t make a whole lot of sense. Feel free to leave a comment and I’ll try and help out (when I get the chance to!)

I must say it feels good to finally contribute back to a project that has saved me sooo many hours of work. CakePHP is truly an EXCELLENT project that has saved me so many hours of work and brought back the pleasure of coding up a site :) I have been reading lots and lots of CakePHP code lately and the more I read it, the more I like it. It has been well thought out.

That’s it for now. If you have any feedback, suggestions, better ways of doing stuff .. please feel free to leave comments!

– Gonzalo (znoG on irc.freenode.net:#cakephp)