diff --git a/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs b/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs new file mode 100644 index 00000000..e94298c3 --- /dev/null +++ b/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs @@ -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; +/// +/// +/// +public record SignPdfByEnvelopeCommand : EnvelopeQueryBase, IRequest +{ + /// + /// + /// + public int? ReceiverId { get; init; } = null; + + internal int? UserId { get; private set; } = null; + + /// + /// + /// + /// + /// + public SignPdfByEnvelopeCommand Authorized(int userId) + { + UserId = userId; + return this; + } +} + +/// +/// +/// +public class SignPdfByEnvelopeCommandHandler(IRepository Repo, ISender sender) : IRequestHandler +{ + /// + /// + /// + /// + /// + /// + /// + public async Task 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; + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Controllers/PdfSignatureController.cs b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Controllers/PdfSignatureController.cs index bd046d93..0900bfca 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Controllers/PdfSignatureController.cs +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Controllers/PdfSignatureController.cs @@ -18,6 +18,23 @@ namespace EnvelopeGenerator.Server.Controllers; [Route("api/[controller]")] public class PdfSignatureController(IPdfDigitalSignatureService SignatureService, IMediator Mediator) : ControllerBase { + /// + /// + /// + /// + /// + /// + [HttpPost] + [Authorize(AuthenticationSchemes = AuthScheme.Sender)] + public async Task 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"); + } + /// /// Gets the document for the specified envelope key. /// @@ -26,7 +43,7 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService /// [Authorize(Policy = AuthPolicy.Receiver)] [HttpPost("{envelopeKey}")] - public async Task SignDocument(string envelopeKey, CancellationToken cancel) + public async Task 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 /// /// /// + [NonAction] [AllowAnonymous] [HttpPost("sign")] [Consumes("multipart/form-data")] @@ -100,6 +118,7 @@ public class PdfSignatureController(IPdfDigitalSignatureService SignatureService /// /// /// + [NonAction] [AllowAnonymous] [HttpPost("is-signed")] [Consumes("multipart/form-data")]