mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 12:33:56 +00:00
147 lines
4.0 KiB
PHP
147 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\{Log, Auth, Session};
|
|
use Tymon\JWTAuth\Facades\JWTAuth;
|
|
use App\Classes\Modules\Affiliate\Services\TracksAffiliateClick;
|
|
|
|
class TrackAffiliateClick
|
|
{
|
|
public function handle(Request $request, Closure $next)
|
|
{
|
|
$isAuthenticated = $this->checkWebAuth() || $this->checkJwtAuth($request);
|
|
|
|
if (!$isAuthenticated && $request->filled('tracking')) {
|
|
$trackingCode = $this->validateTrackingCode($request->get('tracking'));
|
|
if ($trackingCode) {
|
|
$this->trackClick($trackingCode);
|
|
}
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
/**
|
|
* Validate and sanitize tracking code
|
|
*
|
|
* @param mixed $code
|
|
* @return string|null
|
|
*/
|
|
private function validateTrackingCode($code): ?string
|
|
{
|
|
if (!is_string($code)) {
|
|
return null;
|
|
}
|
|
|
|
// Trim whitespace
|
|
$code = trim($code);
|
|
|
|
// Check length (max 255 chars based on database schema)
|
|
if (strlen($code) > 255 || strlen($code) < 1) {
|
|
return null;
|
|
}
|
|
|
|
// Only allow alphanumeric characters, hyphens, and underscores
|
|
// This matches typical affiliate code formats
|
|
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $code)) {
|
|
return null;
|
|
}
|
|
|
|
return $code;
|
|
}
|
|
|
|
/**
|
|
* Check if user is authenticated via WEB session
|
|
*/
|
|
private function checkWebAuth(): bool
|
|
{
|
|
try {
|
|
if (Auth::guard('web')->check()) {
|
|
return true;
|
|
}
|
|
|
|
// fallback session check
|
|
foreach (Session::all() as $key => $value) {
|
|
if (strpos($key, 'login_web_') === 0 && !empty($value)) {
|
|
return true;
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::warning('AffiliateClickMiddleware: Web auth error', ['error' => $e->getMessage()]);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if user is authenticated via JWT token
|
|
*/
|
|
private function checkJwtAuth(Request $request): bool
|
|
{
|
|
try {
|
|
$token =
|
|
$this->getBearerToken($request) ??
|
|
$request->get('token') ??
|
|
$request->cookie('access_token') ??
|
|
$request->cookie('user-token');
|
|
|
|
if (!$token) {
|
|
return false;
|
|
}
|
|
|
|
JWTAuth::setToken($token);
|
|
$user = JWTAuth::authenticate();
|
|
|
|
if ($user) {
|
|
return true;
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::debug('AffiliateClickMiddleware: JWT invalid', ['error' => $e->getMessage()]);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Extract Bearer token
|
|
*/
|
|
private function getBearerToken(Request $request): ?string
|
|
{
|
|
if (!$request->hasHeader('Authorization')) return null;
|
|
|
|
return preg_match('/Bearer\s+(.*)$/i', $request->header('Authorization'), $m)
|
|
? $m[1]
|
|
: null;
|
|
}
|
|
|
|
/**
|
|
* Track affiliate click once per session
|
|
*/
|
|
private function trackClick(string $trackingCode): void
|
|
{
|
|
// Use a single session key with an array to prevent session bloat
|
|
$trackedClicks = Session::get('affiliate_clicks_tracked', []);
|
|
|
|
// Check if this code has already been tracked in this session
|
|
if (in_array($trackingCode, $trackedClicks)) {
|
|
return; // Already tracked
|
|
}
|
|
|
|
// Execute tracking
|
|
app(TracksAffiliateClick::class)->execute($trackingCode);
|
|
|
|
// Add to tracked list
|
|
$trackedClicks[] = $trackingCode;
|
|
|
|
// Limit array size to prevent DoS (keep only last 10 clicks)
|
|
if (count($trackedClicks) > 10) {
|
|
$trackedClicks = array_slice($trackedClicks, -10);
|
|
}
|
|
|
|
Session::put('affiliate_clicks_tracked', $trackedClicks);
|
|
}
|
|
}
|