feat: add captcha-backed forum security hardening

This commit is contained in:
2026-03-17 16:06:28 +01:00
parent 980a15f66e
commit b3fc889452
40 changed files with 2849 additions and 108 deletions

View File

@@ -0,0 +1,66 @@
<?php
namespace App\Http\Middleware;
use Closure;
use cPad\Plugins\Forum\Services\ForumSpamDetector;
use cPad\Plugins\Forum\Services\LinkAnalyzer;
use cPad\Plugins\Forum\Services\Security\ContentPatternAnalyzer;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class ForumSpamDetectionMiddleware
{
public function __construct(
private readonly ForumSpamDetector $spamDetector,
private readonly LinkAnalyzer $linkAnalyzer,
private readonly ContentPatternAnalyzer $contentPatternAnalyzer,
) {
}
public function handle(Request $request, Closure $next, string $action = 'generic'): Response
{
$title = trim((string) $request->input('title', ''));
$content = trim((string) $request->input('content', ''));
$combinedContent = trim($title !== '' ? $title . "\n" . $content : $content);
if ($combinedContent === '') {
$request->attributes->set('forum_spam_assessment', [
'action' => $action,
'spam_score' => 0,
'spam_reasons' => [],
'link_score' => 0,
'link_reasons' => [],
'links' => [],
'domains' => [],
'pattern_score' => 0,
'pattern_reasons' => [],
'matched_categories' => [],
]);
return $next($request);
}
$spam = $this->spamDetector->analyze($combinedContent);
$link = $this->linkAnalyzer->analyze($combinedContent);
$patterns = $this->contentPatternAnalyzer->analyze($combinedContent);
$request->attributes->set('forum_spam_assessment', [
'action' => $action,
'spam_score' => max((int) ($spam['score'] ?? 0), (int) ($patterns['score'] ?? 0)),
'spam_reasons' => array_values(array_unique(array_merge(
(array) ($spam['reasons'] ?? []),
(array) ($patterns['reasons'] ?? []),
))),
'link_score' => (int) ($link['score'] ?? 0),
'link_reasons' => (array) ($link['reasons'] ?? []),
'links' => (array) ($link['links'] ?? []),
'domains' => (array) ($link['domains'] ?? []),
'pattern_score' => (int) ($patterns['score'] ?? 0),
'pattern_reasons' => (array) ($patterns['reasons'] ?? []),
'matched_categories' => (array) ($patterns['matched_categories'] ?? []),
]);
return $next($request);
}
}