Open WebIDE in fork when user doesn't have access

When opening the IDE on a project where the user doesn't have push
access, we create a fork and then redirect back to the IDE. To make
sure the user can actually commit, we need to open the IDE in the forked
project rather than the upstream project.
This commit is contained in:
Markus Koller 2019-07-11 19:27:21 +02:00
parent 21c372827e
commit 60a6074dc9
No known key found for this signature in database
GPG key ID: EC9A8B44C0635CE2
4 changed files with 47 additions and 8 deletions

View file

@ -18,7 +18,16 @@ module BlobHelper
end end
def ide_edit_path(project = @project, ref = @ref, path = @path, options = {}) def ide_edit_path(project = @project, ref = @ref, path = @path, options = {})
segments = [ide_path, 'project', project.full_path, 'edit', ref] project_path =
if !current_user || can?(current_user, :push_code, project)
project.full_path
else
# We currently always fork to the user's namespace
# in edit_fork_button_tag
"#{current_user.namespace.full_path}/#{project.path}"
end
segments = [ide_path, 'project', project_path, 'edit', ref]
segments.concat(['-', encode_ide_path(path)]) if path.present? segments.concat(['-', encode_ide_path(path)]) if path.present?
File.join(segments) File.join(segments)
end end

View file

@ -0,0 +1,5 @@
---
title: Open WebIDE in fork when user doesn't have access
merge_request: 30642
author:
type: changed

View file

@ -162,6 +162,7 @@ describe 'Projects > Files > User edits files', :js do
expect_fork_status expect_fork_status
expect(page).to have_css('.ide-sidebar-project-title', text: "#{project2.name} #{user.namespace.full_path}/#{project2.path}")
expect(page).to have_css('.ide .multi-file-tab', text: '.gitignore') expect(page).to have_css('.ide .multi-file-tab', text: '.gitignore')
end end

View file

@ -29,14 +29,15 @@ describe BlobHelper do
let(:project) { create(:project, :repository, namespace: namespace) } let(:project) { create(:project, :repository, namespace: namespace) }
before do before do
allow(self).to receive(:current_user).and_return(nil) allow(helper).to receive(:current_user).and_return(nil)
allow(self).to receive(:can_collaborate_with_project?).and_return(true) allow(helper).to receive(:can?).and_return(true)
allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
end end
it 'verifies blob is text' do it 'verifies blob is text' do
expect(helper).not_to receive(:blob_text_viewable?) expect(helper).not_to receive(:blob_text_viewable?)
button = edit_blob_button(project, 'refs/heads/master', 'README.md') button = helper.edit_blob_button(project, 'refs/heads/master', 'README.md')
expect(button).to start_with('<button') expect(button).to start_with('<button')
end end
@ -46,25 +47,25 @@ describe BlobHelper do
expect(project.repository).not_to receive(:blob_at) expect(project.repository).not_to receive(:blob_at)
edit_blob_button(project, 'refs/heads/master', 'README.md', blob: blob) helper.edit_blob_button(project, 'refs/heads/master', 'README.md', blob: blob)
end end
it 'returns a link with the proper route' do it 'returns a link with the proper route' do
stub_feature_flags(web_ide_default: false) stub_feature_flags(web_ide_default: false)
link = edit_blob_button(project, 'master', 'README.md') link = helper.edit_blob_button(project, 'master', 'README.md')
expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md") expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md")
end end
it 'returns a link with a Web IDE route' do it 'returns a link with a Web IDE route' do
link = edit_blob_button(project, 'master', 'README.md') link = helper.edit_blob_button(project, 'master', 'README.md')
expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/-/ide/project/#{project.full_path}/edit/master/-/README.md") expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/-/ide/project/#{project.full_path}/edit/master/-/README.md")
end end
it 'returns a link with the passed link_opts on the expected route' do it 'returns a link with the passed link_opts on the expected route' do
stub_feature_flags(web_ide_default: false) stub_feature_flags(web_ide_default: false)
link = edit_blob_button(project, 'master', 'README.md', link_opts: { mr_id: 10 }) link = helper.edit_blob_button(project, 'master', 'README.md', link_opts: { mr_id: 10 })
expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md?mr_id=10") expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md?mr_id=10")
end end
@ -203,6 +204,13 @@ describe BlobHelper do
describe '#ide_edit_path' do describe '#ide_edit_path' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:current_user) { create(:user) }
let(:can_push_code) { true }
before do
allow(helper).to receive(:current_user).and_return(current_user)
allow(helper).to receive(:can?).and_return(can_push_code)
end
around do |example| around do |example|
old_script_name = Rails.application.routes.default_url_options[:script_name] old_script_name = Rails.application.routes.default_url_options[:script_name]
@ -243,5 +251,21 @@ describe BlobHelper do
expect(helper.ide_edit_path(project, "testing/slashes", "readme.md/")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/testing/slashes/-/readme.md/") expect(helper.ide_edit_path(project, "testing/slashes", "readme.md/")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/testing/slashes/-/readme.md/")
end end
context 'when user is not logged in' do
let(:current_user) { nil }
it 'returns IDE path inside the project' do
expect(helper.ide_edit_path(project, "master", "")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master")
end
end
context 'when user cannot push to the project' do
let(:can_push_code) { false }
it "returns IDE path with the user's fork" do
expect(helper.ide_edit_path(project, "master", "")).to eq("/-/ide/project/#{current_user.namespace.full_path}/#{project.path}/edit/master")
end
end
end end
end end