Redirect to external issue tracker from /issues
Prior, in order to display the correct link to "Issues" in the project
navigation, we were performing a check against the project to see if it
used an external issue tracker, and if so, we used that URL. This was
inefficient.
Now, we simply _always_ link to `namespace_project_issues_path`, and
then in the controller we redirect to the external tracker if it's
present.
This also removes the need for the url_for_issue helper. Bonus! 🎉
This commit is contained in:
parent
957331bf45
commit
a70431f874
6 changed files with 45 additions and 86 deletions
|
@ -5,6 +5,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
include ToggleAwardEmoji
|
include ToggleAwardEmoji
|
||||||
include IssuableCollections
|
include IssuableCollections
|
||||||
|
|
||||||
|
before_action :redirect_to_external_issue_tracker, only: [:index]
|
||||||
before_action :module_enabled
|
before_action :module_enabled
|
||||||
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
|
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
|
||||||
:related_branches, :can_create_branch]
|
:related_branches, :can_create_branch]
|
||||||
|
@ -201,6 +202,12 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
return render_404 unless @project.issues_enabled && @project.default_issues_tracker?
|
return render_404 unless @project.issues_enabled && @project.default_issues_tracker?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def redirect_to_external_issue_tracker
|
||||||
|
return unless @project.external_issue_tracker
|
||||||
|
|
||||||
|
redirect_to @project.external_issue_tracker.issues_url
|
||||||
|
end
|
||||||
|
|
||||||
# Since iids are implemented only in 6.1
|
# Since iids are implemented only in 6.1
|
||||||
# user may navigate to issue page using old global ids.
|
# user may navigate to issue page using old global ids.
|
||||||
#
|
#
|
||||||
|
|
|
@ -13,22 +13,6 @@ module IssuesHelper
|
||||||
OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned')
|
OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned')
|
||||||
end
|
end
|
||||||
|
|
||||||
def url_for_project_issues(project = @project, options = {})
|
|
||||||
return '' if project.nil?
|
|
||||||
|
|
||||||
url =
|
|
||||||
if options[:only_path]
|
|
||||||
project.issues_tracker.project_path
|
|
||||||
else
|
|
||||||
project.issues_tracker.project_url
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ensure we return a valid URL to prevent possible XSS.
|
|
||||||
URI.parse(url).to_s
|
|
||||||
rescue URI::InvalidURIError
|
|
||||||
''
|
|
||||||
end
|
|
||||||
|
|
||||||
def url_for_new_issue(project = @project, options = {})
|
def url_for_new_issue(project = @project, options = {})
|
||||||
return '' if project.nil?
|
return '' if project.nil?
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
- if project_nav_tab? :issues
|
- if project_nav_tab? :issues
|
||||||
= nav_link(controller: [:issues, :labels, :milestones]) do
|
= nav_link(controller: [:issues, :labels, :milestones]) do
|
||||||
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
|
= link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues', class: 'shortcuts-issues' do
|
||||||
%span
|
%span
|
||||||
Issues
|
Issues
|
||||||
- if @project.default_issues_tracker?
|
- if @project.default_issues_tracker?
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
%ul{ class: (container_class) }
|
%ul{ class: (container_class) }
|
||||||
- if project_nav_tab?(:issues) && !current_controller?(:merge_requests)
|
- if project_nav_tab?(:issues) && !current_controller?(:merge_requests)
|
||||||
= nav_link(controller: :issues) do
|
= nav_link(controller: :issues) do
|
||||||
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues' do
|
= link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues' do
|
||||||
%span
|
%span
|
||||||
Issues
|
Issues
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,19 @@ describe Projects::IssuesController do
|
||||||
let(:issue) { create(:issue, project: project) }
|
let(:issue) { create(:issue, project: project) }
|
||||||
|
|
||||||
describe "GET #index" do
|
describe "GET #index" do
|
||||||
|
context 'external issue tracker' do
|
||||||
|
it 'redirects to the external issue tracker' do
|
||||||
|
external = double(issues_url: 'https://example.com/issues')
|
||||||
|
allow(project).to receive(:external_issue_tracker).and_return(external)
|
||||||
|
controller.instance_variable_set(:@project, project)
|
||||||
|
|
||||||
|
get :index, namespace_id: project.namespace.path, project_id: project
|
||||||
|
|
||||||
|
expect(response).to redirect_to('https://example.com/issues')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'internal issue tracker' do
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
project.team << [user, :developer]
|
project.team << [user, :developer]
|
||||||
|
@ -39,6 +52,7 @@ describe Projects::IssuesController do
|
||||||
expect(response).to have_http_status(404)
|
expect(response).to have_http_status(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
context 'when moving issue to another private project' do
|
context 'when moving issue to another private project' do
|
||||||
|
|
|
@ -5,52 +5,6 @@ describe IssuesHelper do
|
||||||
let(:issue) { create :issue, project: project }
|
let(:issue) { create :issue, project: project }
|
||||||
let(:ext_project) { create :redmine_project }
|
let(:ext_project) { create :redmine_project }
|
||||||
|
|
||||||
describe "url_for_project_issues" do
|
|
||||||
let(:project_url) { ext_project.external_issue_tracker.project_url }
|
|
||||||
let(:ext_expected) { project_url.gsub(':project_id', ext_project.id.to_s) }
|
|
||||||
let(:int_expected) { polymorphic_path([@project.namespace, project]) }
|
|
||||||
|
|
||||||
it "should return internal path if used internal tracker" do
|
|
||||||
@project = project
|
|
||||||
expect(url_for_project_issues).to match(int_expected)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return path to external tracker" do
|
|
||||||
@project = ext_project
|
|
||||||
|
|
||||||
expect(url_for_project_issues).to match(ext_expected)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return empty string if project nil" do
|
|
||||||
@project = nil
|
|
||||||
|
|
||||||
expect(url_for_project_issues).to eq ""
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns an empty string if project_url is invalid' do
|
|
||||||
expect(project).to receive_message_chain('issues_tracker.project_url') { 'javascript:alert("foo");' }
|
|
||||||
|
|
||||||
expect(url_for_project_issues(project)).to eq ''
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns an empty string if project_path is invalid' do
|
|
||||||
expect(project).to receive_message_chain('issues_tracker.project_path') { 'javascript:alert("foo");' }
|
|
||||||
|
|
||||||
expect(url_for_project_issues(project, only_path: true)).to eq ''
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "when external tracker was enabled and then config removed" do
|
|
||||||
before do
|
|
||||||
@project = ext_project
|
|
||||||
allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return path to external tracker" do
|
|
||||||
expect(url_for_project_issues).to match(ext_expected)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "url_for_issue" do
|
describe "url_for_issue" do
|
||||||
let(:issues_url) { ext_project.external_issue_tracker.issues_url}
|
let(:issues_url) { ext_project.external_issue_tracker.issues_url}
|
||||||
let(:ext_expected) { issues_url.gsub(':id', issue.iid.to_s).gsub(':project_id', ext_project.id.to_s) }
|
let(:ext_expected) { issues_url.gsub(':id', issue.iid.to_s).gsub(':project_id', ext_project.id.to_s) }
|
||||||
|
|
Loading…
Reference in a new issue