Skip to content

Add ability to update DastSiteProfile with GraphQL

What does this MR do?

adds a new graphql mutation for updating dast_site_profiles via:

  • new finder (DastSiteProfileFinder)
  • new service (DastSiteProfiles::UpdateService)
  • new mutation (Mutations::DastSiteProfiles::Update)
  • new specs at the request, mutation, finder and service level

i have not added a changelog entry because the feature is behind a feature flag.

Related Issue(s)

Database Changes

  • currently we see few records in those tables, when we have 15M projects for gitlab.com, it means a fraction of those projects will have multiple dast_site_profiles
  • we may open an issue to think an index for "dast_site_profiles"."project_id" AND "dast_site_profiles"."id" in upcoming releases

Details

Queries
# no filtering
[7] pry(main)> finder = DastSiteProfilesFinder.new
=> #<DastSiteProfilesFinder:0x00007f8a1e875de8 @params={}>
[8] pry(main)> finder.execute
  DastSiteProfile Load (0.4ms)  SELECT "dast_site_profiles".* FROM "dast_site_profiles"
  DastSite Load (0.2ms)  SELECT "dast_sites".* FROM "dast_sites" WHERE "dast_sites"."id" IN ($1, $2, $3)  [["id", 1], ["id", 2], ["id", 3]]
Seq Scan on public.dast_site_profiles  (cost=0.00..4.07 rows=7 width=72) (actual time=0.983..0.984 rows=5 loops=1)
   Buffers: shared read=1 dirtied=1
   I/O Timings: read=0.791

 Seq Scan on public.dast_sites  (cost=0.00..4.05 rows=3 width=64) (actual time=1.062..1.063 rows=3 loops=1)
   Filter: (dast_sites.id = ANY ('{1,2,3}'::bigint[]))
   Rows Removed by Filter: 1
   Buffers: shared read=1
   I/O Timings: read=1.045

# filtering by :id
[11] pry(main)> finder = DastSiteProfilesFinder.new(id: 1)
=> #<DastSiteProfilesFinder:0x00007f8a1ead5480 @params={:id=>1}>
[12] pry(main)> finder.execute
  DastSiteProfile Load (0.4ms)  SELECT "dast_site_profiles".* FROM "dast_site_profiles" WHERE "dast_site_profiles"."id" = $1  [["id", 1]]
  DastSite Load (0.2ms)  SELECT "dast_sites".* FROM "dast_sites" WHERE "dast_sites"."id" = $1  [["id", 1]]
 Index Scan using dast_site_profiles_pkey on public.dast_site_profiles  (cost=0.13..3.15 rows=1 width=72) (actual time=1.133..1.133 rows=0 loops=1)
   Index Cond: (dast_site_profiles.id = 1)
   Buffers: shared hit=5 read=1 dirtied=1
   I/O Timings: read=1.024

 Index Scan using dast_sites_pkey on public.dast_sites  (cost=0.13..3.15 rows=1 width=64) (actual time=1.252..1.254 rows=1 loops=1)
   Index Cond: (dast_sites.id = 1)
   Buffers: shared hit=1 read=1
   I/O Timings: read=1.183

# filtering by :id and :project_id
[15] pry(main)> finder = DastSiteProfilesFinder.new(id: 1, project_id: 20)
=> #<DastSiteProfilesFinder:0x00007f8a1ecc4868 @params={:id=>1, :project_id=>20}>
[16] pry(main)> finder.execute
  DastSiteProfile Load (0.2ms)  SELECT "dast_site_profiles".* FROM "dast_site_profiles" WHERE "dast_site_profiles"."id" = $1 AND "dast_site_profiles"."project_id" = $2  [["id", 1], ["project_id", 20]]
  DastSite Load (0.2ms)  SELECT "dast_sites".* FROM "dast_sites" WHERE "dast_sites"."id" = $1  [["id", 1]]
 Index Scan using index_dast_site_profiles_on_project_id_and_name on public.dast_site_profiles  (cost=0.13..3.15 rows=1 width=72) (actual time=1.896..1.896 rows=0 loops=1)
   Index Cond: (dast_site_profiles.project_id = 278964)
   Filter: (dast_site_profiles.id = 1)
   Rows Removed by Filter: 0
   Buffers: shared read=1
   I/O Timings: read=1.855

 Index Scan using dast_sites_pkey on public.dast_sites  (cost=0.13..3.15 rows=1 width=64) (actual time=1.252..1.254 rows=1 loops=1)
   Index Cond: (dast_sites.id = 1)
   Buffers: shared hit=1 read=1
   I/O Timings: read=1.183

# filtering by :project_id
[17] pry(main)> finder = DastSiteProfilesFinder.new(project_id: 20)
=> #<DastSiteProfilesFinder:0x00007f8a1edc7378 @params={:project_id=>20}>
[18] pry(main)> finder.execute
  DastSiteProfile Load (0.8ms)  SELECT "dast_site_profiles".* FROM "dast_site_profiles" WHERE "dast_site_profiles"."project_id" = $1  [["project_id", 20]]
  DastSite Load (0.2ms)  SELECT "dast_sites".* FROM "dast_sites" WHERE "dast_sites"."id" IN ($1, $2)  [["id", 2], ["id", 1]]
 Index Scan using index_dast_site_profiles_on_project_id_and_name on public.dast_site_profiles  (cost=0.13..3.15 rows=1 width=72) (actual time=1.896..1.896 rows=0 loops=1)
   Index Cond: (dast_site_profiles.project_id = 278964)
   Filter: (dast_site_profiles.id = 1)
   Rows Removed by Filter: 0
   Buffers: shared read=1
   I/O Timings: read=1.855

 Seq Scan on public.dast_sites  (cost=0.00..4.05 rows=2 width=64) (actual time=0.011..0.012 rows=2 loops=1)
   Filter: (dast_sites.id = ANY ('{1,2}'::bigint[]))
   Rows Removed by Filter: 2
   Buffers: shared hit=1

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by Mayra Cabrera

Merge request reports