From b65a014ff794783e8e5eb3421db50c19b273af85 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Thu, 31 Mar 2022 16:55:33 -0600 Subject: [PATCH] WJ accepts Github PAT as author keys --- Wabbajack.Networking.GitHub/Client.cs | 17 ++- Wabbajack.Networking.GitHub/DTOs/UserInfo.cs | 104 ++++++++++++++++++ .../ApiKeyAuthorizationHandler.cs | 40 +++++-- Wabbajack.Server/Controllers/Metrics.cs | 2 +- 4 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 Wabbajack.Networking.GitHub/DTOs/UserInfo.cs diff --git a/Wabbajack.Networking.GitHub/Client.cs b/Wabbajack.Networking.GitHub/Client.cs index 082ed1bf..66688d9e 100644 --- a/Wabbajack.Networking.GitHub/Client.cs +++ b/Wabbajack.Networking.GitHub/Client.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; +using System.Net.Http.Json; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Octokit; using Wabbajack.DTOs; using Wabbajack.DTOs.GitHub; using Wabbajack.DTOs.JsonConverters; +using Wabbajack.Networking.GitHub.DTOs; namespace Wabbajack.Networking.GitHub; @@ -16,9 +19,11 @@ public class Client private readonly DTOSerializer _dtos; private readonly ILogger _logger; private readonly GithubAuthTokenProvider _token; + private readonly HttpClient _httpClient; - public Client(ILogger logger, DTOSerializer dtos, GitHubClient client) + public Client(ILogger logger, DTOSerializer dtos, GitHubClient client, HttpClient httpClient) { + _httpClient = httpClient; _logger = logger; _client = client; _dtos = dtos; @@ -71,6 +76,16 @@ public class Client return (result.Sha, result.Content); } + public async Task GetUserInfoFromPAT(string pat) + { + var msg = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/user"); + msg.Headers.Add("User-Agent", "wabbajack"); + msg.Headers.Add("Authorization", "Token " + pat); + var result = await _httpClient.SendAsync(msg); + if (!result.IsSuccessStatusCode) return null; + return await result.Content.ReadFromJsonAsync(); + } + public async Task PutData(string owner, string repo, string path, string message, string content, string oldSha) { await _client.Repository.Content.UpdateFile(owner, repo, path, new UpdateFileRequest(message, content, oldSha)); diff --git a/Wabbajack.Networking.GitHub/DTOs/UserInfo.cs b/Wabbajack.Networking.GitHub/DTOs/UserInfo.cs new file mode 100644 index 00000000..56b5e750 --- /dev/null +++ b/Wabbajack.Networking.GitHub/DTOs/UserInfo.cs @@ -0,0 +1,104 @@ +using System; +using System.Text.Json.Serialization; + +namespace Wabbajack.Networking.GitHub.DTOs; + + +public class UserInfo +{ + [JsonPropertyName("login")] + public string Login { get; set; } = ""; + + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("node_id")] + public string NodeId { get; set; } + + [JsonPropertyName("avatar_url")] + public string AvatarUrl { get; set; } + + [JsonPropertyName("gravatar_id")] + public string GravatarId { get; set; } + + [JsonPropertyName("url")] + public string Url { get; set; } + + [JsonPropertyName("html_url")] + public string HtmlUrl { get; set; } + + [JsonPropertyName("followers_url")] + public string FollowersUrl { get; set; } + + [JsonPropertyName("following_url")] + public string FollowingUrl { get; set; } + + [JsonPropertyName("gists_url")] + public string GistsUrl { get; set; } + + [JsonPropertyName("starred_url")] + public string StarredUrl { get; set; } + + [JsonPropertyName("subscriptions_url")] + public string SubscriptionsUrl { get; set; } + + [JsonPropertyName("organizations_url")] + public string OrganizationsUrl { get; set; } + + [JsonPropertyName("repos_url")] + public string ReposUrl { get; set; } + + [JsonPropertyName("events_url")] + public string EventsUrl { get; set; } + + [JsonPropertyName("received_events_url")] + public string ReceivedEventsUrl { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("site_admin")] + public bool SiteAdmin { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("company")] + public object Company { get; set; } + + [JsonPropertyName("blog")] + public string Blog { get; set; } + + [JsonPropertyName("location")] + public string Location { get; set; } + + [JsonPropertyName("email")] + public string Email { get; set; } + + [JsonPropertyName("hireable")] + public object Hireable { get; set; } + + [JsonPropertyName("bio")] + public object Bio { get; set; } + + [JsonPropertyName("twitter_username")] + public object TwitterUsername { get; set; } + + [JsonPropertyName("public_repos")] + public int PublicRepos { get; set; } + + [JsonPropertyName("public_gists")] + public int PublicGists { get; set; } + + [JsonPropertyName("followers")] + public int Followers { get; set; } + + [JsonPropertyName("following")] + public int Following { get; set; } + + [JsonPropertyName("created_at")] + public DateTime CreatedAt { get; set; } + + [JsonPropertyName("updated_at")] + public DateTime UpdatedAt { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.Server/ApiKeyAuthorizationHandler.cs b/Wabbajack.Server/ApiKeyAuthorizationHandler.cs index 01c46a1a..8a50a1f1 100644 --- a/Wabbajack.Server/ApiKeyAuthorizationHandler.cs +++ b/Wabbajack.Server/ApiKeyAuthorizationHandler.cs @@ -1,16 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; +using System.Security.Claims; using System.Text.Encodings.Web; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Wabbajack.DTOs.JsonConverters; -using Wabbajack.Paths; -using Wabbajack.Paths.IO; +using Wabbajack.Networking.GitHub; +using Wabbajack.Networking.GitHub.DTOs; using Wabbajack.Server.DataModels; using Wabbajack.Server.DTOs; @@ -33,10 +30,13 @@ public class ApiKeyAuthenticationHandler : AuthenticationHandler> _tarKeys; private readonly Metrics _metricsStore; private readonly TarLog _tarLog; + private readonly Client _githubClient; + private readonly MemoryCache _githubCache; public ApiKeyAuthenticationHandler( IOptionsMonitor options, AuthorKeys authorKeys, + Client githubClient, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, @@ -51,6 +51,8 @@ public class ApiKeyAuthenticationHandler : AuthenticationHandler HandleAuthenticateAsync() @@ -58,7 +60,6 @@ public class ApiKeyAuthenticationHandler : AuthenticationHandler {new(ClaimTypes.Name, owner)}; @@ -120,6 +128,18 @@ public class ApiKeyAuthenticationHandler : AuthenticationHandler GetGithubUserInfo(string authToken) + { + if (_githubCache.TryGetValue(authToken, out var value)) return value; + + var info = await _githubClient.GetUserInfoFromPAT(authToken); + if (info != null) + _githubCache.Set(authToken, info, + new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromHours(6))); + + return info; + } + protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { Response.StatusCode = 401; diff --git a/Wabbajack.Server/Controllers/Metrics.cs b/Wabbajack.Server/Controllers/Metrics.cs index f3e8270b..b25b604f 100644 --- a/Wabbajack.Server/Controllers/Metrics.cs +++ b/Wabbajack.Server/Controllers/Metrics.cs @@ -79,7 +79,7 @@ public class MetricsController : ControllerBase Subject = value, MetricsKey = metricsKey, UserAgent = Request.Headers.UserAgent.FirstOrDefault() ?? "", - Ip = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "" + Ip = Request.Headers["cf-connecting-ip"].FirstOrDefault() ?? (Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "") }); return new Result {Timestamp = date}; }