Commit 6fc90a8c authored by Małgorzata Ksionek's avatar Małgorzata Ksionek

Add methods to delete invited members

Add specs for invitation deletes

Add specs for project members

Add changelog entry

Add cr remarks

Add cr remarks

Add cr remarks

Add cr remarks
parent 1eee55f8
...@@ -76,6 +76,8 @@ class Member < ApplicationRecord ...@@ -76,6 +76,8 @@ class Member < ApplicationRecord
scope :request, -> { where.not(requested_at: nil) } scope :request, -> { where.not(requested_at: nil) }
scope :non_request, -> { where(requested_at: nil) } scope :non_request, -> { where(requested_at: nil) }
scope :not_accepted_invitations_by_user, -> (user) { invite.where(invite_accepted_at: nil, created_by: user) }
scope :has_access, -> { active.where('access_level > 0') } scope :has_access, -> { active.where('access_level > 0') }
scope :guests, -> { active.where(access_level: GUEST) } scope :guests, -> { active.where(access_level: GUEST) }
......
...@@ -18,6 +18,7 @@ module Members ...@@ -18,6 +18,7 @@ module Members
end end
delete_subresources(member) unless skip_subresources delete_subresources(member) unless skip_subresources
delete_project_invitations_by(member) unless skip_subresources
enqueue_delete_todos(member) enqueue_delete_todos(member)
enqueue_unassign_issuables(member) if unassign_issuables enqueue_unassign_issuables(member) if unassign_issuables
...@@ -39,24 +40,48 @@ module Members ...@@ -39,24 +40,48 @@ module Members
delete_project_members(member) delete_project_members(member)
delete_subgroup_members(member) delete_subgroup_members(member)
delete_invited_members(member)
end end
def delete_project_members(member) def delete_project_members(member)
groups = member.group.self_and_descendants groups = member.group.self_and_descendants
ProjectMember.in_namespaces(groups).with_user(member.user).each do |project_member| destroy_project_members(ProjectMember.in_namespaces(groups).with_user(member.user))
self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
end
end end
def delete_subgroup_members(member) def delete_subgroup_members(member)
groups = member.group.descendants groups = member.group.descendants
GroupMember.of_groups(groups).with_user(member.user).each do |group_member| destroy_group_members(GroupMember.of_groups(groups).with_user(member.user))
end
def delete_invited_members(member)
groups = member.group.self_and_descendants
destroy_group_members(GroupMember.of_groups(groups).not_accepted_invitations_by_user(member.user))
destroy_project_members(ProjectMember.in_namespaces(groups).not_accepted_invitations_by_user(member.user))
end
def destroy_project_members(members)
members.each do |project_member|
self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
end
end
def destroy_group_members(members)
members.each do |group_member|
self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true) self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
end end
end end
def delete_project_invitations_by(member)
return unless member.is_a?(ProjectMember) && member.user && member.project
members_to_delete = member.project.members.not_accepted_invitations_by_user(member.user)
destroy_project_members(members_to_delete)
end
def can_destroy_member?(member) def can_destroy_member?(member)
can?(current_user, destroy_member_permission(member), member) can?(current_user, destroy_member_permission(member), member)
end end
......
---
title: Delete members invites created by users being deleted
merge_request:
author:
type: security
...@@ -195,6 +195,19 @@ RSpec.describe Member do ...@@ -195,6 +195,19 @@ RSpec.describe Member do
it { expect(described_class.non_request).to include @accepted_request_member } it { expect(described_class.non_request).to include @accepted_request_member }
end end
describe '.not_accepted_invitations_by_user' do
let(:invited_by_user) { create(:project_member, :invited, project: project, created_by: @owner_user) }
before do
create(:project_member, :invited, invite_email: 'test@test.com', project: project, created_by: @owner_user, invite_accepted_at: Time.zone.now)
create(:project_member, :invited, invite_email: 'test2@test.com', project: project, created_by: @maintainer_user)
end
subject { described_class.not_accepted_invitations_by_user(@owner_user) }
it { is_expected.to contain_exactly(invited_by_user) }
end
describe '.search_invite_email' do describe '.search_invite_email' do
it 'returns only members the matching e-mail' do it 'returns only members the matching e-mail' do
create(:group_member, :invited) create(:group_member, :invited)
......
...@@ -292,6 +292,10 @@ RSpec.describe Members::DestroyService do ...@@ -292,6 +292,10 @@ RSpec.describe Members::DestroyService do
before do before do
create(:group_member, :developer, group: subsubgroup, user: member_user) create(:group_member, :developer, group: subsubgroup, user: member_user)
create(:project_member, :invited, project: group_project, created_by: member_user)
create(:group_member, :invited, group: group, created_by: member_user)
create(:project_member, :invited, project: subsubproject, created_by: member_user)
create(:group_member, :invited, group: subgroup, created_by: member_user)
subsubproject.add_developer(member_user) subsubproject.add_developer(member_user)
control_project.add_maintainer(user) control_project.add_maintainer(user)
...@@ -325,5 +329,41 @@ RSpec.describe Members::DestroyService do ...@@ -325,5 +329,41 @@ RSpec.describe Members::DestroyService do
it 'does not remove the user from the control project' do it 'does not remove the user from the control project' do
expect(control_project.members.map(&:user)).to include(user) expect(control_project.members.map(&:user)).to include(user)
end end
it 'removes group members invited by deleted user' do
expect(group.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
it 'removes project members invited by deleted user' do
expect(group_project.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
it 'removes subgroup members invited by deleted user' do
expect(subgroup.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
it 'removes subproject members invited by deleted user' do
expect(subsubproject.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
end
context 'deletion of invitations created by deleted project member' do
let(:user) { project.owner }
let(:member_user) { create(:user) }
let(:opts) { {} }
let(:project) { create(:project) }
before do
create(:project_member, :invited, project: project, created_by: member_user)
project_member = create(:project_member, :maintainer, user: member_user, project: project)
described_class.new(user).execute(project_member, opts)
end
it 'removes project members invited by deleted user' do
expect(project.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
end end
end end
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