private Uri GetApiRequestUri(Uri targetUri, string apiUrl) { if (GitHubHostProvider.IsGitHubDotCom(targetUri)) { return(new Uri($"https://api.github.com/{apiUrl}")); } else { // If we're here, it's GitHub Enterprise via a configured authority var baseUrl = targetUri.GetLeftPart(UriPartial.Authority); return(new Uri(baseUrl + $"/api/v3/{apiUrl}")); } }
private Uri GetApiRequestUri(Uri targetUri, string apiUrl) { if (GitHubHostProvider.IsGitHubDotCom(targetUri)) { return(new Uri($"https://api.github.com/{apiUrl}")); } else { // If we're here, it's GitHub Enterprise via a configured authority var baseUrl = targetUri.GetLeftPart(UriPartial.Authority); // Check for 'raw.' in the hostname and remove it to get the correct GHE API URL baseUrl = Regex.Replace(baseUrl, @"^(https?://)raw\.", "$1", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); return(new Uri(baseUrl + $"/api/v3/{apiUrl}")); } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); // If we don't have a desktop session/GUI then we cannot offer browser if (!Context.SessionManager.IsDesktopSession) { modes = modes & ~AuthenticationModes.Browser; } // We need at least one mode! if (modes == AuthenticationModes.None) { throw new ArgumentException(@$ "Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if (modes == AuthenticationModes.All) { promptArgs.Append(" --all"); } else { if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.Browser) != 0) { promptArgs.Append(" --browser"); } if ((modes & AuthenticationModes.Device) != 0) { promptArgs.Append(" --device"); } if ((modes & AuthenticationModes.Pat) != 0) { promptArgs.Append(" --pat"); } } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", QuoteCmdArg(targetUri.ToString())); } if (!string.IsNullOrWhiteSpace(userName)) { promptArgs.AppendFormat(" --username {0}", QuoteCmdArg(userName)); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "pat": if (!resultDict.TryGetValue("pat", out string pat)) { throw new Exception("Missing 'pat' in response"); } return(new AuthenticationPromptResult( AuthenticationModes.Pat, new GitCredential(userName, pat))); case "browser": return(new AuthenticationPromptResult(AuthenticationModes.Browser)); case "device": return(new AuthenticationPromptResult(AuthenticationModes.Device)); case "basic": if (!resultDict.TryGetValue("username", out userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); case AuthenticationModes.Browser: return(new AuthenticationPromptResult(AuthenticationModes.Browser)); case AuthenticationModes.Device: return(new AuthenticationPromptResult(AuthenticationModes.Device)); case AuthenticationModes.Pat: Context.Terminal.WriteLine("Enter GitHub personal access token for '{0}'...", targetUri); string pat = Context.Terminal.PromptSecret("Token"); return(new AuthenticationPromptResult( AuthenticationModes.Pat, new GitCredential(userName, pat))); case AuthenticationModes.None: throw new ArgumentOutOfRangeException(nameof(modes), @$ "At least one {nameof(AuthenticationModes)} must be supplied"); default: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle); TerminalMenuItem browserItem = null; TerminalMenuItem deviceItem = null; TerminalMenuItem basicItem = null; TerminalMenuItem patItem = null; if ((modes & AuthenticationModes.Browser) != 0) { browserItem = menu.Add("Web browser"); } if ((modes & AuthenticationModes.Device) != 0) { deviceItem = menu.Add("Device code"); } if ((modes & AuthenticationModes.Pat) != 0) { patItem = menu.Add("Personal access token"); } if ((modes & AuthenticationModes.Basic) != 0) { basicItem = menu.Add("Username/password"); } // Default to the 'first' choice in the menu TerminalMenuItem choice = menu.Show(0); if (choice == browserItem) { goto case AuthenticationModes.Browser; } if (choice == deviceItem) { goto case AuthenticationModes.Device; } if (choice == basicItem) { goto case AuthenticationModes.Basic; } if (choice == patItem) { goto case AuthenticationModes.Pat; } throw new Exception(); } } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); if (modes == AuthenticationModes.None) { throw new ArgumentException($"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.OAuth) != 0) { promptArgs.Append(" --oauth"); } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", targetUri); } if (!string.IsNullOrWhiteSpace(userName)) { promptArgs.AppendFormat("--username {0}", userName); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "oauth": return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case "basic": if (!resultDict.TryGetValue("username", out userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult(new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic | AuthenticationModes.OAuth: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle) { new TerminalMenuItem(1, "Web browser", isDefault: true), new TerminalMenuItem(2, "Username/password") }; int option = menu.Show(); if (option == 1) { goto case AuthenticationModes.OAuth; } if (option == 2) { goto case AuthenticationModes.Basic; } throw new Exception(); case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); default: throw new ArgumentOutOfRangeException(nameof(modes), $"Unknown {nameof(AuthenticationModes)} value"); } } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); // If the GitHub auth stack doesn't support flows such as RFC 8628 and we do not have // an interactive desktop session, we cannot offer OAuth authentication. if ((modes & AuthenticationModes.OAuth) != 0 && !Context.SessionManager.IsDesktopSession && !GitHubConstants.IsOAuthDeviceAuthSupported) { Context.Trace.WriteLine("Ignoring OAuth authentication mode because we are not in an interactive desktop session. GitHub does not support RFC 8628."); modes &= ~AuthenticationModes.OAuth; } if (modes == AuthenticationModes.None) { throw new ArgumentException($"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.OAuth) != 0) { promptArgs.Append(" --oauth"); } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", targetUri.ToString()); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "oauth": return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case "basic": if (!resultDict.TryGetValue("username", out string userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult(new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic | AuthenticationModes.OAuth: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle) { new TerminalMenuItem(1, "Web browser"), new TerminalMenuItem(2, "Username/password", true) }; int option = menu.Show(); if (option == 1) { goto case AuthenticationModes.OAuth; } if (option == 2) { goto case AuthenticationModes.Basic; } throw new Exception(); case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); string userName = Context.Terminal.Prompt("Username"); string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); default: throw new ArgumentOutOfRangeException(nameof(modes), $"Unknown {nameof(AuthenticationModes)} value"); } } }