Commit 1460dd29 authored by Marcos Rocha's avatar Marcos Rocha Committed by Mayra Cabrera

Filter Dast Profiles with Schedule

parent 5e38e52a
......@@ -12644,7 +12644,6 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if Container Registry is enabled for the current user. |
| <a id="projectcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the project. |
| <a id="projectcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of the project creation. |
| <a id="projectdastprofiles"></a>`dastProfiles` | [`DastProfileConnection`](#dastprofileconnection) | DAST Profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastscannerprofiles"></a>`dastScannerProfiles` | [`DastScannerProfileConnection`](#dastscannerprofileconnection) | DAST scanner profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastsiteprofiles"></a>`dastSiteProfiles` | [`DastSiteProfileConnection`](#dastsiteprofileconnection) | DAST Site Profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdescription"></a>`description` | [`String`](#string) | Short description of the project. |
......@@ -12882,8 +12881,25 @@ Returns [`DastProfile`](#dastprofile).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectdastprofilehasdastprofileschedule"></a>`hasDastProfileSchedule` | [`Boolean`](#boolean) | Filter DAST Profiles by whether or not they have a schedule. Will be ignored if `dast_view_scans` feature flag is disabled. |
| <a id="projectdastprofileid"></a>`id` | [`DastProfileID!`](#dastprofileid) | ID of the DAST Profile. |
##### `Project.dastProfiles`
DAST Profiles associated with the project.
Returns [`DastProfileConnection`](#dastprofileconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectdastprofileshasdastprofileschedule"></a>`hasDastProfileSchedule` | [`Boolean`](#boolean) | Filter DAST Profiles by whether or not they have a schedule. Will be ignored if `dast_view_scans` feature flag is disabled. |
##### `Project.dastSiteProfile`
DAST Site Profile associated with the project.
......
......@@ -12,6 +12,7 @@ module Dast
relation = default_relation
relation = by_id(relation)
relation = by_project(relation)
relation = has_schedule?(relation)
sort(relation)
end
......@@ -38,6 +39,12 @@ module Dast
relation.by_project_id(params[:project_id])
end
def has_schedule?(relation)
return relation if params[:has_dast_profile_schedule].nil?
relation.with_schedule(params[:has_dast_profile_schedule])
end
# rubocop: disable CodeReuse/ActiveRecord
def sort(relation)
relation.order(DEFAULT_SORT)
......
......@@ -10,6 +10,10 @@ module Resolvers
type ::Types::Dast::ProfileType.connection_type, null: true
argument :has_dast_profile_schedule, ::GraphQL::Types::Boolean,
required: false,
description: 'Filter DAST Profiles by whether or not they have a schedule. Will be ignored if `dast_view_scans` feature flag is disabled.'
when_single do
argument :id, ::Types::GlobalIDType[::Dast::Profile],
required: true,
......@@ -17,6 +21,7 @@ module Resolvers
end
def resolve_with_lookahead(**args)
args.delete(:has_dast_profile_schedule) unless Feature.enabled?(:dast_view_scans, project, default_enabled: :yaml)
apply_lookahead(find_dast_profiles(args))
end
......@@ -41,6 +46,8 @@ module Resolvers
params[:id] = ::Types::GlobalIDType[::Dast::Profile].coerce_isolated_input(args[:id]).model_id
end
params[:has_dast_profile_schedule] = args[:has_dast_profile_schedule] if args.has_key?(:has_dast_profile_schedule)
::Dast::ProfilesFinder.new(params).execute
end
end
......
......@@ -27,6 +27,10 @@ module Dast
where(project_id: project_id)
end
scope :with_schedule, -> (has_dast_profile_schedule) do
has_dast_profile_schedule ? joins(:dast_profile_schedule) : where.missing(:dast_profile_schedule)
end
delegate :secret_ci_variables, to: :dast_site_profile
sanitizes! :name, :description
......
......@@ -8,6 +8,7 @@ RSpec.describe Dast::ProfilesFinder do
let_it_be(:dast_profile1) { create(:dast_profile, project: project1) }
let_it_be(:dast_profile2) { create(:dast_profile, project: project2) }
let_it_be(:dast_profile3) { create(:dast_profile, project: project1) }
let_it_be(:dast_profile_schedule) { create(:dast_profile_schedule, project: project1, dast_profile: dast_profile3)}
let(:params) { {} }
......@@ -40,6 +41,24 @@ RSpec.describe Dast::ProfilesFinder do
end
end
context 'filtering by has_schedule?' do
let(:params) { { has_dast_profile_schedule: true } }
context 'when has_dast_profile_schedule is true' do
it 'returns the dast_profiles with schedule' do
expect(subject).to contain_exactly(dast_profile3)
end
end
end
context 'filtering by *' do
let(:params) { { id: dast_profile3.id, project_id: project1.id, has_dast_profile_schedule: true } }
it 'returns the matching dast_profile' do
expect(subject).to contain_exactly(dast_profile3)
end
end
context 'when the dast_profile does not exist' do
let(:params) { { project_id: 0 } }
......
......@@ -102,6 +102,33 @@ RSpec.describe Dast::Profile, type: :model do
end
end
end
describe 'with_schedule' do
let_it_be(:another_dast_profile) { create(:dast_profile) }
let_it_be(:dast_profile_schedule) { create(:dast_profile_schedule, project: project, dast_profile: another_dast_profile) }
context 'when has_dast_profile_schedule is true' do
it 'includes the dast_profile with schedule' do
result = described_class.with_schedule(true)
aggregate_failures do
expect(result).to include(another_dast_profile)
expect(result).not_to include(subject)
end
end
end
context 'when has_dast_profile_schedule is false' do
it 'includes the dast_profile without schedule' do
result = described_class.with_schedule(false)
aggregate_failures do
expect(result).to include(subject)
expect(result).not_to include(another_dast_profile)
end
end
end
end
end
describe 'instance methods' do
......
......@@ -11,6 +11,14 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do
let_it_be(:dast_profile2) { create(:dast_profile, project: project) }
let_it_be(:dast_profile3) { create(:dast_profile, project: project) }
let_it_be(:dast_profile4) { create(:dast_profile, project: project) }
let_it_be(:dast_profile5) { create(:dast_profile, project: project) }
let_it_be(:dast_profile_schedule) { create(:dast_profile_schedule, project: project, dast_profile: dast_profile5)}
let(:all_records) do
[dast_profile5, dast_profile4, dast_profile3, dast_profile2, dast_profile1].map { |validation| global_id_of(validation) }
end
let(:query_args) { {} }
let(:query) do
fields = all_graphql_fields_for('DastProfile')
......@@ -18,7 +26,7 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do
graphql_query_for(
:project,
{ full_path: project.full_path },
query_nodes(:dast_profiles, fields)
query_nodes(:dast_profiles, fields, args: query_args)
)
end
......@@ -65,13 +73,18 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do
dast_profiles.map { |dast_profile| dast_profile['id'] }
end
shared_examples 'returns all dastProfiles' do
it 'returns all dastProfiles', :aggregate_failures do
subject
expect(graphql_data_at(:project, :dast_profiles, :nodes).count).to eq(5)
expect(graphql_data_at(:project, :dast_profiles, :nodes, :id)).to contain_exactly(*all_records)
end
end
it_behaves_like 'sorted paginated query' do
let(:sort_param) { nil }
let(:first_param) { 3 }
let(:all_records) do
[dast_profile4, dast_profile3, dast_profile2, dast_profile1].map { |validation| global_id_of(validation)}
end
end
it 'includes branch information' do
......@@ -95,6 +108,36 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do
expect { subject }.not_to exceed_query_limit(control)
end
context 'when `dast_view_scans` feature flag is disabled' do
before do
stub_feature_flags(dast_view_scans: false)
end
context 'when hasDastProfileSchedule is false' do
let(:query_args) { { hasDastProfileSchedule: false } }
include_examples 'returns all dastProfiles'
end
context 'when hasDastProfileSchedule is true' do
let(:query_args) { { hasDastProfileSchedule: true } }
include_examples 'returns all dastProfiles'
end
end
context 'when `dast_view_scans` feature flag is enabled' do
context 'when hasDastProfileSchedule is true' do
let(:query_args) { { hasDastProfileSchedule: true } }
it 'returns all dastProfiles with a schedule' do
subject
expect(graphql_data_at(:project, :dast_profiles, :nodes, :id)).to contain_exactly(dast_profile5.to_global_id.to_s)
end
end
end
end
def pagination_query(arguments)
......
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