Extended `DocReceiverElementDto` to include an optional `Document` reference. Enhanced `ReadDocReceiverElementQuery` with `Id` and `IncludeDocument` properties for filtering and document inclusion. Updated `ReadDocReceiverElementQueryHandler` to handle new query properties, enabling filtering by `Id` and optionally including associated documents. Introduced `SignPdfByElementCommand` and its handler to support signing PDFs using either a provided `DocReceiverElementDto` or an `ElementId`. Added validation via `SignPdfByElementCommandValidator` to ensure proper usage. Refactored and added necessary `using` directives for new dependencies.
85 lines
2.7 KiB
C#
85 lines
2.7 KiB
C#
using DigitalData.Core.Exceptions;
|
|
using EnvelopeGenerator.Application.Common.Dto;
|
|
using EnvelopeGenerator.Application.Common.Interfaces.Doc;
|
|
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
|
using EnvelopeGenerator.Application.DocReceiverElements.Queries;
|
|
using MediatR;
|
|
|
|
namespace EnvelopeGenerator.Application.PdfSigning;
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public record SignPdfByElementCommand : IRequest<Stream>
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public DocReceiverElementDto? Element { get; set; }
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public int? ElementId { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="signService"></param>
|
|
public class SignPdfCommandHandler(ISender sender, IPdfDigitalSignatureService signService, IPdfPageImageRenderer imgRenderer) : IRequestHandler<SignPdfByElementCommand, Stream>
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="request"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<Stream> Handle(SignPdfByElementCommand request, CancellationToken cancellationToken)
|
|
{
|
|
// ensure element
|
|
if(request.Element is null)
|
|
{
|
|
var elements = await sender.Send(new ReadDocReceiverElementQuery()
|
|
{
|
|
Id = request.ElementId!,
|
|
IncludeDocument= true
|
|
}, cancellationToken);
|
|
|
|
if (!elements.Any())
|
|
throw new NotFoundException($"Element with ID {request.ElementId} not found.");
|
|
|
|
request.Element = elements.FirstOrDefault();
|
|
}
|
|
|
|
// ensure document
|
|
var doc = request.Element!.Document;
|
|
|
|
if(doc is null || doc.ByteData is null || doc.ByteData.Length == 0)
|
|
throw new NotFoundException("Document data is missing or empty.");
|
|
|
|
// create signature image from element
|
|
var img = imgRenderer.ComposeSignaturePreviewPng(request.Element);
|
|
|
|
// sign pdf
|
|
var inputPdf = new MemoryStream(doc.ByteData);
|
|
var outputPdf = new MemoryStream();
|
|
|
|
await signService.SignPdfAsync(
|
|
inputPdf: inputPdf,
|
|
outputPdf: outputPdf,
|
|
options: new PdfSignOptionsDto
|
|
{
|
|
Appearance = new PdfSignatureAppearanceDto(
|
|
PageNumber: request.Element.Page,
|
|
Left: request.Element.Left,
|
|
Bottom: request.Element.Y,
|
|
Width: request.Element.Width,
|
|
Height: request.Element.Height)
|
|
},
|
|
image: img,
|
|
cancellationToken: cancellationToken);
|
|
|
|
return outputPdf;
|
|
}
|
|
} |