Commit 12dd2b0c authored by Bob Van Landuyt's avatar Bob Van Landuyt

Share collaboration check between view and presenter

parent 8ad9c4e8
module ChecksCollaboration
def can_collaborate_with_project?(project, ref: nil)
return true if can?(current_user, :push_code, project)
can_create_merge_request =
can?(current_user, :create_merge_request_in, project) &&
current_user.already_forked?(project)
can_create_merge_request ||
user_access(project).can_push_to_branch?(ref)
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
# enabling this so we can easily cache the user access value as it might be
# used across multiple calls in the view
def user_access(project)
@user_access ||= {}
@user_access[project] ||= Gitlab::UserAccess.new(current_user, project: project)
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
end
class Projects::ApplicationController < ApplicationController class Projects::ApplicationController < ApplicationController
include RoutableActions include RoutableActions
include ChecksCollaboration
skip_before_action :authenticate_user! skip_before_action :authenticate_user!
before_action :project before_action :project
...@@ -31,18 +32,6 @@ class Projects::ApplicationController < ApplicationController ...@@ -31,18 +32,6 @@ class Projects::ApplicationController < ApplicationController
@repository ||= project.repository @repository ||= project.repository
end end
def can_collaborate_with_project?(project = nil, ref: nil)
project ||= @project
can_create_merge_request =
can?(current_user, :create_merge_request_in, project) &&
current_user.already_forked?(project)
can?(current_user, :push_code, project) ||
can_create_merge_request ||
user_access(project).can_push_to_branch?(ref)
end
def authorize_action!(action) def authorize_action!(action)
unless can?(current_user, action, project) unless can?(current_user, action, project)
return access_denied! return access_denied!
...@@ -95,9 +84,4 @@ class Projects::ApplicationController < ApplicationController ...@@ -95,9 +84,4 @@ class Projects::ApplicationController < ApplicationController
def check_issues_available! def check_issues_available!
return render_404 unless @project.feature_available?(:issues, current_user) return render_404 unless @project.feature_available?(:issues, current_user)
end end
def user_access(project)
@user_access ||= {}
@user_access[project] ||= Gitlab::UserAccess.new(current_user, project: project)
end
end end
...@@ -163,7 +163,7 @@ module CommitsHelper ...@@ -163,7 +163,7 @@ module CommitsHelper
tooltip = "#{action.capitalize} this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip tooltip = "#{action.capitalize} this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip
btn_class = "btn btn-#{btn_class}" unless btn_class.nil? btn_class = "btn btn-#{btn_class}" unless btn_class.nil?
if can_collaborate_with_project? if can_collaborate_with_project?(@project)
link_to action.capitalize, "#modal-#{action}-commit", 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" link_to action.capitalize, "#modal-#{action}-commit", 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
elsif can?(current_user, :fork_project, @project) elsif can?(current_user, :fork_project, @project)
continue_params = { continue_params = {
......
...@@ -3,6 +3,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated ...@@ -3,6 +3,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
include GitlabRoutingHelper include GitlabRoutingHelper
include MarkupHelper include MarkupHelper
include TreeHelper include TreeHelper
include ChecksCollaboration
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
presents :merge_request presents :merge_request
...@@ -152,11 +153,11 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated ...@@ -152,11 +153,11 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end end
def can_revert_on_current_merge_request? def can_revert_on_current_merge_request?
user_can_collaborate_with_project? && cached_can_be_reverted? can_collaborate_with_project?(project) && cached_can_be_reverted?
end end
def can_cherry_pick_on_current_merge_request? def can_cherry_pick_on_current_merge_request?
user_can_collaborate_with_project? && can_be_cherry_picked? can_collaborate_with_project?(project) && can_be_cherry_picked?
end end
def can_push_to_source_branch? def can_push_to_source_branch?
...@@ -195,16 +196,6 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated ...@@ -195,16 +196,6 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end.sort.to_sentence end.sort.to_sentence
end end
def user_can_collaborate_with_project?
can_create_merge_request =
can?(current_user, :create_merge_request_in, project) &&
current_user.already_forked?(project)
can?(current_user, :push_code, project) ||
can_create_merge_request ||
can_push_to_source_branch?
end
def user_can_fork_project? def user_can_fork_project?
can?(current_user, :fork_project, project) can?(current_user, :fork_project, project)
end end
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
- unless @commit.has_been_reverted?(current_user) - unless @commit.has_been_reverted?(current_user)
%li.clearfix %li.clearfix
= revert_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false) = revert_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
- if can_collaborate_with_project? - if can_collaborate_with_project?(@project)
%li.clearfix %li.clearfix
= cherry_pick_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false) = cherry_pick_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
- if can?(current_user, :push_code, @project) - if can?(current_user, :push_code, @project)
......
...@@ -17,6 +17,6 @@ ...@@ -17,6 +17,6 @@
.limited-width-notes .limited-width-notes
= render "shared/notes/notes_with_form", :autocomplete => true = render "shared/notes/notes_with_form", :autocomplete => true
- if can_collaborate_with_project? - if can_collaborate_with_project?(@project)
- %w(revert cherry-pick).each do |type| - %w(revert cherry-pick).each do |type|
= render "projects/commit/change", type: type, commit: @commit, title: @commit.title = render "projects/commit/change", type: type, commit: @commit, title: @commit.title
require 'spec_helper'
describe ChecksCollaboration do
include ProjectForksHelper
let(:helper) do
fake_class = Class.new(ApplicationController) do
include ChecksCollaboration
end
fake_class.new
end
describe '#can_collaborate_with_project?' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
before do
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?) do |user, ability, subject|
Ability.allowed?(user, ability, subject)
end
end
it 'is true if the user can push to the project' do
project.add_developer(user)
expect(helper.can_collaborate_with_project?(project)).to be_truthy
end
it 'is true when the user can push to a branch of the project' do
fake_access = double('Gitlab::UserAccess')
expect(fake_access).to receive(:can_push_to_branch?).with('a-branch').and_return(true)
expect(Gitlab::UserAccess).to receive(:new).with(user, project: project).and_return(fake_access)
expect(helper.can_collaborate_with_project?(project, ref: 'a-branch')).to be_truthy
end
context 'when the user has forked the project' do
before do
fork_project(project, user, namespace: user.namespace)
end
it 'is true' do
expect(helper.can_collaborate_with_project?(project)).to be_truthy
end
it 'is false when the project is archived' do
project.archived = true
expect(helper.can_collaborate_with_project?(project)).to be_falsy
end
end
end
end
...@@ -12,6 +12,7 @@ describe 'projects/tree/show' do ...@@ -12,6 +12,7 @@ describe 'projects/tree/show' do
assign(:lfs_blob_ids, []) assign(:lfs_blob_ids, [])
allow(view).to receive(:can?).and_return(true) allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:can_contribute_to_project?).and_return(true)
allow(view).to receive(:can_collaborate_with_project?).and_return(true) allow(view).to receive(:can_collaborate_with_project?).and_return(true)
allow(view).to receive_message_chain('user_access.can_push_to_branch?').and_return(true) allow(view).to receive_message_chain('user_access.can_push_to_branch?').and_return(true)
allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings) allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment