Compare commits
12 Commits
165152b7cf
...
f9a73fbe0c
| Author | SHA1 | Date | |
|---|---|---|---|
| f9a73fbe0c | |||
| 282ce3a0b7 | |||
| 26f2da1313 | |||
| bc700e2cd2 | |||
| ea5389df85 | |||
| 87e1bb9187 | |||
| 68cc919bad | |||
| 374365d250 | |||
| 8c79b3a156 | |||
| 0583d07f26 | |||
| fd7744e94e | |||
| a5aac1d0ec |
6
src/ReC.Application/Common/Constants/Http.cs
Normal file
6
src/ReC.Application/Common/Constants/Http.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace ReC.Application.Common.Constants;
|
||||
|
||||
public static class Http
|
||||
{
|
||||
public static readonly string ClientName = "HttpClient-" + Guid.NewGuid().ToString();
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using MediatR;
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ReC.Application.Common.Behaviors;
|
||||
using ReC.Application.Common.Constants;
|
||||
using ReC.Application.Common.Options;
|
||||
using System.Reflection;
|
||||
using FluentValidation;
|
||||
|
||||
namespace ReC.Application;
|
||||
|
||||
@@ -35,7 +36,11 @@ public static class DependencyInjection
|
||||
cfg.LicenseKey = configOpt.LuckyPennySoftwareLicenseKey;
|
||||
});
|
||||
|
||||
services.AddHttpClient();
|
||||
services.AddHttpClient(Http.ClientName)
|
||||
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
||||
{
|
||||
UseDefaultCredentials = false
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using ReC.Application.Common;
|
||||
using ReC.Application.Common.Constants;
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
using ReC.Application.OutResults.Commands;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
@@ -27,7 +31,8 @@ public class InvokeRecActionCommandHandler(
|
||||
public async Task<bool> Handle(InvokeRecActionCommand request, CancellationToken cancel)
|
||||
{
|
||||
var action = request.Action;
|
||||
using var http = clientFactory.CreateClient();
|
||||
|
||||
using var http = clientFactory.CreateClient(Http.ClientName);
|
||||
|
||||
if (action.RestType is null)
|
||||
throw new DataIntegrityException(
|
||||
@@ -40,7 +45,7 @@ public class InvokeRecActionCommandHandler(
|
||||
.ToHttpMethod()
|
||||
.ToHttpRequestMessage(action.EndpointUri);
|
||||
|
||||
if(action.Body is not null)
|
||||
if (action.Body is not null)
|
||||
{
|
||||
using var reqBody = new StringContent(action.Body);
|
||||
httpReq.Content = reqBody;
|
||||
@@ -50,6 +55,70 @@ public class InvokeRecActionCommandHandler(
|
||||
foreach (var header in action.Headers)
|
||||
httpReq.Headers.Add(header.Key, header.Value);
|
||||
|
||||
switch (action.EndpointAuthType)
|
||||
{
|
||||
case "No Auth":
|
||||
break;
|
||||
|
||||
case "API Key":
|
||||
if (action.EndpointAuthApiKey is string apiKey && action.EndpointAuthApiValue is string apiValue)
|
||||
{
|
||||
if (action.EndpointAuthApiKeyAddTo == "Header")
|
||||
{
|
||||
httpReq.Headers.Add(apiKey, apiValue);
|
||||
}
|
||||
else // Defaults to Query String
|
||||
{
|
||||
var uriBuilder = new UriBuilder(httpReq.RequestUri!);
|
||||
var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||
query[apiKey] = apiValue;
|
||||
uriBuilder.Query = query.ToString();
|
||||
httpReq.RequestUri = uriBuilder.Uri;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "Bearer Token":
|
||||
case "JWT Bearer":
|
||||
case "OAuth 2.0": // OAuth 2.0 uses Bearer tokens for authenticated requests
|
||||
if (action.EndpointAuthToken is string authToken)
|
||||
httpReq.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
|
||||
break;
|
||||
|
||||
case "Basic Auth":
|
||||
if (action.EndpointAuthUsername is string authUsername && action.EndpointAuthPassword is string authPassword)
|
||||
{
|
||||
var basicAuth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{authUsername}:{authPassword}"));
|
||||
httpReq.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth);
|
||||
}
|
||||
break;
|
||||
|
||||
case "NTLM Auth":
|
||||
if (!string.IsNullOrWhiteSpace(action.EndpointAuthUsername))
|
||||
{
|
||||
var credentials = new NetworkCredential(
|
||||
action.EndpointAuthUsername,
|
||||
action.EndpointAuthPassword,
|
||||
action.EndpointAuthDomain);
|
||||
var credentialCache = new CredentialCache { { httpReq.RequestUri!, "NTLM", credentials } };
|
||||
httpReq.Options.Set(new HttpRequestOptionsKey<CredentialCache>("Credentials"), credentialCache);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Digest Auth":
|
||||
case "OAuth 1.0":
|
||||
case "AWS Signature":
|
||||
// These authentication methods require more complex implementations,
|
||||
// often involving multi-step handshakes or specialized libraries.
|
||||
// They are left as placeholders for future implementation.
|
||||
default:
|
||||
throw new NotImplementedException(
|
||||
$"The authentication type '{action.EndpointAuthType}' is not supported yet. " +
|
||||
$"ProfileId: {action.ProfileId}, " +
|
||||
$"Id: {action.Id}"
|
||||
);
|
||||
}
|
||||
|
||||
using var response = await http.SendAsync(httpReq, cancel);
|
||||
var resBody = await response.Content.ReadAsStringAsync(cancel);
|
||||
var resHeaders = response.Headers.ToDictionary();
|
||||
|
||||
@@ -38,9 +38,9 @@ public class ReadRecActionQueryHandler(IRepository<RecActionView> repo, IMapper
|
||||
if (request.Invoked is bool invoked)
|
||||
query = invoked ? query.Where(act => act.Root!.OutRes != null) : query.Where(act => act.Root!.OutRes == null);
|
||||
|
||||
var actions = await query.ToListAsync(cancel);
|
||||
var actions = await query.Include(act => act.EndpointAuth).ToListAsync(cancel);
|
||||
|
||||
if(actions.Count == 0)
|
||||
if (actions.Count == 0)
|
||||
throw new NotFoundException($"No actions found for the profile {request.ProfileId}.");
|
||||
|
||||
return mapper.Map<IEnumerable<RecActionDto>>(actions);
|
||||
|
||||
7
src/ReC.Domain/Constants/ErrorAction.cs
Normal file
7
src/ReC.Domain/Constants/ErrorAction.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace ReC.Domain.Constants;
|
||||
|
||||
public enum ErrorAction
|
||||
{
|
||||
Stop = 0,
|
||||
Continue = 1,
|
||||
}
|
||||
@@ -10,8 +10,6 @@ public class OutRes
|
||||
|
||||
public short? Status { get; set; }
|
||||
|
||||
public string? Message { get; set; }
|
||||
|
||||
public string? Header { get; set; }
|
||||
|
||||
public string? Body { get; set; }
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace ReC.Domain.Entities;
|
||||
using ReC.Domain.Constants;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
public class RecAction
|
||||
{
|
||||
@@ -36,7 +38,7 @@ public class RecAction
|
||||
|
||||
public string? PostprocessingQuery { get; set; }
|
||||
|
||||
public string? ErrorAction { get; set; }
|
||||
public ErrorAction? ErrorAction { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ public class RecActionView
|
||||
|
||||
public long? EndpointAuthId { get; set; }
|
||||
|
||||
[ForeignKey("EndpointAuthId")]
|
||||
public EndpointAuth? EndpointAuth { get; set; }
|
||||
|
||||
public string? EndpointAuthType { get; set; }
|
||||
|
||||
public string? EndpointAuthApiKey { get; set; }
|
||||
|
||||
@@ -132,7 +132,6 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
|
||||
|
||||
b.Property(e => e.ActionId).HasColumnName("ACTION_ID");
|
||||
b.Property(e => e.Status).HasColumnName("STATUS");
|
||||
b.Property(e => e.Message).HasColumnName("MESSAGE");
|
||||
b.Property(e => e.Header).HasColumnName("RESULT_HEADER");
|
||||
b.Property(e => e.Body).HasColumnName("RESULT_BODY");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
|
||||
Reference in New Issue
Block a user