From 797393505da279837752e2b2f8e1c22895f886a5 Mon Sep 17 00:00:00 2001 From: Philippe Miossec <pmiossec@gmail.com> Date: Tue, 28 Apr 2020 00:55:01 +0200 Subject: [PATCH 1/2] Transform a NRE in an UnauthorizedAccessException with clearer message First step to handle https://github.com/gitextensions/gitextensions/issues/7641 --- Git.hub/Client.cs | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/Git.hub/Client.cs b/Git.hub/Client.cs index 0bf7922..e5d4379 100644 --- a/Git.hub/Client.cs +++ b/Git.hub/Client.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Threading.Tasks; using RestSharp; using RestSharp.Authenticators; @@ -103,7 +104,7 @@ public Repository getRepository(string username, string repositoryName) request.AddUrlSegment("name", username); request.AddUrlSegment("repo", repositoryName); - var repo = client.Get<Repository>(request).Data; + var repo = DoRequest<Repository>(request); if (repo == null) return null; @@ -142,11 +143,9 @@ public User getCurrentUser() var request = new RestRequest("/user"); - var user = client.Get<User>(request); - if (user.Data == null) - throw new Exception("Bad Credentials"); + var user = DoRequest<User>(request, false); - return user.Data; + return user; } public async Task<User> GetUserAsync(string userName) @@ -172,11 +171,37 @@ public List<Repository> searchRepositories(string query) var request = new RestRequest("/legacy/repos/search/{query}"); request.AddUrlSegment("query", query); - var repos = client.Get<APIv2.RepositoryListV2>(request).Data; + var repos = DoRequest<APIv2.RepositoryListV2>(request); if (repos == null || repos.Repositories == null) throw new Exception(string.Format("Could not search for {0}", query)); return repos.Repositories.Select(r => r.ToV3(client)).ToList(); } + + private T DoRequest<T>(IRestRequest request, bool throwOnError = true) where T : new() + { + var response = client.Get<T>(request); + if (response.IsSuccessful) + { + return response.Data; + } + + if (!throwOnError) + { + return default; + } + + if (response.StatusCode == HttpStatusCode.Unauthorized) + { + if (client.Authenticator == null) + { + throw new UnauthorizedAccessException("Please configure a GitHub authentication token."); + } + + throw new UnauthorizedAccessException("The GitHub authentication token provided is not valid."); + } + + throw new Exception(response.StatusDescription); + } } } From 7a99961842d56a6498f86407ee1aec260eb11f48 Mon Sep 17 00:00:00 2001 From: Philippe Miossec <pmiossec@gmail.com> Date: Tue, 28 Apr 2020 22:40:09 +0200 Subject: [PATCH 2/2] Client: Cleaning/refactoring --- Git.hub/Client.cs | 64 ++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/Git.hub/Client.cs b/Git.hub/Client.cs index e5d4379..87c6dd4 100644 --- a/Git.hub/Client.cs +++ b/Git.hub/Client.cs @@ -13,7 +13,7 @@ namespace Git.hub /// </summary> public class Client { - private RestClient client; + private readonly RestClient _client; /// <summary> /// Creates a new client instance for github.com @@ -26,8 +26,7 @@ public Client() : this("https://api.github.com") { } /// <param name="apiEndpoint">the host to connect to, e.g. 'https://api.github.com'</param> public Client(string apiEndpoint) { - client = new RestClient(apiEndpoint); - client.UserAgent = "mabako/Git.hub"; + _client = new RestClient(apiEndpoint) { UserAgent = "mabako/Git.hub" }; } /// <summary> @@ -37,10 +36,8 @@ public Client(string apiEndpoint) /// <param name="password">password</param> public void setCredentials(string user, string password) { - if (user != null && password != null) - client.Authenticator = new HttpBasicAuthenticator(user, password); - else - client.Authenticator = null; + _client.Authenticator = + user != null && password != null ? new HttpBasicAuthenticator(user, password) : null; } /// <summary> @@ -49,10 +46,7 @@ public void setCredentials(string user, string password) /// <param name="token">oauth2-token</param> public void setOAuth2Token(string token) { - if (token != null) - client.Authenticator = new OAuth2AuthHelper(token); - else - client.Authenticator = null; + _client.Authenticator = token != null ? new OAuth2AuthHelper(token) : null; } /// <summary> @@ -61,16 +55,16 @@ public void setOAuth2Token(string token) /// <returns>list of repositories</returns> public IList<Repository> getRepositories() { - if (client.Authenticator == null) + if (_client.Authenticator == null) throw new ArgumentException("no authentication details"); var request = new RestRequest("/user/repos?type=all"); - var repos = client.GetList<Repository>(request); + var repos = _client.GetList<Repository>(request); if (repos == null) throw new Exception("Bad Credentials"); - repos.ForEach(r => r._client = client); + repos.ForEach(r => r._client = _client); return repos; } @@ -81,14 +75,14 @@ public IList<Repository> getRepositories() /// <returns>list of repositories</returns> public IList<Repository> getRepositories(string username) { - var request = new RestRequest("/users/{name}/repos"); - request.AddUrlSegment("name", username); + var request = new RestRequest("/users/{name}/repos") + .AddUrlSegment("name", username); - var list = client.GetList<Repository>(request); + var list = _client.GetList<Repository>(request); if (list == null) throw new InvalidOperationException("User does not exist."); - list.ForEach(r => r._client = client); + list.ForEach(r => r._client = _client); return list; } @@ -100,15 +94,15 @@ public IList<Repository> getRepositories(string username) /// <returns>fetched repository</returns> public Repository getRepository(string username, string repositoryName) { - var request = new RestRequest("/repos/{name}/{repo}"); - request.AddUrlSegment("name", username); - request.AddUrlSegment("repo", repositoryName); + var request = new RestRequest("/repos/{name}/{repo}") + .AddUrlSegment("name", username) + .AddUrlSegment("repo", repositoryName); var repo = DoRequest<Repository>(request); if (repo == null) return null; - repo._client = client; + repo._client = _client; repo.Detailed = true; return repo; } @@ -120,13 +114,13 @@ public Repository getRepository(string username, string repositoryName) /// <returns></returns> public IList<Repository> getOrganizationRepositories(string organization) { - var request = new RestRequest("/orgs/{org}/repos"); - request.AddUrlSegment("org", organization); + var request = new RestRequest("/orgs/{org}/repos") + .AddUrlSegment("org", organization); - var list = client.GetList<Repository>(request); + var list = _client.GetList<Repository>(request); - Organization org = new Organization { Login = organization }; - list.ForEach(r => { r._client = client; r.Organization = org; }); + var org = new Organization { Login = organization }; + list.ForEach(r => { r._client = _client; r.Organization = org; }); return list; } @@ -138,7 +132,7 @@ public IList<Repository> getOrganizationRepositories(string organization) /// <returns>current user</returns> public User getCurrentUser() { - if (client.Authenticator == null) + if (_client.Authenticator == null) throw new ArgumentException("no authentication details"); var request = new RestRequest("/user"); @@ -157,7 +151,7 @@ public async Task<User> GetUserAsync(string userName) var request = new RestRequest($"/users/{userName}"); - var user = await client.ExecuteGetTaskAsync<User>(request); + var user = await _client.ExecuteGetTaskAsync<User>(request); return user.Data; } @@ -172,15 +166,17 @@ public List<Repository> searchRepositories(string query) request.AddUrlSegment("query", query); var repos = DoRequest<APIv2.RepositoryListV2>(request); - if (repos == null || repos.Repositories == null) - throw new Exception(string.Format("Could not search for {0}", query)); + if (repos?.Repositories == null) + { + throw new Exception($"Could not search for {query}"); + } - return repos.Repositories.Select(r => r.ToV3(client)).ToList(); + return repos.Repositories.Select(r => r.ToV3(_client)).ToList(); } private T DoRequest<T>(IRestRequest request, bool throwOnError = true) where T : new() { - var response = client.Get<T>(request); + var response = _client.Get<T>(request); if (response.IsSuccessful) { return response.Data; @@ -193,7 +189,7 @@ public List<Repository> searchRepositories(string query) if (response.StatusCode == HttpStatusCode.Unauthorized) { - if (client.Authenticator == null) + if (_client.Authenticator == null) { throw new UnauthorizedAccessException("Please configure a GitHub authentication token."); }