cambiado requisito de cabeceras en todas las llamadas y simualcion de datos en la 3 llamada para pruebas
This commit is contained in:
@@ -15,19 +15,13 @@ public sealed class OpeController : ControllerBase
|
|||||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
|
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
|
||||||
|
|
||||||
private readonly OpeOptions _options;
|
private readonly OpeOptions _options;
|
||||||
private readonly InternalDenunciasClient _internalApi;
|
|
||||||
private readonly OpeFieldMapper _fieldMapper;
|
|
||||||
private readonly ILogger<OpeController> _logger;
|
private readonly ILogger<OpeController> _logger;
|
||||||
|
|
||||||
public OpeController(
|
public OpeController(
|
||||||
IOptions<OpeOptions> options,
|
IOptions<OpeOptions> options,
|
||||||
InternalDenunciasClient internalApi,
|
|
||||||
OpeFieldMapper fieldMapper,
|
|
||||||
ILogger<OpeController> logger)
|
ILogger<OpeController> logger)
|
||||||
{
|
{
|
||||||
_options = options.Value;
|
_options = options.Value;
|
||||||
_internalApi = internalApi;
|
|
||||||
_fieldMapper = fieldMapper;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,54 +76,25 @@ public sealed class OpeController : ControllerBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
// Respuesta temporal de pruebas: no consulta la API interna ni exige
|
||||||
{
|
// que el expediente exista. FIELD_0 conserva exactamente el valor
|
||||||
var result = await _internalApi.GetFieldsAsync(
|
// recibido y el resto de campos devuelve un valor ficticio.
|
||||||
lookup,
|
_logger.LogInformation(
|
||||||
requestContext.TransactionId,
|
"Respuesta OPE de prueba para el expediente solicitado {Expediente}. TransactionId={TransactionId}",
|
||||||
cancellationToken);
|
identifier,
|
||||||
|
requestContext.TransactionId);
|
||||||
|
|
||||||
if (result.Status == InternalLookupStatus.NotFound || result.Fields is null)
|
var testData = new Dictionary<string, OpeFieldValue>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
return Error(
|
["FIELD_0"] = new OpeFieldValue("STRING", identifier)
|
||||||
"No se ha encontrado la denuncia o expediente solicitado",
|
};
|
||||||
OpeErrorCauses.ElementNotExists,
|
|
||||||
null);
|
for (var index = 1; index < _options.OutputFields.Count; index++)
|
||||||
|
{
|
||||||
|
testData[$"FIELD_{index}"] = new OpeFieldValue("STRING", "dato de prueba");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json(_fieldMapper.Map(result.Fields), OpeMediaTypes.GenericOperationResponse);
|
return Json(new OpeDataEnvelope(testData), OpeMediaTypes.GenericOperationResponse);
|
||||||
}
|
|
||||||
catch (OperationCanceledException) when (!HttpContext.RequestAborted.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_logger.LogWarning(
|
|
||||||
"Timeout consultando ApiDenuncias para una OPE. TransactionId={TransactionId}",
|
|
||||||
requestContext.TransactionId);
|
|
||||||
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException exception)
|
|
||||||
{
|
|
||||||
_logger.LogWarning(
|
|
||||||
exception,
|
|
||||||
"No se ha podido conectar con ApiDenuncias. TransactionId={TransactionId}",
|
|
||||||
requestContext.TransactionId);
|
|
||||||
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
|
|
||||||
}
|
|
||||||
catch (InternalApiException exception)
|
|
||||||
{
|
|
||||||
_logger.LogWarning(
|
|
||||||
exception,
|
|
||||||
"ApiDenuncias ha devuelto una respuesta no utilizable. TransactionId={TransactionId}",
|
|
||||||
requestContext.TransactionId);
|
|
||||||
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
|
|
||||||
}
|
|
||||||
catch (InvalidDataException exception)
|
|
||||||
{
|
|
||||||
_logger.LogError(
|
|
||||||
exception,
|
|
||||||
"El contrato entre ApiOPE y ApiDenuncias no coincide. TransactionId={TransactionId}",
|
|
||||||
requestContext.TransactionId);
|
|
||||||
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContentResult Error(
|
private static ContentResult Error(
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Security.Claims;
|
|||||||
using ApiOPE.Configuration;
|
using ApiOPE.Configuration;
|
||||||
using ApiOPE.Contracts;
|
using ApiOPE.Contracts;
|
||||||
using ApiOPE.Services;
|
using ApiOPE.Services;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -31,8 +30,7 @@ public sealed class OpeAuthenticationMiddleware
|
|||||||
HttpContext context,
|
HttpContext context,
|
||||||
OpeTokenValidator tokenValidator,
|
OpeTokenValidator tokenValidator,
|
||||||
OpeResponseSigner responseSigner,
|
OpeResponseSigner responseSigner,
|
||||||
OpeRequestFileLogger requestFileLogger,
|
OpeRequestFileLogger requestFileLogger)
|
||||||
IOptions<OpeOptions> options)
|
|
||||||
{
|
{
|
||||||
var authentication = context.GetEndpoint()?.Metadata.GetMetadata<OpeAuthenticatedAttribute>();
|
var authentication = context.GetEndpoint()?.Metadata.GetMetadata<OpeAuthenticatedAttribute>();
|
||||||
if (authentication is null)
|
if (authentication is null)
|
||||||
@@ -54,12 +52,6 @@ public sealed class OpeAuthenticationMiddleware
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ValidateOrganizationHeaders(context.Request.Headers, options.Value, out var organizationFailure))
|
|
||||||
{
|
|
||||||
await RejectAsync(context, organizationFailure, requestFileLogger, token, validation.RequestContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpeRequestContextStore.Set(context, validation.RequestContext);
|
OpeRequestContextStore.Set(context, validation.RequestContext);
|
||||||
context.User = new ClaimsPrincipal(new ClaimsIdentity(
|
context.User = new ClaimsPrincipal(new ClaimsIdentity(
|
||||||
[
|
[
|
||||||
@@ -92,6 +84,13 @@ public sealed class OpeAuthenticationMiddleware
|
|||||||
validation.RequestContext.TransactionId.ToString(),
|
validation.RequestContext.TransactionId.ToString(),
|
||||||
context.TraceIdentifier,
|
context.TraceIdentifier,
|
||||||
Fingerprint(validation.RequestContext.ClientToken),
|
Fingerprint(validation.RequestContext.ClientToken),
|
||||||
|
context.Connection.RemoteIpAddress?.ToString(),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationIdHeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationDir3HeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationCifHeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, "Content-Type"),
|
||||||
|
ReadHeader(context.Request.Headers, "Accept"),
|
||||||
|
ReadHeader(context.Request.Headers, "User-Agent"),
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,6 +117,13 @@ public sealed class OpeAuthenticationMiddleware
|
|||||||
requestContext?.TransactionId.ToString(),
|
requestContext?.TransactionId.ToString(),
|
||||||
context.TraceIdentifier,
|
context.TraceIdentifier,
|
||||||
string.IsNullOrWhiteSpace(token) ? null : Fingerprint(token),
|
string.IsNullOrWhiteSpace(token) ? null : Fingerprint(token),
|
||||||
|
context.Connection.RemoteIpAddress?.ToString(),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationIdHeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationDir3HeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, OrganizationCifHeaderName),
|
||||||
|
ReadHeader(context.Request.Headers, "Content-Type"),
|
||||||
|
ReadHeader(context.Request.Headers, "Accept"),
|
||||||
|
ReadHeader(context.Request.Headers, "User-Agent"),
|
||||||
reason));
|
reason));
|
||||||
|
|
||||||
await OpeResponseWriter.WriteErrorAsync(
|
await OpeResponseWriter.WriteErrorAsync(
|
||||||
@@ -132,26 +138,10 @@ public sealed class OpeAuthenticationMiddleware
|
|||||||
private static string Fingerprint(string value)
|
private static string Fingerprint(string value)
|
||||||
=> Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value)))[..12];
|
=> Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value)))[..12];
|
||||||
|
|
||||||
private static bool ValidateOrganizationHeaders(
|
private static string? ReadHeader(IHeaderDictionary headers, string name)
|
||||||
IHeaderDictionary headers,
|
=> headers.TryGetValue(name, out var values) && values.Count > 0
|
||||||
OpeOptions options,
|
? string.Join(",", values.ToArray()).Trim()
|
||||||
out string failureReason)
|
: null;
|
||||||
{
|
|
||||||
var valid = MatchesHeader(headers, OrganizationIdHeaderName, options.OrganizationId) &&
|
|
||||||
MatchesHeader(headers, OrganizationDir3HeaderName, options.OrganizationDir3) &&
|
|
||||||
MatchesHeader(headers, OrganizationCifHeaderName, options.OrganizationCif);
|
|
||||||
|
|
||||||
failureReason = valid
|
|
||||||
? string.Empty
|
|
||||||
: "Las cabeceras de organizacion no corresponden al conector configurado.";
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool MatchesHeader(IHeaderDictionary headers, string name, string expected)
|
|
||||||
{
|
|
||||||
return TryGetSingleHeader(headers, name, out var value) &&
|
|
||||||
string.Equals(value, expected, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryGetSingleHeader(
|
private static bool TryGetSingleHeader(
|
||||||
IHeaderDictionary headers,
|
IHeaderDictionary headers,
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ public sealed record OpeRequestLogEntry(
|
|||||||
string? TransactionId,
|
string? TransactionId,
|
||||||
string? RequestId,
|
string? RequestId,
|
||||||
string? ClientTokenFingerprint,
|
string? ClientTokenFingerprint,
|
||||||
|
string? RemoteIp,
|
||||||
|
string? OrganizationId,
|
||||||
|
string? OrganizationDir3,
|
||||||
|
string? OrganizationCif,
|
||||||
|
string? ContentType,
|
||||||
|
string? Accept,
|
||||||
|
string? UserAgent,
|
||||||
string? FailureReason)
|
string? FailureReason)
|
||||||
{
|
{
|
||||||
public string ToDisplayLine()
|
public string ToDisplayLine()
|
||||||
@@ -69,8 +76,20 @@ public sealed record OpeRequestLogEntry(
|
|||||||
Path,
|
Path,
|
||||||
$"HTTP {StatusCode}",
|
$"HTTP {StatusCode}",
|
||||||
Result,
|
Result,
|
||||||
|
$"ip={Clean(RemoteIp)}",
|
||||||
|
$"orgId={Clean(OrganizationId)}",
|
||||||
|
$"dir3={Clean(OrganizationDir3)}",
|
||||||
|
$"cif={Clean(OrganizationCif)}",
|
||||||
|
$"contentType={Clean(ContentType)}",
|
||||||
|
$"accept={Clean(Accept)}",
|
||||||
|
$"userAgent={Clean(UserAgent)}",
|
||||||
$"transaccion={TransactionId ?? "-"}",
|
$"transaccion={TransactionId ?? "-"}",
|
||||||
$"peticion={RequestId ?? "-"}",
|
$"peticion={RequestId ?? "-"}",
|
||||||
$"cliente={ClientTokenFingerprint ?? "-"}",
|
$"cliente={ClientTokenFingerprint ?? "-"}",
|
||||||
$"motivo={FailureReason ?? "-"}");
|
$"motivo={Clean(FailureReason)}");
|
||||||
|
|
||||||
|
private static string Clean(string? value)
|
||||||
|
=> string.IsNullOrWhiteSpace(value)
|
||||||
|
? "-"
|
||||||
|
: value.Replace("\r", " ").Replace("\n", " ").Trim();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user