using DigitalData.Core.DTO; using EnvelopeGenerator.Application.Contracts.Services; using EnvelopeGenerator.Application.Envelopes.Commands; using EnvelopeGenerator.Application.Envelopes.Queries.Read; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; namespace EnvelopeGenerator.GeneratorAPI.Controllers; /// /// Dieser Controller stellt Endpunkte für die Verwaltung von Umschlägen bereit. /// /// /// Die API ermöglicht das Abrufen und Verwalten von Umschlägen basierend auf Benutzerinformationen und Statusfiltern. /// /// Mögliche Antworten: /// - 200 OK: Die Anfrage war erfolgreich, und die angeforderten Daten werden zurückgegeben. /// - 400 Bad Request: Die Anfrage war fehlerhaft oder unvollständig. /// - 401 Unauthorized: Der Benutzer ist nicht authentifiziert. /// - 403 Forbidden: Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen. /// - 404 Not Found: Die angeforderte Ressource wurde nicht gefunden. /// - 500 Internal Server Error: Ein unerwarteter Fehler ist aufgetreten. /// [Route("api/[controller]")] [ApiController] [Authorize] public class EnvelopeController : ControllerBase { private readonly ILogger _logger; private readonly IEnvelopeService _envelopeService; private readonly IMediator _mediator; /// /// Erstellt eine neue Instanz des EnvelopeControllers. /// /// Der Logger, der für das Protokollieren von Informationen verwendet wird. /// Der Dienst, der für die Verarbeitung von Umschlägen zuständig ist. /// public EnvelopeController(ILogger logger, IEnvelopeService envelopeService, IMediator mediator) { _logger = logger; _envelopeService = envelopeService; _mediator = mediator; } /// /// Ruft eine Liste von Umschlägen basierend auf dem Benutzer und den angegebenen Statusfiltern ab. /// /// /// Eine IActionResult-Instanz, die die abgerufenen Umschläge oder einen Fehlerstatus enthält. /// Die Anfrage war erfolgreich, und die Umschläge werden zurückgegeben. /// Die Anfrage war fehlerhaft oder unvollständig. /// Der Benutzer ist nicht authentifiziert. /// Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen. /// Ein unerwarteter Fehler ist aufgetreten. [Authorize] [HttpGet] public async Task GetAsync([FromQuery] ReadEnvelopeQuery envelope) { if (User.GetId() is int intId) return await _envelopeService.ReadByUserAsync(intId, min_status: envelope.Status, max_status: envelope.Status).ThenAsync( Success: envelopes => { if (envelope.Id is int id) envelopes = envelopes.Where(e => e.Id == id); if (envelope.Status is int status) envelopes = envelopes.Where(e => e.Status == status); if (envelope.Uuid is string uuid) envelopes = envelopes.Where(e => e.Uuid == uuid); return Ok(envelopes); }, Fail: IActionResult (msg, ntc) => { _logger.LogNotice(ntc); return StatusCode(StatusCodes.Status500InternalServerError); }); else { _logger.LogError("Trotz erfolgreicher Autorisierung wurde die Benutzer-ID nicht als Ganzzahl erkannt. Dies könnte auf eine fehlerhafte Erstellung der Anspruchsliste zurückzuführen sein."); return StatusCode(StatusCodes.Status500InternalServerError); } } /// /// Ruft das Ergebnis eines Dokuments basierend auf der ID ab. /// /// Die eindeutige ID des Umschlags. /// Gibt an, ob das Dokument inline angezeigt werden soll (true) oder als Download bereitgestellt wird (false). /// Eine IActionResult-Instanz, die das Dokument oder einen Fehlerstatus enthält. /// Das Dokument wurde erfolgreich abgerufen. /// Das Dokument wurde nicht gefunden oder ist nicht verfügbar. /// Ein unerwarteter Fehler ist aufgetreten. [HttpGet("doc-result")] public async Task GetDocResultAsync([FromQuery] int id, [FromQuery] bool view = false) { if (User.GetId() is int intId) return await _envelopeService.ReadByUserAsync(intId).ThenAsync( Success: envelopes => { var envelope = envelopes.Where(e => e.Id == id).FirstOrDefault(); if (envelope is null) return NotFound("Envelope not available."); else if (envelope?.DocResult is null) return NotFound("The document has not been fully signed or the result has not yet been released."); else { if (view) { Response.Headers.Append("Content-Disposition", "inline; filename=\"" + envelope.Uuid + ".pdf\""); return File(envelope.DocResult, "application/pdf"); } else return File(envelope.DocResult, "application/pdf", $"{envelope.Uuid}.pdf"); } }, Fail: IActionResult (msg, ntc) => { _logger.LogNotice(ntc); return StatusCode(StatusCodes.Status500InternalServerError); }); else { _logger.LogError("Trotz erfolgreicher Autorisierung wurde die Benutzer-ID nicht als Ganzzahl erkannt. Dies könnte auf eine fehlerhafte Erstellung der Anspruchsliste zurückzuführen sein."); return StatusCode(StatusCodes.Status500InternalServerError); } } /// /// /// /// /// [NonAction] [Authorize] [HttpPost] public async Task CreateAsync([FromQuery] CreateEnvelopeCommand envelope) { envelope.UserId = User.GetId(); var res = await _mediator.Send(envelope); if (res is null) { _logger.LogError("Failed to create envelope. Envelope details: {EnvelopeDetails}", JsonConvert.SerializeObject(envelope)); return StatusCode(StatusCodes.Status500InternalServerError); } else return Ok(res); } }