using DigitalData.Auth.Claims; using EnvelopeGenerator.API.Controllers.Interfaces; using EnvelopeGenerator.API.Extensions; using EnvelopeGenerator.Application.Documents.Queries; using EnvelopeGenerator.Domain.Constants; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Threading.Channels; namespace EnvelopeGenerator.API.Controllers; /// /// Provides access to envelope documents for authenticated receivers. /// /// /// Initializes a new instance of the class. /// [Authorize] [ApiController] [Route("api/[controller]")] public class DocumentController(IMediator mediator, IAuthorizationService authService, ILogger logger) : ControllerBase, IAuthController { /// /// /// public IAuthorizationService AuthService => authService; /// /// Returns the document bytes receiver. /// /// Encoded envelope key. /// Cancellation token. [HttpGet] [Authorize(Policy = AuthPolicy.SenderOrReceiver)] public async Task GetDocument(CancellationToken cancel, [FromQuery] ReadDocumentQuery? query = null) { // Sender: expects query with envelope key if (await this.IsUserInPolicyAsync(AuthPolicy.Sender)) { if (query is null) return BadRequest("Missing document query."); var senderDoc = await mediator.Send(query, cancel); return senderDoc.ByteData is byte[] senderDocByte ? File(senderDocByte, "application/octet-stream") : NotFound("Document is empty."); } // Receiver: resolve envelope id from claims if (await this.IsUserInPolicyAsync(AuthPolicy.Receiver)) { if (query is not null) return BadRequest("Query parameters are not allowed for receiver role."); var envelopeId = User.GetEnvelopeIdOfReceiver(); var receiverDoc = await mediator.Send(new ReadDocumentQuery { EnvelopeId = envelopeId }, cancel); return receiverDoc.ByteData is byte[] receiverDocByte ? File(receiverDocByte, "application/octet-stream") : NotFound("Document is empty."); } return Unauthorized(); } /// /// /// /// /// /// [HttpGet("{envelopeKey}")] [Authorize(Policy = AuthPolicy.Receiver)] public async Task GetDocumentOfReceiver(string envelopeKey, CancellationToken cancel) { var envelopeIdStr = User.FindFirst(EnvelopeClaimNames.EnvelopeId)?.Value; if (!int.TryParse(envelopeIdStr, out int envelopeId)) { logger.LogError( "Inner service error: Failed to parse Envelope ID from claims. Claim '{ClaimName}' had an invalid or missing value: '{ClaimValue}'.", EnvelopeClaimNames.EnvelopeId, envelopeIdStr ?? "null"); return StatusCode(StatusCodes.Status500InternalServerError, "Inner service error: Invalid envelope claim."); } var senderDoc = await mediator.Send(new ReadDocumentQuery() { EnvelopeId = envelopeId }, cancel); return senderDoc.ByteData is byte[] senderDocByte ? File(senderDocByte, "application/octet-stream") : NotFound("Document is empty."); } }