public async Task GitHubHostProvider_GenerateCredentialAsync_Basic_2FARequired_ReturnsCredential() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "github.com", }); var expectedTargetUri = new Uri("https://github.com/"); var expectedUserName = "******"; var expectedPassword = "******"; // [SuppressMessage("Microsoft.Security", "CS001:SecretInline", Justification="Fake credential")] var expectedAuthCode = "123456"; IEnumerable <string> expectedPatScopes = new[] { GitHubConstants.TokenScopes.Gist, GitHubConstants.TokenScopes.Repo, }; var patValue = "PERSONAL-ACCESS-TOKEN"; var response1 = new AuthenticationResult(GitHubAuthenticationResultType.TwoFactorApp); var response2 = new AuthenticationResult(GitHubAuthenticationResultType.Success, patValue); var context = new TestCommandContext(); var ghAuthMock = new Mock <IGitHubAuthentication>(MockBehavior.Strict); ghAuthMock.Setup(x => x.GetAuthenticationAsync(expectedTargetUri, null, It.IsAny <AuthenticationModes>())) .ReturnsAsync(new AuthenticationPromptResult(new GitCredential(expectedUserName, expectedPassword))); ghAuthMock.Setup(x => x.GetTwoFactorCodeAsync(expectedTargetUri, false)) .ReturnsAsync(expectedAuthCode); var ghApiMock = new Mock <IGitHubRestApi>(MockBehavior.Strict); ghApiMock.Setup(x => x.CreatePersonalAccessTokenAsync(expectedTargetUri, expectedUserName, expectedPassword, null, It.IsAny <IEnumerable <string> >())) .ReturnsAsync(response1); ghApiMock.Setup(x => x.CreatePersonalAccessTokenAsync(expectedTargetUri, expectedUserName, expectedPassword, expectedAuthCode, It.IsAny <IEnumerable <string> >())) .ReturnsAsync(response2); ghApiMock.Setup(x => x.GetUserInfoAsync(expectedTargetUri, patValue)) .ReturnsAsync(new GitHubUserInfo { Login = expectedUserName }); var provider = new GitHubHostProvider(context, ghApiMock.Object, ghAuthMock.Object); ICredential credential = await provider.GenerateCredentialAsync(input); Assert.NotNull(credential); Assert.Equal(expectedUserName, credential.Account); Assert.Equal(patValue, credential.Password); ghApiMock.Verify( x => x.CreatePersonalAccessTokenAsync( expectedTargetUri, expectedUserName, expectedPassword, null, expectedPatScopes), Times.Once); ghApiMock.Verify( x => x.CreatePersonalAccessTokenAsync( expectedTargetUri, expectedUserName, expectedPassword, expectedAuthCode, expectedPatScopes), Times.Once); }
private async Task <int> ExecuteAsync(CommandOptions options) { var viewModel = new CredentialsViewModel(Context.Environment) { ShowBrowserLogin = options.All || options.Browser, ShowDeviceLogin = options.All || options.Device, ShowTokenLogin = options.All || options.Pat, ShowBasicLogin = options.All || options.Basic, }; if (!GitHubHostProvider.IsGitHubDotCom(options.EnterpriseUrl)) { viewModel.EnterpriseUrl = options.EnterpriseUrl; } if (!string.IsNullOrWhiteSpace(options.UserName)) { viewModel.UserName = options.UserName; } await ShowAsync(viewModel, CancellationToken.None); if (!viewModel.WindowResult) { throw new Exception("User cancelled dialog."); } var result = new Dictionary <string, string>(); switch (viewModel.SelectedMode) { case AuthenticationModes.Basic: result["mode"] = "basic"; result["username"] = viewModel.UserName; result["password"] = viewModel.Password; break; case AuthenticationModes.Browser: result["mode"] = "browser"; break; case AuthenticationModes.Device: result["mode"] = "device"; break; case AuthenticationModes.Pat: result["mode"] = "pat"; result["pat"] = viewModel.Token; break; default: throw new ArgumentOutOfRangeException(); } WriteResult(result); return(0); }
public async Task GitHubHostProvider_GetSupportedAuthenticationModes_GitHubDotCom_ReturnsDotComModes() { var targetUri = new Uri("https://github.com"); var expectedModes = GitHubConstants.DotComAuthenticationModes; var provider = new GitHubHostProvider(new TestCommandContext()); AuthenticationModes actualModes = await provider.GetSupportedAuthenticationModesAsync(targetUri); Assert.Equal(expectedModes, actualModes); }
public void GitHubHostProvider_GetCredentialServiceUrl(string protocol, string host, string expectedService) { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = protocol, ["host"] = host, }); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.Equal(expectedService, provider.GetServiceName(input)); }
public void GitHubHostProvider_IsSupported(string protocol, string host, bool expected) { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = protocol, ["host"] = host, }); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.Equal(expected, provider.IsSupported(input)); }
public void GitHubHostProvider_IsSupported_NonGitHub_ReturnsFalse() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "example.com", }); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.False(provider.IsSupported(input)); }
public void GitHubHostProvider_IsSupported_GistHost_Https_ReturnsTrue() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "gist.github.com", }); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.True(provider.IsSupported(input)); }
private async Task <int> ExecuteAsync(string enterpriseUrl, string userName, bool basic, bool oauth, bool pat) { var viewModel = new CredentialsViewModel(Context.Environment) { ShowBrowserLogin = oauth, ShowTokenLogin = pat, ShowBasicLogin = basic, }; if (!GitHubHostProvider.IsGitHubDotCom(enterpriseUrl)) { viewModel.EnterpriseUrl = enterpriseUrl; } if (!string.IsNullOrWhiteSpace(userName)) { viewModel.UserName = userName; } await AvaloniaUi.ShowViewAsync <CredentialsView>(viewModel, GetParentHandle(), CancellationToken.None); if (!viewModel.WindowResult) { throw new Exception("User cancelled dialog."); } var result = new Dictionary <string, string>(); switch (viewModel.SelectedMode) { case AuthenticationModes.Basic: result["mode"] = "basic"; result["username"] = viewModel.UserName; result["password"] = viewModel.Password; break; case AuthenticationModes.OAuth: result["mode"] = "oauth"; break; case AuthenticationModes.Pat: result["mode"] = "pat"; result["pat"] = viewModel.Token; break; default: throw new ArgumentOutOfRangeException(); } WriteResult(result); return(0); }
public async Task GitHubHostProvider_GenerateCredentialAsync_OAuth_ReturnsCredential() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "github.com", }); var expectedTargetUri = new Uri("https://github.com/"); IEnumerable <string> expectedOAuthScopes = new[] { GitHubConstants.OAuthScopes.Repo, GitHubConstants.OAuthScopes.Gist, GitHubConstants.OAuthScopes.Workflow, }; var expectedUserName = "******"; var tokenValue = "OAUTH-TOKEN"; var response = new OAuth2TokenResult(tokenValue, "bearer"); var context = new TestCommandContext(); var ghAuthMock = new Mock <IGitHubAuthentication>(MockBehavior.Strict); ghAuthMock.Setup(x => x.GetAuthenticationAsync(expectedTargetUri, null, It.IsAny <AuthenticationModes>())) .ReturnsAsync(new AuthenticationPromptResult(AuthenticationModes.OAuth)); ghAuthMock.Setup(x => x.GetOAuthTokenAsync(expectedTargetUri, It.IsAny <IEnumerable <string> >())) .ReturnsAsync(response); var ghApiMock = new Mock <IGitHubRestApi>(MockBehavior.Strict); ghApiMock.Setup(x => x.GetUserInfoAsync(expectedTargetUri, tokenValue)) .ReturnsAsync(new GitHubUserInfo { Login = expectedUserName }); var provider = new GitHubHostProvider(context, ghApiMock.Object, ghAuthMock.Object); ICredential credential = await provider.GenerateCredentialAsync(input); Assert.NotNull(credential); Assert.Equal(expectedUserName, credential.Account); Assert.Equal(tokenValue, credential.Password); ghAuthMock.Verify( x => x.GetOAuthTokenAsync( expectedTargetUri, expectedOAuthScopes), Times.Once); }
public void GitHubHostProvider_IsSupported_GistHost_UnencryptedHttp_ReturnsTrue() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "http", ["host"] = "gist.github.com", }); var provider = new GitHubHostProvider(new TestCommandContext()); // We report that we support unencrypted HTTP here so that we can fail and // show a helpful error message in the call to `GenerateCredentialAsync` instead. Assert.True(provider.IsSupported(input)); }
public void GitHubHostProvider_GetCredentialKey_GistHost_ReturnsCorrectKey() { const string expectedKey = "git:https://github.com"; var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "gist.github.com", }); var provider = new GitHubHostProvider(new TestCommandContext()); string actualKey = provider.GetCredentialKey(input); Assert.Equal(expectedKey, actualKey); }
public async Task GitHubHostProvider_GenerateCredentialAsync_UnencryptedHttp_ThrowsException() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "http", ["host"] = "github.com", }); var context = new TestCommandContext(); var ghApi = Mock.Of <IGitHubRestApi>(); var ghAuth = Mock.Of <IGitHubAuthentication>(); var provider = new GitHubHostProvider(context, ghApi, ghAuth); await Assert.ThrowsAsync <Exception>(() => provider.GenerateCredentialAsync(input)); }
public async Task GitHubHostProvider_GenerateCredentialAsync_2FARequired_ReturnsCredential() { var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "github.com", }); var expectedTargetUri = new Uri("https://github.com/"); var expectedUserName = "******"; var expectedPassword = "******"; var expectedAuthCode = "123456"; IEnumerable <string> expectedPatScopes = new[] { GitHubConstants.TokenScopes.Repo, GitHubConstants.TokenScopes.Gist }; var patValue = "PERSONAL-ACCESS-TOKEN"; var pat = new GitCredential(Constants.PersonalAccessTokenUserName, patValue); var response1 = new AuthenticationResult(GitHubAuthenticationResultType.TwoFactorApp); var response2 = new AuthenticationResult(GitHubAuthenticationResultType.Success, pat); var context = new TestCommandContext(); var ghAuthMock = new Mock <IGitHubAuthentication>(MockBehavior.Strict); ghAuthMock.Setup(x => x.GetCredentialsAsync(expectedTargetUri)) .ReturnsAsync(new GitCredential(expectedUserName, expectedPassword)); ghAuthMock.Setup(x => x.GetAuthenticationCodeAsync(expectedTargetUri, false)) .ReturnsAsync(expectedAuthCode); var ghApiMock = new Mock <IGitHubRestApi>(MockBehavior.Strict); ghApiMock.Setup(x => x.AcquireTokenAsync(expectedTargetUri, expectedUserName, expectedPassword, null, It.IsAny <IEnumerable <string> >())) .ReturnsAsync(response1); ghApiMock.Setup(x => x.AcquireTokenAsync(expectedTargetUri, expectedUserName, expectedPassword, expectedAuthCode, It.IsAny <IEnumerable <string> >())) .ReturnsAsync(response2); var provider = new GitHubHostProvider(context, ghApiMock.Object, ghAuthMock.Object); ICredential credential = await provider.GenerateCredentialAsync(input); Assert.NotNull(credential); Assert.Equal(Constants.PersonalAccessTokenUserName, credential.UserName); Assert.Equal(patValue, credential.Password); }
public void GitHubHostProvider_GetCredentialServiceUrl(string uriString, string expectedService) { Uri uri = new Uri(uriString); var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = uri.Scheme, ["host"] = uri.Host, }); // Ensure nothing got lost during transformation Assert.Equal(uriString, input.Protocol + "://" + input.Host); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.Equal(expectedService, provider.GetServiceName(input)); }
public void GitHubHostProvider_IsSupported(string uriString, bool expected) { Uri uri = new Uri(uriString); var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = uri.Scheme, ["host"] = uri.Host, }); // Ensure nothing got lost during transformation Assert.Equal(uriString, input.Protocol + "://" + input.Host); var provider = new GitHubHostProvider(new TestCommandContext()); Assert.Equal(expected, provider.IsSupported(input)); }
async Task <ICredential> GetCredentialAsync() { if (credential != null) { return(credential); } var input = new InputArguments(new Dictionary <string, string> { ["protocol"] = "https", ["host"] = "github.com", }); var provider = new GitHubHostProvider(new CommandContext()); credential = await provider.GetCredentialAsync(input); return(credential); }
public async Task GitHubHostProvider_GetSupportedAuthenticationModes(string uriString, string gitHubAuthModes, AuthenticationModes expectedModes) { var targetUri = new Uri(uriString); var context = new TestCommandContext { }; if (gitHubAuthModes != null) { context.Environment.Variables.Add(GitHubConstants.EnvironmentVariables.AuthenticationModes, gitHubAuthModes); } var ghApiMock = new Mock <IGitHubRestApi>(MockBehavior.Strict); var ghAuthMock = new Mock <IGitHubAuthentication>(MockBehavior.Strict); var provider = new GitHubHostProvider(context, ghApiMock.Object, ghAuthMock.Object); AuthenticationModes actualModes = await provider.GetSupportedAuthenticationModesAsync(targetUri); Assert.Equal(expectedModes, actualModes); }
public async Task GitHubHostProvider_GetSupportedAuthenticationModes_NotDotCom_NewInstanceWithPassword_ReturnsBasicAndOAuth() { var targetUri = new Uri("https://ghe.io"); var metaInfo = new GitHubMetaInfo { InstalledVersion = "100.0", VerifiablePasswordAuthentication = true }; var expectedModes = AuthenticationModes.Basic | AuthenticationModes.OAuth; var context = new TestCommandContext(); var ghAuthMock = new Mock <IGitHubAuthentication>(MockBehavior.Strict); var ghApiMock = new Mock <IGitHubRestApi>(MockBehavior.Strict); ghApiMock.Setup(x => x.GetMetaInfoAsync(targetUri)).ReturnsAsync(metaInfo); var provider = new GitHubHostProvider(context, ghApiMock.Object, ghAuthMock.Object); AuthenticationModes actualModes = await provider.GetSupportedAuthenticationModesAsync(targetUri); Assert.Equal(expectedModes, actualModes); }
public void GitHubHostProvider_IsGitHubDotCom(string input, bool expected) { Assert.Equal(expected, GitHubHostProvider.IsGitHubDotCom(new Uri(input))); }