This commit is contained in:
2026-05-06 15:17:20 +03:00
parent 711810d8c2
commit a10908364b
9 changed files with 50 additions and 31 deletions
+21 -2
View File
@@ -1,5 +1,6 @@
using Api.Clients.Api.Contracts;
using Api.Models.Requests;
using Api.Services.Contracts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Swashbuckle.AspNetCore.Annotations;
@@ -16,23 +17,25 @@ public sealed class CvMatcherController : ControllerBase
{
private readonly ICvMatcherApi _cvApi;
private readonly IConfiguration _configuration;
private readonly ICaptchaVerifier _captcha;
private readonly ILogger<CvMatcherController> _logger;
public CvMatcherController(
ICvMatcherApi cvApi,
IConfiguration configuration,
ICaptchaVerifier captcha,
ILogger<CvMatcherController> logger)
{
_cvApi = cvApi;
_configuration = configuration;
_captcha = captcha;
_logger = logger;
}
/// <summary>
/// Upload a CV PDF to the cv-matcher-api.
/// </summary>
/// <param name="cv">The uploaded CV PDF file.</param>
/// <param name="gdprConsent">Whether the user consented to GDPR processing.</param>
/// <param name="request">The uploaded CV request.</param>
/// <param name="ct">Cancellation token.</param>
[HttpPost("upload")]
[Consumes("multipart/form-data")]
@@ -61,6 +64,14 @@ public sealed class CvMatcherController : ControllerBase
_logger.LogInformation("Proxying CV upload to cv-matcher-api. FileName={FileName}, Size={SizeBytes}, GdprConsent={GdprConsent}",
cv.FileName, cv.Length, gdprConsent);
var userIp = HttpContext.Connection.RemoteIpAddress?.ToString();
var verdict = await _captcha.VerifyAsync(request.CaptchaToken ?? string.Empty, userIp, ct);
if (!verdict.Success)
{
_logger.LogWarning("Captcha verification failed for CV upload. IP={IP}", userIp);
return BadRequest(new { error = "Captcha verification failed." });
}
var stream = cv.OpenReadStream();
var part = new Refit.StreamPart(stream, cv.FileName, "application/pdf");
using var response = await _cvApi.Upload(part, gdprConsent);
@@ -100,6 +111,14 @@ public sealed class CvMatcherController : ControllerBase
!string.IsNullOrWhiteSpace(request.JobUrl),
!string.IsNullOrWhiteSpace(request.JobDescription));
var userIp = HttpContext.Connection.RemoteIpAddress?.ToString();
var verdict = await _captcha.VerifyAsync(request.CaptchaToken ?? string.Empty, userIp, ct);
if (!verdict.Success)
{
_logger.LogWarning("Captcha verification failed for job match. IP={IP}", userIp);
return BadRequest(new { error = "Captcha verification failed." });
}
using var response = await _cvApi.MatchJob(request);
return await ProxyResponseAsync(response, ct);
}