Re-authenticate after authentication failure

This commit is contained in:
Jesse van den Kieboom 2014-12-25 11:41:00 +01:00
parent 9d88e34a01
commit 795c4f17fe
4 changed files with 89 additions and 44 deletions

View file

@ -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

View file

@ -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<string, string>? 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);

View file

@ -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();

View file

@ -49,7 +49,7 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="height">4</property>
<property name="height">5</property>
</packing>
</child>
<child>
@ -67,6 +67,26 @@
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_failed">
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="halign">fill</property>
<property name="wrap">True</property>
<property name="label" translatable="yes">The previous attempt to authenticate has failed, please provide your user name and password and try again.</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="max_width_chars">0</property>
<attributes>
<attribute name="style" value="italic"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_username">
<property name="visible">True</property>
@ -78,7 +98,7 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
@ -92,7 +112,7 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
@ -105,7 +125,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
@ -120,7 +140,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
@ -184,7 +204,7 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>