Adding datawapper and disco
This commit is contained in:
@@ -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,10 +2,11 @@ namespace MimeSharp;
|
||||
|
||||
public enum MimecastRegion
|
||||
{
|
||||
ALPHA,
|
||||
AU,
|
||||
EU,
|
||||
US,
|
||||
ZA,
|
||||
AU,
|
||||
DE,
|
||||
JER,
|
||||
QAN,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MimeSharp;
|
||||
|
||||
public class SearializerHelper
|
||||
{
|
||||
|
||||
}
|
||||
+6
-1
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MimeSharp.WTOs;
|
||||
|
||||
public class FailWTO
|
||||
{
|
||||
public List<ErrorWTO> Errors { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MimeSharp.WTOs;
|
||||
|
||||
public class MetaWTO
|
||||
{
|
||||
public int Status { get; set; }
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user