Commit c911acda authored by charlie ablett's avatar charlie ablett Committed by Ash McKenzie

Add DAST resolvers

- DastSiteProfileResolver
- DastSiteValidationResolver
parent d59352ae
......@@ -7,27 +7,16 @@ module EE
prepended do
field :security_scanners, ::Types::SecurityScanners, null: true,
description: 'Information about security analyzers used in the project',
resolve: -> (project, _args, ctx) do
project
end
description: 'Information about security analyzers used in the project'
field :dast_scanner_profiles,
::Types::DastScannerProfileType.connection_type,
null: true,
description: 'The DAST scanner profiles associated with the project',
resolve: -> (project, _args, _ctx) do
DastScannerProfilesFinder.new(project_ids: [project.id]).execute
end
description: 'The DAST scanner profiles associated with the project'
field :sast_ci_configuration, ::Types::CiConfiguration::Sast::Type, null: true,
calls_gitaly: true,
description: 'SAST CI configuration for the project',
resolve: -> (project, args, ctx) do
return unless Ability.allowed?(ctx[:current_user], :download_code, project)
sast_ci_configuration(project)
end
description: 'SAST CI configuration for the project'
field :vulnerabilities,
::Types::VulnerabilityType.connection_type,
......@@ -61,12 +50,7 @@ module EE
resolver: ::Resolvers::RequirementsManagement::RequirementsResolver
field :requirement_states_count, ::Types::RequirementsManagement::RequirementStatesCountType, null: true,
description: 'Number of requirements for the project by their state',
resolve: -> (project, args, ctx) do
return unless Ability.allowed?(ctx[:current_user], :read_requirement, project)
Hash.new(0).merge(project.requirements.counts_by_state)
end
description: 'Number of requirements for the project by their state'
field :compliance_frameworks, ::Types::ComplianceManagement::ComplianceFrameworkType.connection_type,
description: 'Compliance frameworks associated with the project',
......@@ -74,11 +58,8 @@ module EE
null: true
field :security_dashboard_path, GraphQL::STRING_TYPE,
description: "Path to project's security dashboard",
null: true,
resolve: -> (project, args, ctx) do
Rails.application.routes.url_helpers.project_security_dashboard_index_path(project)
end
description: "Path to project's security dashboard",
null: true
field :iterations, ::Types::IterationType.connection_type, null: true,
description: 'Find iterations',
......@@ -87,33 +68,19 @@ module EE
field :dast_site_profile,
::Types::DastSiteProfileType,
null: true,
resolve: -> (obj, args, _ctx) do
# TODO: remove this coercion when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
gid = ::Types::GlobalIDType[::DastSiteProfile].coerce_isolated_input(args[:id])
DastSiteProfilesFinder.new(project_id: obj.id, id: gid.model_id).execute.first
end,
description: 'DAST Site Profile associated with the project' do
argument :id, ::Types::GlobalIDType[::DastSiteProfile], required: true, description: 'ID of the site profile'
end
resolver: ::Resolvers::DastSiteProfileResolver.single,
description: 'DAST Site Profile associated with the project'
field :dast_site_profiles,
::Types::DastSiteProfileType.connection_type,
null: true,
description: 'DAST Site Profiles associated with the project',
resolve: -> (obj, _args, _ctx) { DastSiteProfilesFinder.new(project_id: obj.id).execute }
resolver: ::Resolvers::DastSiteProfileResolver
field :dast_site_validation,
::Types::DastSiteValidationType,
null: true,
resolve: -> (project, args, _ctx) do
unless ::Feature.enabled?(:security_on_demand_scans_site_validation, project)
raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled'
end
url_base = DastSiteValidation.get_normalized_url_base(args.target_url)
DastSiteValidationsFinder.new(project_id: project.id, url_base: url_base).execute.first
end,
resolver: ::Resolvers::DastSiteValidationResolver,
description: 'DAST Site Validation associated with the project' do
argument :target_url, GraphQL::STRING_TYPE, required: true, description: 'target URL of the DAST Site Validation'
end
......@@ -139,8 +106,7 @@ module EE
field :actual_repository_size_limit,
GraphQL::FLOAT_TYPE,
null: true,
description: 'Size limit for the repository in bytes',
resolve: -> (obj, _args, _ctx) { obj.actual_size_limit }
description: 'Size limit for the repository in bytes'
field :code_coverage_summary,
::Types::Ci::CodeCoverageSummaryType,
......@@ -154,8 +120,32 @@ module EE
description: 'Incident Management On-call schedules of the project',
resolver: ::Resolvers::IncidentManagement::OncallScheduleResolver
def self.sast_ci_configuration(project)
::Security::CiConfiguration::SastParserService.new(project).configuration
def actual_repository_size_limit
object.actual_size_limit
end
def dast_scanner_profiles
DastScannerProfilesFinder.new(project_ids: [object.id]).execute
end
def requirement_states_count
return unless Ability.allowed?(current_user, :read_requirement, object)
Hash.new(0).merge(object.requirements.counts_by_state)
end
def sast_ci_configuration
return unless Ability.allowed?(current_user, :download_code, object)
::Security::CiConfiguration::SastParserService.new(object).configuration
end
def security_dashboard_path
Rails.application.routes.url_helpers.project_security_dashboard_index_path(object)
end
def security_scanners
object
end
end
end
......
# frozen_string_literal: true
module Resolvers
class DastSiteProfileResolver < BaseResolver
alias_method :project, :synchronized_object
type Types::DastSiteProfileType.connection_type, null: true
when_single do
argument :id, ::Types::GlobalIDType[::DastSiteProfile], required: true,
description: "ID of the site profile"
end
def resolve(**args)
if args[:id]
# TODO: remove this coercion when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
gid = ::Types::GlobalIDType[::DastSiteProfile].coerce_isolated_input(args[:id])
DastSiteProfilesFinder.new(project_id: project.id, id: gid.model_id).execute
else
DastSiteProfilesFinder.new(project_id: project.id).execute
end
end
end
end
# frozen_string_literal: true
module Resolvers
class DastSiteValidationResolver < BaseResolver
alias_method :project, :synchronized_object
type Types::DastSiteValidationType.connection_type, null: true
def resolve(**args)
unless ::Feature.enabled?(:security_on_demand_scans_site_validation, project)
raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled'
end
url_base = DastSiteValidation.get_normalized_url_base(args[:target_url])
DastSiteValidationsFinder.new(project_id: project.id, url_base: url_base).execute.first
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::DastSiteProfileResolver do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:dast_site_profile1) { create(:dast_site_profile, project: project) }
let_it_be(:dast_site_profile2) { create(:dast_site_profile, project: project) }
before do
project.add_maintainer(current_user)
end
specify do
expect(described_class).to have_nullable_graphql_type(Types::DastSiteProfileType.connection_type)
end
context 'when resolving a single DAST site profile' do
subject { sync(single_dast_site_profile(id: dast_site_profile1.to_global_id)) }
it { is_expected.to contain_exactly(dast_site_profile1) }
end
context 'when resolving multiple DAST site profiles' do
subject { sync(dast_site_profiles) }
it { is_expected.to contain_exactly(dast_site_profile1, dast_site_profile2) }
end
private
def dast_site_profiles(args = {}, context = { current_user: current_user })
resolve(described_class, obj: project, args: args, ctx: context)
end
def single_dast_site_profile(args = {}, context = { current_user: current_user })
resolve(described_class, obj: project, args: args, ctx: context)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::DastSiteValidationResolver do
include GraphqlHelpers
let_it_be(:target_url) { generate(:url) }
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:dast_site_token) { create(:dast_site_token, project: project, url: target_url) }
let_it_be(:dast_site_validation) { create(:dast_site_validation, dast_site_token: dast_site_token) }
subject { sync(resolve_dast_site_validations(target_url: target_url)) }
before do
project.add_maintainer(current_user)
end
specify do
expect(described_class).to have_nullable_graphql_type(Types::DastSiteValidationType.connection_type)
end
it 'returns DAST site validation' do
is_expected.to eq(dast_site_validation)
end
private
def resolve_dast_site_validations(args = {}, context = { current_user: current_user })
resolve(described_class, obj: project, args: args, ctx: context)
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