optimizations

This commit is contained in:
2026-03-28 19:15:39 +01:00
parent 0b25d9570a
commit cab4fbd83e
509 changed files with 1016804 additions and 1605 deletions

View File

@@ -21,6 +21,14 @@ class ForumBotProtectionMiddleware
public function handle(Request $request, Closure $next, string $action = 'generic'): Response|RedirectResponse|JsonResponse
{
if (! (bool) config('forum_bot_protection.enabled', true)) {
return $next($request);
}
if ($this->shouldBypassForLocalE2E($request)) {
return $next($request);
}
$assessment = $this->botProtectionService->assess($request, $action);
$request->attributes->set('forum_bot_assessment', $assessment);
@@ -93,4 +101,19 @@ class ForumBotProtectionMiddleware
return in_array($action, (array) config('forum_bot_protection.captcha.actions', []), true);
}
private function shouldBypassForLocalE2E(Request $request): bool
{
if (! app()->environment(['local', 'testing'])) {
return false;
}
if ($request->cookies->get('e2e_bot_bypass') === '1') {
return true;
}
$userAgent = strtolower((string) $request->userAgent());
return str_contains($userAgent, 'headlesschrome') || str_contains($userAgent, 'playwright');
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;
final class UpdateLastVisit
{
private const SESSION_KEY = 'last_visit.logged_at';
private const THROTTLE_SECONDS = 300;
private static ?bool $usersTableHasLastVisitAt = null;
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
$user = $request->user();
if (! $user) {
return $response;
}
if (! $this->usersTableHasLastVisitAt()) {
return $response;
}
$now = now();
$session = $request->hasSession() ? $request->session() : null;
$lastLoggedAt = $session?->get(self::SESSION_KEY);
if (is_numeric($lastLoggedAt) && ((int) $lastLoggedAt + self::THROTTLE_SECONDS) > $now->getTimestamp()) {
return $response;
}
$lastVisitAt = $user->last_visit_at;
if ($lastVisitAt !== null && method_exists($lastVisitAt, 'getTimestamp')) {
if (($lastVisitAt->getTimestamp() + self::THROTTLE_SECONDS) > $now->getTimestamp()) {
$session?->put(self::SESSION_KEY, $lastVisitAt->getTimestamp());
return $response;
}
}
DB::table('users')
->where('id', $user->id)
->update([
'last_visit_at' => $now,
'updated_at' => $now,
]);
$user->forceFill(['last_visit_at' => $now]);
$session?->put(self::SESSION_KEY, $now->getTimestamp());
return $response;
}
private function usersTableHasLastVisitAt(): bool
{
return self::$usersTableHasLastVisitAt ??= Schema::hasColumn('users', 'last_visit_at');
}
}