Introduced `ReadEnvelopeReceiverSecretQuery` to fetch sensitive fields (e.g., access code, phone number) for envelope receivers. Added extension methods for dispatching the query via `IMediator` and implemented `ReadEnvelopeReceiverSecretQueryHandler` to process the query using repositories and AutoMapper. Updated `EnvelopeController` with a new HTTP GET endpoint `EnvelopeReceiverWithSecretByMediatr` to expose the query functionality. This endpoint returns sensitive data as `EnvelopeReceiverSecretDto` or a 404 response if no match is found. These changes improve modularity, testability, and separation of concerns by leveraging MediatR and CQRS patterns.
128 lines
5.6 KiB
C#
128 lines
5.6 KiB
C#
using AutoMapper;
|
|
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using EnvelopeGenerator.Application.Envelopes.Queries;
|
|
using EnvelopeGenerator.Application.Receivers.Queries;
|
|
using MediatR;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
|
using EnvelopeGenerator.Application.Common.Query;
|
|
using EnvelopeGenerator.Application.Common.Extensions;
|
|
|
|
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
|
|
/// <summary>
|
|
/// Represents a query for reading an envelope receiver including sensitive fields
|
|
/// (access code, phone number) that are excluded from the standard <see cref="ReadEnvelopeReceiverQuery"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Returns a single <see cref="EnvelopeReceiverSecretDto"/> matched by UUID and receiver signature.
|
|
/// Equivalent to the legacy <c>ReadWithSecretByUuidSignatureAsync</c> service method.
|
|
/// </remarks>
|
|
public record ReadEnvelopeReceiverSecretQuery
|
|
: EnvelopeReceiverQueryBase<ReadEnvelopeQuery, ReadReceiverQuery>,
|
|
IRequest<EnvelopeReceiverSecretDto?>;
|
|
|
|
/// <summary>
|
|
/// Extension methods for dispatching <see cref="ReadEnvelopeReceiverSecretQuery"/> via <see cref="IMediator"/>.
|
|
/// </summary>
|
|
public static class ReadEnvelopeReceiverSecretQueryExtensions
|
|
{
|
|
/// <summary>
|
|
/// Sends a <see cref="ReadEnvelopeReceiverSecretQuery"/> using the composite key (uuid::signature).
|
|
/// </summary>
|
|
/// <param name="mediator">The mediator instance.</param>
|
|
/// <param name="key">Composite key in the format <c>uuid::signature</c>.</param>
|
|
/// <param name="cancel">Cancellation token.</param>
|
|
/// <returns>The matching <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if not found.</returns>
|
|
public static Task<EnvelopeReceiverSecretDto?> ReadEnvelopeReceiverSecretAsync(
|
|
this IMediator mediator,
|
|
string key,
|
|
CancellationToken cancel = default)
|
|
=> mediator.Send(new ReadEnvelopeReceiverSecretQuery { Key = key }, cancel);
|
|
|
|
/// <summary>
|
|
/// Sends a <see cref="ReadEnvelopeReceiverSecretQuery"/> using UUID and receiver signature.
|
|
/// </summary>
|
|
/// <param name="mediator">The mediator instance.</param>
|
|
/// <param name="uuid">Envelope UUID.</param>
|
|
/// <param name="signature">Receiver signature.</param>
|
|
/// <param name="cancel">Cancellation token.</param>
|
|
/// <returns>The matching <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if not found.</returns>
|
|
public static Task<EnvelopeReceiverSecretDto?> ReadEnvelopeReceiverSecretAsync(
|
|
this IMediator mediator,
|
|
string uuid,
|
|
string signature,
|
|
CancellationToken cancel = default)
|
|
{
|
|
var q = new ReadEnvelopeReceiverSecretQuery();
|
|
q.Envelope.Uuid = uuid;
|
|
q.Receiver.Signature = signature;
|
|
return mediator.Send(q, cancel);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles <see cref="ReadEnvelopeReceiverSecretQuery"/> and returns a
|
|
/// <see cref="EnvelopeReceiverSecretDto"/> containing sensitive fields.
|
|
/// </summary>
|
|
public class ReadEnvelopeReceiverSecretQueryHandler
|
|
: IRequestHandler<ReadEnvelopeReceiverSecretQuery, EnvelopeReceiverSecretDto?>
|
|
{
|
|
private readonly IRepository<EnvelopeReceiver> _repo;
|
|
private readonly IRepository<Receiver> _rcvRepo;
|
|
private readonly IMapper _mapper;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of <see cref="ReadEnvelopeReceiverSecretQueryHandler"/>.
|
|
/// </summary>
|
|
/// <param name="envelopeReceiver">Repository for <see cref="EnvelopeReceiver"/>.</param>
|
|
/// <param name="rcvRepo">Repository for <see cref="Receiver"/>.</param>
|
|
/// <param name="mapper">AutoMapper instance.</param>
|
|
public ReadEnvelopeReceiverSecretQueryHandler(
|
|
IRepository<EnvelopeReceiver> envelopeReceiver,
|
|
IRepository<Receiver> rcvRepo,
|
|
IMapper mapper)
|
|
{
|
|
_repo = envelopeReceiver;
|
|
_rcvRepo = rcvRepo;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles the query and returns the matching <see cref="EnvelopeReceiverSecretDto"/>.
|
|
/// </summary>
|
|
/// <param name="request">The query containing filter criteria.</param>
|
|
/// <param name="cancel">Cancellation token.</param>
|
|
/// <returns>
|
|
/// The matched <see cref="EnvelopeReceiverSecretDto"/>, or <c>null</c> if no record is found.
|
|
/// </returns>
|
|
public async Task<EnvelopeReceiverSecretDto?> Handle(
|
|
ReadEnvelopeReceiverSecretQuery request,
|
|
CancellationToken cancel)
|
|
{
|
|
var q = _repo.Query.Where(request, notnull: false);
|
|
|
|
var envRcvs = await q
|
|
.Include(er => er.Envelope).ThenInclude(e => e!.Documents!).ThenInclude(d => d.Elements)
|
|
.Include(er => er.Envelope).ThenInclude(e => e!.Histories)
|
|
.Include(er => er.Envelope).ThenInclude(e => e!.User)
|
|
.Include(er => er.Receiver)
|
|
.ToListAsync(cancel);
|
|
|
|
if (request.Receiver.HasAnyCriteria && envRcvs.Count != 0)
|
|
{
|
|
var receiver = await _rcvRepo.Query.Where(request.Receiver).FirstAsync(cancel);
|
|
|
|
foreach (var item in envRcvs)
|
|
item.Envelope?.Documents?.FirstOrDefault()?.Elements?.RemoveAll(s => s.ReceiverId != receiver.Id);
|
|
}
|
|
|
|
var envRcv = envRcvs.FirstOrDefault();
|
|
if (envRcv is null)
|
|
return null;
|
|
|
|
return _mapper.Map<EnvelopeReceiverSecretDto>(envRcv);
|
|
}
|
|
}
|
|
}
|