This should be the final refactoring I need before I can fix the Issues API doesn’t allow full key auth for all actions bug. Here I refactored the test that is authenticating against Redmine using an API token but through HTTP Basic. Basically it’s a cross between the Token Auth and the Username and Password Auth.
Before
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
require "#{File.dirname(__FILE__)}/../../test_helper" class ApiTest::HttpBasicLoginWithApiTokenTest @user, :action => 'api') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') get "/news.xml", nil, :authorization => @authorization end should_respond_with :success should_respond_with_content_type :xml should "login as the user" do assert_equal @user, User.current end end context "with an invalid HTTP authentication" do setup do @user = User.generate_with_protected! @token = Token.generate!(:user => @user, :action => 'feeds') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') get "/news.xml", nil, :authorization => @authorization end should_respond_with :unauthorized should_respond_with_content_type :xml should "not login as the user" do assert_equal User.anonymous, User.current end end end context "in :json format" do context "with a valid HTTP authentication" do setup do @user = User.generate_with_protected! @token = Token.generate!(:user => @user, :action => 'api') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'DoesNotMatter') get "/news.json", nil, :authorization => @authorization end should_respond_with :success should_respond_with_content_type :json should "login as the user" do assert_equal @user, User.current end end context "with an invalid HTTP authentication" do setup do @user = User.generate_with_protected! @token = Token.generate!(:user => @user, :action => 'feeds') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'DoesNotMatter') get "/news.json", nil, :authorization => @authorization end should_respond_with :unauthorized should_respond_with_content_type :json should "not login as the user" do assert_equal User.anonymous, User.current end end end end end |
After
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# Test that a request allows the API key with HTTP BASIC # # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete) # @param [String] url the request url # @param [optional, Hash] parameters additional request parameters def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}) context "should allow http basic auth with a key for #{http_method} #{url}" do context "with a valid HTTP authentication using the API token" do setup do @user = User.generate_with_protected! @token = Token.generate!(:user => @user, :action => 'api') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') send(http_method, url, parameters, {:authorization => @authorization}) end should_respond_with :success should_respond_with_content_type_based_on_url(url) should "login as the user" do assert_equal @user, User.current end end context "with an invalid HTTP authentication" do setup do @user = User.generate_with_protected! @token = Token.generate!(:user => @user, :action => 'feeds') @authorization = ActionController::HttpAuthentication::Basic.encode_credentials(@token.value, 'X') send(http_method, url, parameters, {:authorization => @authorization}) end should_respond_with :unauthorized should_respond_with_content_type_based_on_url(url) should "not login as the user" do assert_equal User.anonymous, User.current end end end end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
require "#{File.dirname(__FILE__)}/../../test_helper" class ApiTest::HttpBasicLoginWithApiTokenTest < ActionController::IntegrationTest fixtures :all def setup Setting.rest_api_enabled = '1' Setting.login_required = '1' end def teardown Setting.rest_api_enabled = '0' Setting.login_required = '0' end # Using the NewsController because it's a simple API. context "get /news" do context "in :xml format" do should_allow_http_basic_auth_with_key(:get, "/news.xml") end context "in :json format" do should_allow_http_basic_auth_with_key(:get, "/news.json") end end end |
Now I can use the three new shoulda macros to test that a url works with all of Redmine’s authentication methods:
should_allow_http_basic_auth_with_username_and_password
should_allow_http_basic_auth_with_key
should_allow_key_based_auth
This has been a roundabout way of fixing bug #6447 but it’s necessary with large code bases like Redmine. Refactoring and paying back technical debt has to happen every once in a while. A good time for that is right before you are fixing a bug in that area.
I’m getting 404s on the last two links in your first paragraph.
Should be fixed now. Thanks.