summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/concerns/membership_actions.rb34
-rw-r--r--app/controllers/groups/group_members_controller.rb6
-rw-r--r--app/controllers/projects/project_members_controller.rb6
-rw-r--r--app/services/members/destroy_service.rb26
-rw-r--r--lib/gitlab/access.rb2
-rw-r--r--spec/services/members/destroy_service_spec.rb24
7 files changed, 42 insertions, 60 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index dd1bc6f5d52..9cc31620d9f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -36,6 +36,10 @@ class ApplicationController < ActionController::Base
render_404
end
+ rescue_from Gitlab::Access::AccessDeniedError do |exception|
+ render_403
+ end
+
def redirect_back_or_default(default: root_path, options: {})
redirect_to request.referer.present? ? :back : default, options
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 7e6b83bcc37..52dc396af6a 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -21,32 +21,18 @@ module MembershipActions
def leave
@member = membershipable.members.find_by(user_id: current_user)
- return render_403 unless @member
-
- @member = Members::DestroyService.new(@member, current_user).execute
+ Members::DestroyService.new(@member, current_user).execute
source_type = @member.real_source_type.humanize(capitalize: false)
-
- if @member.destroyed?
- notice =
- if @member.request?
- "Your access request to the #{source_type} has been withdrawn."
- else
- "You left the \"#{@member.source.human_name}\" #{source_type}."
- end
- redirect_path = @member.request? ? @member.source : [:dashboard, @member.real_source_type.tableize]
-
- redirect_to redirect_path, notice: notice
- else
- if cannot_leave?
- alert = "You can not leave the \"#{@member.source.human_name}\" #{source_type}."
- alert << " Transfer or delete the #{source_type}."
-
- redirect_to polymorphic_url(membershipable), alert: alert
+ notice =
+ if @member.request?
+ "Your access request to the #{source_type} has been withdrawn."
else
- render_403
+ "You left the \"#{@member.source.human_name}\" #{source_type}."
end
- end
+ redirect_path = @member.request? ? @member.source : [:dashboard, @member.real_source_type.tableize]
+
+ redirect_to redirect_path, notice: notice
end
protected
@@ -54,8 +40,4 @@ module MembershipActions
def membershipable
raise NotImplementedError
end
-
- def cannot_leave?
- raise NotImplementedError
- end
end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index c3929ded6dd..2c49fe3833e 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -36,8 +36,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
def destroy
@group_member = @group.group_members.find(params[:id])
- return render_403 unless can?(current_user, :destroy_group_member, @group_member)
-
Members::DestroyService.new(@group_member, current_user).execute
respond_to do |format|
@@ -68,8 +66,4 @@ class Groups::GroupMembersController < Groups::ApplicationController
# MembershipActions concern
alias_method :membershipable, :group
-
- def cannot_leave?
- @group.last_owner?(current_user)
- end
end
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index ff0ac115f55..6ba32d33403 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -50,8 +50,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
def destroy
@project_member = @project.project_members.find(params[:id])
- return render_403 unless can?(current_user, :destroy_project_member, @project_member)
-
Members::DestroyService.new(@project_member, current_user).execute
respond_to do |format|
@@ -98,8 +96,4 @@ class Projects::ProjectMembersController < Projects::ApplicationController
# MembershipActions concern
alias_method :membershipable, :project
-
- def cannot_leave?
- current_user == @project.owner
- end
end
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index 59a55e42e38..15358f80208 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -7,29 +7,15 @@ module Members
end
def execute
- if can?(current_user, "destroy_#{member.type.underscore}".to_sym, member)
- member.destroy
-
- if member.request? && member.user != current_user
- notification_service.decline_access_request(member)
- end
+ unless member && can?(current_user, "destroy_#{member.type.underscore}".to_sym, member)
+ raise Gitlab::Access::AccessDeniedError
end
- member
- end
-
- private
-
- def abilities
- Ability.abilities
- end
-
- def can?(object, action, subject)
- abilities.allowed?(object, action, subject)
- end
+ member.destroy
- def notification_service
- NotificationService.new
+ if member.request? && member.user != current_user
+ notification_service.decline_access_request(member)
+ end
end
end
end
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index 6d0e30e916f..831f1e635ba 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -5,6 +5,8 @@
#
module Gitlab
module Access
+ class AccessDeniedError < StandardError; end
+
GUEST = 10
REPORTER = 20
DEVELOPER = 30
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 04c2782c125..2395445e7fd 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -5,13 +5,23 @@ describe Members::DestroyService, services: true do
let(:project) { create(:project) }
let!(:member) { create(:project_member, source: project) }
+ context 'when member is nil' do
+ before do
+ project.team << [user, :developer]
+ end
+
+ it 'does not destroy the member' do
+ expect { destroy_member(nil, user) }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+
context 'when current user cannot destroy the given member' do
before do
project.team << [user, :developer]
end
it 'does not destroy the member' do
- expect(destroy_member(member, user)).not_to be_destroyed
+ expect { destroy_member(member, user) }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
@@ -21,7 +31,9 @@ describe Members::DestroyService, services: true do
end
it 'destroys the member' do
- expect(destroy_member(member, user)).to be_destroyed
+ destroy_member(member, user)
+
+ expect(member).to be_destroyed
end
context 'when the given member is a requester' do
@@ -42,6 +54,14 @@ describe Members::DestroyService, services: true do
destroy_member(member, member.user)
end
end
+
+ context 'when current user is the member and ' do
+ it 'does not call Member#after_decline_request' do
+ expect_any_instance_of(NotificationService).not_to receive(:decline_access_request).with(member)
+
+ destroy_member(member, member.user)
+ end
+ end
end
end