Adding datawapper and disco

This commit is contained in:
frank
2024-09-08 15:15:23 -04:00
parent fcbaadda6f
commit 481347652d
15 changed files with 289 additions and 16 deletions
+120
View File
@@ -0,0 +1,120 @@
using System.Net;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using MimeSharp.WTOs;
namespace MimeSharp;
public class MimeSharp
{
private const string HmacSha1Algorithm = "HMACSHA1";
private const string XmcReqId = "x-mcm-req-id";
private const string XmcDate = "x-mcm-date";
private const string XmcAppId = "x-mcm-app-id";
private const string Authorization = "Authorization";
private const string XmcApiVersion = "x-mcm-api-version";
private const string ApiVersion = "2017.2.22";
private WebHelper _webHelper = new();
public MimeSharp(string username, string appKey, string appId)
{
Username = username;
AppKey = appKey;
AppId = appId;
}
public string AccessKey { get; set; } = string.Empty;
public string Username { get; set; }
public string AppKey { get; set; }
public string AppId { get; set; }
private MimecastRegion _region;
private LoginResponseWTO _login;
private Urls _urls;
public static string GetGuid()
{
return Guid.NewGuid().ToString("N");
}
private bool Login(string loginType, SecureString password, string? guid = null)
{
if (string.IsNullOrEmpty(guid))
{
guid = GetGuid();
}
var authHeader = GetAuthHeader(loginType, password);
var requestHeader = new Dictionary<string, string>
{
{ Authorization, authHeader }, { XmcReqId, guid }, { XmcApiVersion, ApiVersion }
};
}
public static string DiscoverRegion(string username)
{
// Validates Username is valid
if (Validation.IsValidEmail(username))
{
// Creates data object for request body containing the user's email address
//var body = AddressToRequestBody(Username);
var dataWrapper = DataWrapper<DiscoveryRequestWTO>.FromObject(new DiscoveryRequestWTO(username));
var requestHeaders = new Dictionary<string, string>
{
{ "x-mc-req-id", Guid.NewGuid().ToString() },
{ "x-mc-date", DateTimeHelper.GetRfc1123() }
};
// Creates a WebRequest object to pass to MakeWebCall
var discoveryResponseWto =
MakePostCall<DataWrapper<DiscoveryRequestWTO>, DataWrapper<DiscoveryResponseWTO>>(Urls.GetDiscoveryUri(), requestHeaders, dataWrapper);
// new WebRequest(URIs.BaseURI, URIs.Discover, body, requestHeaders, HttpMethod.Post);
var response = WebHelper.MakeWebCall<DiscoveryResponse>(request);
if (response != null)
{
return response.data[0].region.api;
}
}
return string.Empty;
}
private DataWrapper<TR>? MakePostCall<T,TR>(string url, Dictionary<string, string>? headers, T body)
{
var bodyJson = body == null ? null : JsonSerializer.Serialize(body);
var response = _webHelper.Post(url, headers, bodyJson);
return JsonSerializer.Deserialize<DataWrapper<TR>>(response.Result);
}
/// <summary>
/// Generates signed token for request header
/// </summary>
/// <param name="uuid"></param>
/// <param name="time"></param>
/// <param name="Uri"></param>
/// <param name="Token"></param>
/// <returns></returns>
private string GenerateSignedToken(string uuid, string time, string Uri)
{
// This is the raw base string that will be encoded to form the signed token
var data = $"{time}:{uuid}:{Uri}:{AppKey}";
// Creates an HMACSHA1 instance with the Secret Key as a key
using var hmac = new HMACSHA1(Convert.FromBase64String(_login.SecretKey));
// Calculates the hash of the plain text signature byte[]
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
// Converts the hash into a Base64 string
var encodedHash = Convert.ToBase64String(hash);
// Creates the signature string
return $"MC {_login.AccessKey}:{encodedHash}";
}
}
+2 -1
View File
@@ -2,10 +2,11 @@ namespace MimeSharp;
public enum MimecastRegion
{
ALPHA,
AU,
EU,
US,
ZA,
AU,
DE,
JER,
QAN,
+6
View File
@@ -0,0 +1,6 @@
namespace MimeSharp;
public class SearializerHelper
{
}
+6 -1
View File
@@ -3,7 +3,12 @@ namespace MimeSharp;
public class Urls(MimecastRegion region)
{
private const string Protocol = "https://";
public static String GetDiscoveryUri()
{
return "https://api.mimecast.com/api/login/discover-authentication";
}
public String GetLogin()
{
return GetUrl(Endpoints.Login);
@@ -0,0 +1,15 @@
namespace MimeSharp.WTOs;
public class DiscoveryRequestWTO
{
public DiscoveryRequestWTO(string username)
{
EmailAddress = username;
}
public string EmailAddress { get; set; } = string.Empty;
public string EmailToken { get; set; } = string.Empty;
public string LastUserToken { get; set; } = string.Empty;
public string CustomerToken { get; set; } = string.Empty;
public string SwgToken { get; set; } = string.Empty;
}
@@ -0,0 +1,9 @@
namespace MimeSharp.WTOs;
public class DiscoveryResponseWTO
{
public string EmailAddress { get; set; } = string.Empty;
public string EmailToken { get; set; } = string.Empty;
public string lastAuthType { get; set; } = string.Empty;
private RegionDetailsWTO region { get; set; }
}
@@ -0,0 +1,7 @@
namespace MimeSharp.WTOs;
public class LoginRequestWTO
{
public string Username { get; set; } = string.Empty;
public string AccessKey { get; set; } = string.Empty;
}
@@ -0,0 +1,11 @@
namespace MimeSharp.WTOs;
public class LoginResponseWTO
{
public string AccessKey { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public long Duration { get; set; }
public string BindingType { get; set; } = string.Empty;
public bool ExtendOnValidate { get; set; }
public string LastUserToken { get; set; } = string.Empty;
}
@@ -0,0 +1,10 @@
namespace MimeSharp.WTOs;
public class RegionDetailsWTO
{
public string Code { get; set; } = string.Empty;
public string Api { get; set; } = string.Empty;
public string Mpp { get; set; } = string.Empty;
public string AdminConsole { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
}
+24
View File
@@ -0,0 +1,24 @@
namespace MimeSharp.WTOs;
public class DataWrapper<T>
{
public List<FailWTO> Fail { get; set; }
public MetaWTO Meta { get; set; }
public required List<T> Data { get; set; }
public static DataWrapper<T> FromObject(T data)
{
return new DataWrapper<T>
{
Data = [data]
};
}
public static DataWrapper<T> FromList(List<T> data)
{
return new DataWrapper<T>()
{
Data = data
};
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace MimeSharp.WTOs;
public class ErrorWTO
{
public string Code { get; set; }
public string Message { get; set; }
public bool Retryable { get; set; }
}
+6
View File
@@ -0,0 +1,6 @@
namespace MimeSharp.WTOs;
public class FailWTO
{
public List<ErrorWTO> Errors { get; set; }
}
+6
View File
@@ -0,0 +1,6 @@
namespace MimeSharp.WTOs;
public class MetaWTO
{
public int Status { get; set; }
}
+4 -3
View File
@@ -15,11 +15,12 @@ public class WebHelper
_client = client;
}
public async Task<string> Post(string url, Dictionary<string, string>? headers, string body)
public async Task<string> Post(string url, Dictionary<string, string>? headers, string? body)
{
headers?.ToList().ForEach(h => _client.DefaultRequestHeaders.TryAddWithoutValidation(h.Key, h.Value));
var content = new StringContent(body, Encoding.UTF8, "application/json");
var content = new StringContent(body ?? string.Empty, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
+55 -11
View File
@@ -9,28 +9,72 @@ namespace MimeSharpUnitTests;
public class WebHelperUnitTests
{
private readonly HttpClient _client;
private const string _mockResponseBody = "\"[{'id':1,'value':'1'}]\"";
private const string _mockUrl = "https://example.com";
[Test]
public async Task CanMakeCallUsingGet()
{
//arrange
var mockHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
var mockResponseBody = "\"[{'id':1,'value':'1'}]\"";
var mockUrl = "https://example.com";
mockHandler.SetupRequest(HttpMethod.Get, mockUrl)
.ReturnsResponse(HttpStatusCode.OK, mockResponseBody);
//arrange
mockHandler.SetupRequest(HttpMethod.Get, _mockUrl)
.ReturnsResponse(HttpStatusCode.OK, _mockResponseBody);
// Inject the handler or client into your application code
var httpClient = mockHandler.CreateClient();
var webHelper = new WebHelper(httpClient);
//act
var actual = await webHelper.Get(mockUrl, null);
var actual = await webHelper.Get(_mockUrl, null);
//assert
Assert.NotNull(actual);
Assert.That(actual, Is.EqualTo(mockResponseBody));
mockHandler.VerifyRequest(HttpMethod.Get, mockUrl, Times.Once());
Assert.That(actual, Is.Not.Null);
Assert.That(actual, Is.EqualTo(_mockResponseBody));
mockHandler.VerifyRequest(HttpMethod.Get, _mockUrl, Times.Once());
}
[Test]
public async Task CanMakeCallUsingPostNullBody()
{
var mockHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
//arrange
mockHandler.SetupRequest(HttpMethod.Post, _mockUrl)
.ReturnsResponse(HttpStatusCode.OK, _mockResponseBody);
// Inject the handler or client into your application code
var httpClient = mockHandler.CreateClient();
var webHelper = new WebHelper(httpClient);
//act
var actual = await webHelper.Post(_mockUrl, null, null);
//assert
Assert.That(actual, Is.Not.Null);
Assert.That(actual, Is.EqualTo(_mockResponseBody));
mockHandler.VerifyRequest(HttpMethod.Post, _mockUrl, Times.Once());
}
[Test]
public async Task CanMakeCallUsingPostWithBody()
{
var mockHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
//arrange
mockHandler.SetupRequest(HttpMethod.Post, _mockUrl)
.ReturnsResponse(HttpStatusCode.OK, _mockResponseBody);
// Inject the handler or client into your application code
var httpClient = mockHandler.CreateClient();
var webHelper = new WebHelper(httpClient);
var obj = "{\"id\":1}";
//act
var actual = await webHelper.Post(_mockUrl, null, obj);
//assert
Assert.That(actual, Is.Not.Null);
Assert.That(actual, Is.EqualTo(_mockResponseBody));
mockHandler.VerifyRequest(HttpMethod.Post, _mockUrl, Times.Once());
}
}