Add sender endpoint for envelope-level PDF signing
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.PdfSigning;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record SignPdfByEnvelopeCommand : EnvelopeQueryBase, IRequest<Stream>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int? ReceiverId { get; init; } = null;
|
||||
|
||||
internal int? UserId { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public SignPdfByEnvelopeCommand Authorized(int userId)
|
||||
{
|
||||
UserId = userId;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class SignPdfByEnvelopeCommandHandler(IRepository<Envelope> Repo, ISender sender) : IRequestHandler<SignPdfByEnvelopeCommand, Stream>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<Stream> Handle(SignPdfByEnvelopeCommand request, CancellationToken cancel)
|
||||
{
|
||||
var envelopeQuery = Repo.Query;
|
||||
|
||||
if (request.Id is int id)
|
||||
envelopeQuery = envelopeQuery.Where(e => e.Id == id);
|
||||
else if (request.Uuid is string uuid)
|
||||
envelopeQuery = envelopeQuery.Where(e => e.Uuid == uuid);
|
||||
|
||||
var envelope = await envelopeQuery.Include(e => e.EnvelopeReceivers).Include(e => e.Documents).SingleOrDefaultAsync(cancel)
|
||||
?? throw new NotFoundException($"Envelope is not found ID: {request.Id} UUID: {request.Uuid}");
|
||||
|
||||
if (request.UserId is int userId && userId != envelope.UserId)
|
||||
throw new UnauthorizedAccessException($"Envelope is not authorized for user with Id: {request.UserId} Envelope ID: {request.Id} UUID: {request.Uuid}");
|
||||
|
||||
if (envelope.EnvelopeReceivers.Count == 0)
|
||||
throw new NotFoundException($"Envelope has no receivers to sign ID: {request.Id} UUID: {request.Uuid}");
|
||||
|
||||
if(envelope.Documents.FirstOrDefault() is not Document document || document.ByteData is not byte[] byteData || byteData.Length == 0)
|
||||
throw new NotFoundException($"Envelope has no documents to sign ID: {request.Id} UUID: {request.Uuid}");
|
||||
|
||||
Stream doc = new MemoryStream(byteData);
|
||||
|
||||
var eReceivers = request.ReceiverId is int receiverId
|
||||
? envelope.EnvelopeReceivers.Where(e => e.ReceiverId == receiverId)
|
||||
: envelope.EnvelopeReceivers;
|
||||
|
||||
foreach (var eReceiver in eReceivers)
|
||||
{
|
||||
var signedDoc = await sender.Send(new SignPdfByEnvelopeReceiverCommand()
|
||||
{
|
||||
EnvelopeId = eReceiver.EnvelopeId,
|
||||
ReceiverId = eReceiver.ReceiverId
|
||||
}, cancel);
|
||||
|
||||
await doc.DisposeAsync();
|
||||
doc = signedDoc;
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,23 @@ namespace EnvelopeGenerator.Server.Controllers;
|
||||
[Route("api/[controller]")]
|
||||
public class PdfSignatureController(IPdfDigitalSignatureService SignatureService, IMediator Mediator) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Authorize(AuthenticationSchemes = AuthScheme.Sender)]
|
||||
public async Task<IActionResult> SignDocument(SignPdfByEnvelopeCommand command, CancellationToken cancel)
|
||||
{
|
||||
var senderId = User.SenderId();
|
||||
var result = await Mediator.Send(command.Authorized(senderId), cancel);
|
||||
result.Position = 0;
|
||||
var fileName = Path.GetFileNameWithoutExtension($"e{command.Id.ToString() ?? command.Uuid}_s{senderId}");
|
||||
return File(result, "application/pdf", $"{fileName}_signed.pdf");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document for the specified envelope key.
|
||||
/// </summary>
|
||||
@@ -26,7 +43,7 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("{envelopeKey}")]
|
||||
public async Task<IActionResult> SignDocument(string envelopeKey, CancellationToken cancel)
|
||||
public async Task<IActionResult> SignDocumentByReceiver(string envelopeKey, CancellationToken cancel)
|
||||
{
|
||||
int envelopeId = User.EnvelopeId();
|
||||
int receiverId = User.ReceiverId();
|
||||
@@ -38,8 +55,8 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService
|
||||
}, cancel);
|
||||
|
||||
senderDoc.Position = 0;
|
||||
var fileName = Path.GetFileNameWithoutExtension(envelopeKey);
|
||||
return File(senderDoc, "application/pdf", $"{fileName}-signed.pdf");
|
||||
var fileName = Path.GetFileNameWithoutExtension($"e{envelopeId}_r{receiverId}");
|
||||
return File(senderDoc, "application/pdf", $"{fileName}_signed.pdf");
|
||||
}
|
||||
|
||||
#region Test Endpoints
|
||||
@@ -76,6 +93,7 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
[AllowAnonymous]
|
||||
[HttpPost("sign")]
|
||||
[Consumes("multipart/form-data")]
|
||||
@@ -100,6 +118,7 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
[AllowAnonymous]
|
||||
[HttpPost("is-signed")]
|
||||
[Consumes("multipart/form-data")]
|
||||
|
||||
Reference in New Issue
Block a user