diff --git a/README.md b/README.md index 85d66b5..74b9e12 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,12 @@ We use [CASino](http://casino.rbcas.com) as CAS server, but it might work with o ### Usage -This plugin was made for redmine installations without public areas ("Authentication required"). -The default login page will still work when you access it directly (http://example.com/path-to-redmine/login). +If your installation has no public areas ("Authentication required") and you are not logged in, you will be +redirected to the CAS-login page. The default login page will still work when you access it directly +(http://example.com/path-to-redmine/login). + +If your installation is not "Authentication required", the login page will show a link that lets you login +with CAS. ### Single Sign Out, Single Logout diff --git a/app/views/redmine_cas/_cas_login_link.html.erb b/app/views/redmine_cas/_cas_login_link.html.erb new file mode 100644 index 0000000..37ef4b2 --- /dev/null +++ b/app/views/redmine_cas/_cas_login_link.html.erb @@ -0,0 +1,5 @@ +<% if Setting.plugin_redmine_cas[:enabled] %> +

+ <%= link_to("Login with CAS", :controller => "account", :action => "cas") %> +

+<% end %> diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..2d16db9 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,3 @@ +RedmineApp::Application.routes.draw do + get 'cas', :to => 'account#cas' +end diff --git a/init.rb b/init.rb index 60ac357..90d7e97 100644 --- a/init.rb +++ b/init.rb @@ -3,6 +3,8 @@ require 'redmine_cas' require 'redmine_cas/application_controller_patch' require 'redmine_cas/account_controller_patch' +require_dependency 'redmine_cas_hook_listener' + Redmine::Plugin.register :redmine_cas do name 'Redmine CAS' author 'Nils Caspar (Nine Internet Solutions AG)' diff --git a/lib/redmine_cas/account_controller_patch.rb b/lib/redmine_cas/account_controller_patch.rb index e6b32f0..2c04560 100644 --- a/lib/redmine_cas/account_controller_patch.rb +++ b/lib/redmine_cas/account_controller_patch.rb @@ -15,6 +15,61 @@ module RedmineCAS logout_user CASClient::Frameworks::Rails::Filter.logout(self, home_url) end + + def cas + return redirect_to_action('login') unless RedmineCAS.enabled? + + if User.current.logged? + # User already logged in. + redirect_back_or_default my_page_path + return + end + + # The rest of this file just contains what was in + # application_controller_patch.rb before. + + if CASClient::Frameworks::Rails::Filter.filter(self) + user = User.find_by_login(session[:cas_user]) + + # Auto-create user if possible + if user.nil? && RedmineCAS.autocreate_users? + user = User.new + user.login = session[:cas_user] + user.assign_attributes(RedmineCAS.user_extra_attributes_from_session(session)) + return cas_user_not_created(user) if !user.save + user.reload + end + + return cas_user_not_found if user.nil? + return cas_account_pending unless user.active? + user.update_attribute(:last_login_on, Time.now) + user.update_attributes(RedmineCAS.user_extra_attributes_from_session(session)) + if RedmineCAS.single_sign_out_enabled? + # logged_user= would start a new session and break single sign-out + User.current = user + start_user_session(user) + else + self.logged_user = user + end + redirect_to url_for(params.merge(:ticket => nil)) + else + # CASClient called redirect_to + end + end + + def cas_account_pending + render_403 :message => l(:notice_account_pending) + end + + def cas_user_not_found + render_403 :message => l(:redmine_cas_user_not_found, :user => session[:cas_user]) + end + + def cas_user_not_created(user) + logger.error "Could not auto-create user: #{user.errors.full_messages.to_sentence}" + render_403 :message => l(:redmine_cas_user_not_created, :user => session[:cas_user]) + end + end end end diff --git a/lib/redmine_cas/application_controller_patch.rb b/lib/redmine_cas/application_controller_patch.rb index f3b5e6f..484db28 100644 --- a/lib/redmine_cas/application_controller_patch.rb +++ b/lib/redmine_cas/application_controller_patch.rb @@ -15,8 +15,8 @@ module RedmineCAS return require_login_without_cas unless RedmineCAS.enabled? if !User.current.logged? respond_to do |format| - format.html { login_with_cas } - format.atom { login_with_cas } + format.html { redirect_to :controller => 'account', :action => 'cas' } + format.atom { redirect_to :controller => 'account', :action => 'cas' } format.xml { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } format.js { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' } @@ -26,36 +26,6 @@ module RedmineCAS true end - def login_with_cas - if CASClient::Frameworks::Rails::Filter.filter(self) - user = User.find_by_login(session[:cas_user]) - - # Auto-create user if possible - if user.nil? && RedmineCAS.autocreate_users? - user = User.new - user.login = session[:cas_user] - user.assign_attributes(RedmineCAS.user_extra_attributes_from_session(session)) - return cas_user_not_created(user) if !user.save - user.reload - end - - return cas_user_not_found if user.nil? - return cas_account_pending unless user.active? - user.update_attribute(:last_login_on, Time.now) - user.update_attributes(RedmineCAS.user_extra_attributes_from_session(session)) - if RedmineCAS.single_sign_out_enabled? - # logged_user= would start a new session and break single sign-out - User.current = user - start_user_session(user) - else - self.logged_user = user - end - redirect_to url_for(params.merge(:ticket => nil)) - else - # CASClient called redirect_to - end - end - def verify_authenticity_token_with_cas if cas_logout_request? logger.info 'CAS logout request detected: Skipping validation of authenticity token' @@ -68,18 +38,6 @@ module RedmineCAS request.post? && params.has_key?('logoutRequest') end - def cas_account_pending - render_403 :message => l(:notice_account_pending) - end - - def cas_user_not_found - render_403 :message => l(:redmine_cas_user_not_found, :user => session[:cas_user]) - end - - def cas_user_not_created(user) - logger.error "Could not auto-create user: #{user.errors.full_messages.to_sentence}" - render_403 :message => l(:redmine_cas_user_not_created, :user => session[:cas_user]) - end end end end diff --git a/lib/redmine_cas_hook_listener.rb b/lib/redmine_cas_hook_listener.rb new file mode 100644 index 0000000..2142704 --- /dev/null +++ b/lib/redmine_cas_hook_listener.rb @@ -0,0 +1,5 @@ +module RedmineCAS + class RedmineCASHookListener < Redmine::Hook::ViewListener + render_on :view_account_login_top, :partial => 'redmine_cas/cas_login_link' + end +end