@@ -1,3 +1,4 @@
|
||||
using Api.Services.Contracts.Models;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Settings;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -17,14 +18,14 @@ namespace Api.Services
|
||||
_log = log;
|
||||
}
|
||||
|
||||
public async Task<CaptchaVerdict> VerifyAsync(string token, string? userIp, CancellationToken ct)
|
||||
public async Task<CaptchaVerdictModel> VerifyAsync(string token, string? userIp, CancellationToken ct)
|
||||
{
|
||||
_log.LogDebug("Verifying captcha token for IP {Ip}", userIp ?? "unknown");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_opt.SecretKey))
|
||||
{
|
||||
_log.LogWarning("Captcha verification attempted but SecretKey is not configured");
|
||||
return new CaptchaVerdict(false, "Captcha not configured", null);
|
||||
return new CaptchaVerdictModel(false, "Captcha not configured", null);
|
||||
}
|
||||
|
||||
var form = new Dictionary<string, string>
|
||||
@@ -45,21 +46,21 @@ namespace Api.Services
|
||||
{
|
||||
_log.LogWarning("Captcha HTTP request failed with status {StatusCode} for IP {Ip}",
|
||||
(int)resp.StatusCode, userIp ?? "unknown");
|
||||
return new CaptchaVerdict(false, $"Captcha HTTP {(int)resp.StatusCode}", null);
|
||||
return new CaptchaVerdictModel(false, $"Captcha HTTP {(int)resp.StatusCode}", null);
|
||||
}
|
||||
|
||||
var data = await resp.Content.ReadFromJsonAsync<RecaptchaResponse>(cancellationToken: ct);
|
||||
if (data is null)
|
||||
{
|
||||
_log.LogError("Failed to parse captcha response for IP {Ip}", userIp ?? "unknown");
|
||||
return new CaptchaVerdict(false, "Captcha parse error", null);
|
||||
return new CaptchaVerdictModel(false, "Captcha parse error", null);
|
||||
}
|
||||
|
||||
if (!data.success)
|
||||
{
|
||||
_log.LogWarning("Captcha verification failed for IP {Ip}. Score={Score}",
|
||||
userIp ?? "unknown", data.score);
|
||||
return new CaptchaVerdict(false, "Captcha failed", data.score);
|
||||
return new CaptchaVerdictModel(false, "Captcha failed", data.score);
|
||||
}
|
||||
|
||||
// v3 score check (score is typically null for v2)
|
||||
@@ -67,7 +68,7 @@ namespace Api.Services
|
||||
{
|
||||
_log.LogWarning("Captcha score {Score} below minimum {MinScore} for IP {Ip}",
|
||||
score, _opt.MinimumScore, userIp ?? "unknown");
|
||||
return new CaptchaVerdict(false, "Captcha score too low", score);
|
||||
return new CaptchaVerdictModel(false, "Captcha score too low", score);
|
||||
}
|
||||
|
||||
// Optional strictness (usually v3): action/hostname checks
|
||||
@@ -76,7 +77,7 @@ namespace Api.Services
|
||||
{
|
||||
_log.LogWarning("Captcha action mismatch. Expected={Expected}, Actual={Actual}, IP={Ip}",
|
||||
_opt.ExpectedAction, data.action, userIp ?? "unknown");
|
||||
return new CaptchaVerdict(false, "Captcha action mismatch", data.score);
|
||||
return new CaptchaVerdictModel(false, "Captcha action mismatch", data.score);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_opt.ExpectedHostname) &&
|
||||
@@ -84,12 +85,12 @@ namespace Api.Services
|
||||
{
|
||||
_log.LogWarning("Captcha hostname mismatch. Expected={Expected}, Actual={Actual}, IP={Ip}",
|
||||
_opt.ExpectedHostname, data.hostname, userIp ?? "unknown");
|
||||
return new CaptchaVerdict(false, "Captcha hostname mismatch", data.score);
|
||||
return new CaptchaVerdictModel(false, "Captcha hostname mismatch", data.score);
|
||||
}
|
||||
|
||||
_log.LogInformation("Captcha verified successfully for IP {Ip}. Score={Score}",
|
||||
userIp ?? "unknown", data.score);
|
||||
return new CaptchaVerdict(true, null, data.score);
|
||||
return new CaptchaVerdictModel(true, null, data.score);
|
||||
}
|
||||
|
||||
private sealed class RecaptchaResponse
|
||||
|
||||
Reference in New Issue
Block a user