From 881c672a8b3aea170f3b29d00c9fd4282a994411 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Wed, 10 Jul 2024 15:34:39 +0200 Subject: [PATCH] GetProfileByProjectAndID includes selectors (#3833) We'll want to have the selectors in the reply to use in profile handlers. Relates: #3723 --- database/query/profiles.sql | 17 ++++++++++++++++- internal/db/profiles.sql.go | 19 ++++++++++++++++++- internal/db/profiles_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/database/query/profiles.sql b/database/query/profiles.sql index e6ed815ebb..bd0ac7ed42 100644 --- a/database/query/profiles.sql +++ b/database/query/profiles.sql @@ -50,7 +50,22 @@ DELETE FROM entity_profiles WHERE profile_id = $1 AND entity = $2; SELECT * FROM entity_profiles WHERE profile_id = $1 AND entity = $2; -- name: GetProfileByProjectAndID :many -SELECT sqlc.embed(profiles), sqlc.embed(profiles_with_entity_profiles) FROM profiles JOIN profiles_with_entity_profiles ON profiles.id = profiles_with_entity_profiles.profid +WITH helper AS( + SELECT pr.id as profid, + ARRAY_AGG(ROW(ps.id, ps.profile_id, ps.entity, ps.selector, ps.comment)::profile_selector) AS selectors + FROM profiles pr + JOIN profile_selectors ps + ON pr.id = ps.profile_id + WHERE pr.project_id = $1 + GROUP BY pr.id +) +SELECT + sqlc.embed(profiles), + sqlc.embed(profiles_with_entity_profiles), + helper.selectors::profile_selector[] AS profiles_with_selectors +FROM profiles +JOIN profiles_with_entity_profiles ON profiles.id = profiles_with_entity_profiles.profid +LEFT JOIN helper ON profiles.id = helper.profid WHERE profiles.project_id = $1 AND profiles.id = $2; -- name: GetProfileByID :one diff --git a/internal/db/profiles.sql.go b/internal/db/profiles.sql.go index bcb1b2d201..1af91c33e7 100644 --- a/internal/db/profiles.sql.go +++ b/internal/db/profiles.sql.go @@ -276,7 +276,22 @@ func (q *Queries) GetProfileByNameAndLock(ctx context.Context, arg GetProfileByN } const getProfileByProjectAndID = `-- name: GetProfileByProjectAndID :many -SELECT profiles.id, profiles.name, profiles.provider, profiles.project_id, profiles.remediate, profiles.alert, profiles.created_at, profiles.updated_at, profiles.provider_id, profiles.subscription_id, profiles.display_name, profiles.labels, profiles_with_entity_profiles.id, profiles_with_entity_profiles.entity, profiles_with_entity_profiles.profile_id, profiles_with_entity_profiles.contextual_rules, profiles_with_entity_profiles.created_at, profiles_with_entity_profiles.updated_at, profiles_with_entity_profiles.profid FROM profiles JOIN profiles_with_entity_profiles ON profiles.id = profiles_with_entity_profiles.profid +WITH helper AS( + SELECT pr.id as profid, + ARRAY_AGG(ROW(ps.id, ps.profile_id, ps.entity, ps.selector, ps.comment)::profile_selector) AS selectors + FROM profiles pr + JOIN profile_selectors ps + ON pr.id = ps.profile_id + WHERE pr.project_id = $1 + GROUP BY pr.id +) +SELECT + profiles.id, profiles.name, profiles.provider, profiles.project_id, profiles.remediate, profiles.alert, profiles.created_at, profiles.updated_at, profiles.provider_id, profiles.subscription_id, profiles.display_name, profiles.labels, + profiles_with_entity_profiles.id, profiles_with_entity_profiles.entity, profiles_with_entity_profiles.profile_id, profiles_with_entity_profiles.contextual_rules, profiles_with_entity_profiles.created_at, profiles_with_entity_profiles.updated_at, profiles_with_entity_profiles.profid, + helper.selectors::profile_selector[] AS profiles_with_selectors +FROM profiles +JOIN profiles_with_entity_profiles ON profiles.id = profiles_with_entity_profiles.profid +LEFT JOIN helper ON profiles.id = helper.profid WHERE profiles.project_id = $1 AND profiles.id = $2 ` @@ -288,6 +303,7 @@ type GetProfileByProjectAndIDParams struct { type GetProfileByProjectAndIDRow struct { Profile Profile `json:"profile"` ProfilesWithEntityProfile ProfilesWithEntityProfile `json:"profiles_with_entity_profile"` + ProfilesWithSelectors []ProfileSelector `json:"profiles_with_selectors"` } func (q *Queries) GetProfileByProjectAndID(ctx context.Context, arg GetProfileByProjectAndIDParams) ([]GetProfileByProjectAndIDRow, error) { @@ -319,6 +335,7 @@ func (q *Queries) GetProfileByProjectAndID(ctx context.Context, arg GetProfileBy &i.ProfilesWithEntityProfile.CreatedAt, &i.ProfilesWithEntityProfile.UpdatedAt, &i.ProfilesWithEntityProfile.Profid, + pq.Array(&i.ProfilesWithSelectors), ); err != nil { return nil, err } diff --git a/internal/db/profiles_test.go b/internal/db/profiles_test.go index 398555fe24..87f7ca9a1a 100644 --- a/internal/db/profiles_test.go +++ b/internal/db/profiles_test.go @@ -314,6 +314,35 @@ func TestProfileListWithSelectors(t *testing.T) { require.Contains(t, rows[genSelIdx].ProfilesWithSelectors, genericSel) }) + t.Run("Get profile by project and ID", func(t *testing.T) { + t.Parallel() + + oneResult, err := testQueries.GetProfileByProjectAndID(context.Background(), GetProfileByProjectAndIDParams{ + ProjectID: randomEntities.proj.ID, + ID: oneSelectorProfile.ID, + }) + require.NoError(t, err) + require.Len(t, oneResult, 1) + require.Len(t, oneResult[0].ProfilesWithSelectors, 1) + require.Contains(t, oneResult[0].ProfilesWithSelectors, oneSel) + + noResult, err := testQueries.GetProfileByProjectAndID(context.Background(), GetProfileByProjectAndIDParams{ + ProjectID: randomEntities.proj.ID, + ID: noSelectors.ID, + }) + require.NoError(t, err) + require.Len(t, noResult, 1) + require.Len(t, noResult[0].ProfilesWithSelectors, 0) + + multiResult, err := testQueries.GetProfileByProjectAndID(context.Background(), GetProfileByProjectAndIDParams{ + ProjectID: randomEntities.proj.ID, + ID: multiSelectorProfile.ID, + }) + require.NoError(t, err) + require.Len(t, multiResult, 1) + require.Len(t, multiResult[0].ProfilesWithSelectors, 3) + require.Subset(t, multiResult[0].ProfilesWithSelectors, []ProfileSelector{mulitSel1, mulitSel2, mulitSel3}) + }) } func TestProfileLabels(t *testing.T) {