Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

various improvements to saved searches#63539

Merged
sqs merged 1 commit into
mainfrom
sqs/modernize-saved-searches
Jul 15, 2024
Merged

various improvements to saved searches#63539
sqs merged 1 commit into
mainfrom
sqs/modernize-saved-searches

Conversation

@sqs

@sqs sqs commented Jun 28, 2024

Copy link
Copy Markdown
Member
  • Remove long-deprecated and long-ineffective notifications for saved searches (removed in https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/commit/de8ae5ee28e5d942fe30c5493fd39b63fd1233f6 2.5 years ago). Note that code monitors were the replacement for saved searches and work great.
  • Clean up UI.
  • Make the UI global instead of in the user/org area.
  • Convert React class components to function components.
  • Add default patterntype: because it's required.
  • Use useQuery and useMutation instead of requestGraphQL.
  • Use a single namespace owner GraphQL arg instead of separating out userID and orgID.
  • Clean up GraphQL resolver code and factor out common auth checking.
  • Support transferring ownership of saved searches among owners (the user's own user account and the orgs they're a member of).

(I know this is not in Svelte.)

SECURITY: There is one substantive change. Site admins may now view any user's and any org's saved searches. This is so that they can audit and delete them if needed.

image
image
image
image

Test plan

Try creating, updating, and deleting saved searches, and transferring ownership of them.

Changelog

  • Improved the saved searches feature, which lets you save search queries to easily reuse them later and share them with other people in an organization.
  • Added the ability to transfer ownership of a saved search to a user's organizations or from an organization to a user's account.
  • Removed a long-deprecated and ineffective settings search.savedQueries field. You can manage saved searches in a user's or organization's profile area (e.g., at /user/searches).

@sqs sqs requested a review from a team June 28, 2024 09:09
@cla-bot cla-bot Bot added the cla-signed label Jun 28, 2024
@sqs sqs changed the base branch from main to sqs/query-form-control June 28, 2024 09:09
@sqs sqs force-pushed the sqs/query-form-control branch from dadf645 to 1288e3f Compare June 29, 2024 03:55
@sqs sqs force-pushed the sqs/modernize-saved-searches branch from 4029982 to 965bfe9 Compare June 29, 2024 03:57
@sqs sqs force-pushed the sqs/query-form-control branch from 1288e3f to f3c38f9 Compare June 29, 2024 04:10
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 2 times, most recently from e89f99d to 34a18ab Compare June 29, 2024 04:56
@sqs sqs force-pushed the sqs/query-form-control branch from f3c38f9 to 117daec Compare June 29, 2024 05:03
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 3 times, most recently from 915302a to 600bab0 Compare June 29, 2024 05:24
@sqs sqs force-pushed the sqs/query-form-control branch from 117daec to 87057f5 Compare June 29, 2024 05:25
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 2 times, most recently from 644de16 to 09a049e Compare June 29, 2024 06:23
Comment thread cmd/frontend/graphqlbackend/namespaces.go Fixed
Comment on lines 94 to 110

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 2 times, most recently from 2d59b24 to 460f423 Compare June 29, 2024 20:01
@sqs sqs marked this pull request as draft July 1, 2024 05:40
@sqs sqs force-pushed the sqs/query-form-control branch 2 times, most recently from 19d47ec to 0821d14 Compare July 2, 2024 00:13
Base automatically changed from sqs/query-form-control to main July 2, 2024 00:34
@sqs sqs force-pushed the sqs/modernize-saved-searches branch from 460f423 to 40b67f5 Compare July 3, 2024 10:16
Comment on lines +94 to +99
// 🚨 SECURITY: Make sure the current user has permission for the specified namespace.
if err := CheckAuthorizedForNamespaceByIDs(ctx, db, *namespace); err != nil {
return nil, err
}
return namespace, nil

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines +69 to +83
// 🚨 SECURITY: Make sure the current user has permission to get the saved search.
if err := graphqlbackend.CheckAuthorizedForNamespaceByIDs(ctx, r.db, ss.Owner); err != nil {
return nil, err
}

savedSearch := &savedSearchResolver{
db: r.db,
s: *ss,
}
return savedSearch, nil

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines +129 to +148
// 🚨 SECURITY: Make sure the current user has permission to view saved searches of the
// specified owner.
owner, err := graphqlbackend.CheckAuthorizedForNamespace(ctx, r.db, *args.Owner)
if err != nil {
return nil, err
}
connectionStore.listArgs.Owner = owner

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread cmd/frontend/internal/savedsearches/resolvers/resolvers.go Fixed
Comment on lines +202 to +211
// 🚨 SECURITY: Make sure the current user has permission to create a saved search in the
// specified owner namespace.
namespace, err := graphqlbackend.CheckAuthorizedForNamespace(ctx, r.db, args.Input.Owner)
if err != nil {
return nil, err
}

if !queryHasPatternType(args.Input.Query) {
return nil, errMissingPatternType
}

ss, err := r.db.SavedSearches().Create(ctx, &types.SavedSearch{
Description: args.Input.Description,
Query: args.Input.Query,
Owner: *namespace,
})
if err != nil {
return nil, err
}

return r.toSavedSearchResolver(*ss), nil

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
// 🚨 SECURITY: ...and check the user can administer saved searches in the new owner's
// namespace:
newOwner, err := graphqlbackend.CheckAuthorizedForNamespace(ctx, r.db, args.NewOwner)
if err != nil {
return nil, err
}

ss, err = r.db.SavedSearches().UpdateOwner(ctx, id, *newOwner)
if err != nil {
return nil, err
}
return r.toSavedSearchResolver(*ss), nil

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines +77 to +114
// 🚨 SECURITY: This method does NOT verify the user's identity or that the user is an admin. It is
// the caller's responsibility to ensure the user has proper permissions to perform the update.
func (s *savedSearchStore) Update(ctx context.Context, savedSearch *types.SavedSearch) (updated *types.SavedSearch, err error) {
tr, ctx := trace.New(ctx, "database.SavedSearches.Update")
defer tr.EndWithErr(&err)

q := sqlf.Sprintf(`SELECT
id,
description,
query,
notify_owner,
notify_slack,
user_id,
org_id,
slack_webhook_url FROM saved_searches
`)
rows, err := s.Query(ctx, q)
if err != nil {
return nil, errors.Wrap(err, "QueryContext")
}
return s.update(ctx, savedSearch.ID, []*sqlf.Query{
sqlf.Sprintf("description=%s", savedSearch.Description),
sqlf.Sprintf("query=%s", savedSearch.Query),
})
}

for rows.Next() {
var sq api.SavedQuerySpecAndConfig
if err := rows.Scan(
&sq.Config.Key,
&sq.Config.Description,
&sq.Config.Query,
&sq.Config.Notify,
&sq.Config.NotifySlack,
&sq.Config.UserID,
&sq.Config.OrgID,
&sq.Config.SlackWebhookURL); err != nil {
return nil, errors.Wrap(err, "Scan")
}
sq.Spec.Key = sq.Config.Key
if sq.Config.UserID != nil {
sq.Spec.Subject.User = sq.Config.UserID
} else if sq.Config.OrgID != nil {
sq.Spec.Subject.Org = sq.Config.OrgID
}
// UpdateOwner updates the owner of an existing saved search.
//
// 🚨 SECURITY: This method does NOT verify that the user has permissions to do this. The caller
// MUST do so.
func (s *savedSearchStore) UpdateOwner(ctx context.Context, id int32, newOwner types.Namespace) (updated *types.SavedSearch, err error) {
tr, ctx := trace.New(ctx, "database.SavedSearches.UpdateOwner")
defer tr.EndWithErr(&err)
return s.update(ctx, id, []*sqlf.Query{
sqlf.Sprintf("user_id=%v", newOwner.User),
sqlf.Sprintf("org_id=%v", newOwner.Org),
})
}

savedSearches = append(savedSearches, sq)
}
return savedSearches, nil
func (s *savedSearchStore) update(ctx context.Context, id int32, updates []*sqlf.Query) (updated *types.SavedSearch, err error) {
updates = append(updates, sqlf.Sprintf("updated_at=now()"))
return scanSavedSearch(
s.QueryRow(ctx,
sqlf.Sprintf(
`UPDATE saved_searches SET %s WHERE id=%v RETURNING id, %v`,

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread internal/database/saved_searches.go Fixed
Comment thread cmd/frontend/graphqlbackend/viewer.go Fixed
Comment thread cmd/frontend/graphqlbackend/affiliated_namespaces.go Fixed
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 5 times, most recently from 659dc81 to b9ab5c0 Compare July 5, 2024 13:40
@sqs sqs marked this pull request as ready for review July 5, 2024 13:40
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 206 to 244

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 55 to 88

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines 143 to 162

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines 150 to 160

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines 156 to 187

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment on lines 163 to 187

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 120 to 158

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 134 to 164

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 3 times, most recently from 745d1b9 to 5f87978 Compare July 5, 2024 15:47

@camdencheek camdencheek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted to give this a real review (and also pulled it down and did some manual poking around), but it's also large, so relying a bit on your confidence 🙂

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for splitting this out into its own file!

Comment on lines +156 to +159
"""
The owner of the saved search, either a user or organization.
"""
owner: Namespace!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you came across this during the refactor: do you know why we have a special type for Namespace? Seems like it would be more ergonomic to just type it in GraphQL as User | Org.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we’ll want it to also support global and team namespaces. That was part of the original idea from years ago, and I think it’s finally nearing time for that again (with multi-tenant private code this year and supporting groupings within an org).

Comment on lines -39 to -46
return &types.SavedSearches{
TotalSavedSearches: int32(totalSavedSearches),
UniqueUsers: int32(uniqueUsers),
NotificationsSent: int32(notificationsSent),
NotificationsClicked: int32(notificationsClicked),
UniqueUserPageViews: int32(uniqueUserPageViews),
OrgSavedSearches: int32(orgSavedSearches),
}, nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, I think if we updated the payload shape for pings, we needed to update the schema found here. That might have changed, so also cc @dadlerj

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dadlerj said:

That JSON file should be updated yes and then the changes have to be published to BigQuery. I'll file a ticket on my team for us to go do all this after your PR.

It's fine to merge now though, unless this is an urgent patch release going out to customers asap... It'll be a while til this goes live and our changes only need to be done on our side.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for following up 👍

Comment on lines +1 to +3
-- no default value
ALTER TABLE saved_searches ALTER COLUMN notify_owner DROP DEFAULT;
ALTER TABLE saved_searches ALTER COLUMN notify_slack DROP DEFAULT;

@camdencheek camdencheek Jul 9, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I forgot to ever follow up on removing these columns.

Comment thread client/web/src/savedSearches/ListPage.tsx Outdated
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 3 times, most recently from 1933074 to 67dafc0 Compare July 14, 2024 23:16
Comment on lines 179 to 181

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 259 to 293

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 3 times, most recently from 1851293 to 1fbf274 Compare July 15, 2024 02:43
Comment thread internal/database/saved_searches.go Outdated
Comment on lines 124 to 154

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: security-semgrep-rules.semgrep-rules.generic.comment-tagging-rule

Code that highlight SECURITY in comment has changed. Please review the code for changes. The changes might be sensitive.
@sqs sqs force-pushed the sqs/modernize-saved-searches branch 3 times, most recently from 5747699 to 63cb9ce Compare July 15, 2024 05:13
@sqs sqs changed the base branch from main to sqs/gql-conn July 15, 2024 19:01
@sqs sqs force-pushed the sqs/modernize-saved-searches branch from 63cb9ce to 919aa0e Compare July 15, 2024 19:01
@sqs sqs force-pushed the sqs/modernize-saved-searches branch from 919aa0e to aa65e93 Compare July 15, 2024 19:11
Base automatically changed from sqs/gql-conn to main July 15, 2024 19:18
- Remove long-deprecated and long-ineffective notifications for saved searches (removed in https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/commit/de8ae5ee28e5d942fe30c5493fd39b63fd1233f6 2.5 years ago). Note that code monitors were the replacement for saved searches and work great.
- Clean up UI.
- Make the UI global instead of in the user/org area.
- Convert React class components to function components.
- Add default `patterntype:` because it's required.
- Use `useQuery` and `useMutation` instead of `requestGraphQL`.
- Use a single namespace `owner` GraphQL arg instead of separating out `userID` and `orgID`.
- Clean up GraphQL resolver code and factor out common auth checking.
- Support transferring ownership of saved searches among owners (the user's own user account and the orgs they're a member of).

(I know this is not in Svelte.)

SECURITY: There is one substantive change. Site admins may now view any user's and any org's saved searches. This is so that they can audit and delete them if needed.

![image](https://github.com/sourcegraph/sourcegraph/assets/1976/7ba22c1c-b92e-4089-836b-135a503c96a0)
![image](https://github.com/sourcegraph/sourcegraph/assets/1976/a1f2f43d-f681-4ec9-b2a1-8273707b34ee)
![image](https://github.com/sourcegraph/sourcegraph/assets/1976/5ee1164f-ed2e-4144-9aca-db61fa7c20f4)
![image](https://github.com/sourcegraph/sourcegraph/assets/1976/d631529e-6c0d-49c6-9be1-33a7ff53ed97)

Test plan:

Try creating, updating, and deleting saved searches, and transferring ownership of them.

Changelog:

- Improved the saved searches feature, which lets you save search queries to easily reuse them later and share them with other people in an organization.
- Added the ability to transfer ownership of a saved search to a user's organizations or from an organization to a user's account.
- Removed a long-deprecated and ineffective settings `search.savedQueries` field. You can manage saved searches in a user's or organization's profile area (e.g., at `/user/searches`).
@sqs sqs force-pushed the sqs/modernize-saved-searches branch from aa65e93 to 37928cb Compare July 15, 2024 20:01
@sqs sqs enabled auto-merge (squash) July 15, 2024 20:01
@sqs sqs merged commit 7ba706e into main Jul 15, 2024
@sqs sqs deleted the sqs/modernize-saved-searches branch July 15, 2024 20:12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants