]> source.dussan.org Git - redmine.git/commitdiff
Test API authentification once.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 30 Nov 2014 14:11:56 +0000 (14:11 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 30 Nov 2014 14:11:56 +0000 (14:11 +0000)
git-svn-id: http://svn.redmine.org/redmine/trunk@13675 e93f8b46-1217-0410-a6f0-8f06a7374b81

test/integration/api_test/authentication_test.rb
test/integration/api_test/http_basic_login_test.rb [deleted file]
test/integration/api_test/http_basic_login_with_api_token_test.rb [deleted file]
test/integration/api_test/issues_test.rb
test/integration/api_test/news_test.rb
test/integration/api_test/projects_test.rb
test/integration/api_test/token_authentication_test.rb [deleted file]
test/integration/api_test/users_test.rb
test/test_helper.rb

index b8c9e0746b9b8c867d7a28dbe43217c26b7147a8..8452717e3529bc577fcf72836d1178ded3a8088a 100644 (file)
@@ -28,6 +28,79 @@ class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base
     Setting.rest_api_enabled = '0'
   end
 
+  def test_api_should_deny_without_credentials
+    get '/users/current.xml', {}
+    assert_response 401
+    assert_equal User.anonymous, User.current
+    assert response.headers.has_key?('WWW-Authenticate')
+  end
+
+  def test_api_should_accept_http_basic_auth_using_username_and_password
+    user = User.generate! do |user|
+      user.password = 'my_password'
+    end
+    get '/users/current.xml', {}, credentials(user.login, 'my_password')
+    assert_response 200
+    assert_equal user, User.current
+  end
+
+  def test_api_should_deny_http_basic_auth_using_username_and_wrong_password
+    user = User.generate! do |user|
+      user.password = 'my_password'
+    end
+    get '/users/current.xml', {}, credentials(user.login, 'wrong_password')
+    assert_response 401
+    assert_equal User.anonymous, User.current
+  end
+
+  def test_api_should_accept_http_basic_auth_using_api_key
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'api')
+    get '/users/current.xml', {}, credentials(token.value, 'X')
+    assert_response 200
+    assert_equal user, User.current
+  end
+
+  def test_api_should_deny_http_basic_auth_using_wrong_api_key
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'feeds') # not the API key
+    get '/users/current.xml', {}, credentials(token.value, 'X')
+    assert_response 401
+    assert_equal User.anonymous, User.current
+  end
+
+  def test_api_should_accept_auth_using_api_key_as_parameter
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'api')
+    get "/users/current.xml?key=#{token.value}", {}
+    assert_response 200
+    assert_equal user, User.current
+  end
+
+  def test_api_should_deny_auth_using_wrong_api_key_as_parameter
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'feeds') # not the API key
+    get "/users/current.xml?key=#{token.value}", {}
+    assert_response 401
+    assert_equal User.anonymous, User.current
+  end
+
+  def test_api_should_accept_auth_using_api_key_as_request_header
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'api')
+    get "/users/current.xml", {}, {'X-Redmine-API-Key' => token.value.to_s}
+    assert_response 200
+    assert_equal user, User.current
+  end
+
+  def test_api_should_deny_auth_using_wrong_api_key_as_request_header
+    user = User.generate!
+    token = Token.create!(:user => user, :action => 'feeds') # not the API key
+    get "/users/current.xml", {}, {'X-Redmine-API-Key' => token.value.to_s}
+    assert_response 401
+    assert_equal User.anonymous, User.current
+  end
+
   def test_api_should_trigger_basic_http_auth_with_basic_authorization_header
     ApplicationController.any_instance.expects(:authenticate_with_http_basic).once
     get '/users/current.xml', {}, credentials('jsmith')
diff --git a/test/integration/api_test/http_basic_login_test.rb b/test/integration/api_test/http_basic_login_test.rb
deleted file mode 100644 (file)
index 2fbf610..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2014  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '1'
-    project = Project.find('onlinestore')
-    EnabledModule.create(:project => project, :name => 'news')
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '0'
-  end
-
-  should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
-  should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
-end
diff --git a/test/integration/api_test/http_basic_login_with_api_token_test.rb b/test/integration/api_test/http_basic_login_with_api_token_test.rb
deleted file mode 100644 (file)
index 6213399..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2014  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  def setup
-    Setting.rest_api_enabled = '1'
-    Setting.login_required = '1'
-  end
-
-  def teardown
-    Setting.rest_api_enabled = '0'
-    Setting.login_required = '0'
-  end
-
-  should_allow_http_basic_auth_with_key(:get, "/news.xml")
-  should_allow_http_basic_auth_with_key(:get, "/news.json")
-end
index b63ce88ef8a88e73b9187d3e5aaa8ebbf8e020af..68b9c6b7749c77eb5c5053c3224b16ec2be14ac2 100644 (file)
@@ -48,44 +48,6 @@ class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
     Setting.rest_api_enabled = '1'
   end
 
-  # Use a private project to make sure auth is really working and not just
-  # only showing public issues.
-  should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
-  should_allow_api_authentication(:get, "/projects/private-child/issues.json")
-
-  should_allow_api_authentication(:get, "/issues/6.xml")
-  should_allow_api_authentication(:get, "/issues/6.json")
-
-  should_allow_api_authentication(
-    :post,
-    '/issues.xml',
-    {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
-    {:success_code => :created}
-  )
-  should_allow_api_authentication(:post,
-                                  '/issues.json',
-                                  {:issue => {:project_id => 1, :subject => 'API test',
-                                   :tracker_id => 2, :status_id => 3}},
-                                  {:success_code => :created})
-
-  should_allow_api_authentication(:put,
-                                  '/issues/6.xml',
-                                  {:issue => {:subject => 'API update', :notes => 'A new note'}},
-                                  {:success_code => :ok})
-  should_allow_api_authentication(:put,
-                                  '/issues/6.json',
-                                  {:issue => {:subject => 'API update', :notes => 'A new note'}},
-                                  {:success_code => :ok})
-
-  should_allow_api_authentication(:delete,
-                                  '/issues/6.xml',
-                                  {},
-                                  {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-                                  '/issues/6.json',
-                                  {},
-                                  {:success_code => :ok})
-
   test "GET /issues.xml should contain metadata" do
     get '/issues.xml'
     assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]',
index 67984e70f579aae34f2f1ee4394bb3ebc6737439..a450c476564e8f8fec75ebf9a7b803c7846c85b0 100644 (file)
@@ -31,9 +31,6 @@ class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base
     Setting.rest_api_enabled = '1'
   end
 
-  should_allow_api_authentication(:get, "/projects/onlinestore/news.xml")
-  should_allow_api_authentication(:get, "/projects/onlinestore/news.json")
-
   test "GET /news.xml should return news" do
     get '/news.xml'
 
index 16c556ddee0d73061b50d2b56b71bba90d73e2cf..32d5eb9199dcef5903b9f89eb8bbde34dbb96b44 100644 (file)
@@ -27,23 +27,6 @@ class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
     set_tmp_attachments_directory
   end
 
-  # TODO: A private project is needed because should_allow_api_authentication
-  # actually tests that authentication is *required*, not just allowed
-  should_allow_api_authentication(:get, "/projects/2.xml")
-  should_allow_api_authentication(:get, "/projects/2.json")
-  should_allow_api_authentication(:post,
-                                  '/projects.xml',
-                                  {:project => {:name => 'API test', :identifier => 'api-test'}},
-                                  {:success_code => :created})
-  should_allow_api_authentication(:put,
-                                  '/projects/2.xml',
-                                  {:project => {:name => 'API update'}},
-                                  {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-                                  '/projects/2.xml',
-                                  {},
-                                  {:success_code => :ok})
-
   test "GET /projects.xml should return projects" do
     get '/projects.xml'
     assert_response :success
diff --git a/test/integration/api_test/token_authentication_test.rb b/test/integration/api_test/token_authentication_test.rb
deleted file mode 100644 (file)
index 2728232..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2014  Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::TokenAuthenticationTest < Redmine::ApiTest::Base
-  fixtures :projects, :trackers, :issue_statuses, :issues,
-           :enumerations, :users, :issue_categories,
-           :projects_trackers,
-           :roles,
-           :member_roles,
-           :members,
-           :enabled_modules
-
-  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.
-  should_allow_key_based_auth(:get, "/news.xml")
-  should_allow_key_based_auth(:get, "/news.json")
-end
index f44948c542946684d17b85d5467ab5ddd24fc8ba..89fdadaf8b9445faa32b0c5acdd2bbae2eb9e539 100644 (file)
@@ -24,45 +24,6 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base
     Setting.rest_api_enabled = '1'
   end
 
-  should_allow_api_authentication(:get, "/users.xml")
-  should_allow_api_authentication(:get, "/users.json")
-  should_allow_api_authentication(:post,
-    '/users.xml',
-     {:user => {
-        :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-        :mail => 'foo@example.net', :password => 'secret123'
-      }},
-    {:success_code => :created})
-  should_allow_api_authentication(:post,
-    '/users.json',
-    {:user => {
-       :login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
-       :mail => 'foo@example.net'
-    }},
-    {:success_code => :created})
-  should_allow_api_authentication(:put,
-    '/users/2.xml',
-    {:user => {
-        :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-        :mail => 'jsmith@somenet.foo'
-    }},
-    {:success_code => :ok})
-  should_allow_api_authentication(:put,
-    '/users/2.json',
-    {:user => {
-        :login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
-        :mail => 'jsmith@somenet.foo'
-    }},
-    {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-    '/users/2.xml',
-    {},
-    {:success_code => :ok})
-  should_allow_api_authentication(:delete,
-    '/users/2.xml',
-    {},
-    {:success_code => :ok})
-
   test "GET /users/:id.xml should return the user" do
     get '/users/2.xml'
 
index 022d6af082f8d3baab2e44bca568f5336a2e8ed3..c66fd60f52820e94136fdb76f7e97b6e1cfcf788 100644 (file)
@@ -263,255 +263,6 @@ module Redmine
 
     # Base class for API tests
     class Base < ActionDispatch::IntegrationTest
-      # Test that a request allows the three types of API authentication
-      #
-      # * HTTP Basic with username and password
-      # * HTTP Basic with an api key for the username
-      # * Key based with the key=X parameter
-      #
-      # @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
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
-        should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
-        should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
-        should_allow_key_based_auth(http_method, url, parameters, options)
-      end
-    
-      # Test that a request allows the username and password for 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
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        context "should allow http basic auth using a username and password for #{http_method} #{url}" do
-          context "with a valid HTTP authentication" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-                user.password = 'my_password'
-              end
-              send(http_method, url, parameters, credentials(@user.login, 'my_password'))
-            end
-    
-            should_respond_with success_code
-            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!
-              send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
-            end
-    
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "not login as the user" do
-              assert_equal User.anonymous, User.current
-            end
-          end
-    
-          context "without credentials" do
-            setup do
-              send(http_method, url, parameters)
-            end
-    
-            should_respond_with failure_code
-            should_respond_with_content_type_based_on_url(url)
-            should "include_www_authenticate_header" do
-              assert @controller.response.headers.has_key?('WWW-Authenticate')
-            end
-          end
-        end
-      end
-    
-      # 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
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        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! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'api')
-              send(http_method, url, parameters, credentials(@token.value, 'X'))
-            end
-            should_respond_with success_code
-            should_respond_with_content_type_based_on_url(url)
-            should_be_a_valid_response_string_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!
-              @token = Token.create!(:user => @user, :action => 'feeds')
-              send(http_method, url, parameters, credentials(@token.value, 'X'))
-            end
-            should_respond_with failure_code
-            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
-    
-      # Test that a request allows full key authentication
-      #
-      # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
-      # @param [String] url the request url, without the key=ZXY parameter
-      # @param [optional, Hash] parameters additional request parameters
-      # @param [optional, Hash] options additional options
-      # @option options [Symbol] :success_code Successful response code (:success)
-      # @option options [Symbol] :failure_code Failure response code (:unauthorized)
-      def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
-        success_code = options[:success_code] || :success
-        failure_code = options[:failure_code] || :unauthorized
-    
-        context "should allow key based auth using key=X for #{http_method} #{url}" do
-          context "with a valid api token" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'api')
-              # Simple url parse to add on ?key= or &key=
-              request_url = if url.match(/\?/)
-                              url + "&key=#{@token.value}"
-                            else
-                              url + "?key=#{@token.value}"
-                            end
-              send(http_method, request_url, parameters)
-            end
-            should_respond_with success_code
-            should_respond_with_content_type_based_on_url(url)
-            should_be_a_valid_response_string_based_on_url(url)
-            should "login as the user" do
-              assert_equal @user, User.current
-            end
-          end
-    
-          context "with an invalid api token" do
-            setup do
-              @user = User.generate! do |user|
-                user.admin = true
-              end
-              @token = Token.create!(:user => @user, :action => 'feeds')
-              # Simple url parse to add on ?key= or &key=
-              request_url = if url.match(/\?/)
-                              url + "&key=#{@token.value}"
-                            else
-                              url + "?key=#{@token.value}"
-                            end
-              send(http_method, request_url, parameters)
-            end
-            should_respond_with failure_code
-            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
-    
-        context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
-          setup do
-            @user = User.generate! do |user|
-              user.admin = true
-            end
-            @token = Token.create!(:user => @user, :action => 'api')
-            send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
-          end
-          should_respond_with success_code
-          should_respond_with_content_type_based_on_url(url)
-          should_be_a_valid_response_string_based_on_url(url)
-          should "login as the user" do
-            assert_equal @user, User.current
-          end
-        end
-      end
-    
-      # Uses should_respond_with_content_type based on what's in the url:
-      #
-      # '/project/issues.xml' => should_respond_with_content_type :xml
-      # '/project/issues.json' => should_respond_with_content_type :json
-      #
-      # @param [String] url Request
-      def self.should_respond_with_content_type_based_on_url(url)
-        case
-        when url.match(/xml/i)
-          should "respond with XML" do
-            assert_equal 'application/xml', @response.content_type
-          end
-        when url.match(/json/i)
-          should "respond with JSON" do
-            assert_equal 'application/json', @response.content_type
-          end
-        else
-          raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
-        end
-      end
-    
-      # Uses the url to assert which format the response should be in
-      #
-      # '/project/issues.xml' => should_be_a_valid_xml_string
-      # '/project/issues.json' => should_be_a_valid_json_string
-      #
-      # @param [String] url Request
-      def self.should_be_a_valid_response_string_based_on_url(url)
-        case
-        when url.match(/xml/i)
-          should_be_a_valid_xml_string
-        when url.match(/json/i)
-          should_be_a_valid_json_string
-        else
-          raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
-        end
-      end
-    
-      # Checks that the response is a valid JSON string
-      def self.should_be_a_valid_json_string
-        should "be a valid JSON string (or empty)" do
-          assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
-        end
-      end
-    
-      # Checks that the response is a valid XML string
-      def self.should_be_a_valid_xml_string
-        should "be a valid XML string" do
-          assert REXML::Document.new(response.body)
-        end
-      end
-    
-      def self.should_respond_with(status)
-        should "respond with #{status}" do
-          assert_response status
-        end
-      end
     end
 
     class Routing < Redmine::RoutingTest