Commit 8d740b97 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents c443b101 3ec8079f
...@@ -60,15 +60,32 @@ class MembersFinder ...@@ -60,15 +60,32 @@ class MembersFinder
# We're interested in a list of members without duplicates by user_id. # We're interested in a list of members without duplicates by user_id.
# We prefer project members over group members, project members should go first. # We prefer project members over group members, project members should go first.
<<~SQL <<~SQL
SELECT DISTINCT ON (user_id, invite_email) member_union.* SELECT DISTINCT ON (user_id, invite_email) #{member_columns}
FROM (#{union.to_sql}) AS member_union FROM (#{union.to_sql}) AS #{member_union_table}
ORDER BY user_id, LEFT JOIN users on users.id = member_union.user_id
invite_email, LEFT JOIN project_authorizations on project_authorizations.user_id = users.id
CASE AND
WHEN type = 'ProjectMember' THEN 1 project_authorizations.project_id = #{project.id}
WHEN type = 'GroupMember' THEN 2 ORDER BY user_id,
ELSE 3 invite_email,
END CASE
WHEN type = 'ProjectMember' THEN 1
WHEN type = 'GroupMember' THEN 2
ELSE 3
END
SQL SQL
end end
def member_union_table
'member_union'
end
def member_columns
Member.column_names.map do |column_name|
# fallback to members.access_level when project_authorizations.access_level is missing
next "COALESCE(#{ProjectAuthorization.table_name}.access_level, #{member_union_table}.access_level) access_level" if column_name == 'access_level'
"#{member_union_table}.#{column_name}"
end.join(',')
end
end end
---
title: Uses projects_authorizations.access_level in MembersFinder
merge_request: 28887
author: Jacopo Beschi @jacopo-beschi
type: fixed
...@@ -13,7 +13,7 @@ importance. ...@@ -13,7 +13,7 @@ importance.
GitLab is built on top of [Ruby on Rails](https://rubyonrails.org/), and we're using [RSpec] for all GitLab is built on top of [Ruby on Rails](https://rubyonrails.org/), and we're using [RSpec] for all
the backend tests, with [Capybara] for end-to-end integration testing. the backend tests, with [Capybara] for end-to-end integration testing.
On the frontend side, we're using [Karma] and [Jasmine] for JavaScript unit and On the frontend side, we're using [Jest](https://jestjs.io/) and [Karma](http://karma-runner.github.io/)/[Jasmine](https://jasmine.github.io/) for JavaScript unit and
integration testing. integration testing.
Following are two great articles that everyone should read to understand what Following are two great articles that everyone should read to understand what
...@@ -64,6 +64,4 @@ Everything you should know about how to run end-to-end tests using ...@@ -64,6 +64,4 @@ Everything you should know about how to run end-to-end tests using
[RSpec]: https://github.com/rspec/rspec-rails#feature-specs [RSpec]: https://github.com/rspec/rspec-rails#feature-specs
[Capybara]: https://github.com/teamcapybara/capybara [Capybara]: https://github.com/teamcapybara/capybara
[Karma]: http://karma-runner.github.io/
[Jasmine]: https://jasmine.github.io/
[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa [gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
...@@ -17,11 +17,10 @@ describe MembersFinder, '#execute' do ...@@ -17,11 +17,10 @@ describe MembersFinder, '#execute' do
result = described_class.new(project, user2).execute result = described_class.new(project, user2).execute
expect(result.to_a).to match_array([member1, member2, member3]) expect(result).to contain_exactly(member1, member2, member3)
end end
it 'includes nested group members if asked' do it 'includes nested group members if asked', :nested_groups do
project = create(:project, namespace: group)
nested_group.request_access(user1) nested_group.request_access(user1)
member1 = group.add_maintainer(user2) member1 = group.add_maintainer(user2)
member2 = nested_group.add_maintainer(user3) member2 = nested_group.add_maintainer(user3)
...@@ -29,7 +28,28 @@ describe MembersFinder, '#execute' do ...@@ -29,7 +28,28 @@ describe MembersFinder, '#execute' do
result = described_class.new(project, user2).execute(include_descendants: true) result = described_class.new(project, user2).execute(include_descendants: true)
expect(result.to_a).to match_array([member1, member2, member3]) expect(result).to contain_exactly(member1, member2, member3)
end
it 'returns the members.access_level when the user is invited', :nested_groups do
member_invite = create(:project_member, :invited, project: project, invite_email: create(:user).email)
member1 = group.add_maintainer(user2)
result = described_class.new(project, user2).execute(include_descendants: true)
expect(result).to contain_exactly(member1, member_invite)
expect(result.last.access_level).to eq(member_invite.access_level)
end
it 'returns the highest access_level for the user', :nested_groups do
member1 = project.add_guest(user1)
group.add_developer(user1)
nested_group.add_reporter(user1)
result = described_class.new(project, user1).execute(include_descendants: true)
expect(result).to contain_exactly(member1)
expect(result.first.access_level).to eq(Gitlab::Access::DEVELOPER)
end end
context 'when include_invited_groups_members == true' do context 'when include_invited_groups_members == true' do
...@@ -37,8 +57,8 @@ describe MembersFinder, '#execute' do ...@@ -37,8 +57,8 @@ describe MembersFinder, '#execute' do
set(:linked_group) { create(:group, :public, :access_requestable) } set(:linked_group) { create(:group, :public, :access_requestable) }
set(:nested_linked_group) { create(:group, parent: linked_group) } set(:nested_linked_group) { create(:group, parent: linked_group) }
set(:linked_group_member) { linked_group.add_developer(user1) } set(:linked_group_member) { linked_group.add_guest(user1) }
set(:nested_linked_group_member) { nested_linked_group.add_developer(user2) } set(:nested_linked_group_member) { nested_linked_group.add_guest(user2) }
it 'includes all the invited_groups members including members inherited from ancestor groups' do it 'includes all the invited_groups members including members inherited from ancestor groups' do
create(:project_group_link, project: project, group: nested_linked_group) create(:project_group_link, project: project, group: nested_linked_group)
...@@ -60,5 +80,17 @@ describe MembersFinder, '#execute' do ...@@ -60,5 +80,17 @@ describe MembersFinder, '#execute' do
expect(subject).to contain_exactly(linked_group_member) expect(subject).to contain_exactly(linked_group_member)
end end
context 'when the user is a member of invited group and ancestor groups' do
it 'returns the highest access_level for the user limited by project_group_link.group_access', :nested_groups do
create(:project_group_link, project: project, group: nested_linked_group, group_access: Gitlab::Access::REPORTER)
nested_linked_group.add_developer(user1)
result = subject
expect(result).to contain_exactly(linked_group_member, nested_linked_group_member)
expect(result.first.access_level).to eq(Gitlab::Access::REPORTER)
end
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