diff --git a/EnvelopeGenerator.GeneratorAPI/Controllers/AnnotationController.cs b/EnvelopeGenerator.GeneratorAPI/Controllers/AnnotationController.cs new file mode 100644 index 00000000..34c255fc --- /dev/null +++ b/EnvelopeGenerator.GeneratorAPI/Controllers/AnnotationController.cs @@ -0,0 +1,130 @@ +using DigitalData.Core.Abstraction.Application.DTO; +using DigitalData.Core.Exceptions; +using EnvelopeGenerator.Application.Common.Extensions; +using EnvelopeGenerator.Application.Common.Interfaces.Services; +using EnvelopeGenerator.Application.Common.Notifications.DocSigned; +using EnvelopeGenerator.Application.EnvelopeReceivers.Queries; +using EnvelopeGenerator.Application.Histories.Queries; +using EnvelopeGenerator.Domain.Constants; +using EnvelopeGenerator.GeneratorAPI.Extensions; +using MediatR; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace EnvelopeGenerator.GeneratorAPI.Controllers; + +/// +/// Manages annotations and signature lifecycle for envelopes. +/// +[Authorize(Roles = ReceiverRole.FullyAuth)] +[ApiController] +[Route("api/[controller]")] +public class AnnotationController : ControllerBase +{ + [Obsolete("Use MediatR")] + private readonly IEnvelopeHistoryService _historyService; + + [Obsolete("Use MediatR")] + private readonly IEnvelopeReceiverService _envelopeReceiverService; + + private readonly IMediator _mediator; + + private readonly ILogger _logger; + + /// + /// Initializes a new instance of . + /// + [Obsolete("Use MediatR")] + public AnnotationController( + ILogger logger, + IEnvelopeHistoryService envelopeHistoryService, + IEnvelopeReceiverService envelopeReceiverService, + IMediator mediator) + { + _historyService = envelopeHistoryService; + _envelopeReceiverService = envelopeReceiverService; + _mediator = mediator; + _logger = logger; + } + + /// + /// Creates or updates annotations for the authenticated envelope receiver. + /// + /// Annotation payload. + /// Cancellation token. + [Authorize(Roles = ReceiverRole.FullyAuth)] + [HttpPost] + [Obsolete("This endpoint is for PSPDF Kit.")] + public async Task CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default) + { + var signature = User.GetAuthReceiverSignature(); + var uuid = User.GetAuthEnvelopeUuid(); + + if (signature is null || uuid is null) + { + _logger.LogError("Authorization failed: authenticated user does not have a valid signature or envelope UUID."); + return Unauthorized("User authentication is incomplete. Missing required claims for processing this request."); + } + + var envelopeReceiver = await _mediator.ReadEnvelopeReceiverAsync(uuid, signature, cancel).ThrowIfNull(Exceptions.NotFound); + + if (!envelopeReceiver.Envelope!.ReadOnly && psPdfKitAnnotation is null) + return BadRequest(); + + if (await _mediator.IsSignedAsync(uuid, signature, cancel)) + return Problem(statusCode: StatusCodes.Status409Conflict); + else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel)) + return Problem(statusCode: StatusCodes.Status423Locked); + + var docSignedNotification = await _mediator + .ReadEnvelopeReceiverAsync(uuid, signature, cancel) + .ToDocSignedNotification(psPdfKitAnnotation) + ?? throw new NotFoundException("Envelope receiver is not found."); + + await _mediator.PublishSafely(docSignedNotification, cancel); + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + + return Ok(); + } + + /// + /// Rejects the document for the current receiver. + /// + /// Optional rejection reason. + [Authorize(Roles = ReceiverRole.FullyAuth)] + [HttpPost("reject")] + [Obsolete("Use MediatR")] + public async Task Reject([FromBody] string? reason = null) + { + var signature = User.GetAuthReceiverSignature(); + var uuid = User.GetAuthEnvelopeUuid(); + var mail = User.GetAuthReceiverMail(); + if (uuid is null || signature is null || mail is null) + { + _logger.LogEnvelopeError(uuid: uuid, signature: signature, + message: @$"Unauthorized POST request in api\\envelope\\reject. One of claims, Envelope, signature or mail ({mail}) is null."); + return Unauthorized(); + } + + var envRcvRes = await _envelopeReceiverService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature); + + if (envRcvRes.IsFailed) + { + _logger.LogNotice(envRcvRes.Notices); + return Unauthorized("you are not authorized"); + } + + var histRes = await _historyService.RecordAsync(envRcvRes.Data.EnvelopeId, userReference: mail, EnvelopeStatus.DocumentRejected, comment: reason); + if (histRes.IsSuccess) + { + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + return NoContent(); + } + + _logger.LogEnvelopeError(uuid: uuid, signature: signature, message: "Unexpected error happened in api/envelope/reject"); + _logger.LogNotice(histRes.Notices); + return StatusCode(500, histRes.Messages); + } +}