2019-07-07 11:18:12 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-09-02 18:07:02 +05:30
|
|
|
require "spec_helper"
|
|
|
|
|
2023-04-23 21:23:45 +05:30
|
|
|
RSpec.describe ProjectTeam, feature_category: :subgroups do
|
2020-11-24 15:15:51 +05:30
|
|
|
include ProjectForksHelper
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
let(:maintainer) { create(:user) }
|
2014-09-02 18:07:02 +05:30
|
|
|
let(:reporter) { create(:user) }
|
|
|
|
let(:guest) { create(:user) }
|
|
|
|
let(:nonmember) { create(:user) }
|
|
|
|
|
|
|
|
context 'personal project' do
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) { create(:project) }
|
2014-09-02 18:07:02 +05:30
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
project.add_maintainer(maintainer)
|
2017-08-17 22:00:37 +05:30
|
|
|
project.add_reporter(reporter)
|
|
|
|
project.add_guest(guest)
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe 'members collection' do
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.maintainers).to include(maintainer) }
|
|
|
|
it { expect(project.team.maintainers).not_to include(guest) }
|
|
|
|
it { expect(project.team.maintainers).not_to include(reporter) }
|
|
|
|
it { expect(project.team.maintainers).not_to include(nonmember) }
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe 'access methods' do
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.maintainer?(maintainer)).to be_truthy }
|
|
|
|
it { expect(project.team.maintainer?(guest)).to be_falsey }
|
|
|
|
it { expect(project.team.maintainer?(reporter)).to be_falsey }
|
|
|
|
it { expect(project.team.maintainer?(nonmember)).to be_falsey }
|
2015-04-26 12:48:37 +05:30
|
|
|
it { expect(project.team.member?(nonmember)).to be_falsey }
|
|
|
|
it { expect(project.team.member?(guest)).to be_truthy }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.member?(reporter, Gitlab::Access::REPORTER)).to be_truthy }
|
|
|
|
it { expect(project.team.member?(guest, Gitlab::Access::REPORTER)).to be_falsey }
|
|
|
|
it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey }
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'group project' do
|
|
|
|
let(:group) { create(:group) }
|
2017-09-10 17:25:29 +05:30
|
|
|
let!(:project) { create(:project, group: group) }
|
2014-09-02 18:07:02 +05:30
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(maintainer)
|
2015-09-11 14:41:01 +05:30
|
|
|
group.add_reporter(reporter)
|
|
|
|
group.add_guest(guest)
|
2014-09-02 18:07:02 +05:30
|
|
|
|
|
|
|
# If user is a group and a project member - GitLab uses highest permission
|
2018-11-18 11:00:15 +05:30
|
|
|
# So we add group guest as maintainer and add group maintainer as guest
|
2014-09-02 18:07:02 +05:30
|
|
|
# to this project to test highest access
|
2018-11-18 11:00:15 +05:30
|
|
|
project.add_maintainer(guest)
|
|
|
|
project.add_guest(maintainer)
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe 'members collection' do
|
2015-04-26 12:48:37 +05:30
|
|
|
it { expect(project.team.reporters).to include(reporter) }
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.maintainers).to include(maintainer) }
|
|
|
|
it { expect(project.team.maintainers).to include(guest) }
|
|
|
|
it { expect(project.team.maintainers).not_to include(reporter) }
|
|
|
|
it { expect(project.team.maintainers).not_to include(nonmember) }
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe 'access methods' do
|
2015-04-26 12:48:37 +05:30
|
|
|
it { expect(project.team.reporter?(reporter)).to be_truthy }
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.maintainer?(maintainer)).to be_truthy }
|
|
|
|
it { expect(project.team.maintainer?(guest)).to be_truthy }
|
|
|
|
it { expect(project.team.maintainer?(reporter)).to be_falsey }
|
|
|
|
it { expect(project.team.maintainer?(nonmember)).to be_falsey }
|
2015-04-26 12:48:37 +05:30
|
|
|
it { expect(project.team.member?(nonmember)).to be_falsey }
|
|
|
|
it { expect(project.team.member?(guest)).to be_truthy }
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.member?(guest, Gitlab::Access::MAINTAINER)).to be_truthy }
|
|
|
|
it { expect(project.team.member?(reporter, Gitlab::Access::MAINTAINER)).to be_falsey }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey }
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|
|
|
|
end
|
2015-10-24 18:46:33 +05:30
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
describe 'owner methods' do
|
|
|
|
context 'personal project' do
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
let(:owner) { project.first_owner }
|
|
|
|
|
|
|
|
specify { expect(project.team.owners).to contain_exactly(owner) }
|
|
|
|
specify { expect(project.team.owner?(owner)).to be_truthy }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'group project' do
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
let(:project) { create(:project, group: group) }
|
|
|
|
let(:user1) { create(:user) }
|
|
|
|
let(:user2) { create(:user) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
group.add_owner(user1)
|
|
|
|
group.add_owner(user2)
|
|
|
|
end
|
|
|
|
|
|
|
|
specify { expect(project.team.owners).to contain_exactly(user1, user2) }
|
|
|
|
specify { expect(project.team.owner?(user1)).to be_truthy }
|
|
|
|
specify { expect(project.team.owner?(user2)).to be_truthy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
describe '#fetch_members' do
|
2016-06-16 23:09:34 +05:30
|
|
|
context 'personal project' do
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) { create(:project) }
|
2016-11-03 12:29:30 +05:30
|
|
|
|
|
|
|
it 'returns project members' do
|
2022-04-04 11:22:00 +05:30
|
|
|
# TODO this can be updated when we have multiple project owners
|
|
|
|
# See https://gitlab.com/gitlab-org/gitlab/-/issues/350605
|
2016-11-03 12:29:30 +05:30
|
|
|
user = create(:user)
|
2017-08-17 22:00:37 +05:30
|
|
|
project.add_guest(user)
|
2016-11-03 12:29:30 +05:30
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
expect(project.team.members).to contain_exactly(user, project.first_owner)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns project members of a specified level' do
|
|
|
|
user = create(:user)
|
2017-08-17 22:00:37 +05:30
|
|
|
project.add_reporter(user)
|
2016-11-03 12:29:30 +05:30
|
|
|
|
|
|
|
expect(project.team.guests).to be_empty
|
|
|
|
expect(project.team.reporters).to contain_exactly(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns invited members of a group' do
|
|
|
|
group_member = create(:group_member)
|
2020-06-23 00:09:42 +05:30
|
|
|
create(:project_group_link, group: group_member.group,
|
|
|
|
project: project,
|
|
|
|
group_access: Gitlab::Access::GUEST)
|
2016-11-03 12:29:30 +05:30
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
expect(project.team.members)
|
2022-04-04 11:22:00 +05:30
|
|
|
.to contain_exactly(group_member.user, project.first_owner)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns invited members of a group of a specified level' do
|
|
|
|
group_member = create(:group_member)
|
2020-06-23 00:09:42 +05:30
|
|
|
create(:project_group_link, group: group_member.group,
|
|
|
|
project: project,
|
|
|
|
group_access: Gitlab::Access::REPORTER)
|
2016-11-03 12:29:30 +05:30
|
|
|
|
|
|
|
expect(project.team.guests).to be_empty
|
|
|
|
expect(project.team.reporters).to contain_exactly(group_member.user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'group project' do
|
|
|
|
let(:group) { create(:group) }
|
2017-09-10 17:25:29 +05:30
|
|
|
let!(:project) { create(:project, group: group) }
|
2016-11-03 12:29:30 +05:30
|
|
|
|
|
|
|
it 'returns project members' do
|
|
|
|
group_member = create(:group_member, group: group)
|
|
|
|
|
|
|
|
expect(project.team.members).to contain_exactly(group_member.user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns project members of a specified level' do
|
|
|
|
group_member = create(:group_member, :reporter, group: group)
|
|
|
|
|
|
|
|
expect(project.team.guests).to be_empty
|
|
|
|
expect(project.team.reporters).to contain_exactly(group_member.user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-06-09 08:11:10 +05:30
|
|
|
describe '#import_team' do
|
|
|
|
let_it_be(:source_project) { create(:project) }
|
|
|
|
let_it_be(:target_project) { create(:project) }
|
|
|
|
let_it_be(:source_project_owner) { source_project.first_owner }
|
|
|
|
let_it_be(:source_project_developer) { create(:user) { |user| source_project.add_developer(user) } }
|
|
|
|
let_it_be(:current_user) { create(:user) { |user| target_project.add_maintainer(user) } }
|
|
|
|
|
|
|
|
subject(:import) { target_project.team.import(source_project, current_user) }
|
|
|
|
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
|
|
|
|
it 'target project includes source member with the same access' do
|
|
|
|
import
|
|
|
|
|
|
|
|
imported_member_access = target_project.members.find_by!(user: source_project_developer).access_level
|
|
|
|
expect(imported_member_access).to eq(Gitlab::Access::DEVELOPER)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not change the source project members' do
|
|
|
|
import
|
|
|
|
|
|
|
|
expect(source_project.users).to include(source_project_developer)
|
|
|
|
expect(source_project.users).not_to include(current_user)
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples 'imports source owners with correct access' do
|
|
|
|
specify do
|
|
|
|
import
|
|
|
|
|
|
|
|
source_owner_access_in_target = target_project.members.find_by!(user: source_project_owner).access_level
|
|
|
|
expect(source_owner_access_in_target).to eq(target_access_level)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when importer is a maintainer in target project' do
|
|
|
|
it_behaves_like 'imports source owners with correct access' do
|
|
|
|
let(:target_access_level) { Gitlab::Access::MAINTAINER }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when importer is an owner in target project' do
|
|
|
|
before do
|
|
|
|
target_project.add_owner(current_user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'imports source owners with correct access' do
|
|
|
|
let(:target_access_level) { Gitlab::Access::OWNER }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
describe '#find_member' do
|
|
|
|
context 'personal project' do
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) do
|
2019-12-21 20:55:43 +05:30
|
|
|
create(:project, :public)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
|
|
|
|
2016-06-16 23:09:34 +05:30
|
|
|
let(:requester) { create(:user) }
|
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
project.add_maintainer(maintainer)
|
2017-08-17 22:00:37 +05:30
|
|
|
project.add_reporter(reporter)
|
|
|
|
project.add_guest(guest)
|
2016-06-16 23:09:34 +05:30
|
|
|
project.request_access(requester)
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.find_member(maintainer.id)).to be_a(ProjectMember) }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.find_member(reporter.id)).to be_a(ProjectMember) }
|
|
|
|
it { expect(project.team.find_member(guest.id)).to be_a(ProjectMember) }
|
|
|
|
it { expect(project.team.find_member(nonmember.id)).to be_nil }
|
|
|
|
it { expect(project.team.find_member(requester.id)).to be_nil }
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
2016-06-16 23:09:34 +05:30
|
|
|
context 'group project' do
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:group) { create(:group) }
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) { create(:project, group: group) }
|
2016-06-16 23:09:34 +05:30
|
|
|
let(:requester) { create(:user) }
|
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(maintainer)
|
2016-06-16 23:09:34 +05:30
|
|
|
group.add_reporter(reporter)
|
|
|
|
group.add_guest(guest)
|
|
|
|
group.request_access(requester)
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.find_member(maintainer.id)).to be_a(GroupMember) }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.find_member(reporter.id)).to be_a(GroupMember) }
|
|
|
|
it { expect(project.team.find_member(guest.id)).to be_a(GroupMember) }
|
|
|
|
it { expect(project.team.find_member(nonmember.id)).to be_nil }
|
|
|
|
it { expect(project.team.find_member(requester.id)).to be_nil }
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-02-02 18:00:53 +05:30
|
|
|
describe '#members_in_project_and_ancestors' do
|
|
|
|
context 'group project' do
|
|
|
|
it 'filters out users who are not members of the project' do
|
|
|
|
group = create(:group)
|
|
|
|
project = create(:project, group: group)
|
|
|
|
group_member = create(:group_member, group: group)
|
|
|
|
old_user = create(:user)
|
|
|
|
|
|
|
|
ProjectAuthorization.create!(project: project, user: old_user, access_level: Gitlab::Access::GUEST)
|
|
|
|
|
|
|
|
expect(project.team.members_in_project_and_ancestors).to contain_exactly(group_member.user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
describe '#members_with_access_levels' do
|
|
|
|
let_it_be(:maintainer) { create(:user) }
|
|
|
|
let_it_be(:developer) { create(:user) }
|
|
|
|
let_it_be(:guest) { create(:user) }
|
2022-05-07 20:08:51 +05:30
|
|
|
let_it_be(:project) { create(:project, group: create(:group)) }
|
2021-10-27 15:23:28 +05:30
|
|
|
let_it_be(:access_levels) { [Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER] }
|
|
|
|
|
|
|
|
subject(:members_with_access_levels) { project.team.members_with_access_levels(access_levels) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
project.team.add_developer(developer)
|
|
|
|
project.team.add_maintainer(maintainer)
|
|
|
|
project.team.add_guest(guest)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with access_levels' do
|
|
|
|
it 'filters members who have given access levels' do
|
|
|
|
expect(members_with_access_levels).to contain_exactly(developer, maintainer)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without access_levels' do
|
|
|
|
let_it_be(:access_levels) { [] }
|
|
|
|
|
|
|
|
it 'returns empty array' do
|
|
|
|
expect(members_with_access_levels).to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
describe '#add_members' do
|
2019-07-07 11:18:12 +05:30
|
|
|
let(:user1) { create(:user) }
|
|
|
|
let(:user2) { create(:user) }
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
|
|
|
|
it 'add the given users to the team' do
|
2022-08-13 15:12:31 +05:30
|
|
|
project.team.add_members([user1, user2], :reporter)
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
expect(project.team.reporter?(user1)).to be(true)
|
|
|
|
expect(project.team.reporter?(user2)).to be(true)
|
|
|
|
end
|
2021-12-11 22:18:48 +05:30
|
|
|
|
|
|
|
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
|
|
|
|
before do
|
2022-08-13 15:12:31 +05:30
|
|
|
project.team.add_members([user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: project.id)
|
2021-12-11 22:18:48 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'creates a member_task with the correct attributes', :aggregate_failures do
|
|
|
|
member = project.project_members.last
|
|
|
|
|
|
|
|
expect(member.tasks_to_be_done).to match_array([:ci, :code])
|
|
|
|
expect(member.member_task.project).to eq(project)
|
|
|
|
end
|
|
|
|
end
|
2019-07-07 11:18:12 +05:30
|
|
|
end
|
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
describe '#add_member' do
|
2019-07-07 11:18:12 +05:30
|
|
|
let(:user) { create(:user) }
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
|
|
|
|
it 'add the given user to the team' do
|
2022-08-13 15:12:31 +05:30
|
|
|
project.team.add_member(user, :reporter)
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
expect(project.team.reporter?(user)).to be(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-24 18:46:33 +05:30
|
|
|
describe "#human_max_access" do
|
2018-11-08 19:23:39 +05:30
|
|
|
it 'returns Maintainer role' do
|
2016-04-02 18:10:28 +05:30
|
|
|
user = create(:user)
|
|
|
|
group = create(:group)
|
2017-09-10 17:25:29 +05:30
|
|
|
project = create(:project, namespace: group)
|
2016-04-02 18:10:28 +05:30
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(user)
|
2016-04-02 18:10:28 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
expect(project.team.human_max_access(user.id)).to eq 'Maintainer'
|
2016-04-02 18:10:28 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns Owner role' do
|
|
|
|
user = create(:user)
|
|
|
|
group = create(:group)
|
2017-09-10 17:25:29 +05:30
|
|
|
project = create(:project, namespace: group)
|
2016-04-02 18:10:28 +05:30
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
group.add_owner(user)
|
2016-04-02 18:10:28 +05:30
|
|
|
|
|
|
|
expect(project.team.human_max_access(user.id)).to eq 'Owner'
|
2015-10-24 18:46:33 +05:30
|
|
|
end
|
|
|
|
end
|
2016-06-16 23:09:34 +05:30
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
describe '#contributor?' do
|
|
|
|
let(:project) { create(:project, :public, :repository) }
|
|
|
|
|
|
|
|
context 'when user is a member of project' do
|
|
|
|
before do
|
|
|
|
project.add_maintainer(maintainer)
|
|
|
|
project.add_reporter(reporter)
|
|
|
|
project.add_guest(guest)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { expect(project.team.contributor?(maintainer.id)).to be false }
|
|
|
|
it { expect(project.team.contributor?(reporter.id)).to be false }
|
|
|
|
it { expect(project.team.contributor?(guest.id)).to be false }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user has at least one merge request merged into default_branch' do
|
|
|
|
let(:contributor) { create(:user) }
|
|
|
|
let(:user_without_access) { create(:user) }
|
|
|
|
let(:first_fork_project) { fork_project(project, contributor, repository: true) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:merge_request, :merged, author: contributor, target_project: project, source_project: first_fork_project, target_branch: project.default_branch.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { expect(project.team.contributor?(contributor.id)).to be true }
|
|
|
|
it { expect(project.team.contributor?(user_without_access.id)).to be false }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-16 23:09:34 +05:30
|
|
|
describe '#max_member_access' do
|
|
|
|
let(:requester) { create(:user) }
|
|
|
|
|
|
|
|
context 'personal project' do
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) do
|
2019-12-21 20:55:43 +05:30
|
|
|
create(:project, :public)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
2016-06-16 23:09:34 +05:30
|
|
|
|
|
|
|
context 'when project is not shared with group' do
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
project.add_maintainer(maintainer)
|
2017-08-17 22:00:37 +05:30
|
|
|
project.add_reporter(reporter)
|
|
|
|
project.add_guest(guest)
|
2016-06-16 23:09:34 +05:30
|
|
|
project.request_access(requester)
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::MAINTAINER) }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
|
|
|
|
it { expect(project.team.max_member_access(guest.id)).to eq(Gitlab::Access::GUEST) }
|
2016-09-13 17:45:13 +05:30
|
|
|
it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
|
|
|
it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
2016-06-16 23:09:34 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'when project is shared with group' do
|
|
|
|
before do
|
|
|
|
group = create(:group)
|
2021-06-08 01:23:25 +05:30
|
|
|
project.project_group_links.create!(
|
2016-06-16 23:09:34 +05:30
|
|
|
group: group,
|
|
|
|
group_access: Gitlab::Access::DEVELOPER)
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(maintainer)
|
2016-06-16 23:09:34 +05:30
|
|
|
group.add_reporter(reporter)
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::DEVELOPER) }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
|
2016-09-13 17:45:13 +05:30
|
|
|
it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
|
|
|
it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
2016-06-16 23:09:34 +05:30
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
context 'but share_with_group_lock is true', :sidekiq_inline do
|
2017-09-10 17:25:29 +05:30
|
|
|
before do
|
2021-06-08 01:23:25 +05:30
|
|
|
project.namespace.update!(share_with_group_lock: true)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
2016-06-16 23:09:34 +05:30
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
2016-09-13 17:45:13 +05:30
|
|
|
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
2016-06-16 23:09:34 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'group project' do
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:group) { create(:group) }
|
2017-09-10 17:25:29 +05:30
|
|
|
let!(:project) do
|
|
|
|
create(:project, group: group)
|
|
|
|
end
|
2016-06-16 23:09:34 +05:30
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(maintainer)
|
2016-06-16 23:09:34 +05:30
|
|
|
group.add_reporter(reporter)
|
|
|
|
group.add_guest(guest)
|
|
|
|
group.request_access(requester)
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::MAINTAINER) }
|
2016-06-16 23:09:34 +05:30
|
|
|
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
|
|
|
|
it { expect(project.team.max_member_access(guest.id)).to eq(Gitlab::Access::GUEST) }
|
2016-09-13 17:45:13 +05:30
|
|
|
it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
|
|
|
it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
|
2016-06-16 23:09:34 +05:30
|
|
|
end
|
|
|
|
end
|
2016-09-13 17:45:13 +05:30
|
|
|
|
2022-07-16 23:28:13 +05:30
|
|
|
describe '#purge_member_access_cache_for_user_id', :request_store do
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
let(:user_id) { 1 }
|
|
|
|
let(:resource_data) { { user_id => 50, 42 => 50 } }
|
|
|
|
|
|
|
|
before do
|
|
|
|
Gitlab::SafeRequestStore[project.max_member_access_for_resource_key(User)] = resource_data
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'removes cached max access for user from store' do
|
|
|
|
project.team.purge_member_access_cache_for_user_id(user_id)
|
|
|
|
|
|
|
|
expect(Gitlab::SafeRequestStore[project.max_member_access_for_resource_key(User)]).to eq({ 42 => 50 })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
describe '#member?' do
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
let(:developer) { create(:user) }
|
2018-11-18 11:00:15 +05:30
|
|
|
let(:maintainer) { create(:user) }
|
2017-09-10 17:25:29 +05:30
|
|
|
|
|
|
|
let(:personal_project) do
|
|
|
|
create(:project, namespace: developer.namespace)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:group_project) do
|
|
|
|
create(:project, namespace: group)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:members_project) { create(:project) }
|
|
|
|
let(:shared_project) { create(:project) }
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(maintainer)
|
2017-08-17 22:00:37 +05:30
|
|
|
group.add_developer(developer)
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
members_project.add_developer(developer)
|
2018-11-18 11:00:15 +05:30
|
|
|
members_project.add_maintainer(maintainer)
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
create(:project_group_link, project: shared_project, group: group)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns false for no user' do
|
|
|
|
expect(personal_project.team.member?(nil)).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true for personal projects of the user' do
|
|
|
|
expect(personal_project.team.member?(developer)).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true for projects of groups the user is a member of' do
|
|
|
|
expect(group_project.team.member?(developer)).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true for projects for which the user is a member of' do
|
|
|
|
expect(members_project.team.member?(developer)).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true for projects shared on a group the user is a member of' do
|
|
|
|
expect(shared_project.team.member?(developer)).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'checks for the correct minimum level access' do
|
2018-11-18 11:00:15 +05:30
|
|
|
expect(group_project.team.member?(developer, Gitlab::Access::MAINTAINER)).to be(false)
|
|
|
|
expect(group_project.team.member?(maintainer, Gitlab::Access::MAINTAINER)).to be(true)
|
|
|
|
expect(members_project.team.member?(developer, Gitlab::Access::MAINTAINER)).to be(false)
|
|
|
|
expect(members_project.team.member?(maintainer, Gitlab::Access::MAINTAINER)).to be(true)
|
|
|
|
expect(shared_project.team.member?(developer, Gitlab::Access::MAINTAINER)).to be(false)
|
|
|
|
expect(shared_project.team.member?(maintainer, Gitlab::Access::MAINTAINER)).to be(false)
|
2017-08-17 22:00:37 +05:30
|
|
|
expect(shared_project.team.member?(developer, Gitlab::Access::DEVELOPER)).to be(true)
|
2018-11-18 11:00:15 +05:30
|
|
|
expect(shared_project.team.member?(maintainer, Gitlab::Access::DEVELOPER)).to be(true)
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
describe '#contribution_check_for_user_ids', :request_store do
|
|
|
|
let(:project) { create(:project, :public, :repository) }
|
|
|
|
let(:contributor) { create(:user) }
|
|
|
|
let(:second_contributor) { create(:user) }
|
|
|
|
let(:user_without_access) { create(:user) }
|
|
|
|
let(:first_fork_project) { fork_project(project, contributor, repository: true) }
|
|
|
|
let(:second_fork_project) { fork_project(project, second_contributor, repository: true) }
|
|
|
|
|
|
|
|
let(:users) do
|
|
|
|
[contributor, second_contributor, user_without_access].map(&:id)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:expected) do
|
|
|
|
{
|
|
|
|
contributor.id => true,
|
|
|
|
second_contributor.id => true,
|
|
|
|
user_without_access.id => false
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
create(:merge_request, :merged, author: contributor, target_project: project, source_project: first_fork_project, target_branch: project.default_branch.to_s)
|
|
|
|
create(:merge_request, :merged, author: second_contributor, target_project: project, source_project: second_fork_project, target_branch: project.default_branch.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
def contributors(users)
|
|
|
|
project.team.contribution_check_for_user_ids(users)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not perform extra queries when asked for users who have already been found' do
|
|
|
|
contributors(users)
|
|
|
|
|
|
|
|
expect { contributors([contributor.id]) }.not_to exceed_query_limit(0)
|
|
|
|
|
|
|
|
expect(contributors([contributor.id])).to eq(expected)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'only requests the extra users when uncached users are passed' do
|
|
|
|
new_contributor = create(:user)
|
|
|
|
new_fork_project = fork_project(project, new_contributor, repository: true)
|
|
|
|
second_new_user = create(:user)
|
|
|
|
all_users = users + [new_contributor.id, second_new_user.id]
|
|
|
|
create(:merge_request, :merged, author: new_contributor, target_project: project, source_project: new_fork_project, target_branch: project.default_branch.to_s)
|
|
|
|
|
|
|
|
expected_all = expected.merge(new_contributor.id => true,
|
|
|
|
second_new_user.id => false)
|
|
|
|
|
|
|
|
contributors(users)
|
|
|
|
|
|
|
|
queries = ActiveRecord::QueryRecorder.new { contributors(all_users) }
|
|
|
|
|
|
|
|
expect(queries.count).to eq(1)
|
|
|
|
expect(contributors([new_contributor.id])).to eq(expected_all)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns correct contributors' do
|
|
|
|
expect(contributors(users)).to eq(expected)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
shared_examples 'max member access for users' do
|
|
|
|
let(:project) { create(:project) }
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
let(:second_group) { create(:group) }
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
let(:maintainer) { create(:user) }
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:reporter) { create(:user) }
|
|
|
|
let(:guest) { create(:user) }
|
|
|
|
|
|
|
|
let(:promoted_guest) { create(:user) }
|
|
|
|
|
|
|
|
let(:group_developer) { create(:user) }
|
|
|
|
let(:second_developer) { create(:user) }
|
|
|
|
|
|
|
|
let(:user_without_access) { create(:user) }
|
|
|
|
let(:second_user_without_access) { create(:user) }
|
|
|
|
|
|
|
|
let(:users) do
|
2018-11-18 11:00:15 +05:30
|
|
|
[maintainer, reporter, promoted_guest, guest, group_developer, second_developer, user_without_access].map(&:id)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
let(:expected) do
|
|
|
|
{
|
2018-11-18 11:00:15 +05:30
|
|
|
maintainer.id => Gitlab::Access::MAINTAINER,
|
2017-09-10 17:25:29 +05:30
|
|
|
reporter.id => Gitlab::Access::REPORTER,
|
|
|
|
promoted_guest.id => Gitlab::Access::DEVELOPER,
|
|
|
|
guest.id => Gitlab::Access::GUEST,
|
|
|
|
group_developer.id => Gitlab::Access::DEVELOPER,
|
2018-11-18 11:00:15 +05:30
|
|
|
second_developer.id => Gitlab::Access::MAINTAINER,
|
2017-09-10 17:25:29 +05:30
|
|
|
user_without_access.id => Gitlab::Access::NO_ACCESS
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
project.add_maintainer(maintainer)
|
2017-09-10 17:25:29 +05:30
|
|
|
project.add_reporter(reporter)
|
|
|
|
project.add_guest(promoted_guest)
|
|
|
|
project.add_guest(guest)
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
project.project_group_links.create!(
|
2017-09-10 17:25:29 +05:30
|
|
|
group: group,
|
|
|
|
group_access: Gitlab::Access::DEVELOPER
|
|
|
|
)
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
group.add_maintainer(promoted_guest)
|
2017-09-10 17:25:29 +05:30
|
|
|
group.add_developer(group_developer)
|
|
|
|
group.add_developer(second_developer)
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
project.project_group_links.create!(
|
2017-09-10 17:25:29 +05:30
|
|
|
group: second_group,
|
2018-11-18 11:00:15 +05:30
|
|
|
group_access: Gitlab::Access::MAINTAINER
|
2017-09-10 17:25:29 +05:30
|
|
|
)
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
second_group.add_maintainer(second_developer)
|
2017-09-10 17:25:29 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns correct roles for different users' do
|
|
|
|
expect(project.team.max_member_access_for_user_ids(users)).to eq(expected)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#max_member_access_for_user_ids' do
|
|
|
|
context 'with RequestStore enabled', :request_store do
|
|
|
|
include_examples 'max member access for users'
|
|
|
|
|
|
|
|
def access_levels(users)
|
|
|
|
project.team.max_member_access_for_user_ids(users)
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
it 'does not perform extra queries when asked for users who have already been found' do
|
|
|
|
access_levels(users)
|
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
expect { access_levels([maintainer.id]) }.not_to exceed_query_limit(0)
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
expect(access_levels([maintainer.id])).to eq(expected)
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
it 'only requests the extra users when uncached users are passed' do
|
|
|
|
new_user = create(:user)
|
|
|
|
second_new_user = create(:user)
|
|
|
|
all_users = users + [new_user.id, second_new_user.id]
|
2016-09-13 17:45:13 +05:30
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
expected_all = expected.merge(new_user.id => Gitlab::Access::NO_ACCESS,
|
|
|
|
second_new_user.id => Gitlab::Access::NO_ACCESS)
|
2016-09-13 17:45:13 +05:30
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
access_levels(users)
|
|
|
|
|
|
|
|
queries = ActiveRecord::QueryRecorder.new { access_levels(all_users) }
|
|
|
|
|
|
|
|
expect(queries.count).to eq(1)
|
|
|
|
expect(queries.log_message).to match(/\W#{new_user.id}\W/)
|
|
|
|
expect(queries.log_message).to match(/\W#{second_new_user.id}\W/)
|
|
|
|
expect(queries.log_message).not_to match(/\W#{promoted_guest.id}\W/)
|
|
|
|
expect(access_levels(all_users)).to eq(expected_all)
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
context 'with RequestStore disabled' do
|
|
|
|
include_examples 'max member access for users'
|
|
|
|
end
|
2016-09-13 17:45:13 +05:30
|
|
|
end
|
2014-09-02 18:07:02 +05:30
|
|
|
end
|