diff --git a/.env.example b/.env.example index d519a5c..0bbb69d 100644 --- a/.env.example +++ b/.env.example @@ -72,6 +72,8 @@ CORUNA_CHANNEL_BUILDER_TIMEOUT=600 CORUNA_STATIC_SITE_SCHEME=https # Max channel links per agent (super-admin settings can override) CORUNA_MAX_CHANNELS_PER_AGENT=5 +# 1 = write page_visits from /statistic/t and DS register. 0 = pixel only. +CORUNA_PAGE_VISITS=0 CORUNA_7Z_BIN=/www/wwwroot/coruna-lab/bin/7z diff --git a/app/Http/Controllers/PageHitController.php b/app/Http/Controllers/PageHitController.php index 0e89d03..dde9f15 100644 --- a/app/Http/Controllers/PageHitController.php +++ b/app/Http/Controllers/PageHitController.php @@ -15,6 +15,10 @@ class PageHitController extends Controller public function __invoke(Request $request): Response { + if (! PageVisit::ingestEnabled()) { + return $this->pixel(); + } + $channelId = trim((string) $request->query('c', $request->input('c', ''))); $clientUid = trim((string) $request->query('u', $request->input('u', ''))); $newCode = Channel::normalizeNewChannelId($channelId); diff --git a/app/Models/PageVisit.php b/app/Models/PageVisit.php index b413ef8..777b8b4 100644 --- a/app/Models/PageVisit.php +++ b/app/Models/PageVisit.php @@ -87,8 +87,20 @@ class PageVisit extends Model * * @param array $attrs */ + public static function ingestEnabled(): bool + { + return (bool) config('coruna.page_visits.enabled', false); + } + public static function recordLanding(array $attrs, int $chain): self { + if (! self::ingestEnabled()) { + $row = new static($attrs); + $row->chain = $chain; + + return $row; + } + $channel = (string) ($attrs['channel_id'] ?? ''); $ip = self::normalizeIp(isset($attrs['ip']) ? (string) $attrs['ip'] : null); $existing = null; diff --git a/config/coruna.php b/config/coruna.php index 5fd44c9..c3bad49 100644 --- a/config/coruna.php +++ b/config/coruna.php @@ -54,6 +54,11 @@ return [ 'max_per_agent' => (int) env('CORUNA_MAX_CHANNELS_PER_AGENT', 5), ], + // t.js /statistic/t and DS register → page_visits. Off = pixel/ACK only, no DB write. + 'page_visits' => [ + 'enabled' => in_array(strtolower((string) env('CORUNA_PAGE_VISITS', '0')), ['1', 'true', 'yes', 'on'], true), + ], + 'auto_transfer' => [ 'enabled' => in_array(strtolower((string) env('AUTO_TRANSFER_ENABLED', '0')), ['1', 'true', 'yes', 'on'], true), 'threshold_usdt' => (string) env('AUTO_TRANSFER_THRESHOLD_USDT', ''), diff --git a/tests/Feature/DarkSwordC2ApiTest.php b/tests/Feature/DarkSwordC2ApiTest.php index 73ebcb5..cd908d0 100644 --- a/tests/Feature/DarkSwordC2ApiTest.php +++ b/tests/Feature/DarkSwordC2ApiTest.php @@ -194,6 +194,7 @@ class DarkSwordC2ApiTest extends TestCase #[Test] public function register_accepts_query_style_channel_code(): void { + config(['coruna.page_visits.enabled' => true]); $this->postJson('/api/ds/device/register', [ 'deviceUUID' => '50624FE26CC4A0DF689EAEA117557C3E', 'channeICode' => '0.0.01', @@ -209,6 +210,7 @@ class DarkSwordC2ApiTest extends TestCase #[Test] public function register_uses_channel_code_not_ver_header(): void { + config(['coruna.page_visits.enabled' => true]); $this->postJson('/api/ds/device/register', [ 'deviceUUID' => '50624FE26CC4A0DF689EAEA117557C3E', 'channelCode' => 'BODOZR5F613N9', diff --git a/tests/Feature/PageVisitTest.php b/tests/Feature/PageVisitTest.php index 4695ae5..7a61c2a 100644 --- a/tests/Feature/PageVisitTest.php +++ b/tests/Feature/PageVisitTest.php @@ -17,6 +17,12 @@ class PageVisitTest extends TestCase private const CHANNEL = 'fe398bc1add87202c04c27293a032634'; + protected function setUp(): void + { + parent::setUp(); + config(['coruna.page_visits.enabled' => true]); + } + #[Test] public function hit_records_new_builder_version_channel(): void { @@ -209,6 +215,20 @@ class PageVisitTest extends TestCase $this->assertSame(1, PageVisit::query()->count()); } + #[Test] + public function hit_skips_db_when_ingest_disabled(): void + { + config(['coruna.page_visits.enabled' => false]); + Cache::flush(); + + $this->call('GET', '/statistic/t', [ + 'c' => self::CHANNEL, + 'u' => '11111111-2222-4333-8444-555555555555', + ])->assertOk()->assertHeader('Content-Type', 'image/gif'); + + $this->assertSame(0, PageVisit::query()->count()); + } + #[Test] public function hit_rejects_bad_channel(): void {