From 1ddb2ba46644ab0d1445e1738588de25395293d3 Mon Sep 17 00:00:00 2001 From: Jens Kraemer Date: Tue, 21 Jul 2020 17:15:08 +0800 Subject: [PATCH 7/7] [oauth] adds system test to test the oauth provider capabilities - application creation - authorization and access token generation by a user - API access using access token --- Gemfile | 3 + test/system/oauth_provider_test.rb | 98 ++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 test/system/oauth_provider_test.rb diff --git a/Gemfile b/Gemfile index 26d633ab3..9553335e1 100644 --- a/Gemfile +++ b/Gemfile @@ -93,6 +93,9 @@ group :test do gem 'rubocop', '~> 0.81.0' gem 'rubocop-performance', '~> 1.5.0' gem 'rubocop-rails', '~> 2.5.0' + # for testing oauth provider capabilities + gem 'oauth2' + gem 'rest-client' end local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") diff --git a/test/system/oauth_provider_test.rb b/test/system/oauth_provider_test.rb new file mode 100644 index 000000000..188dfd8a3 --- /dev/null +++ b/test/system/oauth_provider_test.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require File.expand_path('../../application_system_test_case', __FILE__) +require 'oauth2' + +class OauthProviderSystemTest < ApplicationSystemTestCase + + fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, + :trackers, :projects_trackers, :enabled_modules, :issue_statuses, :issues, + :enumerations, :custom_fields, :custom_values, :custom_fields_trackers, + :watchers, :journals, :journal_details, :versions, + :workflows + + + test 'application creation and authorization' do + # admin creates the application, granting permissions and generating a uuid + # and secret. + log_user 'admin', 'admin' + with_settings rest_api_enabled: 1 do + visit '/admin' + within 'div#admin-menu ul' do + click_link 'Applications' + end + click_link 'New Application' + fill_in 'Name', with: 'Oauth Test' + fill_in 'Redirect URI', with: 'urn:ietf:wg:oauth:2.0:oob' + find('#doorkeeper_application_scopes_view_issues').set(true) + click_button 'Create' + end + + assert app = Doorkeeper::Application.find_by_name('Oauth Test') + + find 'h2', visible: true, text: /Oauth Test/ + find 'p code', visible: true, text: app.uid + find 'p code', visible: true, text: app.secret + find 'p code', visible: true, text: /View Issues/ + click_link 'Sign out' + + # regular user authorizes the application to act on his behalf + + client = OAuth2::Client.new(app.uid, app.secret, site: "http://localhost:#{test_port}/") + + log_user 'jsmith', 'jsmith' + with_settings rest_api_enabled: 1 do + visit '/my/account' + click_link 'Your applications' + find 'p.nodata', visible: true + + # an oauth client would send the user to this url for him to grant + # permission: + url = client.auth_code.authorize_url redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', scope: 'view_issues view_project' + uri = URI.parse url + visit uri.path+'?'+uri.query + + find 'h2', visible: true, text: 'Authorization required' + find 'p', visible: true, text: /Authorize Oauth Test/ + find '.oauth-permissions', visible: true, text: /View Issues/ + find '.oauth-permissions', visible: true, text: /View project/ + + click_button 'Authorize' + assert grant = app.access_grants.last + assert_equal 'view_issues view_project', grant.scopes.to_s + + find 'p', visible: true, text: /Authorization code/ + find 'p', visible: true, text: grant.token + + # exchange the code for an access token + token = client.auth_code.get_token(grant.token, redirect_uri: 'urn:ietf:wg:oauth:2.0:oob') + + visit '/my/account' + click_link 'Your applications' + find 'td', visible: true, text: /Oauth Test/ + click_link 'Sign out' + + # Now, use the token for some API requests + assert_raise(RestClient::Unauthorized) do + RestClient.get "http://localhost:#{test_port}/projects/onlinestore/issues.json" + end + + headers = { 'Authorization' => "Bearer #{token.token}" } + r = RestClient.get "http://localhost:#{test_port}/projects/onlinestore/issues.json", headers + issues = JSON.parse(r.body)['issues'] + assert issues.any? + + # time entries access is not part of the granted scopes + assert_raise(RestClient::Forbidden) do + RestClient.get "http://localhost:#{test_port}/projects/onlinestore/time_entries.json", headers + end + end + end + + private + + def test_port + Capybara.current_session.server.port + end +end + -- 2.20.1