diff --git a/ee/app/models/preloaders/user_member_roles_in_projects_preloader.rb b/ee/app/models/preloaders/user_member_roles_in_projects_preloader.rb index 4ffb245e40edb22f661ae7f9eb00bb70762ab11a..d8f0ce9e88d975e8c3554f9167997fddccef6d18 100644 --- a/ee/app/models/preloaders/user_member_roles_in_projects_preloader.rb +++ b/ee/app/models/preloaders/user_member_roles_in_projects_preloader.rb @@ -148,6 +148,14 @@ def user_group_member_roles_query group_permissions_query.select('member_roles.permissions').to_sql ) + if custom_role_for_project_link_enabled? + shared_projects_permissions_query = ::Authz::UserProjectMemberRole.joins(:member_role) + .where('user_project_member_roles.project_id = project_ids.project_id') + .where(user: user) + .select('member_roles.permissions').to_sql + union_queries.push(shared_projects_permissions_query) + end + union_queries.join(" UNION ALL ") end @@ -183,6 +191,14 @@ def custom_role_for_group_link_enabled? end end + def custom_role_for_project_link_enabled? + return false unless ::Gitlab::Saas.feature_available?(:gitlab_com_subscriptions) + + projects_relation.any? do |project| + ::Feature.enabled?(:assign_custom_roles_to_project_links_saas, project.root_ancestor) + end + end + def log_statistics(project_ids) ::Gitlab::AppLogger.info( class: self.class.name, diff --git a/ee/spec/models/preloaders/user_member_roles_in_projects_preloader_spec.rb b/ee/spec/models/preloaders/user_member_roles_in_projects_preloader_spec.rb index b3db709eb847c932f141e96fc60cd93fca418aeb..81b7715fd48b775418a7d831f984c2548fc01271 100644 --- a/ee/spec/models/preloaders/user_member_roles_in_projects_preloader_spec.rb +++ b/ee/spec/models/preloaders/user_member_roles_in_projects_preloader_spec.rb @@ -234,6 +234,37 @@ it_behaves_like 'custom roles', ability end + context 'when project is shared to a group with a member role', :saas do + let_it_be(:shared_project) { create(:project, :private) } + let_it_be(:invited_group) { create(:group, developers: [user]) } + let_it_be(:ability) { MemberRole.all_customizable_project_permissions.sample } + let_it_be(:member_role) { create_member_role(shared_project.root_ancestor, ability) } + let_it_be(:projects_list) { [shared_project] } + let_it_be(:expected_abilities) { expected_project_abilities(ability) } + + before_all do + create(:project_group_link, project: shared_project, group: invited_group, group_access: Gitlab::Access::GUEST, + member_role: member_role) + + member = invited_group.members.find_by(user_id: user.id) + ::Authz::UserGroupMemberRoles::UpdateForGroupService.new(member).execute + end + + it 'returns abilities assigned to the invited group' do + expect(result[shared_project.id]).to match_array(expected_abilities) + end + + context 'when assign_custom_roles_to_project_links_saas feature flag is disabled' do + before do + stub_feature_flags(assign_custom_roles_to_project_links_saas: false) + end + + it 'does not return abilities assigned to the invited group' do + expect(result[shared_project.id]).to be_empty + end + end + end + context "when project's parent group invites a group with a custom role" do let(:source) { project }