The Wayback Machine - https://web.archive.org/web/20201215054320/https://github.com/github/VisualStudio/pull/845
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Logins, Part Uno #845

Merged
merged 37 commits into from Jun 19, 2017
Merged

Refactor Logins, Part Uno #845

merged 37 commits into from Jun 19, 2017

Conversation

@grokys
Copy link
Contributor

@grokys grokys commented Feb 9, 2017

This is the first step of #809. I wanted to stop here and submit a PR even if everything isn't finished as there's enough to review already. If need be I can probably split this into separate "refactor" and "bug fix" PRs but I wanted to a) actually get some bug fixes in with the refactoring, and b) test that the refactoring actually helps solve real problems.

Refactored

  • Moved API client configuration into static ApiClientConfiguration class in GitHub.Api
  • Added GitHub.Api.LoginManager service which contains the actual login code (moved out of RepositoryHost which is a model and shouldn't contain such code)
  • Removed Akavache dependency in LoginCache (now WindowsLoginCache)
  • Moved IO out of ConnectionManager and into IConnectionCache (JsonConnectionCache)
  • Made SimpleApiClientFactory.Create and ApiClientFactory.Create async (this will pave the way for first checking if there is a valid connection)
  • Don't use UserError.Throw on LoginTabViewModel - instead just expose the UserError in a property - this removes the need for the changing tabs hack, simplifies things, and more importantly avoids a race condition when moving back to the login view with an error.
  • Slightly simplified TwoFactorDialogViewModel.Show: 7843278
  • Added unit tests to things I touched

Fixes

  • Check that connection credentials are valid when loading connections
  • Fix #19 2FA dialog stays busy when network connection is down
  • Fix #829 Login dialog hangs when max 2FA login attempts is exceeded
grokys added 11 commits Jan 27, 2017
Injecting it into RepositoryHost, but not using it yet.
Also updated serilog to correctly handle `Received()` on async methods.
Rather than having login logic in `RepositoryHost`.
Delegate loading/saving of connections to an `IConnectionCache`
interface so that loading/saving of connections can be tested separately
from actual `ConnectionManager` behavior.
@shana

This comment has been minimized.

Copy link
Collaborator

@shana shana commented on src/GitHub.Exports/Models/ConnectionDetails.cs in 164e780 Feb 3, 2017

This will call ReferenceEquals 4 times, plus GetType twice and still do a cast, if both are valid but different. Why not

if (ReferenceEquals(this, obj) return true;
var other = obj as ConnectionDetails;
return other != null && Equals(other);

This comment has been minimized.

Copy link
Contributor

@haacked haacked replied Feb 9, 2017

If you override the == operator then other != null would not actually check for not being null but would be calling into the operator overload which could lead to infinite regression.

However, this code already does that checking in the other Equals method. I would expect this method to simply be:

public override bool Equals(object obj)
{
    return Equals(obj as ConnectionDetails);
}

There's no need to duplicate all that ReferenceEquals logic in this method. Note that the as operator does not invoke implicit cast operators if you were worried about that, which makes what I described safe.

This comment has been minimized.

Copy link
Contributor Author

@grokys grokys replied Feb 10, 2017

Heh, so this is what I get for using Resharper to generate the equality code automatically. First and last time! Thanks guys.

This comment has been minimized.

Copy link
Collaborator

@shana shana replied Feb 10, 2017

I spent two hours on this code last week because I suspected infinite recursion somewhere in here and still couldn't see it, nice catch!

We already have code that does this in a safe way in our various models that implement IEquatable, btw, for sanity checking.

This comment has been minimized.

Copy link
Collaborator

@shana shana replied Feb 10, 2017

To be clear, this recursion is totally on me! The code I pasted above is how we implement equals everywhere else, but it relies on != and == being implemented differently, the way we do it in other places.

grokys added 12 commits Feb 3, 2017
And add some doc comments.
Make it return a `TwoFactorChallengeResult` as that's what we're
interested in, rather than returning a `RecoveryOptionResult` and
passing the actual result back in the `UserError` that was passed into
it.
Don't stop listening for changes to `UserError` when control is unloaded
- this meant that if a page with a `UserError` is removed and then shown
again, the `UserErrorMessages` control stopped working.
Handle non 2FA-errors in the 2FA flow. When such an error occurs, the
user is taken back to the username/password view and an error message is
shown. Fixes #829. Fixes #19.
And fixed unused fields that it detected.
@grokys grokys changed the base branch from master to release/2.3 Feb 9, 2017
grokys added 3 commits Feb 10, 2017
Rather than using reflection in `GitHub.Api/ApiClientConfiguration` to
get hold of the client ID/secret from `ApiClient`, inject them
directly into `ApiClientConfiguration` and retreive them from there in
`ApiClient.
@grokys grokys requested review from shana and haacked Feb 10, 2017
@grokys grokys changed the title WIP: Refactor Logins, Part Uno Refactor Logins, Part Uno Feb 10, 2017
@grokys grokys changed the base branch from release/2.3 to master Apr 6, 2017
grokys and others added 4 commits Apr 28, 2017
 Conflicts:
	src/GitHub.App/ViewModels/TwoFactorDialogViewModel.cs
	src/GitHub.Exports/Settings/Guids.cs
	src/GitHub.VisualStudio/UI/Views/Controls/LoginControl.xaml.cs
This reverts commit f684f6f.
Make sure the observables are signalled on the UI thread.
namespace GitHub.Api
{
public partial class ApiClient : IApiClient
static partial class ApiClientConfiguration

This comment has been minimized.

@jcansdale

jcansdale Apr 28, 2017
Collaborator

It would be nice if rather than getting the ClientId / ClientSecret from source, it got it from an environment variable (GITHUB_CLIENT_ID or something). That way the developer wouldn't have to dirty their repo whenever they wanted to try something out (a hassle when changing branches). It could complain with a visible/helpful error when these variables aren't set.

This comment has been minimized.

@grokys

grokys May 3, 2017
Author Contributor

Yeah, I was wondering about that as well. We can think about that later I'd say.

This comment has been minimized.

@shana

shana May 3, 2017
Collaborator

These IDs need to be in the code, users can't be configuring this data manually on their systems in order to get the extension working. We can gitignore the file that keeps these variables in the public build so people can configure and build with them without having the repo dirtied or accidentally pushed.

This comment has been minimized.

@jcansdale

jcansdale May 3, 2017
Collaborator

Sounds like a plan!

@grokys can we .gitignore the local ApiClientConfiguration_User.cs file?

This comment has been minimized.

@shana

shana May 3, 2017
Collaborator

We might need to tweak the csproj and the default codepath a bit so that if it doesn't find the file, it can still build with fake data (right now the file always has to be there). Probably also better to move it to the common folder, since it's "common" configuration data and that's an easier location to point to than all the way inside GitHub.Api, and maybe rename it to something more obvious. The steps would probably be something like:

  • Set default ClientId and ClientSecret values in ApiClientConfiguration.cs if they're null after Configure()
  • Delete the public ApiClientConfiguration_User.cs file
  • Add a src/common/ApplicationKeys.cs file to .gitignore
  • Include src/common/ApplicationKeys.cs in the csproj if it exists and it's not an internal build
  • Add a little script that asks the user for a client id and client secret and generates the code with them.
  • Update the docs with these instructions (and also the template if people want to do it manually)

We can do this on a separate PR, probably 😄

This comment has been minimized.

@jcansdale

jcansdale May 3, 2017
Collaborator

A separate PR that fixes a few things for public builds would certainly be good. We could sort out the public / open source signing issue at the same time. Recent versions need to be signed and this isn't happening at the moment. They're all related issues with quite similar fixes.

@@ -130,6 +132,7 @@ protected override Task InitializeAsync(CancellationToken cancellationToken, IPr
{
AddService(typeof(IGitHubServiceProvider), CreateService, true);
AddService(typeof(IUsageTracker), CreateService, true);
AddService(typeof(ILoginManager), CreateService, true);

This comment has been minimized.

@jcansdale

jcansdale Apr 28, 2017
Collaborator

Could this be exposed as MEF export rather than a Visual Studio service? If we're ever going to add support for Blend (which also hosts TeamExplorer), we'll need to avoid using custom services.

This comment has been minimized.

@grokys

grokys May 3, 2017
Author Contributor

Actually, I think it could. I think it was originally a service as it had an async initialization, but that's not there any more.

This comment has been minimized.

@shana

shana May 3, 2017
Collaborator

The services that need to be initialized here are things that we need to use at VS startup. MEF is too slow at loading its catalog and causes a performance hit that we can't afford at this stage. The login manager is not one of these services, so it should definitely be an export.

This comment has been minimized.

@grokys

grokys May 16, 2017
Author Contributor

Replying to first message.

Copy link
Collaborator

@jcansdale jcansdale left a comment

I've prodded and poked these changes and they look good to me! 👍

@@ -14,7 +14,7 @@
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<BuildType Condition="Exists('..\..\script\src\ApiClientConfiguration.cs')">Internal</BuildType>
<BuildType Condition="Exists('..\..\script\src\ApiClientConfiguration_User.cs')">Internal</BuildType>

This comment has been minimized.

@jcansdale

jcansdale Apr 28, 2017
Collaborator

Just a observation having seen all the .csproj tweaks. It would be nice to factor out these common signing related properties into a separate .props file. I'll do this in a separate PR along with the public key stuff.

This comment has been minimized.

@grokys

grokys May 3, 2017
Author Contributor

👍

@shana
Copy link
Collaborator

@shana shana commented May 3, 2017

FYI, @StanleyGoldman and I went to town on how git manages credentials yesterday and found a few interesting things, including how to easily break our credential and login code in GHfVS by logging in with GCM, wincred, Unity and command line git. I suspect some of the issues we are seeing are coming from other providers doing things and we not handling that very well (especially the weird git:https message in the login)

I'm 👍 for merging this but we need a comprehensive session on testing all this code and fixing every single paranoid failure codepath before we ship it, I'm thinking it's going to be an agenda item for the mini-summit.

grokys added 3 commits Jun 12, 2017
#979 added a delay to the login process, but when porting that to the `fixes/809-refactor-logins` branch for #845 I discovered that a single 1s delay is sometimes not enough. Trying 3 times with a 1s delay however does seem to work.
 Conflicts:
	src/GitHub.App/Models/RepositoryHost.cs
@grokys grokys merged commit 06b4c7d into master Jun 19, 2017
5 checks passed
5 checks passed
GitHub CLA @grokys has accepted the GitHub Contributor License Agreement.
Details
VisualStudio Build #6929916 succeeded in 90s
Details
continuous-integration/appveyor/branch AppVeyor build succeeded
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
jenkins/build_log Jenkins Build Log
Details
@grokys grokys deleted the fixes/809-refactor-logins branch Jun 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.