Score artwork comments with local signatures plus Together AI, and optionally require Turnstile before posting.
66 lines
2.6 KiB
PHP
66 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use cPad\Plugins\Forum\Services\Security\BotProtectionService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class CommentCaptchaMiddleware
|
|
{
|
|
public function __construct(private readonly BotProtectionService $botProtection) {}
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
if (! (bool) config('comment_spam.captcha.enabled', false)) {
|
|
return $next($request);
|
|
}
|
|
|
|
$assessment = $this->botProtection->assess($request, 'comment_create');
|
|
if ((bool) ($assessment['blocked'] ?? false)) {
|
|
return response()->json(['message' => 'Suspicious activity detected.', 'errors' => ['bot' => ['Suspicious activity detected.']]], 429);
|
|
}
|
|
$threshold = (int) config('comment_spam.captcha.threshold', 40);
|
|
if ((int) ($assessment['risk_score'] ?? 0) < $threshold) {
|
|
return $next($request);
|
|
}
|
|
|
|
$token = (string) ($request->input('comment-turnstile-response') ?: $request->header('X-Turnstile-Token', ''));
|
|
$valid = false;
|
|
if ($token !== '') {
|
|
try {
|
|
$valid = (bool) Http::asForm()->timeout(5)->post(
|
|
(string) config('comment_spam.captcha.verify_url'),
|
|
['secret' => (string) config('comment_spam.captcha.secret_key'), 'response' => $token, 'remoteip' => $request->ip()],
|
|
)->json('success', false);
|
|
} catch (\Throwable) {
|
|
$valid = (bool) config('comment_spam.captcha.fail_open', false);
|
|
}
|
|
}
|
|
|
|
if ($valid) {
|
|
return $next($request);
|
|
}
|
|
|
|
$payload = [
|
|
'message' => 'Complete the captcha challenge to continue.',
|
|
'errors' => ['captcha' => ['Complete the captcha challenge to continue.']],
|
|
'requires_captcha' => true,
|
|
'captcha' => [
|
|
'provider' => 'turnstile',
|
|
'siteKey' => (string) config('comment_spam.captcha.site_key'),
|
|
'inputName' => 'comment-turnstile-response',
|
|
'scriptUrl' => (string) config('comment_spam.captcha.script_url'),
|
|
],
|
|
'captcha_provider' => 'turnstile',
|
|
'captcha_site_key' => (string) config('comment_spam.captcha.site_key'),
|
|
'captcha_input' => 'comment-turnstile-response',
|
|
'captcha_script_url' => (string) config('comment_spam.captcha.script_url'),
|
|
];
|
|
|
|
return response()->json($payload, 422);
|
|
}
|
|
}
|