Redmine includes functionality for authenticating users against Active Directory (and LDAP in general). With "on the fly user creation" users can authenticate with their AD username and password: a user will be created on first login.
The problem is that until a user authenticates for the first time on Redmine, she does not appear in the user list. This means that when a project manager needs to start a new project, she needs to create it, notify project members to log in and then assign specific roles to each one of them (developers, managers, testers etc.).
It would be much easier if the project Manager could immediately see the new users listed within Redmine and assign roles to them without waiting for them to log in for the first time. There is a patch for Redmine that provides exactly this functionality. Unfortunately, applying a patch to the Redmine code will certainly break the possibility for easy updates. Redmine is still under heavy development and having to merge future versions with old patches could be painful.
Ruby to the rescue!
The standard Rails application skeleton includes a set of useful scripts under the {application root}/script folder:
>> indice@hostname:/0.8-stable/script$ ls about breakpointer console dbconsole destroy generate performance plugin process runner server indice@hostname:/0.8-stable/script$
Starting the console script gives a ruby shell with all redmine application classes and environment available. The console also features history and autocompletion.
indice@hostname:/0.8-stable/script$ ./console Loading development environment(Rails 2.1.2) GLoc v1.1 running in development mode. Strings can be modified at runtime. >> Redmine.name=> "Redmine" >>
Having the console loaded, I could load the one and only Ldap authentication source from the Redmine database by calling:
A cool feature of the ruby language is the ability to easily manipulate classes on runtime. I can add a method to the AuthSourceLdap class by typing it on the console. The new method adds functionality to import all users from the AD Server in Redmine.
The search filter that should be applied on the Ldap database to select all users is just hardcoded in the script, but it does not make such a big difference since this attribute is expected to never change.
The method will immediately become available for all objects of the class that are already loaded as well. So this method is now also available on the @auth_method object I had already loaded from the database. Calling it imports all found users:
>> @auth_method.import=> {:skipped=>0, :found=>67, :imported=>67}
The scripts directory of every Ruby on Rails application also includes a "runner" script, with which ruby scripts can be called in the context of the application.
Finally I could make a little script that loads the authentication source object from the Redmine Database, adds an import method to it and immediately calls it to import all users from AD.
A simple cron job synchronises the Redmine User Database with Active Directory every five minutes by calling my ruby script through the Redmine runner:
* crontab -e*/5 * * * * /0.8-stable/script/runner \/script-location/ldapimport.rb > \/log-file-location/ldapimport.log 2>&1