mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 10:40:54 +00:00
Don't try keychain after authentication fails
Previously, we were achieving this by deleting the keychain item, but this can sometimes fail which leads to an infinite loop. Now, we explicitly never try the keychain when reattempting authentication after authentication fails. Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
29892ce5d7
commit
ee9ed936e4
6 changed files with 27 additions and 22 deletions
|
@ -327,7 +327,12 @@ impl ChatPanel {
|
|||
let rpc = rpc.clone();
|
||||
let this = this.clone();
|
||||
cx.spawn(|mut cx| async move {
|
||||
if rpc.authenticate_and_connect(&cx).log_err().await.is_some() {
|
||||
if rpc
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.log_err()
|
||||
.await
|
||||
.is_some()
|
||||
{
|
||||
cx.update(|cx| {
|
||||
if let Some(this) = this.upgrade(cx) {
|
||||
if this.is_focused(cx) {
|
||||
|
|
|
@ -55,7 +55,7 @@ action!(Authenticate);
|
|||
pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) {
|
||||
cx.add_global_action(move |_: &Authenticate, cx| {
|
||||
let rpc = rpc.clone();
|
||||
cx.spawn(|cx| async move { rpc.authenticate_and_connect(&cx).log_err().await })
|
||||
cx.spawn(|cx| async move { rpc.authenticate_and_connect(true, &cx).log_err().await })
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ impl Client {
|
|||
state._reconnect_task = Some(cx.spawn(|cx| async move {
|
||||
let mut rng = StdRng::from_entropy();
|
||||
let mut delay = Duration::from_millis(100);
|
||||
while let Err(error) = this.authenticate_and_connect(&cx).await {
|
||||
while let Err(error) = this.authenticate_and_connect(true, &cx).await {
|
||||
log::error!("failed to connect {}", error);
|
||||
this.set_status(
|
||||
Status::ReconnectionError {
|
||||
|
@ -547,6 +547,7 @@ impl Client {
|
|||
#[async_recursion(?Send)]
|
||||
pub async fn authenticate_and_connect(
|
||||
self: &Arc<Self>,
|
||||
try_keychain: bool,
|
||||
cx: &AsyncAppContext,
|
||||
) -> anyhow::Result<()> {
|
||||
let was_disconnected = match *self.status().borrow() {
|
||||
|
@ -568,23 +569,22 @@ impl Client {
|
|||
self.set_status(Status::Reauthenticating, cx)
|
||||
}
|
||||
|
||||
let mut used_keychain = false;
|
||||
let credentials = self.state.read().credentials.clone();
|
||||
let credentials = if let Some(credentials) = credentials {
|
||||
credentials
|
||||
} else if let Some(credentials) = read_credentials_from_keychain(cx) {
|
||||
used_keychain = true;
|
||||
credentials
|
||||
} else {
|
||||
let credentials = match self.authenticate(&cx).await {
|
||||
let mut read_from_keychain = false;
|
||||
let mut credentials = self.state.read().credentials.clone();
|
||||
if credentials.is_none() && try_keychain {
|
||||
credentials = read_credentials_from_keychain(cx);
|
||||
read_from_keychain = credentials.is_some();
|
||||
}
|
||||
if credentials.is_none() {
|
||||
credentials = Some(match self.authenticate(&cx).await {
|
||||
Ok(credentials) => credentials,
|
||||
Err(err) => {
|
||||
self.set_status(Status::ConnectionError, cx);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
credentials
|
||||
};
|
||||
});
|
||||
}
|
||||
let credentials = credentials.unwrap();
|
||||
|
||||
if was_disconnected {
|
||||
self.set_status(Status::Connecting, cx);
|
||||
|
@ -595,7 +595,7 @@ impl Client {
|
|||
match self.establish_connection(&credentials, cx).await {
|
||||
Ok(conn) => {
|
||||
self.state.write().credentials = Some(credentials.clone());
|
||||
if !used_keychain && IMPERSONATE_LOGIN.is_none() {
|
||||
if !read_from_keychain && IMPERSONATE_LOGIN.is_none() {
|
||||
write_credentials_to_keychain(&credentials, cx).log_err();
|
||||
}
|
||||
self.set_connection(conn, cx).await;
|
||||
|
@ -603,10 +603,10 @@ impl Client {
|
|||
}
|
||||
Err(EstablishConnectionError::Unauthorized) => {
|
||||
self.state.write().credentials.take();
|
||||
if used_keychain {
|
||||
if read_from_keychain {
|
||||
cx.platform().delete_credentials(&ZED_SERVER_URL).log_err();
|
||||
self.set_status(Status::SignedOut, cx);
|
||||
self.authenticate_and_connect(cx).await
|
||||
self.authenticate_and_connect(false, cx).await
|
||||
} else {
|
||||
self.set_status(Status::ConnectionError, cx);
|
||||
Err(EstablishConnectionError::Unauthorized)?
|
||||
|
|
|
@ -91,7 +91,7 @@ impl FakeServer {
|
|||
});
|
||||
|
||||
client
|
||||
.authenticate_and_connect(&cx.to_async())
|
||||
.authenticate_and_connect(false, &cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
server
|
||||
|
|
|
@ -377,7 +377,7 @@ impl Project {
|
|||
fs: Arc<dyn Fs>,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<ModelHandle<Self>> {
|
||||
client.authenticate_and_connect(&cx).await?;
|
||||
client.authenticate_and_connect(true, &cx).await?;
|
||||
|
||||
let response = client
|
||||
.request(proto::JoinProject {
|
||||
|
|
|
@ -5021,7 +5021,7 @@ mod tests {
|
|||
});
|
||||
|
||||
client
|
||||
.authenticate_and_connect(&cx.to_async())
|
||||
.authenticate_and_connect(false, &cx.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ fn main() {
|
|||
let client = client.clone();
|
||||
|cx| async move {
|
||||
if client.has_keychain_credentials(&cx) {
|
||||
client.authenticate_and_connect(&cx).await?;
|
||||
client.authenticate_and_connect(true, &cx).await?;
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue