From 795c4f17fe0e93f5e06dae05480cfa4f3677e543 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Thu, 25 Dec 2014 11:41:00 +0100 Subject: [PATCH] Re-authenticate after authentication failure --- libgitg/gitg-authentication-dialog.vala | 29 ++++++++++++- libgitg/gitg-credentials-manager.vala | 31 ++------------ libgitg/gitg-remote.vala | 41 +++++++++++++++---- .../resources/gitg-authentication-dialog.ui | 32 ++++++++++++--- 4 files changed, 89 insertions(+), 44 deletions(-) diff --git a/libgitg/gitg-authentication-dialog.vala b/libgitg/gitg-authentication-dialog.vala index eef47dc0..64689044 100644 --- a/libgitg/gitg-authentication-dialog.vala +++ b/libgitg/gitg-authentication-dialog.vala @@ -33,6 +33,9 @@ public class AuthenticationDialog : Gtk.Dialog [GtkChild ( name = "label_title" )] private Gtk.Label d_label_title; + [GtkChild ( name = "label_failed" )] + private Gtk.Label d_label_failed; + [GtkChild ( name = "entry_username" )] private Gtk.Entry d_entry_username; @@ -45,7 +48,17 @@ public class AuthenticationDialog : Gtk.Dialog [GtkChild ( name = "radio_button_session" )] private Gtk.RadioButton d_radio_button_session; - public AuthenticationDialog(string url, string? username) + [GtkChild ( name = "radio_button_forever" )] + private Gtk.RadioButton d_radio_button_forever; + + private static AuthenticationLifeTime s_last_lifetime; + + static construct + { + s_last_lifetime = AuthenticationLifeTime.SESSION; + } + + public AuthenticationDialog(string url, string? username, bool failed) { Object(use_header_bar: 1); @@ -54,12 +67,26 @@ public class AuthenticationDialog : Gtk.Dialog /* Translators: %s will be replaced with a URL indicating the resource for which the authentication is required. */ d_label_title.label = _("Password required for %s").printf(url); + d_label_failed.visible = failed; if (username != null) { d_entry_username.text = username; d_entry_password.grab_focus(); } + + switch (s_last_lifetime) + { + case AuthenticationLifeTime.FORGET: + d_radio_button_forget.active = true; + break; + case AuthenticationLifeTime.SESSION: + d_radio_button_session.active = true; + break; + case AuthenticationLifeTime.FOREVER: + d_radio_button_forever.active = true; + break; + } } public string username diff --git a/libgitg/gitg-credentials-manager.vala b/libgitg/gitg-credentials-manager.vala index a80cadb5..db2d8c1e 100644 --- a/libgitg/gitg-credentials-manager.vala +++ b/libgitg/gitg-credentials-manager.vala @@ -27,29 +27,9 @@ public errordomain CredentialsError public class CredentialsManager { - class CredSshInteractive : Ggit.CredSshInteractive - { - private weak Remote d_remote; - - public CredSshInteractive(Remote remote, string username) throws Error - { - Object(username: username); - - d_remote = remote; - - ((Initable)this).init(null); - } - - protected override void prompt(Ggit.CredSshInteractivePrompt[] prompts) - { - // TODO - } - } - private weak Remote d_remote; private Gtk.Window d_window; private Gee.HashMap? d_usermap; - private static Secret.Schema s_secret_schema; static construct @@ -106,7 +86,7 @@ public class CredentialsManager AuthenticationLifeTime lifetime = AuthenticationLifeTime.FORGET; Idle.add(() => { - var d = new AuthenticationDialog(url, username); + var d = new AuthenticationDialog(url, username, d_remote.authentication_error != null); d.set_transient_for(d_window); response = (Gtk.ResponseType)d.run(); @@ -164,7 +144,6 @@ public class CredentialsManager attributes["host"] = host; attributes["user"] = newusername; - // Save secret if (lifetime != AuthenticationLifeTime.FORGET) { @@ -233,7 +212,7 @@ public class CredentialsManager user = username; } - if (user != null) + if (user != null && d_remote.authentication_error == null) { string? secret = null; @@ -270,14 +249,10 @@ public class CredentialsManager string? username, Ggit.Credtype allowed_types) throws Error { - if ((allowed_types & Ggit.Credtype.SSH_KEY) != 0) + if (d_remote.authentication_error != null && (allowed_types & Ggit.Credtype.SSH_KEY) != 0) { return new Ggit.CredSshKeyFromAgent(username); } - else if ((allowed_types & Ggit.Credtype.SSH_INTERACTIVE) != 0) - { - return new CredSshInteractive(d_remote, username); - } else if ((allowed_types & Ggit.Credtype.USERPASS_PLAINTEXT) != 0) { return query_user_pass(url, username); diff --git a/libgitg/gitg-remote.vala b/libgitg/gitg-remote.vala index df7763c3..b04f1a9d 100644 --- a/libgitg/gitg-remote.vala +++ b/libgitg/gitg-remote.vala @@ -39,6 +39,12 @@ public errordomain RemoteError public class Remote : Ggit.Remote { private RemoteState d_state; + private Error? d_authentication_error; + + public Error authentication_error + { + get { return d_authentication_error; } + } public RemoteState state { @@ -69,6 +75,7 @@ public class Remote : Ggit.Remote else { state = RemoteState.CONNECTED; + d_authentication_error = null; } } else @@ -95,16 +102,32 @@ public class Remote : Ggit.Remote state = RemoteState.CONNECTING; - try + while (true) { - yield Async.thread(() => { - base.connect(direction); - }); - } - catch (Error e) - { - update_state(); - throw e; + try + { + yield Async.thread(() => { + base.connect(direction); + }); + } + catch (Error e) + { + // NOTE: need to check the message for now in case of failed + // http auth. + if (e.message == "Unexpected HTTP status code: 401") + { + d_authentication_error = e; + continue; + } + else + { + update_state(); + throw e; + } + } + + d_authentication_error = null; + break; } update_state(); diff --git a/libgitg/resources/gitg-authentication-dialog.ui b/libgitg/resources/gitg-authentication-dialog.ui index 5ce69e09..7cdc8023 100644 --- a/libgitg/resources/gitg-authentication-dialog.ui +++ b/libgitg/resources/gitg-authentication-dialog.ui @@ -49,7 +49,7 @@ 0 0 - 4 + 5 @@ -67,6 +67,26 @@ 2 + + + False + False + fill + True + The previous attempt to authenticate has failed, please provide your user name and password and try again. + 12 + 12 + 0 + + + + + + 1 + 1 + 2 + + True @@ -78,7 +98,7 @@ 1 - 1 + 2 @@ -92,7 +112,7 @@ 1 - 2 + 3 @@ -105,7 +125,7 @@ 2 - 1 + 2 @@ -120,7 +140,7 @@ 2 - 2 + 3 @@ -184,7 +204,7 @@ 1 - 3 + 4 2