From 81bd12d1b608dbfbafc11f97d9512636b19b9538 Mon Sep 17 00:00:00 2001 From: mboshu Date: Wed, 3 May 2023 14:20:37 -0400 Subject: [PATCH] Added api key parser Updated calls to alter how api key is provided depending on parse result --- .../InjectionApi/Core/ApiKeyParser.cs | 54 +++++++++++++++++++ .../Core/Enum/ApiKeyParseResultCode.cs | 34 ++++++++++++ .../InjectionApi/Core/IApiKeyParser.cs | 13 +++++ .../InjectionApi/Core/Models/ApiKey.cs | 27 ++++++++++ .../Core/Models/ApiKeyParseResult.cs | 23 ++++++++ .../InjectionApi/SocketLabsClient.cs | 25 ++++++++- 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs create mode 100644 src/SocketLabs/InjectionApi/Core/Enum/ApiKeyParseResultCode.cs create mode 100644 src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs create mode 100644 src/SocketLabs/InjectionApi/Core/Models/ApiKey.cs create mode 100644 src/SocketLabs/InjectionApi/Core/Models/ApiKeyParseResult.cs diff --git a/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs b/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs new file mode 100644 index 0000000..d6a9edf --- /dev/null +++ b/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; +using SocketLabs.InjectionApi.Core.Enum; +using SocketLabs.InjectionApi.Core.Models; + +namespace SocketLabs.InjectionApi.Core +{ + /// + /// Parses a provided api key and provides a result + /// + public class ApiKeyParser : IApiKeyParser + { + /// + /// Parses the provided Api key. + /// + /// + /// An ApiKeyParseResult with the api key data and result code from the parse. + public ApiKeyParseResult Parse(string wholeApiKey) + { + var key = new ApiKey { IsValidFormat = false }; + if (string.IsNullOrWhiteSpace(wholeApiKey)) + return new ApiKeyParseResult { ApiKey = null, ResultCode = ApiKeyParseResultCode.InvalidEmptyOrWhitespace }; + + //if (!wholeApiKey.StartsWith("SL.", StringComparison.InvariantCulture)) + // return new ApiKeyParseResult {ApiKey = null, ResultCode = ApiKeyParseResultCode.InvalidMissingProperPrefix}; + + //extract public part + var maxCount = Math.Min(50, wholeApiKey.Length); + var publicPartEnd = wholeApiKey.IndexOf('.', startIndex: 0, maxCount); //don't check more than 50 chars + if (publicPartEnd == -1) + return new ApiKeyParseResult { ApiKey = null, ResultCode = ApiKeyParseResultCode.InvalidUnableToExtractPublicPart }; + var publicPart = wholeApiKey.Substring(0, publicPartEnd); + + + //now extract the private part + if (wholeApiKey.Length <= publicPartEnd + 1) + return new ApiKeyParseResult { ApiKey = null, ResultCode = ApiKeyParseResultCode.InvalidUnableToExtractSecretPart }; + var privatePart = wholeApiKey.Substring(publicPartEnd + 1); + + //success + return new ApiKeyParseResult + { + ApiKey = new ApiKey + { + PublicPart = publicPart, + PrivatePart = privatePart, + IsValidFormat = true, + }, + ResultCode = ApiKeyParseResultCode.Success + }; + } + } +} diff --git a/src/SocketLabs/InjectionApi/Core/Enum/ApiKeyParseResultCode.cs b/src/SocketLabs/InjectionApi/Core/Enum/ApiKeyParseResultCode.cs new file mode 100644 index 0000000..aae2218 --- /dev/null +++ b/src/SocketLabs/InjectionApi/Core/Enum/ApiKeyParseResultCode.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SocketLabs.InjectionApi.Core.Enum +{ + /// + /// A code describing the result of an attempt to parse an Api key. + /// + public enum ApiKeyParseResultCode + { + + /// + /// No result could be produced. + /// + None, + /// + /// The key was found to be blank or invalid. + /// + InvalidEmptyOrWhitespace, + /// + /// The public portion of the key was unable to be parsed. + /// + InvalidUnableToExtractPublicPart, + /// + /// The secret portion of the key was unable to be parsed. + /// + InvalidUnableToExtractSecretPart, + /// + /// Key was successfully parsed. + /// + Success + } +} diff --git a/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs b/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs new file mode 100644 index 0000000..64be894 --- /dev/null +++ b/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs @@ -0,0 +1,13 @@ +using SocketLabs.InjectionApi.Core.Enum; +using SocketLabs.InjectionApi.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SocketLabs.InjectionApi.Core +{ + public interface IApiKeyParser + { + ApiKeyParseResult Parse(string wholeApiKey); + } +} diff --git a/src/SocketLabs/InjectionApi/Core/Models/ApiKey.cs b/src/SocketLabs/InjectionApi/Core/Models/ApiKey.cs new file mode 100644 index 0000000..20b6dae --- /dev/null +++ b/src/SocketLabs/InjectionApi/Core/Models/ApiKey.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SocketLabs.InjectionApi.Core.Models +{ + /// + /// A class representing an Api Key + /// + public class ApiKey + { + /// + /// The public part of the Api Key. + /// + public string PublicPart { get; set; } = ""; + + /// + /// The private part of the Api Key + /// + public string PrivatePart { get; set; } = ""; + + /// + /// A boolean value describing the validity of the Api Key format + /// + public bool IsValidFormat { get; set; } + } +} diff --git a/src/SocketLabs/InjectionApi/Core/Models/ApiKeyParseResult.cs b/src/SocketLabs/InjectionApi/Core/Models/ApiKeyParseResult.cs new file mode 100644 index 0000000..eec93bc --- /dev/null +++ b/src/SocketLabs/InjectionApi/Core/Models/ApiKeyParseResult.cs @@ -0,0 +1,23 @@ +using SocketLabs.InjectionApi.Core.Enum; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SocketLabs.InjectionApi.Core.Models +{ + /// + /// The result of an Api Key Parse Attempt + /// + public class ApiKeyParseResult + { + /// + /// The object representing the parsed Api Key + /// + public ApiKey ApiKey { get; set; } + + /// + /// A code describing the result of the attempt to parse the Api key. + /// + public ApiKeyParseResultCode ResultCode { get; set; } + } +} diff --git a/src/SocketLabs/InjectionApi/SocketLabsClient.cs b/src/SocketLabs/InjectionApi/SocketLabsClient.cs index b3cda97..e46bcf1 100644 --- a/src/SocketLabs/InjectionApi/SocketLabsClient.cs +++ b/src/SocketLabs/InjectionApi/SocketLabsClient.cs @@ -1,11 +1,13 @@ using System; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using SocketLabs.InjectionApi.Core; +using SocketLabs.InjectionApi.Core.Enum; using SocketLabs.InjectionApi.Message; namespace SocketLabs.InjectionApi @@ -35,8 +37,8 @@ public class SocketLabsClient : ISocketLabsClient, IDisposable private string UserAgent { get; } = $"SocketLabs-csharp/{typeof(SocketLabsClient).GetTypeInfo().Assembly.GetName().Version}"; private readonly int _serverId; - private readonly string _apiKey; private readonly HttpClient _httpClient; + private string _apiKey; /// @@ -228,6 +230,16 @@ public async Task SendAsync(IBasicMessage message, CancellationTok validationResult = validator.ValidateMessage(message); if (validationResult.Result != SendResult.Success) return validationResult; + + var apiKeyParser = new ApiKeyParser(); + var parseResult = apiKeyParser.Parse(_apiKey); + + if (parseResult.ResultCode == ApiKeyParseResultCode.Success) + { + _httpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", _apiKey); + _apiKey = string.Empty; + } var factory = new InjectionRequestFactory(_serverId, _apiKey); var injectionRequest = factory.GenerateRequest(message); @@ -282,6 +294,17 @@ public async Task SendAsync(IBulkMessage message, CancellationToke validationResult = validator.ValidateMessage(message); if (validationResult.Result != SendResult.Success) return validationResult; + + var apiKeyParser = new ApiKeyParser(); + var parseResult = apiKeyParser.Parse(_apiKey); + + if (parseResult.ResultCode == ApiKeyParseResultCode.Success) + { + _httpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", _apiKey); + _apiKey = string.Empty; + } + var factory = new InjectionRequestFactory(_serverId, _apiKey); var injectionRequest = factory.GenerateRequest(message); var json = injectionRequest.GetAsJson();