summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/helpers/application_helper_test.rb8
-rw-r--r--test/system/oauth_provider_test.rb131
-rw-r--r--test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb2
-rw-r--r--test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb12
-rw-r--r--test/unit/member_test.rb2
-rw-r--r--test/unit/role_test.rb26
-rw-r--r--test/unit/user_test.rb61
7 files changed, 234 insertions, 8 deletions
diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb
index c9ec72467..2e2e8b933 100644
--- a/test/helpers/application_helper_test.rb
+++ b/test/helpers/application_helper_test.rb
@@ -2403,6 +2403,14 @@ class ApplicationHelperTest < Redmine::HelperTest
assert_equal expected, format_activity_description(text)
end
+ def test_render_flash_messages_should_ignore_non_string_values
+ flash[:array_value] = ['1', '2']
+ flash[:hash_value] = { foo: 'bar' }
+
+ result = render_flash_messages
+ assert_equal '', result
+ end
+
private
def wiki_links_with_special_characters
diff --git a/test/system/oauth_provider_test.rb b/test/system/oauth_provider_test.rb
new file mode 100644
index 000000000..897af72c0
--- /dev/null
+++ b/test/system/oauth_provider_test.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+
+require_relative '../application_system_test_case'
+require 'oauth2'
+require 'webrick'
+
+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'
+
+ # as per https://tools.ietf.org/html/rfc8252#section-7.3, the port can be
+ # anything when the redirect URI's host is 127.0.0.1.
+ fill_in 'Redirect URI', with: 'http://127.0.0.1'
+
+ check 'View Issues'
+ click_button 'Create'
+ end
+
+ assert_text "Application created"
+
+ 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 strong', visible: true, text: /will not be shown again/
+ find 'p code', visible: true, text: /View Issues/
+
+ # scrape the clear text secret from the page
+ app_secret = all(:css, 'p code')[1].text
+
+ click_link 'Sign out'
+
+ #
+ # regular user authorizes the application
+ #
+ client = OAuth2::Client.new(app.uid, app_secret, site: "http://127.0.0.1:#{test_port}/")
+
+ # set up a dummy http listener to handle the redirect
+ port = rand 10000..20000
+ redirect_uri = "http://127.0.0.1:#{port}"
+ # the request handler below will set this to the auth token
+ token = nil
+
+ # launches webrick, listening for the redirect with the auth code.
+ launch_client_app(port: port) do |req, res|
+ # get access code from code url param
+ if code = req.query['code'].presence
+ # exchange it for token
+ token = client.auth_code.get_token(code, redirect_uri: redirect_uri)
+ res.body = "<html><body><p>Authorization succeeded, you may close this window now.</p></body></html>"
+ end
+ end
+
+ log_user 'jsmith', 'jsmith'
+ with_settings rest_api_enabled: 1 do
+ visit '/my/account'
+ click_link 'Authorized applications'
+ find 'p.nodata', visible: true
+
+ # an oauth client would send the user to this url to request permission
+ url = client.auth_code.authorize_url redirect_uri: redirect_uri, 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
+
+ # check for output defined above in the request handler
+ find 'p', visible: true, text: /Authorization succeeded/
+ assert token.present?
+
+ visit '/my/account'
+ click_link 'Authorized 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 launch_client_app(port: 12345, path: '/', &block)
+ server = WEBrick::HTTPServer.new Port: port
+ trap('INT') { server.shutdown }
+ server.mount_proc(path, block)
+ Thread.new { server.start }
+ port
+ end
+
+ def test_port
+ Capybara.current_session.server.port
+ end
+end
diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
index d267abbf9..bb0c5d450 100644
--- a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
+++ b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
@@ -226,7 +226,7 @@ class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase
text = STR_WITH_PRE.join("\n\n")
replacement = "New text"
- assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
+ assert_equal [STR_WITH_PRE[0..1], "New text"].join("\n\n"),
@formatter.new(text).update_section(3, replacement)
end
diff --git a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb
index 32280cfdf..678d4c6b2 100644
--- a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb
+++ b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb
@@ -466,19 +466,19 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
replacement = "New text"
assert_equal(
- [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
+ [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
)
assert_equal(
- [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"),
+ [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
)
assert_equal(
- [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"),
+ [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
)
assert_equal(
- [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"),
+ [STR_WITHOUT_PRE[0..3], replacement].join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
)
assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
@@ -488,7 +488,7 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
def test_update_section_with_hash_should_update_the_requested_section
replacement = "New text"
assert_equal(
- [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
+ [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).
update_section(2, replacement, ActiveSupport::Digest.hexdigest(STR_WITHOUT_PRE[1]))
)
@@ -552,7 +552,7 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
text = STR_WITH_PRE.join("\n\n")
replacement = "New text"
assert_equal(
- [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
+ [STR_WITH_PRE[0..1], "New text"].join("\n\n"),
@formatter.new(text).update_section(3, replacement)
)
end
diff --git a/test/unit/member_test.rb b/test/unit/member_test.rb
index 42fba4783..df9088027 100644
--- a/test/unit/member_test.rb
+++ b/test/unit/member_test.rb
@@ -108,7 +108,7 @@ class MemberTest < ActiveSupport::TestCase
assert !member.save
assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
assert_equal 'Rôle doit être renseigné(e)',
- [member.errors.full_messages].flatten.join
+ [member.errors.full_messages].join
end
def test_validate_member_role
diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb
index 21103919f..1d0d39d7e 100644
--- a/test/unit/role_test.rb
+++ b/test/unit/role_test.rb
@@ -175,6 +175,32 @@ class RoleTest < ActiveSupport::TestCase
assert_equal false, role.permissions_tracker_ids?(:view_issues, 1)
end
+ def test_allowed_to_with_symbol
+ role = Role.create!(:name => 'Test', :permissions => [:view_issues])
+ assert_equal true, role.allowed_to?(:view_issues)
+ assert_equal false, role.allowed_to?(:add_issues)
+ end
+
+ def test_allowed_to_with_symbol_and_scope
+ role = Role.create!(:name => 'Test', :permissions => [:view_issues, :delete_issues])
+ assert_equal true, role.allowed_to?(:view_issues, [:view_issues, :add_issues])
+ assert_equal false, role.allowed_to?(:add_issues, [:view_issues, :add_issues])
+ assert_equal false, role.allowed_to?(:delete_issues, [:view_issues, :add_issues])
+ end
+
+ def test_allowed_to_with_hash
+ role = Role.create!(:name => 'Test', :permissions => [:view_issues])
+ assert_equal true, role.allowed_to?(:controller => 'issues', :action => 'show')
+ assert_equal false, role.allowed_to?(:controller => 'issues', :action => 'create')
+ end
+
+ def test_allowed_to_with_hash_and_scope
+ role = Role.create!(:name => 'Test', :permissions => [:view_issues, :delete_issues])
+ assert_equal true, role.allowed_to?({:controller => 'issues', :action => 'show'}, [:view_issues, :add_issues])
+ assert_equal false, role.allowed_to?({:controller => 'issues', :action => 'create'}, [:view_issues, :add_issues])
+ assert_equal false, role.allowed_to?({:controller => 'issues', :action => 'destroy'}, [:view_issues, :add_issues])
+ end
+
def test_has_permission_without_permissions
role = Role.create!(:name => 'Test')
assert_equal false, role.has_permission?(:delete_issues)
diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb
index 8474e174b..967771c87 100644
--- a/test/unit/user_test.rb
+++ b/test/unit/user_test.rb
@@ -1398,6 +1398,67 @@ class UserTest < ActiveSupport::TestCase
end
end
+ def test_should_recognize_authorized_by_oauth
+ u = User.find 2
+ assert_not u.authorized_by_oauth?
+ u.oauth_scope = [:add_issues, :view_issues]
+ assert u.authorized_by_oauth?
+ end
+
+ def test_admin_should_be_limited_by_oauth_scope
+ u = User.find_by_admin(true)
+ assert u.admin?
+
+ u.oauth_scope = [:add_issues, :view_issues]
+ assert_not u.admin?
+
+ u.oauth_scope = [:add_issues, :view_issues, :admin]
+ assert u.admin?
+
+ u = User.find_by_admin(false)
+ assert_not u.admin?
+ u.oauth_scope = [:add_issues, :view_issues, :admin]
+ assert_not u.admin?
+ end
+
+ def test_oauth_scope_should_limit_global_user_permissions
+ admin = User.find 1
+ user = User.find 2
+ [admin, user].each do |u|
+ assert u.allowed_to?(:add_issues, nil, global: true)
+ assert u.allowed_to?(:view_issues, nil, global: true)
+ u.oauth_scope = [:view_issues]
+ assert_not u.allowed_to?(:add_issues, nil, global: true)
+ assert u.allowed_to?(:view_issues, nil, global: true)
+ end
+ end
+
+ def test_oauth_scope_should_limit_project_user_permissions
+ admin = User.find 1
+ project = Project.find 5
+ assert admin.allowed_to?(:add_issues, project)
+ assert admin.allowed_to?(:view_issues, project)
+ admin.oauth_scope = [:view_issues]
+ assert_not admin.allowed_to?(:add_issues, project)
+ assert admin.allowed_to?(:view_issues, project)
+
+ admin.oauth_scope = [:view_issues, :admin]
+ assert admin.allowed_to?(:add_issues, project)
+ assert admin.allowed_to?(:view_issues, project)
+
+ user = User.find 2
+ project = Project.find 1
+ assert user.allowed_to?(:add_issues, project)
+ assert user.allowed_to?(:view_issues, project)
+ user.oauth_scope = [:view_issues]
+ assert_not user.allowed_to?(:add_issues, project)
+ assert user.allowed_to?(:view_issues, project)
+
+ user.oauth_scope = [:view_issues, :admin]
+ assert_not user.allowed_to?(:add_issues, project)
+ assert user.allowed_to?(:view_issues, project)
+ end
+
def test_destroy_should_delete_associated_reactions
users(:users_004).reactions.create!(
[