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 rpc = rpc.clone();
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
cx.spawn(|mut cx| async move {
|
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| {
|
cx.update(|cx| {
|
||||||
if let Some(this) = this.upgrade(cx) {
|
if let Some(this) = this.upgrade(cx) {
|
||||||
if this.is_focused(cx) {
|
if this.is_focused(cx) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ action!(Authenticate);
|
||||||
pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) {
|
pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) {
|
||||||
cx.add_global_action(move |_: &Authenticate, cx| {
|
cx.add_global_action(move |_: &Authenticate, cx| {
|
||||||
let rpc = rpc.clone();
|
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();
|
.detach();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ impl Client {
|
||||||
state._reconnect_task = Some(cx.spawn(|cx| async move {
|
state._reconnect_task = Some(cx.spawn(|cx| async move {
|
||||||
let mut rng = StdRng::from_entropy();
|
let mut rng = StdRng::from_entropy();
|
||||||
let mut delay = Duration::from_millis(100);
|
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);
|
log::error!("failed to connect {}", error);
|
||||||
this.set_status(
|
this.set_status(
|
||||||
Status::ReconnectionError {
|
Status::ReconnectionError {
|
||||||
|
@ -547,6 +547,7 @@ impl Client {
|
||||||
#[async_recursion(?Send)]
|
#[async_recursion(?Send)]
|
||||||
pub async fn authenticate_and_connect(
|
pub async fn authenticate_and_connect(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
|
try_keychain: bool,
|
||||||
cx: &AsyncAppContext,
|
cx: &AsyncAppContext,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let was_disconnected = match *self.status().borrow() {
|
let was_disconnected = match *self.status().borrow() {
|
||||||
|
@ -568,23 +569,22 @@ impl Client {
|
||||||
self.set_status(Status::Reauthenticating, cx)
|
self.set_status(Status::Reauthenticating, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut used_keychain = false;
|
let mut read_from_keychain = false;
|
||||||
let credentials = self.state.read().credentials.clone();
|
let mut credentials = self.state.read().credentials.clone();
|
||||||
let credentials = if let Some(credentials) = credentials {
|
if credentials.is_none() && try_keychain {
|
||||||
credentials
|
credentials = read_credentials_from_keychain(cx);
|
||||||
} else if let Some(credentials) = read_credentials_from_keychain(cx) {
|
read_from_keychain = credentials.is_some();
|
||||||
used_keychain = true;
|
}
|
||||||
credentials
|
if credentials.is_none() {
|
||||||
} else {
|
credentials = Some(match self.authenticate(&cx).await {
|
||||||
let credentials = match self.authenticate(&cx).await {
|
|
||||||
Ok(credentials) => credentials,
|
Ok(credentials) => credentials,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.set_status(Status::ConnectionError, cx);
|
self.set_status(Status::ConnectionError, cx);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
credentials
|
}
|
||||||
};
|
let credentials = credentials.unwrap();
|
||||||
|
|
||||||
if was_disconnected {
|
if was_disconnected {
|
||||||
self.set_status(Status::Connecting, cx);
|
self.set_status(Status::Connecting, cx);
|
||||||
|
@ -595,7 +595,7 @@ impl Client {
|
||||||
match self.establish_connection(&credentials, cx).await {
|
match self.establish_connection(&credentials, cx).await {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
self.state.write().credentials = Some(credentials.clone());
|
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();
|
write_credentials_to_keychain(&credentials, cx).log_err();
|
||||||
}
|
}
|
||||||
self.set_connection(conn, cx).await;
|
self.set_connection(conn, cx).await;
|
||||||
|
@ -603,10 +603,10 @@ impl Client {
|
||||||
}
|
}
|
||||||
Err(EstablishConnectionError::Unauthorized) => {
|
Err(EstablishConnectionError::Unauthorized) => {
|
||||||
self.state.write().credentials.take();
|
self.state.write().credentials.take();
|
||||||
if used_keychain {
|
if read_from_keychain {
|
||||||
cx.platform().delete_credentials(&ZED_SERVER_URL).log_err();
|
cx.platform().delete_credentials(&ZED_SERVER_URL).log_err();
|
||||||
self.set_status(Status::SignedOut, cx);
|
self.set_status(Status::SignedOut, cx);
|
||||||
self.authenticate_and_connect(cx).await
|
self.authenticate_and_connect(false, cx).await
|
||||||
} else {
|
} else {
|
||||||
self.set_status(Status::ConnectionError, cx);
|
self.set_status(Status::ConnectionError, cx);
|
||||||
Err(EstablishConnectionError::Unauthorized)?
|
Err(EstablishConnectionError::Unauthorized)?
|
||||||
|
|
|
@ -91,7 +91,7 @@ impl FakeServer {
|
||||||
});
|
});
|
||||||
|
|
||||||
client
|
client
|
||||||
.authenticate_and_connect(&cx.to_async())
|
.authenticate_and_connect(false, &cx.to_async())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
|
|
|
@ -377,7 +377,7 @@ impl Project {
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Result<ModelHandle<Self>> {
|
) -> Result<ModelHandle<Self>> {
|
||||||
client.authenticate_and_connect(&cx).await?;
|
client.authenticate_and_connect(true, &cx).await?;
|
||||||
|
|
||||||
let response = client
|
let response = client
|
||||||
.request(proto::JoinProject {
|
.request(proto::JoinProject {
|
||||||
|
|
|
@ -5021,7 +5021,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
|
|
||||||
client
|
client
|
||||||
.authenticate_and_connect(&cx.to_async())
|
.authenticate_and_connect(false, &cx.to_async())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ fn main() {
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
|cx| async move {
|
|cx| async move {
|
||||||
if client.has_keychain_credentials(&cx) {
|
if client.has_keychain_credentials(&cx) {
|
||||||
client.authenticate_and_connect(&cx).await?;
|
client.authenticate_and_connect(true, &cx).await?;
|
||||||
}
|
}
|
||||||
Ok::<_, anyhow::Error>(())
|
Ok::<_, anyhow::Error>(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue