Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit ad6a715

Browse files
committed
Merge pull request #40 from github/haacked/14-better-login
Better login failed error tooltip
2 parents ca51ff1 + d9f6e5a commit ad6a715

File tree

7 files changed

+65
-41
lines changed

7 files changed

+65
-41
lines changed

src/GitHub.App/ViewModels/LoginTabViewModel.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,17 @@ protected LoginTabViewModel(IRepositoryHosts repositoryHosts, IVisualStudioBrows
4141

4242
Login.ThrownExceptions.Subscribe(ex =>
4343
{
44-
if (!ex.IsCriticalException())
44+
if (ex.IsCriticalException()) return;
45+
46+
log.Info(string.Format(CultureInfo.InvariantCulture, "Error logging into '{0}' as '{1}'", BaseUri,
47+
UsernameOrEmail), ex);
48+
if (ex is Octokit.ForbiddenException)
49+
{
50+
ShowLogInFailedError = true;
51+
LoginFailedMessage = "Make sure to use your password and not a Personal Access token to log in.";
52+
}
53+
else
4554
{
46-
log.Info(string.Format(CultureInfo.InvariantCulture, "Error logging into '{0}' as '{1}'", BaseUri, UsernameOrEmail), ex);
4755
ShowConnectingToHostFailed = true;
4856
}
4957
});
@@ -64,13 +72,20 @@ protected LoginTabViewModel(IRepositoryHosts repositoryHosts, IVisualStudioBrows
6472
return Observable.Return(Unit.Default);
6573
});
6674
}
67-
protected IRepositoryHosts RepositoryHosts { get; private set; }
75+
protected IRepositoryHosts RepositoryHosts { get; }
6876
protected abstract Uri BaseUri { get; }
69-
public IReactiveCommand<Unit> SignUp { get; private set; }
77+
public IReactiveCommand<Unit> SignUp { get; }
7078

71-
public IReactiveCommand<AuthenticationResult> Login { get; private set; }
72-
public IReactiveCommand<Unit> Reset { get; private set; }
73-
public IReactiveCommand<Unit> NavigateForgotPassword { get; private set; }
79+
public IReactiveCommand<AuthenticationResult> Login { get; }
80+
public IReactiveCommand<Unit> Reset { get; }
81+
public IReactiveCommand<Unit> NavigateForgotPassword { get; }
82+
83+
string loginFailedMessage = "Check your username and password, then try again";
84+
public string LoginFailedMessage
85+
{
86+
get { return loginFailedMessage; }
87+
set { this.RaiseAndSetIfChanged(ref loginFailedMessage, value); }
88+
}
7489

7590
string usernameOrEmail;
7691
[AllowNull]

src/GitHub.App/ViewModels/LoginToGitHubForEnterpriseViewModel.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class LoginToGitHubForEnterpriseViewModel : LoginTabViewModel, ILoginToGi
2121
[ImportingConstructor]
2222
public LoginToGitHubForEnterpriseViewModel(IRepositoryHosts hosts, IVisualStudioBrowser browser) : base(hosts, browser)
2323
{
24-
enterpriseUrlValidator = ReactivePropertyValidator.For(this, x => x.EnterpriseUrl)
24+
EnterpriseUrlValidator = ReactivePropertyValidator.For(this, x => x.EnterpriseUrl)
2525
.IfNullOrEmpty("Please enter an Enterprise URL")
2626
.IfNotUri("Please enter a valid Enterprise URL")
2727
.IfGitHubDotComHost("Not an Enterprise server. Please enter an Enterprise URL");
@@ -55,24 +55,13 @@ public string EnterpriseUrl
5555
set { this.RaiseAndSetIfChanged(ref enterpriseUrl, value); }
5656
}
5757

58-
readonly ReactivePropertyValidator enterpriseUrlValidator;
59-
public ReactivePropertyValidator EnterpriseUrlValidator
60-
{
61-
get { return enterpriseUrlValidator; }
62-
}
58+
public ReactivePropertyValidator EnterpriseUrlValidator { get; }
6359

64-
protected override Uri BaseUri
65-
{
66-
get
67-
{
68-
return new Uri(EnterpriseUrl);
69-
}
70-
}
60+
protected override Uri BaseUri => new Uri(EnterpriseUrl);
7161

7262
public IReactiveCommand<Unit> NavigateLearnMore
7363
{
7464
get;
75-
private set;
7665
}
7766

7867
protected override async Task ResetValidation()

src/GitHub.App/ViewModels/LoginToGitHubViewModel.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ namespace GitHub.ViewModels
1515
[PartCreationPolicy(CreationPolicy.NonShared)]
1616
public class LoginToGitHubViewModel : LoginTabViewModel, ILoginToGitHubViewModel
1717
{
18-
readonly Uri baseUri;
19-
2018
[ImportingConstructor]
2119
public LoginToGitHubViewModel(IRepositoryHosts repositoryHosts, IVisualStudioBrowser browser)
2220
: base(repositoryHosts, browser)
2321
{
24-
baseUri = HostAddress.GitHubDotComHostAddress.WebUri;
22+
BaseUri = HostAddress.GitHubDotComHostAddress.WebUri;
2523

2624
NavigatePricing = ReactiveCommand.CreateAsyncObservable(_ =>
2725
{
@@ -31,16 +29,13 @@ public LoginToGitHubViewModel(IRepositoryHosts repositoryHosts, IVisualStudioBro
3129
});
3230
}
3331

34-
public IReactiveCommand<Unit> NavigatePricing { get; private set; }
32+
public IReactiveCommand<Unit> NavigatePricing { get; }
3533

36-
protected override Uri BaseUri
37-
{
38-
get { return baseUri; }
39-
}
34+
protected override Uri BaseUri { get; }
4035

41-
protected override IObservable<AuthenticationResult> LogIn(object args)
42-
{
43-
return LogInToHost(HostAddress.GitHubDotComHostAddress);
44-
}
36+
protected override IObservable<AuthenticationResult> LogIn(object args)
37+
{
38+
return LogInToHost(HostAddress.GitHubDotComHostAddress);
4539
}
40+
}
4641
}

src/GitHub.Exports.Reactive/ViewModels/ILoginToHostViewModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public interface ILoginToHostViewModel
5959
/// </summary>
6060
bool ShowLogInFailedError { get; }
6161

62+
/// <summary>
63+
/// The message to show if login failed.
64+
/// </summary>
65+
string LoginFailedMessage { get; }
66+
6267
/// <summary>
6368
/// Gets a command which, when invoked, resets all properties
6469
/// and validators.

src/GitHub.VisualStudio/UI/Views/Controls/LoginControl.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Linq;
32
using System.Reactive.Linq;
43
using System.Windows;
54
using System.Windows.Input;
@@ -63,6 +62,7 @@ void SetupDotComBindings(Action<IDisposable> d)
6362
d(this.OneWayBind(ViewModel, vm => vm.GitHubLogin.NavigatePricing, v => v.pricingLink.Command));
6463

6564
d(this.OneWayBind(ViewModel, vm => vm.GitHubLogin.ShowLogInFailedError, v => v.dotComLoginFailedMessage.Visibility));
65+
d(this.OneWayBind(ViewModel, vm => vm.GitHubLogin.LoginFailedMessage, v => v.dotComLoginFailedMessage.Message));
6666
d(this.OneWayBind(ViewModel, vm => vm.GitHubLogin.ShowConnectingToHostFailed, v => v.dotComConnectionFailedMessage.Visibility));
6767
}
6868

@@ -86,6 +86,7 @@ void SetupEnterpriseBindings(Action<IDisposable> d)
8686
d(this.OneWayBind(ViewModel, vm => vm.EnterpriseLogin.NavigateLearnMore, v => v.learnMoreLink.Command));
8787

8888
d(this.OneWayBind(ViewModel, vm => vm.EnterpriseLogin.ShowLogInFailedError, v => v.enterpriseLoginFailedMessage.Visibility));
89+
d(this.OneWayBind(ViewModel, vm => vm.EnterpriseLogin.LoginFailedMessage, v => v.enterpriseLoginFailedMessage.Message));
8990
d(this.OneWayBind(ViewModel, vm => vm.EnterpriseLogin.ShowConnectingToHostFailed, v => v.enterpriseConnectingFailedMessage.Visibility));
9091
}
9192

src/UnitTests/GitHub.App/ViewModels/LoginToGitHubViewModelTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,39 @@
11
using System;
2+
using System.Net;
3+
using System.Reactive.Linq;
4+
using GitHub.Authentication;
25
using GitHub.Info;
36
using GitHub.Models;
47
using GitHub.Primitives;
58
using GitHub.Services;
69
using GitHub.ViewModels;
710
using NSubstitute;
11+
using Octokit;
812
using Xunit;
913

1014
public class LoginToGitHubViewModelTests
1115
{
16+
public class TheLoginCommand : TestBaseClass
17+
{
18+
[Fact]
19+
public void ShowsHelpfulTooltipWhenForbiddenResponseReceived()
20+
{
21+
var response = Substitute.For<IResponse>();
22+
response.StatusCode.Returns(HttpStatusCode.Forbidden);
23+
var repositoryHosts = Substitute.For<IRepositoryHosts>();
24+
repositoryHosts.LogIn(HostAddress.GitHubDotComHostAddress, Args.String, Args.String)
25+
.Returns(_ => Observable.Throw<AuthenticationResult>(new ForbiddenException(response)));
26+
var browser = Substitute.For<IVisualStudioBrowser>();
27+
var loginViewModel = new LoginToGitHubViewModel(repositoryHosts, browser);
28+
29+
loginViewModel.Login.Execute(null);
30+
31+
Assert.True(loginViewModel.ShowLogInFailedError);
32+
Assert.Equal("Make sure to use your password and not a Personal Access token to log in.",
33+
loginViewModel.LoginFailedMessage);
34+
}
35+
}
36+
1237
public class TheSignupCommand : TestBaseClass
1338
{
1439
[Fact]

src/UnitTests/Helpers/TestBaseClass.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using EntryExitDecoratorInterfaces;
7-
using GitHub.VisualStudio;
1+
using EntryExitDecoratorInterfaces;
82

93
/// <summary>
104
/// This base class will get its methods called by the most-derived

0 commit comments

Comments
 (0)