CASify Redmine
Redmine is a project management web application. It’s written in Ruby using the Rails framework. There is a CAS client available written in Ruby: RubyCAS-Client.
So, I’ve made some modifications on Redmine code in order to use the CAS service to authenticate Redmine users. Moreover, user information is updated from a LDAP every time the user login in the Redmine website (using Net::LDAP). And the fields to modify this data will be disabled on My account page.
Summarizing, I’ve uploaded a patch which provides this specific behaviour (this patch is done against the revision 2824 of Redmine). I know that it’s hardcoded, but it could be a base for further steps and I hope that it could be useful for someone else (or even for me in the future ;-) ). In the next paragraphs I’ll go into more technical details.
Instructions
Once you’ve installed the last version of Redmine (I’m using trunk revision 2824), you’ll need to install RubyCAS-Client (again from trunk because of some functions are not available at last stable 2.0.1):
./script/plugin install http://rubycas-client.googlecode.com/svn/trunk/rubycas-client
First of all, you should add the basic configuration for CAS at config/environment.rb
:
CASClient::Frameworks::Rails::Filter.configure( :cas_base_url => 'https://localhost/cas/' )
Moreover, it’s needed to add the next line to the class AccountController
at app/controllers/account_controller.rb
:
before_filter CASClient::Frameworks::Rails::Filter
Then, in order to change the login behaviour you should modify the login
action of the account
controller. Change the method login
at app/controllers/account_controller.rb
:
require 'casclient' require 'casclient/frameworks/rails/filter' def login if session[:cas_user].empty? # Logout user self.logged_user = nil CASClient::Frameworks::Rails::Filter::redirect_to_cas_for_authentication(self) else cas_authentication(session[:cas_user]) end end
Now, it’s necessary to add the new method cas_authentication
, which register an user if it’s the first time that makes login on the Redmine website:
def cas_authentication(cas_user) user = User.find_or_initialize_by_login(cas_user) if user.new_record? # Create on the fly user.login = cas_user user = update_user_data_from_ldap(user) user.status = User::STATUS_REGISTERED register_automatically(user) do onthefly_creation_failed(user) end else if user.active? user = update_user_data_from_ldap(user, true) successful_authentication(user) else account_pending end end end
The method update_user_data_from_ldap
gets the user data from LDAP, and update user data on database if needed:
def update_user_data_from_ldap (user, save = false) ldap = Net::LDAP::new ldap.host = 'localhost' ldap.port = '389' treebase = 'dc=example,dc=com' filter = Net::LDAP::Filter.eq('uid', user.login) entry = ldap.search( :base => treebase, :filter => filter, :attributes => ['cn', 'sn', 'mail'] ).first user.firstname = entry.cn.first user.lastname = entry.sn.first user.mail = entry.mail.first user.save if save return user end
Following, you should modify the logout behaviour, changing the method logout
of the same controller:
def logout cookies.delete :autologin Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? self.logged_user = nil CASClient::Frameworks::Rails::Filter::logout(self) end
The last step is to disable the fields gotten from LDAP at My account page. Modify the app/views/my/account.rhtml
file adding :disabled => true
option:
<p><%= f.text_field :firstname, :required => true, :disabled => true %></p> <p><%= f.text_field :lastname, :required => true, :disabled => true %></p> <p><%= f.text_field :mail, :required => true, :disabled => true %></p>
Finally, you can get all this stuff from a single patch. Any comment or suggestion are, as usual, welcomed.
Comments
Hello,
I use Redmine 0.8.4 (latest stable release)
CASifying Redmine will be great. But why do you write a function to connect to LDAP although LDAP configuration can be made in the Redmine interface ?
I’m dreaming of a SSO plugin for Redmine. But I’m not be able to do it. :-(
Do you ? ;-)Regards, Neoh
PS: Sorry for my poor english, I’m french.
On 09/08/14 07:22, Manuel Rego Casasnovas wrote:
I’m just using LDAP for a specific requirement. I need that the first time the user login Redmine, the information from LDAP about this use was stored on the database (morover every time the user login again I should update the data if that has changed on LDAP). Anyway, I could have a look at LDAP plugin, maybe it fulfils my requirements ;-)
About the SSO plugin, maybe this patch could be useful as example for that plugin. But for the moment it’s enough for my needs.
On 09/11/25 12:15, rubiojr wrote:
Awesome mate. Your patch saved us hours of work!!!
On 10/04/15 16:44, lnomine wrote:
Hi,
Do you plan to use the 0.9.x version of Redmine? I’d love to see your patch working for the current version.
On 10/04/15 16:52, Manuel Rego Casasnovas wrote:
Maybe in the future we could update to this version, but not in the short term. Sorry.
I’ll keep you informed if we update the patch.
- Previous: GCDS Day 6 – Last day
- Next: Reviewing gedit project