From f4c2c9e148374f462592c19e8ffd4db14672805d Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 6 Jan 2024 13:09:27 -0500 Subject: initial migration to .net 8.0 --- .../src/Endpoints/GitHubOauth.cs | 214 --------------------- 1 file changed, 214 deletions(-) delete mode 100644 plugins/VNLib.Plugins.Essentials.SocialOauth/src/Endpoints/GitHubOauth.cs (limited to 'plugins/VNLib.Plugins.Essentials.SocialOauth/src/Endpoints/GitHubOauth.cs') diff --git a/plugins/VNLib.Plugins.Essentials.SocialOauth/src/Endpoints/GitHubOauth.cs b/plugins/VNLib.Plugins.Essentials.SocialOauth/src/Endpoints/GitHubOauth.cs deleted file mode 100644 index e8abf5a..0000000 --- a/plugins/VNLib.Plugins.Essentials.SocialOauth/src/Endpoints/GitHubOauth.cs +++ /dev/null @@ -1,214 +0,0 @@ -/* -* Copyright (c) 2023 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Plugins.Essentials.SocialOauth -* File: GitHubOauth.cs -* -* GitHubOauth.cs is part of VNLib.Plugins.Essentials.SocialOauth which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Plugins.Essentials.SocialOauth is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* VNLib.Plugins.Essentials.SocialOauth is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - -using System; -using System.Threading; -using System.Text.Json; -using System.Threading.Tasks; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -using RestSharp; - -using VNLib.Hashing; -using VNLib.Utils.Logging; -using VNLib.Plugins.Essentials.Accounts; -using VNLib.Plugins.Extensions.Loading; -using VNLib.Net.Rest.Client.Construction; - - -namespace VNLib.Plugins.Essentials.SocialOauth.Endpoints -{ - [ConfigurationName("github")] - internal sealed partial class GitHubOauth : SocialOauthBase - { - private const string GITHUB_V3_ACCEPT = "application/vnd.github.v3+json"; - - private readonly string UserEmailUrl; - - - public GitHubOauth(PluginBase plugin, IConfigScope config) : base(plugin, config) - { - UserEmailUrl = config["user_email_url"].GetString() ?? throw new KeyNotFoundException("Missing required key 'user_email_url' for github configuration"); - - //Define profile endpoint, gets users required profile information - SiteAdapter.DefineSingleEndpoint() - .WithEndpoint() - .WithMethod(Method.Get) - .WithUrl(Config.UserDataUrl) - .WithHeader("Accept", GITHUB_V3_ACCEPT) - .WithHeader("Authorization", at => $"{at.AccessToken.Type} {at.AccessToken.Token}"); - - //Define email endpoint, gets users email address - SiteAdapter.DefineSingleEndpoint() - .WithEndpoint() - .WithMethod(Method.Get) - .WithUrl(UserEmailUrl) - .WithHeader("Accept", GITHUB_V3_ACCEPT) - .WithHeader("Authorization", at => $"{at.AccessToken.Type} {at.AccessToken.Token}"); - } - - /* - * Creates a repeatable, and source specific user id for - * GitHub users. This format is identical to the algorithim used - * in the Auth0 Github connection, so it is compatible with Auth0 - */ - private static string GetUserIdFromPlatform(int userId) => $"github|{userId}"; - - - protected override async Task GetLoginDataAsync(IOAuthAccessState accessToken, CancellationToken cancellationToken) - { - GetProfileRequest req = new(accessToken); - - //Exec the get for the profile - RestResponse profResponse = await SiteAdapter.ExecuteAsync(req, cancellationToken); - - if (!profResponse.IsSuccessful || profResponse.RawBytes == null) - { - Log.Debug("Github login data attempt responded with status code {code}", profResponse.StatusCode); - return null; - } - - GithubProfile profile = JsonSerializer.Deserialize(profResponse.RawBytes)!; - - if (profile.ID < 100) - { - Log.Debug("Github login data attempt responded with empty or invalid response body", profResponse.StatusCode); - return null; - } - - //Return login data - return new() - { - //User-id is just the SHA 1 - UserId = GetUserIdFromPlatform(profile.ID) - }; - } - - protected override async Task GetAccountDataAsync(IOAuthAccessState accessToken, CancellationToken cancellationToken = default) - { - AccountData? accountData = null; - - //Get the user's email address's - GetEmailRequest request = new(accessToken); - - //get user's emails - RestResponse getEmailResponse = await SiteAdapter.ExecuteAsync(request, cancellationToken); - - //Check status - if (getEmailResponse.IsSuccessful && getEmailResponse.RawBytes != null) - { - //Filter emails addresses - foreach (EmailContainer email in JsonSerializer.Deserialize(getEmailResponse.RawBytes)!) - { - //Capture the first primary email address and make sure its verified - if (email.Primary && email.Verified) - { - accountData = new() - { - //store email on current profile - EmailAddress = email.Email - }; - goto Continue; - } - } - //No primary email found - return null; - } - else - { - Log.Debug("Github account data request failed but GH responded with status code {code}", getEmailResponse.StatusCode); - return null; - } - Continue: - - //We need to get the user's profile again - GetProfileRequest prof = new(accessToken); - - //Exec request against site adapter - RestResponse profResponse = await SiteAdapter.ExecuteAsync(prof, cancellationToken); - - if (!profResponse.IsSuccessful || profResponse.RawBytes == null) - { - Log.Debug("Github account data request failed but GH responded with status code {code}", profResponse.StatusCode); - return null; - } - - //Deserialize the profile - GithubProfile profile = JsonSerializer.Deserialize(profResponse.RawBytes)!; - - //Get the user's name from gh profile - string[] names = profile.FullName!.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - - //setup the user's profile data - accountData.First = names.Length > 0 ? names[0] : string.Empty; - accountData.Last = names.Length > 1 ? names[1] : string.Empty; - return accountData; - } - - //Requests to get required data from github - - private sealed record class GetProfileRequest(IOAuthAccessState AccessToken) - { } - - private sealed record class GetEmailRequest(IOAuthAccessState AccessToken) - { } - - /* - * Matches the json result from the - */ - private sealed class GithubProfile - { - [JsonPropertyName("login")] - public string? Username { 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("url")] - public string? ProfileUrl { get; set; } - [JsonPropertyName("type")] - public string? Type { get; set; } - [JsonPropertyName("name")] - public string? FullName { get; set; } - [JsonPropertyName("company")] - public string? Company { get; set; } - } - /* - * Matches the required data from the github email endpoint - */ - private sealed class EmailContainer - { - [JsonPropertyName("email")] - public string? Email { get; set; } - [JsonPropertyName("primary")] - public bool Primary { get; set; } - [JsonPropertyName("verified")] - public bool Verified { get; set; } - } - - } -} \ No newline at end of file -- cgit