From f520a87e0a05a7beac7fcd92df00016bd6fff0db Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 12 Oct 2023 10:47:48 -0600 Subject: [PATCH 1/8] Add spec to filter by project_ids --- .../groups/dependencies_controller_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ee/spec/requests/groups/dependencies_controller_spec.rb b/ee/spec/requests/groups/dependencies_controller_spec.rb index 3c9deedcabcda2..97094364a961bd 100644 --- a/ee/spec/requests/groups/dependencies_controller_spec.rb +++ b/ee/spec/requests/groups/dependencies_controller_spec.rb @@ -338,6 +338,20 @@ expect(json_response['dependencies'].pluck('name')).to eq([sbom_occurrence_bundler.name]) end end + + context 'when filtered by projects' do + let_it_be(:other_project) { create(:project, group: group) } + let_it_be(:occurrence_from_other_project) { create(:sbom_occurrence, project: other_project) } + + let(:params) { { project_ids: [other_project.id] } } + + it 'returns a filtered list' do + subject + + expect(json_response['dependencies'].count).to eq(1) + expect(json_response['dependencies'].pluck('name')).to eq([occurrence_from_other_project.name]) + end + end end end end -- GitLab From cbef823fea98c8d030ab4dac0c148c099b335580 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 12 Oct 2023 10:53:07 -0600 Subject: [PATCH 2/8] Pass project_ids[] query string parameter to finder --- ee/app/controllers/groups/dependencies_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ee/app/controllers/groups/dependencies_controller.rb b/ee/app/controllers/groups/dependencies_controller.rb index 872a61708792ce..44ebd44e317ed9 100644 --- a/ee/app/controllers/groups/dependencies_controller.rb +++ b/ee/app/controllers/groups/dependencies_controller.rb @@ -69,7 +69,8 @@ def dependencies_finder_params :sort_by, component_names: [], licenses: [], - package_managers: [] + package_managers: [], + project_ids: [] ) else params.permit(:page, :per_page, :sort, :sort_by) -- GitLab From e25e0980268505bc99bfc689e5513f21e0f3b82d Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 12 Oct 2023 13:52:13 -0600 Subject: [PATCH 3/8] Add finder spec to filter by projects --- ee/spec/finders/sbom/dependencies_finder_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ee/spec/finders/sbom/dependencies_finder_spec.rb b/ee/spec/finders/sbom/dependencies_finder_spec.rb index 116da6542f08f7..a466bcdbd482b9 100644 --- a/ee/spec/finders/sbom/dependencies_finder_spec.rb +++ b/ee/spec/finders/sbom/dependencies_finder_spec.rb @@ -154,6 +154,16 @@ end end + context 'when filtered by project' do + let_it_be(:other_project) { create(:project, group: subgroup) } + let_it_be(:occurrence_from_other_project) { create(:sbom_occurrence, project: other_project) } + let_it_be(:params) { { project_ids: [other_project.id] } } + + it 'returns only records corresponding to the filter' do + expect(dependencies.map(&:id)).to match_array([occurrence_from_other_project.id]) + end + end + context 'when params is invalid' do let_it_be(:params) do { -- GitLab From b542b04a73a2bec920dfdce6bb80e9d9247edf8f Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 12 Oct 2023 14:21:55 -0600 Subject: [PATCH 4/8] Filter sbom occurrences by project_ids --- ee/app/finders/sbom/dependencies_finder.rb | 1 + ee/app/models/sbom/occurrence.rb | 2 ++ .../finders/sbom/dependencies_finder_spec.rb | 21 ++++++++++++++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ee/app/finders/sbom/dependencies_finder.rb b/ee/app/finders/sbom/dependencies_finder.rb index 82dc1b1e1292ad..b24aa6abb17d93 100644 --- a/ee/app/finders/sbom/dependencies_finder.rb +++ b/ee/app/finders/sbom/dependencies_finder.rb @@ -33,6 +33,7 @@ def filtered_collection collection = filter_by_component_names(collection) if params[:component_names].present? collection = collection.by_licenses(params[:licenses]) if params[:licenses].present? + collection = collection.by_project_ids(params[:project_ids]) if params[:project_ids].present? collection end diff --git a/ee/app/models/sbom/occurrence.rb b/ee/app/models/sbom/occurrence.rb index 9a801603a02044..e6e8ac558d720f 100644 --- a/ee/app/models/sbom/occurrence.rb +++ b/ee/app/models/sbom/occurrence.rb @@ -57,6 +57,8 @@ class Occurrence < ApplicationRecord where(query_parts.join(' OR '), licenses: Array(licenses)) end + scope :by_project_ids, ->(project_ids) { where(project_id: project_ids) } + scope :filter_by_package_managers, ->(package_managers) do where(package_manager: package_managers) end diff --git a/ee/spec/finders/sbom/dependencies_finder_spec.rb b/ee/spec/finders/sbom/dependencies_finder_spec.rb index a466bcdbd482b9..ff64a01ef24cd5 100644 --- a/ee/spec/finders/sbom/dependencies_finder_spec.rb +++ b/ee/spec/finders/sbom/dependencies_finder_spec.rb @@ -26,6 +26,8 @@ end shared_examples 'filter and sorting' do + subject(:dependencies) { described_class.new(project_or_group, params: params).execute } + context 'without params' do let_it_be(:params) { {} } @@ -156,11 +158,20 @@ context 'when filtered by project' do let_it_be(:other_project) { create(:project, group: subgroup) } - let_it_be(:occurrence_from_other_project) { create(:sbom_occurrence, project: other_project) } + let_it_be(:occurrence_from_other_project) do + component = create(:sbom_component, name: SecureRandom.uuid) + component_version = create(:sbom_component_version, component: component) + create(:sbom_occurrence, project: other_project, component_version: component_version) + end + let_it_be(:params) { { project_ids: [other_project.id] } } it 'returns only records corresponding to the filter' do - expect(dependencies.map(&:id)).to match_array([occurrence_from_other_project.id]) + if project_or_group.is_a?(Project) + expect(dependencies.map(&:id)).to be_empty + else + expect(dependencies.map(&:id)).to match_array([occurrence_from_other_project.id]) + end end end @@ -181,19 +192,19 @@ end context 'with project' do - subject(:dependencies) { described_class.new(project, params: params).execute } + let(:project_or_group) { project } include_examples 'filter and sorting' end context 'with group' do - subject(:dependencies) { described_class.new(group, params: params).execute } + let(:project_or_group) { group } include_examples 'filter and sorting' end context 'with subgroup' do - subject(:dependencies) { described_class.new(subgroup, params: params).execute } + let(:project_or_group) { subgroup } include_examples 'filter and sorting' end -- GitLab From 2052d57f0ee11f1843dc398984f09f7f4e5794ff Mon Sep 17 00:00:00 2001 From: Brian Williams Date: Mon, 23 Oct 2023 08:40:21 -0500 Subject: [PATCH 5/8] Query project_ids without namespace traversal The namespace traversal query is expensive, and isn't needed when we are querying for a specific set of project_ids. Query for those project_ids directly instead. --- .../groups/dependencies_controller.rb | 2 +- ee/app/finders/sbom/dependencies_finder.rb | 33 +++++-- .../finders/sbom/dependencies_finder_spec.rb | 99 +++++++++++-------- .../groups/dependencies_controller_spec.rb | 6 +- 4 files changed, 86 insertions(+), 54 deletions(-) diff --git a/ee/app/controllers/groups/dependencies_controller.rb b/ee/app/controllers/groups/dependencies_controller.rb index 44ebd44e317ed9..8edda2b725e44a 100644 --- a/ee/app/controllers/groups/dependencies_controller.rb +++ b/ee/app/controllers/groups/dependencies_controller.rb @@ -57,7 +57,7 @@ def authorize_read_dependency_list! end def dependencies_finder - ::Sbom::DependenciesFinder.new(group, params: dependencies_finder_params) + ::Sbom::DependenciesFinder.new(group, current_user, params: dependencies_finder_params) end def dependencies_finder_params diff --git a/ee/app/finders/sbom/dependencies_finder.rb b/ee/app/finders/sbom/dependencies_finder.rb index b24aa6abb17d93..a72a91c53389db 100644 --- a/ee/app/finders/sbom/dependencies_finder.rb +++ b/ee/app/finders/sbom/dependencies_finder.rb @@ -2,8 +2,11 @@ module Sbom class DependenciesFinder - def initialize(project_or_group, params: {}) + include Gitlab::Utils::StrongMemoize + + def initialize(project_or_group, current_user = nil, params: {}) @project_or_group = project_or_group + @current_user = current_user @params = params end @@ -24,17 +27,13 @@ def execute private - attr_reader :project_or_group, :params + attr_reader :project_or_group, :current_user, :params def filtered_collection - collection = project_or_group.sbom_occurrences - + collection = occurrences collection = filter_by_package_managers(collection) if params[:package_managers].present? - collection = filter_by_component_names(collection) if params[:component_names].present? collection = collection.by_licenses(params[:licenses]) if params[:licenses].present? - collection = collection.by_project_ids(params[:project_ids]) if params[:project_ids].present? - collection end @@ -49,5 +48,25 @@ def filter_by_component_names(sbom_occurrences) def sort_direction params[:sort]&.downcase == 'desc' ? 'desc' : 'asc' end + + def occurrences + return project_or_group.sbom_occurrences if params[:project_ids].blank? || project? + return Sbom::Occurrence.none if authorized_projects.blank? + + Sbom::Occurrence.by_project_ids(authorized_projects) + end + + def authorized_projects + return Project.none if current_user.blank? + + Project.id_in(params[:project_ids]).filter do |project| + Ability.allowed?(current_user, :read_dependency, project) + end + end + strong_memoize_attr :authorized_projects + + def project? + project_or_group.is_a?(::Project) + end end end diff --git a/ee/spec/finders/sbom/dependencies_finder_spec.rb b/ee/spec/finders/sbom/dependencies_finder_spec.rb index ff64a01ef24cd5..3c023a6798994b 100644 --- a/ee/spec/finders/sbom/dependencies_finder_spec.rb +++ b/ee/spec/finders/sbom/dependencies_finder_spec.rb @@ -3,37 +3,35 @@ require 'spec_helper' RSpec.describe Sbom::DependenciesFinder, feature_category: :dependency_management do + let_it_be(:current_user) { nil } let_it_be(:group) { create(:group) } let_it_be(:subgroup) { create(:group, parent: group) } let_it_be(:project) { create(:project, group: subgroup) } - let_it_be(:component_1) { create(:sbom_component, name: 'component-1') } - let_it_be(:component_2) { create(:sbom_component, name: 'component-2') } - let_it_be(:component_3) { create(:sbom_component, name: 'component-3') } - let_it_be(:component_version_1) { create(:sbom_component_version, component: component_1) } - let_it_be(:component_version_2) { create(:sbom_component_version, component: component_2) } - let_it_be(:component_version_3) { create(:sbom_component_version, component: component_3) } let_it_be(:occurrence_1) do - create(:sbom_occurrence, :mit, component_version: component_version_1, packager_name: 'nuget', project: project) + create(:sbom_occurrence, :mit, packager_name: 'nuget', project: project) end let_it_be(:occurrence_2) do - create(:sbom_occurrence, :apache_2, component_version: component_version_2, packager_name: 'npm', project: project) + create(:sbom_occurrence, :apache_2, packager_name: 'npm', project: project) end let_it_be(:occurrence_3) do - create(:sbom_occurrence, :mpl_2, component_version: component_version_3, source: nil, project: project) + create(:sbom_occurrence, :mpl_2, source: nil, project: project) + end + + before do + stub_licensed_features(dependency_scanning: true) end shared_examples 'filter and sorting' do - subject(:dependencies) { described_class.new(project_or_group, params: params).execute } + subject(:dependencies) { described_class.new(project_or_group, current_user, params: params).execute } context 'without params' do let_it_be(:params) { {} } it 'returns the dependencies associated with the project ordered by id' do - expect(dependencies.first.id).to eq(occurrence_1.id) - expect(dependencies.last.id).to eq(occurrence_3.id) + expect(dependencies.map(&:id)).to be_sorted end end @@ -47,8 +45,7 @@ end it 'returns array of data properly sorted' do - expect(dependencies.first.name).to eq('component-1') - expect(dependencies.last.name).to eq('component-3') + expect(dependencies.map(&:name)).to be_sorted end end @@ -61,8 +58,7 @@ end it 'returns array of data properly sorted' do - expect(dependencies.first.name).to eq('component-3') - expect(dependencies.last.name).to eq('component-1') + expect(dependencies.map(&:name)).to be_sorted(verse: :desc) end end @@ -100,9 +96,9 @@ let_it_be(:params) { { sort: 'asc', sort_by: 'license' } } it 'returns sorted results' do - expect(dependencies[0].licenses[0]["spdx_identifier"]).to eq('Apache-2.0') - expect(dependencies[1].licenses[0]["spdx_identifier"]).to eq('MIT') - expect(dependencies[2].licenses[0]["spdx_identifier"]).to eq('MPL-2.0') + spdx_ids = dependencies.map { |dependency| dependency.licenses.first['spdx_identifier'] } + + expect(spdx_ids).to be_sorted end end @@ -110,9 +106,9 @@ let_it_be(:params) { { sort: 'desc', sort_by: 'license' } } it 'returns sorted results' do - expect(dependencies[0].licenses[0]["spdx_identifier"]).to eq('MPL-2.0') - expect(dependencies[1].licenses[0]["spdx_identifier"]).to eq('MIT') - expect(dependencies[2].licenses[0]["spdx_identifier"]).to eq('Apache-2.0') + spdx_ids = dependencies.map { |dependency| dependency.licenses.first['spdx_identifier'] } + + expect(spdx_ids).to be_sorted(verse: :desc) end end @@ -156,25 +152,6 @@ end end - context 'when filtered by project' do - let_it_be(:other_project) { create(:project, group: subgroup) } - let_it_be(:occurrence_from_other_project) do - component = create(:sbom_component, name: SecureRandom.uuid) - component_version = create(:sbom_component_version, component: component) - create(:sbom_occurrence, project: other_project, component_version: component_version) - end - - let_it_be(:params) { { project_ids: [other_project.id] } } - - it 'returns only records corresponding to the filter' do - if project_or_group.is_a?(Project) - expect(dependencies.map(&:id)).to be_empty - else - expect(dependencies.map(&:id)).to match_array([occurrence_from_other_project.id]) - end - end - end - context 'when params is invalid' do let_it_be(:params) do { @@ -184,28 +161,64 @@ end it 'returns the dependencies associated with the project ordered by id' do - expect(dependencies.first.id).to eq(occurrence_1.id) - expect(dependencies.last.id).to eq(occurrence_3.id) + expect(dependencies.map(&:id)).to be_sorted end end end end + shared_examples 'group with project_id filters' do + context 'when filtering by project_id' do + let_it_be(:current_user) { create(:user).tap { |user| group.add_developer(user) } } + let_it_be(:authorized_project) { create(:project, group: group) } + let_it_be(:occurrence_from_authorized_project) do + create(:sbom_occurrence, project: authorized_project) + end + + let_it_be(:unauthorized_project) { create(:project) } + let_it_be(:occurrence_from_unauthorized_project) do + create(:sbom_occurrence, project: unauthorized_project) + end + + let_it_be(:params) { { project_ids: [authorized_project, unauthorized_project].map(&:id) } } + + it 'returns records for authorized projects only' do + expect(dependencies.map(&:id)).to match_array([occurrence_from_authorized_project.id]) + end + end + end + context 'with project' do let(:project_or_group) { project } include_examples 'filter and sorting' + + context 'when filtering by project_id' do + let_it_be(:current_user) { create(:user).tap { |user| group.add_developer(user) } } + let_it_be(:other_project) { create(:project, group: group) } + let_it_be(:occurrence_from_other_project) do + create(:sbom_occurrence, project: other_project) + end + + let_it_be(:params) { { project_ids: [other_project.id] } } + + it 'ignores the project_id param' do + expect(dependencies).to match_array([occurrence_1, occurrence_2, occurrence_3]) + end + end end context 'with group' do let(:project_or_group) { group } include_examples 'filter and sorting' + include_examples 'group with project_id filters' end context 'with subgroup' do let(:project_or_group) { subgroup } include_examples 'filter and sorting' + include_examples 'group with project_id filters' end end diff --git a/ee/spec/requests/groups/dependencies_controller_spec.rb b/ee/spec/requests/groups/dependencies_controller_spec.rb index 97094364a961bd..2c66ca62fcd79a 100644 --- a/ee/spec/requests/groups/dependencies_controller_spec.rb +++ b/ee/spec/requests/groups/dependencies_controller_spec.rb @@ -16,7 +16,7 @@ context 'when security dashboard feature is enabled' do before do - stub_licensed_features(security_dashboard: true) + stub_licensed_features(security_dashboard: true, dependency_scanning: true) end context 'and user is allowed to access group level dependencies' do @@ -81,7 +81,7 @@ context 'when security dashboard feature is enabled' do before do - stub_licensed_features(security_dashboard: true) + stub_licensed_features(security_dashboard: true, dependency_scanning: true) end context 'and user is allowed to access group level dependencies' do @@ -384,7 +384,7 @@ context 'when security dashboard feature is enabled' do before do - stub_licensed_features(security_dashboard: true) + stub_licensed_features(security_dashboard: true, dependency_scanning: true) end context 'and user is allowed to access group level dependencies' do -- GitLab From 9784a97b8b7be0fb4c88826a09b940f1d464c192 Mon Sep 17 00:00:00 2001 From: Brian Williams Date: Fri, 27 Oct 2023 10:13:03 -0500 Subject: [PATCH 6/8] Limit dependency list search to 10 projects at once --- .../groups/dependencies_controller.rb | 27 ++++++++++++++++--- .../groups/dependencies_controller_spec.rb | 16 +++++++++++ locale/gitlab.pot | 3 +++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/ee/app/controllers/groups/dependencies_controller.rb b/ee/app/controllers/groups/dependencies_controller.rb index 8edda2b725e44a..e28da5d9b7752f 100644 --- a/ee/app/controllers/groups/dependencies_controller.rb +++ b/ee/app/controllers/groups/dependencies_controller.rb @@ -4,7 +4,12 @@ module Groups class DependenciesController < Groups::ApplicationController include GovernUsageGroupTracking + before_action only: :index do + push_frontend_feature_flag(:group_level_dependencies_filtering, group) + end + before_action :authorize_read_dependency_list! + before_action :validate_project_ids_limit!, only: :index feature_category :dependency_management urgency :low @@ -12,10 +17,7 @@ class DependenciesController < Groups::ApplicationController # More details on https://gitlab.com/gitlab-org/gitlab/-/issues/411257#note_1508315283 GROUP_COUNT_LIMIT = 600 - - before_action only: :index do - push_frontend_feature_flag(:group_level_dependencies_filtering, group) - end + PROJECT_IDS_LIMIT = 10 def index respond_to do |format| @@ -56,6 +58,15 @@ def authorize_read_dependency_list! render_not_authorized end + def validate_project_ids_limit! + return unless params.fetch(:project_ids, []).size > PROJECT_IDS_LIMIT + + render_error( + :unprocessable_entity, + format(_('A maximum of %{limit} projects can be searched for at one time.'), limit: PROJECT_IDS_LIMIT) + ) + end + def dependencies_finder ::Sbom::DependenciesFinder.new(group, current_user, params: dependencies_finder_params) end @@ -94,6 +105,14 @@ def render_not_authorized end end + def render_error(status, message) + respond_to do |format| + format.json do + render json: { message: message }, status: status + end + end + end + def set_enable_project_search @enable_project_search = filtering_allowed? end diff --git a/ee/spec/requests/groups/dependencies_controller_spec.rb b/ee/spec/requests/groups/dependencies_controller_spec.rb index 2c66ca62fcd79a..361ad05813b9f1 100644 --- a/ee/spec/requests/groups/dependencies_controller_spec.rb +++ b/ee/spec/requests/groups/dependencies_controller_spec.rb @@ -351,6 +351,22 @@ expect(json_response['dependencies'].count).to eq(1) expect(json_response['dependencies'].pluck('name')).to eq([occurrence_from_other_project.name]) end + + context 'when trying to search for too many projects' do + let(:params) { { project_ids: (1..11).to_a } } + + it 'returns an error' do + subject + + expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(json_response['message']).to eq( + format( + _('A maximum of %{limit} projects can be searched for at one time.'), + limit: described_class::PROJECT_IDS_LIMIT + ) + ) + end + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c658795361cfc5..34e7472b837ee1 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1813,6 +1813,9 @@ msgstr "" msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system." msgstr "" +msgid "A maximum of %{limit} projects can be searched for at one time." +msgstr "" + msgid "A member of the abuse team will review your report as soon as possible." msgstr "" -- GitLab From 49fa23b53f5b4a99b4774e4b84a5daef6a7ac587 Mon Sep 17 00:00:00 2001 From: Brian Williams Date: Mon, 30 Oct 2023 16:37:42 -0500 Subject: [PATCH 7/8] Ensure given project_ids are in group hierarchy --- .../groups/dependencies_controller.rb | 2 +- ee/app/finders/sbom/dependencies_finder.rb | 20 ++++++++----------- .../finders/sbom/dependencies_finder_spec.rb | 5 +---- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/ee/app/controllers/groups/dependencies_controller.rb b/ee/app/controllers/groups/dependencies_controller.rb index e28da5d9b7752f..a9012a0b6c12ba 100644 --- a/ee/app/controllers/groups/dependencies_controller.rb +++ b/ee/app/controllers/groups/dependencies_controller.rb @@ -68,7 +68,7 @@ def validate_project_ids_limit! end def dependencies_finder - ::Sbom::DependenciesFinder.new(group, current_user, params: dependencies_finder_params) + ::Sbom::DependenciesFinder.new(group, params: dependencies_finder_params) end def dependencies_finder_params diff --git a/ee/app/finders/sbom/dependencies_finder.rb b/ee/app/finders/sbom/dependencies_finder.rb index a72a91c53389db..e8519fb2365978 100644 --- a/ee/app/finders/sbom/dependencies_finder.rb +++ b/ee/app/finders/sbom/dependencies_finder.rb @@ -4,9 +4,8 @@ module Sbom class DependenciesFinder include Gitlab::Utils::StrongMemoize - def initialize(project_or_group, current_user = nil, params: {}) + def initialize(project_or_group, params: {}) @project_or_group = project_or_group - @current_user = current_user @params = params end @@ -27,7 +26,7 @@ def execute private - attr_reader :project_or_group, :current_user, :params + attr_reader :project_or_group, :params def filtered_collection collection = occurrences @@ -51,19 +50,16 @@ def sort_direction def occurrences return project_or_group.sbom_occurrences if params[:project_ids].blank? || project? - return Sbom::Occurrence.none if authorized_projects.blank? - Sbom::Occurrence.by_project_ids(authorized_projects) + Sbom::Occurrence.by_project_ids(project_ids_in_group_hierarchy) end - def authorized_projects - return Project.none if current_user.blank? - - Project.id_in(params[:project_ids]).filter do |project| - Ability.allowed?(current_user, :read_dependency, project) - end + def project_ids_in_group_hierarchy + Project + .id_in(params[:project_ids]) + .for_group_and_its_ancestor_groups(project_or_group) + .select(:id) end - strong_memoize_attr :authorized_projects def project? project_or_group.is_a?(::Project) diff --git a/ee/spec/finders/sbom/dependencies_finder_spec.rb b/ee/spec/finders/sbom/dependencies_finder_spec.rb index 3c023a6798994b..5f2947d545e1b1 100644 --- a/ee/spec/finders/sbom/dependencies_finder_spec.rb +++ b/ee/spec/finders/sbom/dependencies_finder_spec.rb @@ -3,7 +3,6 @@ require 'spec_helper' RSpec.describe Sbom::DependenciesFinder, feature_category: :dependency_management do - let_it_be(:current_user) { nil } let_it_be(:group) { create(:group) } let_it_be(:subgroup) { create(:group, parent: group) } let_it_be(:project) { create(:project, group: subgroup) } @@ -25,7 +24,7 @@ end shared_examples 'filter and sorting' do - subject(:dependencies) { described_class.new(project_or_group, current_user, params: params).execute } + subject(:dependencies) { described_class.new(project_or_group, params: params).execute } context 'without params' do let_it_be(:params) { {} } @@ -169,7 +168,6 @@ shared_examples 'group with project_id filters' do context 'when filtering by project_id' do - let_it_be(:current_user) { create(:user).tap { |user| group.add_developer(user) } } let_it_be(:authorized_project) { create(:project, group: group) } let_it_be(:occurrence_from_authorized_project) do create(:sbom_occurrence, project: authorized_project) @@ -194,7 +192,6 @@ include_examples 'filter and sorting' context 'when filtering by project_id' do - let_it_be(:current_user) { create(:user).tap { |user| group.add_developer(user) } } let_it_be(:other_project) { create(:project, group: group) } let_it_be(:occurrence_from_other_project) do create(:sbom_occurrence, project: other_project) -- GitLab From b46b94768f539d905805477708bc59f694e36ba8 Mon Sep 17 00:00:00 2001 From: Brian Williams Date: Tue, 31 Oct 2023 09:46:11 -0500 Subject: [PATCH 8/8] Fix incorrect hierarchy filtering We should be searching through descendants, not ancestors. --- ee/app/finders/sbom/dependencies_finder.rb | 2 +- ee/spec/finders/sbom/dependencies_finder_spec.rb | 2 +- ee/spec/models/sbom/occurrence_spec.rb | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ee/app/finders/sbom/dependencies_finder.rb b/ee/app/finders/sbom/dependencies_finder.rb index e8519fb2365978..bd78d1d7c3870c 100644 --- a/ee/app/finders/sbom/dependencies_finder.rb +++ b/ee/app/finders/sbom/dependencies_finder.rb @@ -57,7 +57,7 @@ def occurrences def project_ids_in_group_hierarchy Project .id_in(params[:project_ids]) - .for_group_and_its_ancestor_groups(project_or_group) + .for_group_and_its_subgroups(project_or_group) .select(:id) end diff --git a/ee/spec/finders/sbom/dependencies_finder_spec.rb b/ee/spec/finders/sbom/dependencies_finder_spec.rb index 5f2947d545e1b1..9fbbc5b75d2659 100644 --- a/ee/spec/finders/sbom/dependencies_finder_spec.rb +++ b/ee/spec/finders/sbom/dependencies_finder_spec.rb @@ -168,7 +168,7 @@ shared_examples 'group with project_id filters' do context 'when filtering by project_id' do - let_it_be(:authorized_project) { create(:project, group: group) } + let_it_be(:authorized_project) { create(:project, group: subgroup) } let_it_be(:occurrence_from_authorized_project) do create(:sbom_occurrence, project: authorized_project) end diff --git a/ee/spec/models/sbom/occurrence_spec.rb b/ee/spec/models/sbom/occurrence_spec.rb index c563a451ef36cb..99291f8ecea024 100644 --- a/ee/spec/models/sbom/occurrence_spec.rb +++ b/ee/spec/models/sbom/occurrence_spec.rb @@ -369,6 +369,15 @@ end end + describe '.by_project_ids' do + let_it_be(:occurrence_1) { create(:sbom_occurrence) } + let_it_be(:occurrence_2) { create(:sbom_occurrence) } + + it 'returns records filtered by project_id' do + expect(described_class.by_project_ids(occurrence_1.project)).to eq([occurrence_1]) + end + end + describe '.filter_by_package_managers' do let_it_be(:occurrence_nuget) { create(:sbom_occurrence, packager_name: 'nuget') } let_it_be(:occurrence_npm) { create(:sbom_occurrence, packager_name: 'npm') } -- GitLab