Add credentials_url setting for keychain storage#50047
Merged
probably-neb merged 2 commits intozed-industries:mainfrom Apr 23, 2026
Merged
Add credentials_url setting for keychain storage#50047probably-neb merged 2 commits intozed-industries:mainfrom
credentials_url setting for keychain storage#50047probably-neb merged 2 commits intozed-industries:mainfrom
Conversation
|
We require contributors to sign our Contributor License Agreement, and we don't have @parndt on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
This comment was marked as outdated.
This comment was marked as outdated.
|
The cla-bot has been summoned, and re-checked this pull request! |
5ab5638 to
6fc6475
Compare
Comment on lines
+2251
to
+2359
| #[derive(Default)] | ||
| struct SpyCredentialsProvider { | ||
| recorded_urls: Mutex<Vec<String>>, | ||
| stored: Mutex<HashMap<String, (String, Vec<u8>)>>, | ||
| } | ||
|
|
||
| impl CredentialsProvider for SpyCredentialsProvider { | ||
| fn read_credentials<'a>( | ||
| &'a self, | ||
| url: &'a str, | ||
| _cx: &'a AsyncApp, | ||
| ) -> Pin<Box<dyn Future<Output = Result<Option<(String, Vec<u8>)>>> + 'a>> { | ||
| async move { | ||
| self.recorded_urls.lock().push(url.to_string()); | ||
| Ok(self.stored.lock().get(url).cloned()) | ||
| } | ||
| .boxed_local() | ||
| } | ||
|
|
||
| fn write_credentials<'a>( | ||
| &'a self, | ||
| url: &'a str, | ||
| username: &'a str, | ||
| password: &'a [u8], | ||
| _cx: &'a AsyncApp, | ||
| ) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> { | ||
| async move { | ||
| self.recorded_urls.lock().push(url.to_string()); | ||
| self.stored | ||
| .lock() | ||
| .insert(url.to_string(), (username.to_string(), password.to_vec())); | ||
| Ok(()) | ||
| } | ||
| .boxed_local() | ||
| } | ||
|
|
||
| fn delete_credentials<'a>( | ||
| &'a self, | ||
| url: &'a str, | ||
| _cx: &'a AsyncApp, | ||
| ) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> { | ||
| async move { | ||
| self.recorded_urls.lock().push(url.to_string()); | ||
| self.stored.lock().remove(url); | ||
| Ok(()) | ||
| } | ||
| .boxed_local() | ||
| } | ||
| } | ||
|
|
||
| #[gpui::test] | ||
| async fn test_credentials_use_configured_url(cx: &mut TestAppContext) { | ||
| init_test(cx); | ||
| let spy = Arc::new(SpyCredentialsProvider::default()); | ||
| let provider = ClientCredentialsProvider::with_provider(spy.clone()); | ||
| let async_cx = cx.to_async(); | ||
|
|
||
| provider | ||
| .write_credentials(42, "test-token".to_string(), &async_cx) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| let expected_url = cx.update(|cx| ClientSettings::get_global(cx).server_url.clone()); | ||
| let recorded = spy.recorded_urls.lock().clone(); | ||
| assert_eq!(recorded, vec![expected_url.clone()]); | ||
|
|
||
| let credentials = provider.read_credentials(&async_cx).await.unwrap(); | ||
| assert_eq!(credentials.user_id, 42); | ||
| assert_eq!(credentials.access_token, "test-token"); | ||
|
|
||
| provider.delete_credentials(&async_cx).await.unwrap(); | ||
| let recorded = spy.recorded_urls.lock().clone(); | ||
| assert_eq!( | ||
| recorded, | ||
| vec![expected_url.clone(), expected_url.clone(), expected_url] | ||
| ); | ||
|
|
||
| assert!(provider.read_credentials(&async_cx).await.is_none()); | ||
| } | ||
|
|
||
| #[gpui::test] | ||
| async fn test_credentials_are_keyed_by_url(cx: &mut TestAppContext) { | ||
| init_test(cx); | ||
| let spy = Arc::new(SpyCredentialsProvider::default()); | ||
| let provider = ClientCredentialsProvider::with_provider(spy.clone()); | ||
| let async_cx = cx.to_async(); | ||
|
|
||
| provider | ||
| .write_credentials(1, "token-a".to_string(), &async_cx) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| let expected_url = cx.update(|cx| ClientSettings::get_global(cx).server_url.clone()); | ||
|
|
||
| let other_url = format!("{}/other", expected_url); | ||
| spy.stored.lock().insert( | ||
| other_url.clone(), | ||
| ("2".to_string(), b"token-b".to_vec()), | ||
| ); | ||
|
|
||
| let credentials = provider.read_credentials(&async_cx).await.unwrap(); | ||
| assert_eq!(credentials.user_id, 1); | ||
| assert_eq!(credentials.access_token, "token-a"); | ||
|
|
||
| provider.delete_credentials(&async_cx).await.unwrap(); | ||
| assert!(provider.read_credentials(&async_cx).await.is_none()); | ||
|
|
||
| assert!(spy.stored.lock().get(&other_url).is_some()); | ||
| } |
Collaborator
There was a problem hiding this comment.
I don't think these tests are worth keeping around. They are essentially just checking the if credentials_url { return credentials_url } else { return server_url }
Collaborator
|
are you still working on this @parndt? |
Contributor
Author
Yes, I'm happy to. After the initial review I do intend to make the change to remove the tests. |
This falls back to `server_url` if not configured, and is usable as the key for storing information inside Keychain Access. This allows distinct copies of Zed to use different keys which allows the use of multiple profiles.
329e2b5 to
cd63b73
Compare
Improve credentials_url doc comment
cd63b73 to
28b6691
Compare
Contributor
Author
|
@probably-neb updated, thanks! I took the opportunity to rebase it. |
probably-neb
approved these changes
Apr 23, 2026
Merged
via the queue into
zed-industries:main
with commit Apr 23, 2026
4b01676
49 of 51 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added support for
credentials_url, falling back toserver_url, to be used as the key for storing information inside Keychain Access. This allows two copies of Zed to be used side by side if the other is launched with a custom--user-data-dir.Release Notes:
credentials_url, falling back toserver_url, to be used as the key for storing information inside Keychain Access.