-
Notifications
You must be signed in to change notification settings - Fork 238
feat(compass-web): add the AtlasUserData class to save user data COMPASS-9565 #7152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for using the AtlasUserData class to demonstrate saving user data in Compass Web, integrating Atlas cloud storage for queries and pipelines alongside the existing file-based storage.
- Updates query and pipeline storage classes to support both Atlas cloud storage and file-based storage
- Modifies ID generation from UUID to ObjectId and changes schema validation to accept any string for
_id
- Integrates Atlas storage providers into the Compass Web entrypoint with proper authentication
Reviewed Changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 6 comments.
Show a summary per file
File | Description |
---|---|
packages/my-queries-storage/src/query-storage.ts | Adds optional id parameter to favorite query interface |
packages/my-queries-storage/src/query-storage-schema.ts | Changes _id validation from UUID to any string |
packages/my-queries-storage/src/compass-query-storage.ts | Adds Atlas storage support and switches from UUID to ObjectId |
packages/my-queries-storage/src/compass-pipeline-storage.ts | Adds Atlas storage support with dual storage backend logic |
packages/my-queries-storage/src/compass-pipeline-storage.spec.ts | Updates test to use new constructor options format |
packages/compass-web/src/entrypoint.tsx | Integrates Atlas storage providers and removes context menu tracking |
packages/compass-user-data/src/user-data.ts | Adds readOne method to interface and refactors AtlasUserData API calls |
packages/compass-user-data/src/user-data.spec.ts | Updates tests for new API endpoint structure |
packages/compass-sidebar/src/components/multiple-connections/navigation/navigation.tsx | Adds redundant condition to My Queries visibility |
packages/compass-query-bar/src/stores/query-bar-reducer.ts | Changes from updateAttributes to saveQuery method |
packages/compass-data-modeling/src/services/data-model-storage-electron.tsx | Adds whitespace formatting |
packages/atlas-service/src/provider.tsx | Exports useAtlasServiceContext function |
packages/atlas-service/src/atlas-service.ts | Adds user data endpoints and includes credentials in authenticated requests |
package.json | Adds @leafygreen-ui/avatar dependency |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
packages/compass-sidebar/src/components/multiple-connections/navigation/navigation.tsx
Outdated
Show resolved
Hide resolved
return `https://cluster-connection.cloud-dev.mongodb.com${normalizePath( | ||
path | ||
)}`; | ||
} | ||
userDataEndpoint(path?: string): string { | ||
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( | ||
path | ||
)}`; |
Copilot
AI
Sep 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded development endpoint URL in production code poses security risks. This should be configurable or removed from production builds.
return `https://cluster-connection.cloud-dev.mongodb.com${normalizePath( | |
path | |
)}`; | |
} | |
userDataEndpoint(path?: string): string { | |
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( | |
path | |
)}`; | |
if (!this.config.tempBaseUrl) { | |
throw new Error('tempBaseUrl is not configured'); | |
} | |
return `${this.config.tempBaseUrl}${normalizePath(path)}`; | |
} | |
userDataEndpoint(path?: string): string { | |
if (!this.config.tempBaseUrl) { | |
throw new Error('tempBaseUrl is not configured'); | |
} | |
return `${this.config.tempBaseUrl}/userData${normalizePath(path)}`; |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will be fixed in follow up pr
return `https://cluster-connection.cloud-dev.mongodb.com${normalizePath( | ||
path | ||
)}`; | ||
} | ||
userDataEndpoint(path?: string): string { | ||
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( | ||
path | ||
)}`; |
Copilot
AI
Sep 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded development endpoint URL in production code poses security risks. This should be configurable or removed from production builds.
return `https://cluster-connection.cloud-dev.mongodb.com${normalizePath( | |
path | |
)}`; | |
} | |
userDataEndpoint(path?: string): string { | |
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( | |
path | |
)}`; | |
if (!this.config.tempEndpointBaseUrl) { | |
throw new Error('tempEndpointBaseUrl is not configured'); | |
} | |
return `${this.config.tempEndpointBaseUrl}${normalizePath(path)}`; | |
} | |
userDataEndpoint(path?: string): string { | |
if (!this.config.userDataEndpointBaseUrl) { | |
throw new Error('userDataEndpointBaseUrl is not configured'); | |
} | |
return `${this.config.userDataEndpointBaseUrl}${normalizePath(path)}`; |
Copilot uses AI. Check for mistakes.
packages/compass-aggregations/src/components/pipeline-toolbar/pipeline-settings/index.tsx
Outdated
Show resolved
Hide resolved
options.orgId && | ||
options.projectId && | ||
options.getResourceUrl && | ||
options.authenticatedFetch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where it decides to use atlas user data -- if all Atlas options are provided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, seems.. okay not something we want to just explicitly request? The Welcome page is split into web and desktop variants at build time, I was originally imagining this would also be build time. Seems fine for an initial approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for other services that's the patterns we're following and we should stick to it here too. See data-modeling exports for example where we have a pretty similar case, there is a shared interface and two separate exports, one for web, one for electron
* - Recent queries autocomplete | ||
* - Favorite queries/aggregations | ||
*/ | ||
export function useMyQueriesFeature(): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not used anywhere?
options.orgId && | ||
options.projectId && | ||
options.getResourceUrl && | ||
options.authenticatedFetch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, seems.. okay not something we want to just explicitly request? The Welcome page is split into web and desktop variants at build time, I was originally imagining this would also be build time. Seems fine for an initial approach
return this.cloudEndpoint(path); | ||
} | ||
userDataEndpoint(path?: string): string { | ||
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be coming from the config property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I was going to do this in a followup PR for this ticket: https://jira.mongodb.org/browse/COMPASS-9663
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super small nit for the future, if you already have a TODO like that in mind, it's super helpful to add it in the code to clarify that something is out of scope for the particular change being up for review 🙂
options.orgId && | ||
options.projectId && | ||
options.getResourceUrl && | ||
options.authenticatedFetch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for other services that's the patterns we're following and we should stick to it here too. See data-modeling exports for example where we have a pretty similar case, there is a shared interface and two separate exports, one for web, one for electron
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very neat!
return this.cloudEndpoint(path); | ||
} | ||
userDataEndpoint(path?: string): string { | ||
return `https://cluster-connection.cloud-dev.mongodb.com/userData${normalizePath( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super small nit for the future, if you already have a TODO like that in mind, it's super helpful to add it in the code to clarify that something is out of scope for the particular change being up for review 🙂
...(shouldAddCSRFHeaders(init?.method) && getCSRFHeaders()), | ||
...init?.headers, | ||
}, | ||
headers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Hard to leave a comment about this in more relevant place) Because we now doing cross origin authenticated requests through AtlasService, we need to allow fetch to include cookies in the request when possible. This is how you do it:
headers, | |
headers, | |
credentials: 'include', |
But we should probably do this only for authenticatedFetch below
<PipelineStorageProvider value={pipelineStorage.current}> | ||
<FavoriteQueryStorageProvider value={favoriteQueryStorage.current}> | ||
<RecentQueryStorageProvider value={recentQueryStorage.current}> | ||
{children} | ||
</RecentQueryStorageProvider> | ||
</FavoriteQueryStorageProvider> | ||
</PipelineStorageProvider> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not super important, but we can probably do all this wiring inside my-queries package and expose only something like MyQueriesStorageProvider
component outside. And a similar cleanup can be done for desktop counterpart. This would probably require moving around even more code, so fine as is for now, just thinking out loud.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final stretch!!
Description
Checklist
Motivation and Context
Open Questions
Dependents
Types of changes