gitlab-org--gitlab-foss/spec/models/project_team_spec.rb
Jan Provaznik 4d7fa59af2
Sent notification only to authorized users
When moving a project, it's possible that some users who had
access to the project in old path can not access the project
in the new path.

Because `project_authorizations` records are updated asynchronously,
when we send the notification about moved project the list of project
team members contains old project members, we want to notify all these
members except the old users who can not access the new location.
2019-01-31 16:52:49 +01:00

448 lines
16 KiB
Ruby

require "spec_helper"
describe ProjectTeam do
let(:maintainer) { create(:user) }
let(:reporter) { create(:user) }
let(:guest) { create(:user) }
let(:nonmember) { create(:user) }
context 'personal project' do
let(:project) { create(:project) }
before do
project.add_maintainer(maintainer)
project.add_reporter(reporter)
project.add_guest(guest)
end
describe 'members collection' do
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) }
end
describe 'access methods' do
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 }
it { expect(project.team.member?(nonmember)).to be_falsey }
it { expect(project.team.member?(guest)).to be_truthy }
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 }
end
end
context 'group project' do
let(:group) { create(:group) }
let!(:project) { create(:project, group: group) }
before do
group.add_maintainer(maintainer)
group.add_reporter(reporter)
group.add_guest(guest)
# If user is a group and a project member - GitLab uses highest permission
# So we add group guest as maintainer and add group maintainer as guest
# to this project to test highest access
project.add_maintainer(guest)
project.add_guest(maintainer)
end
describe 'members collection' do
it { expect(project.team.reporters).to include(reporter) }
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) }
end
describe 'access methods' do
it { expect(project.team.reporter?(reporter)).to be_truthy }
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 }
it { expect(project.team.member?(nonmember)).to be_falsey }
it { expect(project.team.member?(guest)).to be_truthy }
it { expect(project.team.member?(guest, Gitlab::Access::MAINTAINER)).to be_truthy }
it { expect(project.team.member?(reporter, Gitlab::Access::MAINTAINER)).to be_falsey }
it { expect(project.team.member?(nonmember, Gitlab::Access::GUEST)).to be_falsey }
end
end
describe '#fetch_members' do
context 'personal project' do
let(:project) { create(:project) }
it 'returns project members' do
user = create(:user)
project.add_guest(user)
expect(project.team.members).to contain_exactly(user, project.owner)
end
it 'returns project members of a specified level' do
user = create(:user)
project.add_reporter(user)
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)
project.project_group_links.create!(
group: group_member.group,
group_access: Gitlab::Access::GUEST
)
expect(project.team.members)
.to contain_exactly(group_member.user, project.owner)
end
it 'returns invited members of a group of a specified level' do
group_member = create(:group_member)
project.project_group_links.create!(
group: group_member.group,
group_access: Gitlab::Access::REPORTER
)
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) }
let!(:project) { create(:project, group: group) }
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
describe '#find_member' do
context 'personal project' do
let(:project) do
create(:project, :public, :access_requestable)
end
let(:requester) { create(:user) }
before do
project.add_maintainer(maintainer)
project.add_reporter(reporter)
project.add_guest(guest)
project.request_access(requester)
end
it { expect(project.team.find_member(maintainer.id)).to be_a(ProjectMember) }
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 }
end
context 'group project' do
let(:group) { create(:group, :access_requestable) }
let(:project) { create(:project, group: group) }
let(:requester) { create(:user) }
before do
group.add_maintainer(maintainer)
group.add_reporter(reporter)
group.add_guest(guest)
group.request_access(requester)
end
it { expect(project.team.find_member(maintainer.id)).to be_a(GroupMember) }
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 }
end
end
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
describe "#human_max_access" do
it 'returns Maintainer role' do
user = create(:user)
group = create(:group)
project = create(:project, namespace: group)
group.add_maintainer(user)
expect(project.team.human_max_access(user.id)).to eq 'Maintainer'
end
it 'returns Owner role' do
user = create(:user)
group = create(:group)
project = create(:project, namespace: group)
group.add_owner(user)
expect(project.team.human_max_access(user.id)).to eq 'Owner'
end
end
describe '#max_member_access' do
let(:requester) { create(:user) }
context 'personal project' do
let(:project) do
create(:project, :public, :access_requestable)
end
context 'when project is not shared with group' do
before do
project.add_maintainer(maintainer)
project.add_reporter(reporter)
project.add_guest(guest)
project.request_access(requester)
end
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::MAINTAINER) }
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) }
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) }
end
context 'when project is shared with group' do
before do
group = create(:group)
project.project_group_links.create(
group: group,
group_access: Gitlab::Access::DEVELOPER)
group.add_maintainer(maintainer)
group.add_reporter(reporter)
end
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::DEVELOPER) }
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::REPORTER) }
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) }
context 'but share_with_group_lock is true' do
before do
project.namespace.update(share_with_group_lock: true)
end
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::NO_ACCESS) }
it { expect(project.team.max_member_access(reporter.id)).to eq(Gitlab::Access::NO_ACCESS) }
end
end
end
context 'group project' do
let(:group) { create(:group, :access_requestable) }
let!(:project) do
create(:project, group: group)
end
before do
group.add_maintainer(maintainer)
group.add_reporter(reporter)
group.add_guest(guest)
group.request_access(requester)
end
it { expect(project.team.max_member_access(maintainer.id)).to eq(Gitlab::Access::MAINTAINER) }
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) }
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) }
end
end
describe '#member?' do
let(:group) { create(:group) }
let(:developer) { create(:user) }
let(:maintainer) { create(:user) }
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) }
before do
group.add_maintainer(maintainer)
group.add_developer(developer)
members_project.add_developer(developer)
members_project.add_maintainer(maintainer)
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
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)
expect(shared_project.team.member?(developer, Gitlab::Access::DEVELOPER)).to be(true)
expect(shared_project.team.member?(maintainer, Gitlab::Access::DEVELOPER)).to be(true)
end
end
shared_examples 'max member access for users' do
let(:project) { create(:project) }
let(:group) { create(:group) }
let(:second_group) { create(:group) }
let(:maintainer) { create(:user) }
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
[maintainer, reporter, promoted_guest, guest, group_developer, second_developer, user_without_access].map(&:id)
end
let(:expected) do
{
maintainer.id => Gitlab::Access::MAINTAINER,
reporter.id => Gitlab::Access::REPORTER,
promoted_guest.id => Gitlab::Access::DEVELOPER,
guest.id => Gitlab::Access::GUEST,
group_developer.id => Gitlab::Access::DEVELOPER,
second_developer.id => Gitlab::Access::MAINTAINER,
user_without_access.id => Gitlab::Access::NO_ACCESS
}
end
before do
project.add_maintainer(maintainer)
project.add_reporter(reporter)
project.add_guest(promoted_guest)
project.add_guest(guest)
project.project_group_links.create(
group: group,
group_access: Gitlab::Access::DEVELOPER
)
group.add_maintainer(promoted_guest)
group.add_developer(group_developer)
group.add_developer(second_developer)
project.project_group_links.create(
group: second_group,
group_access: Gitlab::Access::MAINTAINER
)
second_group.add_maintainer(second_developer)
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)
end
it 'does not perform extra queries when asked for users who have already been found' do
access_levels(users)
expect { access_levels(users) }.not_to exceed_query_limit(0)
expect(access_levels(users)).to eq(expected)
end
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]
expected_all = expected.merge(new_user.id => Gitlab::Access::NO_ACCESS,
second_new_user.id => Gitlab::Access::NO_ACCESS)
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)
end
end
context 'with RequestStore disabled' do
include_examples 'max member access for users'
end
end
end