diff --git a/app/models/user.rb b/app/models/user.rb index e58e57645fd748e290323f2bc273cbacee231253..9dd8d16787bff6b4892daf41ec00e7e23a1a6f42 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1243,7 +1243,17 @@ def update_invalid_gpg_signatures # Returns the groups a user has access to, either through a membership or a project authorization def authorized_groups Group.unscoped do - authorized_groups_with_shared_membership + direct_groups_cte = Gitlab::SQL::CTE.new(:direct_groups, groups) + direct_groups_cte_alias = direct_groups_cte.table.alias(Group.table_name) + + Group + .with(direct_groups_cte.to_arel) + .from_union([ + Group.from(direct_groups_cte_alias), + Group.id_in(authorized_projects.select(:namespace_id)), + Group.joins(:shared_with_group_links) + .where(group_group_links: { shared_with_group_id: Group.from(direct_groups_cte_alias) }) + ]) end end @@ -2526,28 +2536,6 @@ def group_callouts_by_feature_name @group_callouts_by_feature_name ||= group_callouts.index_by(&:source_feature_name) end - def authorized_groups_without_shared_membership - Group.from_union( - [ - groups, - Group.id_in(authorized_projects.select(:namespace_id)) - ] - ) - end - - def authorized_groups_with_shared_membership - cte = Gitlab::SQL::CTE.new(:direct_groups, authorized_groups_without_shared_membership) - cte_alias = cte.table.alias(Group.table_name) - - Group - .with(cte.to_arel) - .from_union([ - Group.from(cte_alias), - Group.joins(:shared_with_group_links) - .where(group_group_links: { shared_with_group_id: Group.from(cte_alias) }) - ]) - end - def has_current_license? false end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6345ed6d2a031c9a09deb70322a88504dfa2338f..0c426c428b44473797a9caeb31d19b9e4394a800 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -4795,14 +4795,14 @@ def login_method(login) end describe '#authorized_groups' do - let!(:user) { create(:user) } - let!(:private_group) { create(:group) } - let!(:child_group) { create(:group, parent: private_group) } + let_it_be(:user) { create(:user) } + let_it_be(:private_group) { create(:group) } + let_it_be(:child_group) { create(:group, parent: private_group) } - let!(:project_group) { create(:group) } - let!(:project) { create(:project, group: project_group) } + let_it_be(:project_group) { create(:group) } + let_it_be(:project) { create(:project, group: project_group) } - before do + before_all do private_group.add_member(user, Gitlab::Access::MAINTAINER) project.add_maintainer(user) end @@ -4812,16 +4812,18 @@ def login_method(login) it { is_expected.to contain_exactly private_group, project_group } context 'with shared memberships' do - let!(:shared_group) { create(:group) } - let!(:other_group) { create(:group) } + let_it_be(:shared_group) { create(:group) } + let_it_be(:other_group) { create(:group) } + let_it_be(:shared_with_project_group) { create(:group) } - before do + before_all do create(:group_group_link, shared_group: shared_group, shared_with_group: private_group) create(:group_group_link, shared_group: private_group, shared_with_group: other_group) + create(:group_group_link, shared_group: shared_with_project_group, shared_with_group: project_group) end it { is_expected.to include shared_group } - it { is_expected.not_to include other_group } + it { is_expected.not_to include other_group, shared_with_project_group } end context 'when a new column is added to namespaces table' do