From 5344a35f723bf1501bb6274ef80195154c3e061f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Thu, 11 Oct 2012 17:07:24 +0000 Subject: [PATCH] Adds an optional X-Redmine-Switch-User header to let admin users swicth user in API calls (#11755). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10608 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/application_controller.rb | 15 +++++++ .../api_test/authentication_test.rb | 41 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e5234a4bc..6c7779636 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -110,6 +110,16 @@ class ApplicationController < ActionController::Base user = User.try_to_login(username, password) || User.find_by_api_key(username) end end + # Switch user if requested by an admin user + if user && user.admin? && (username = api_switch_user_from_request) + su = User.find_by_login(username) + if su && su.active? + logger.info(" User switched by: #{user.login} (id=#{user.id})") if logger + user = su + else + render_error :message => 'Invalid X-Redmine-Switch-User header', :status => 412 + end + end end user end @@ -508,6 +518,11 @@ class ApplicationController < ActionController::Base end end + # Returns the API 'switch user' value if present + def api_switch_user_from_request + request.headers["X-Redmine-Switch-User"].to_s.presence + end + # Renders a warning flash if obj has unsaved attachments def render_attachment_warning_if_needed(obj) flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present? diff --git a/test/integration/api_test/authentication_test.rb b/test/integration/api_test/authentication_test.rb index 10527431a..a22c8897b 100644 --- a/test/integration/api_test/authentication_test.rb +++ b/test/integration/api_test/authentication_test.rb @@ -20,6 +20,14 @@ require File.expand_path('../../../test_helper', __FILE__) class ApiTest::AuthenticationTest < ActionController::IntegrationTest fixtures :users + def setup + Setting.rest_api_enabled = '1' + end + + def teardown + Setting.rest_api_enabled = '0' + end + def test_api_request_should_not_use_user_session log_user('jsmith', 'jsmith') @@ -29,4 +37,37 @@ class ApiTest::AuthenticationTest < ActionController::IntegrationTest get '/users/current.json' assert_response 401 end + + def test_api_should_accept_switch_user_header_for_admin_user + user = User.find(1) + su = User.find(4) + + get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login} + assert_response :success + assert_equal su, assigns(:user) + assert_equal su, User.current + end + + def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user + get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => 'foobar'} + assert_response 412 + end + + def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user + user = User.find(5) + assert user.locked? + + get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => user.login} + assert_response 412 + end + + def test_api_should_not_accept_switch_user_header_for_non_admin_user + user = User.find(2) + su = User.find(4) + + get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login} + assert_response :success + assert_equal user, assigns(:user) + assert_equal user, User.current + end end -- 2.39.5