diff options
author | Rémy Coutable <remy@rymai.me> | 2016-09-21 14:40:02 +0000 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2016-09-21 14:40:02 +0000 |
commit | 94bb16aeabb198b64f07890d8d0073890b7e5758 (patch) | |
tree | 7c6d1403b87989d6af3e721fbba18d21579199f2 | |
parent | 67b6dad3667a1e3b0a01c416ad5dbea2c19cdbaf (diff) | |
parent | e2c2bd69f2ccb6b8df41685b48259c4cde91eb8b (diff) | |
download | gitlab-ce-94bb16aeabb198b64f07890d8d0073890b7e5758.tar.gz |
Merge branch 'rs-simplify-fetch_members' into 'master'
Simplify ProjectTeam#fetch_members to satisfy flog
## What does this MR do?
- Add specs for ProjectTeam#fetch_members
- Simplify ProjectTeam#fetch_members to satisfy flog
## What are the relevant issue numbers?
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/22200
See merge request !6431
-rw-r--r-- | app/models/project_team.rb | 72 | ||||
-rw-r--r-- | spec/factories/group_members.rb | 6 | ||||
-rw-r--r-- | spec/models/project_team_spec.rb | 62 |
3 files changed, 108 insertions, 32 deletions
diff --git a/app/models/project_team.rb b/app/models/project_team.rb index ab6ea2aae36..d9ce5088903 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -163,7 +163,7 @@ class ProjectTeam # Each group produces a list of maximum access level per user. We take the # max of the values produced by each group. - if project.invited_groups.any? && project.allowed_to_share_with_group? + if project_shared_with_group? project.project_group_links.each do |group_link| invited_access = max_invited_level_for_users(group_link, user_ids) merge_max!(access, invited_access) @@ -200,43 +200,17 @@ class ProjectTeam def fetch_members(level = nil) project_members = project.members group_members = group ? group.members : [] - invited_members = [] - - if project.invited_groups.any? && project.allowed_to_share_with_group? - project.project_group_links.includes(group: [:group_members]).each do |group_link| - invited_group = group_link.group - im = invited_group.members - - if level - int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize] - - # Skip group members if we ask for masters - # but max group access is developers - next if int_level > group_link.group_access - - # If we ask for developers and max - # group access is developers we need to provide - # both group master, developers as devs - if int_level == group_link.group_access - im.where("access_level >= ?)", group_link.group_access) - else - im.send(level) - end - end - - invited_members << im - end - - invited_members = invited_members.flatten.compact - end if level - project_members = project_members.send(level) - group_members = group_members.send(level) if group + project_members = project_members.public_send(level) + group_members = group_members.public_send(level) if group end user_ids = project_members.pluck(:user_id) + + invited_members = fetch_invited_members(level) user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? + user_ids.push(*group_members.pluck(:user_id)) if group User.where(id: user_ids) @@ -249,4 +223,38 @@ class ProjectTeam def merge_max!(first_hash, second_hash) first_hash.merge!(second_hash) { |_key, old, new| old > new ? old : new } end + + def project_shared_with_group? + project.invited_groups.any? && project.allowed_to_share_with_group? + end + + def fetch_invited_members(level = nil) + invited_members = [] + + return invited_members unless project_shared_with_group? + + project.project_group_links.includes(group: [:group_members]).each do |link| + invited_group_members = link.group.members + + if level + numeric_level = GroupMember.access_level_roles[level.to_s.singularize.titleize] + + # If we're asked for a level that's higher than the group's access, + # there's nothing left to do + next if numeric_level > link.group_access + + # Make sure we include everyone _above_ the requested level as well + invited_group_members = + if numeric_level == link.group_access + invited_group_members.where("access_level >= ?", link.group_access) + else + invited_group_members.public_send(level) + end + end + + invited_members << invited_group_members + end + + invited_members.flatten.compact + end end diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index 2044ebec09a..795df5dfda9 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -3,5 +3,11 @@ FactoryGirl.define do access_level { GroupMember::OWNER } group user + + trait(:guest) { access_level GroupMember::GUEST } + trait(:reporter) { access_level GroupMember::REPORTER } + trait(:developer) { access_level GroupMember::DEVELOPER } + trait(:master) { access_level GroupMember::MASTER } + trait(:owner) { access_level GroupMember::OWNER } end end diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 5eaf0d3b7a6..f979d66c88c 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -73,6 +73,68 @@ describe ProjectTeam, models: true do end end + describe '#fetch_members' do + context 'personal project' do + let(:project) { create(:empty_project) } + + it 'returns project members' do + user = create(:user) + project.team << [user, :guest] + + expect(project.team.members).to contain_exactly(user) + end + + it 'returns project members of a specified level' do + user = create(:user) + project.team << [user, :reporter] + + 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) + 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(:empty_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) { create(:empty_project) } |