Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into ofmcc-636-setup-uat-e…
Browse files Browse the repository at this point in the history
…nvironment
  • Loading branch information
SoLetsDev committed Nov 21, 2023
2 parents d6a6c82 + 8262edc commit e63470e
Show file tree
Hide file tree
Showing 48 changed files with 2,689 additions and 272 deletions.
18 changes: 9 additions & 9 deletions OFM.Infrastructure.WebAPI/Extensions/ApiKeyMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ namespace OFM.Infrastructure.WebAPI.Extensions;
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ApiKeyMiddleware> _logger;
private readonly ILogger _logger;

public ApiKeyMiddleware(RequestDelegate next, ILogger<ApiKeyMiddleware> logger)
public ApiKeyMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = logger;
_logger = loggerFactory.CreateLogger(LogCategory.API);
}

public async Task InvokeAsync(HttpContext context,
IOptions<AuthenticationSettings> options)
IOptionsSnapshot<AuthenticationSettings> options)
{
var apiKeys = options.Value.Schemes.ApiKeyScheme.Keys;
var apiKeyPresentInHeader = context.Request.Headers.TryGetValue(options.Value.Schemes.ApiKeyScheme.ApiKeyName ?? "", out var extractedApiKey);
Expand All @@ -31,10 +32,9 @@ public async Task InvokeAsync(HttpContext context,
var pattern = @"(?<=[\w]{5})[\w-\._\+%]*(?=[\w]{3})";
var maskedKey = Regex.Replace(newKeyValue ?? "", pattern, m => new string('*', m.Length));

using (_logger.BeginScope("x-ofm-apikey:{maskedKey}", maskedKey))
{
await _next(context);
}
_logger.LogInformation(CustomLogEvent.API, "x-ofm-apikey:{maskedKey}", maskedKey);

await _next(context);

return;
}
Expand All @@ -43,7 +43,7 @@ public async Task InvokeAsync(HttpContext context,
var isAllowAnonymous = endpoint?.Metadata.Any(x => x.GetType() == typeof(AllowAnonymousAttribute));
if (isAllowAnonymous == true)
{
_logger.LogWarning("Anonymous user detected.");
_logger.LogWarning(CustomLogEvent.API, "Anonymous user detected.");
await _next(context);
return;
}
Expand Down
60 changes: 0 additions & 60 deletions OFM.Infrastructure.WebAPI/Extensions/CommonInfo.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Microsoft.Extensions.Logging;
using OFM.Infrastructure.WebAPI.Services.Processes;
using System.Reflection.Metadata;

namespace OFM.Infrastructure.WebAPI.Extensions;

public interface ID365BackgroundProcessHandler
{
void Execute(Func<ID365ScheduledProcessService, Task> processor);
}

public class D365BackgroundProcessHandler : ID365BackgroundProcessHandler
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger _logger;

//[FromServices] IServiceScopeFactory
public D365BackgroundProcessHandler(IServiceScopeFactory serviceScopeFactory, ILoggerFactory loggerFactory)
{
_serviceScopeFactory = serviceScopeFactory;
_logger = loggerFactory.CreateLogger(LogCategory.Process);
}

public void Execute(Func<ID365ScheduledProcessService, Task> processor)
{
Task.Run(async () =>
{
try
{
using var scope = _serviceScopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<ID365ScheduledProcessService>();
await processor(service);
}
catch (Exception exp)
{
_logger.LogCritical(exp.Message);
}
});
}
}
48 changes: 48 additions & 0 deletions OFM.Infrastructure.WebAPI/Extensions/D365ServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Net;

namespace OFM.Infrastructure.WebAPI.Extensions;
public class D365ServiceException : Exception
{
public HttpStatusCode HttpStatusCode { get; set; }

public string? ReasonPhrase { get; set; }

public ODataError? ODataError { get; set; }

public string? Content { get; set; }

public string? RequestId { get; set; }

public D365ServiceException()
{
}

public D365ServiceException(string message)
: base(message)
{
}

public D365ServiceException(string message, Exception inner)
: base(message, inner)
{
}
}

public class ODataException
{
public string? Message { get; set; }
public string? ExceptionMessage { get; set; }
public string? StackTrace { get; set; }
public string? ErrorCode { get; set; }
}

public class ODataError
{
public Error? Error { get; set; }
}

public class Error
{
public string? Code { get; set; }
public string? Message { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,53 +1,70 @@
using OFM.Infrastructure.WebAPI.Handlers;
using OFM.Infrastructure.WebAPI.Handlers.D365;

namespace OFM.Infrastructure.WebAPI.Extensions;

public static class EndpointRouteBuilderExtensions
{
#region Portal

public static void RegisterEnvironmentEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var endpoints = endpointRouteBuilder.MapGroup("/api/environment");

endpoints.MapGet("", EnvironmentHandlers.Get).WithTags("Environment").Produces(200).ProducesProblem(404);
endpoints.MapGet("", EnvironmentHandlers.Get).WithTags("Portal Environment").Produces(200).ProducesProblem(404);
}

public static void RegisterSearchesEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var searchesEndpoints = endpointRouteBuilder.MapGroup("/api/searches");

searchesEndpoints.MapPost("", SearchesHandlers.DataverseSearchAsync).WithTags("Searches").Produces(200).ProducesProblem(404);
searchesEndpoints.MapPost("", SearchesHandlers.DataverseSearchAsync).WithTags("Portal Searches").Produces(200).ProducesProblem(404);
}

public static void RegisterProviderProfileEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var searchesEndpoints = endpointRouteBuilder.MapGroup("/api/providerprofile");

searchesEndpoints.MapGet("", ProviderProfilesHandlers.GetProfileAsync).WithTags("Providers").Produces(200).ProducesProblem(404);
searchesEndpoints.MapGet("", ProviderProfilesHandlers.GetProfileAsync).WithTags("Portal Providers").Produces(200).ProducesProblem(404);
}

public static void RegisterOperationsEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var operationsEndpoints = endpointRouteBuilder.MapGroup("/api/operations");

operationsEndpoints.MapGet("", OperationsHandlers.GetAsync).WithTags("Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapPost("", OperationsHandlers.PostAsync).WithTags("Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapPatch("", OperationsHandlers.PatchAsync).WithTags("Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapDelete("", OperationsHandlers.DeleteAsync).WithTags("Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapGet("", OperationsHandlers.GetAsync).WithTags("Portal Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapPost("", OperationsHandlers.PostAsync).WithTags("Portal Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapPatch("", OperationsHandlers.PatchAsync).WithTags("Portal Operations").Produces(200).ProducesProblem(404);
operationsEndpoints.MapDelete("", OperationsHandlers.DeleteAsync).WithTags("Portal Operations").Produces(200).ProducesProblem(404);
}

public static void RegisterDocumentsEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var documentsEndpoints = endpointRouteBuilder.MapGroup("/api/documents");

documentsEndpoints.MapGet("", DocumentsHandlers.GetAsync).WithTags("Documents").Produces(200).ProducesProblem(404);
documentsEndpoints.MapPost("", DocumentsHandlers.PostAsync).WithTags("Documents").Produces(200).ProducesProblem(404);
documentsEndpoints.MapDelete("", DocumentsHandlers.DeleteAsync).WithTags("Documents").Produces(200).ProducesProblem(404);
documentsEndpoints.MapGet("", DocumentsHandlers.GetAsync).WithTags("Portal Documents").Produces(200).ProducesProblem(404);
documentsEndpoints.MapPost("", DocumentsHandlers.PostAsync).WithTags("Portal Documents").Produces(200).ProducesProblem(404).DisableAntiforgery();
documentsEndpoints.MapDelete("", DocumentsHandlers.DeleteAsync).WithTags("Portal Documents").Produces(200).ProducesProblem(404);
}

public static void RegisterBatchOperationsEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var searchesEndpoints = endpointRouteBuilder.MapGroup("/api/batches");
var batchEndpoints = endpointRouteBuilder.MapGroup("/api/batches");

searchesEndpoints.MapPost("", BatchOperationsHandlers.BatchOperationAsync).WithTags("Batches").Produces(200).ProducesProblem(404);
batchEndpoints.MapPost("", BatchOperationsHandlers.BatchOperationsAsync).WithTags("Portal Batches").Produces(200).ProducesProblem(404);
}

#endregion

#region D365

public static void RegisterBatchProcessesEndpoints(this IEndpointRouteBuilder endpointRouteBuilder)
{
var requestsEndpoints = endpointRouteBuilder.MapGroup("/api/processes");

requestsEndpoints.MapPost("/{processId}", ProcessesHandlers.RunProcessById).WithTags("D365 Processes");

}

#endregion
}
82 changes: 82 additions & 0 deletions OFM.Infrastructure.WebAPI/Extensions/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Polly.Extensions.Http;
using Polly;
using System.Net.Http.Headers;
using System.Text;

namespace OFM.Infrastructure.WebAPI.Extensions;

Expand Down Expand Up @@ -49,4 +50,85 @@ private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(AppSettings appS
onRetryAsync: (_, _, _, _) => { return Task.CompletedTask; }
);
}

public static async Task<string> ToRawString(this HttpRequestMessage request)
{
var sb = new StringBuilder();

var line1 = $"{request.Method} {request.RequestUri} HTTP/{request.Version}";
sb.AppendLine(line1);

foreach (var (key, value) in request.Headers)
foreach (var val in value)
{
var header = $"{key}: {val}";
sb.AppendLine(header);
}

if (request.Content?.Headers != null)
{
foreach (var (key, value) in request.Content.Headers)
foreach (var val in value)
{
var header = $"{key}: {val}";
sb.AppendLine(header);
}
}
sb.AppendLine();

var body = await (request.Content?.ReadAsStringAsync() ?? Task.FromResult<string>(null));
if (!string.IsNullOrWhiteSpace(body))
sb.AppendLine(body);

return sb.ToString();
}

public static async Task<string> ToRawString(this HttpResponseMessage response)
{
var sb = new StringBuilder();

var statusCode = (int)response.StatusCode;
var line1 = $"HTTP/{response.Version} {statusCode} {response.ReasonPhrase}";
sb.AppendLine(line1);

foreach (var (key, value) in response.Headers)
foreach (var val in value)
{
var header = $"{key}: {val}";
sb.AppendLine(header);
}

foreach (var (key, value) in response.Content.Headers)
foreach (var val in value)
{
var header = $"{key}: {val}";
sb.AppendLine(header);
}
sb.AppendLine();

var body = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrWhiteSpace(body))
sb.AppendLine(body);

return sb.ToString();
}

/// <summary>
/// Converts HttpResponseMessage to derived type
/// </summary>
/// <typeparam name="T">The type derived from HttpResponseMessage</typeparam>
/// <param name="response">The HttpResponseMessage</param>
/// <returns></returns>
public static T As<T>(this HttpResponseMessage response) where T : HttpResponseMessage
{
T? typedResponse = (T)Activator.CreateInstance(typeof(T));

//Copy the properties
typedResponse.StatusCode = response.StatusCode;
response.Headers.ToList().ForEach(h => {
typedResponse.Headers.TryAddWithoutValidation(h.Key, h.Value);
});
typedResponse.Content = response.Content;
return typedResponse;
}
}
Loading

0 comments on commit e63470e

Please sign in to comment.