feat(api): add PdfSignatureController and wire signing DI
This commit is contained in:
72
DocumentService.API/Controllers/PdfSignatureController.cs
Normal file
72
DocumentService.API/Controllers/PdfSignatureController.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using DocumentOperator.Application.Common.Dto;
|
||||
using DocumentOperator.Application.SignPdf;
|
||||
using DocumentService.Domain.Common.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DocumentService.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller for PDF digital signing (PKCS#11 / company certificate).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/pdf/signature")]
|
||||
public class PdfSignatureController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Digitally signs a PDF using the configured PKCS#11 signing infrastructure.
|
||||
/// </summary>
|
||||
/// <param name="request">Base64-encoded PDF, optional signature image, and signing options</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
/// <returns>Signed PDF</returns>
|
||||
/// <response code="200">PDF signed successfully - returns signed PDF</response>
|
||||
/// <response code="400">Invalid input (Base64 format error, invalid appearance)</response>
|
||||
/// <response code="500">Internal server error during signing</response>
|
||||
[HttpPost("sign")]
|
||||
[Consumes("application/json")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)]
|
||||
public async Task<IActionResult> Sign([FromBody] SignPdfRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
byte[] signedPdf;
|
||||
try
|
||||
{
|
||||
signedPdf = await mediator.Send(new SignPdfCommand
|
||||
{
|
||||
InputPdf = new MemoryStream(Convert.FromBase64String(request.Base64Pdf)),
|
||||
Options = request.Options,
|
||||
SignatureImage = string.IsNullOrWhiteSpace(request.Base64SignatureImage)
|
||||
? null
|
||||
: new MemoryStream(Convert.FromBase64String(request.Base64SignatureImage))
|
||||
}, cancellationToken);
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
throw new BadRequestException("Invalid Base64 format: " + ex.Message);
|
||||
}
|
||||
|
||||
return File(signedPdf, "application/pdf", "signed.pdf");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request DTO for PDF signing via JSON payload.
|
||||
/// </summary>
|
||||
public sealed class SignPdfRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Base64-encoded PDF to sign.
|
||||
/// </summary>
|
||||
public required string Base64Pdf { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional Base64-encoded signature image (PNG/JPEG).
|
||||
/// </summary>
|
||||
public string? Base64SignatureImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Signing options (metadata + appearance).
|
||||
/// </summary>
|
||||
public required PdfSignOptionsDto Options { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user