230 lines
8.1 KiB
PHP
230 lines
8.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Admin;
|
|
use App\Models\Channel;
|
|
use App\Models\Device;
|
|
use App\Models\User;
|
|
use App\Models\WalletAddress;
|
|
use App\Services\ChannelProjectService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Mockery;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Tests\TestCase;
|
|
|
|
class AdminAgentPortalTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
#[Test]
|
|
public function users_and_channels_tables_exist_via_models(): void
|
|
{
|
|
$user = User::query()->create([
|
|
'username' => 'agent1',
|
|
'password' => 'secret12',
|
|
'status' => 1,
|
|
'comment' => 'test',
|
|
]);
|
|
$channel = Channel::query()->create([
|
|
'channel_id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
'user_id' => $user->id,
|
|
'status' => 1,
|
|
'remark' => 'demo',
|
|
]);
|
|
|
|
config([
|
|
'coruna.channel_domains' => ['cdn.example.com'],
|
|
'coruna.deployment_domains' => ['cdn.example.com'],
|
|
]);
|
|
|
|
$this->assertDatabaseHas('users', ['username' => 'agent1']);
|
|
$this->assertDatabaseHas('channels', ['channel_id' => $channel->channel_id, 'user_id' => $user->id]);
|
|
$this->assertSame(
|
|
['https://cdn.example.com/web/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/support.html'],
|
|
$channel->supportLinks()
|
|
);
|
|
}
|
|
|
|
#[Test]
|
|
public function disabled_agent_cannot_login(): void
|
|
{
|
|
User::query()->create([
|
|
'username' => 'disabled',
|
|
'password' => 'secret12',
|
|
'status' => 0,
|
|
]);
|
|
|
|
$this->post('/user/login', [
|
|
'username' => 'disabled',
|
|
'password' => 'secret12',
|
|
])->assertSessionHasErrors('username');
|
|
|
|
$this->assertGuest('agent');
|
|
}
|
|
|
|
#[Test]
|
|
public function enabled_agent_can_login(): void
|
|
{
|
|
User::query()->create([
|
|
'username' => 'okagent',
|
|
'password' => 'secret12',
|
|
'status' => 1,
|
|
]);
|
|
|
|
$this->post('/user/login', [
|
|
'username' => 'okagent',
|
|
'password' => 'secret12',
|
|
])->assertRedirect(route('user.home'));
|
|
|
|
$this->assertAuthenticated('agent');
|
|
}
|
|
|
|
#[Test]
|
|
public function admin_can_create_channel_with_random_id_and_links_fallback_domains(): void
|
|
{
|
|
config([
|
|
'coruna.channel_domains' => ['fallback.test'],
|
|
'coruna.deployment_domains' => ['fallback.test'],
|
|
]);
|
|
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
|
|
|
|
$projects = Mockery::mock(ChannelProjectService::class);
|
|
$projects->shouldReceive('generate')->once()->andReturn([
|
|
'channel_id' => 'placeholder',
|
|
'seeds' => [
|
|
'deployment_seed' => '11111111111111111111111111111111',
|
|
'reporting_seed' => '11111111111111111111111111111111',
|
|
],
|
|
'domains' => ['deployment' => [], 'reporting' => []],
|
|
'seeds_initialized' => false,
|
|
'sync_rebuilt' => false,
|
|
'support_path' => '/web/x/support.html',
|
|
'daily_path' => '/sync/daily.html',
|
|
]);
|
|
$this->app->instance(ChannelProjectService::class, $projects);
|
|
|
|
$random = $this->actingAs($admin, 'admin')
|
|
->get(route('admin.channels.randomId'))
|
|
->assertOk()
|
|
->assertJsonPath('code', 0)
|
|
->json('data.channel_id');
|
|
$this->assertIsString($random);
|
|
$this->assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $random);
|
|
|
|
$channelId = Channel::randomChannelId();
|
|
$this->assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $channelId);
|
|
|
|
$this->actingAs($admin, 'admin')
|
|
->post(route('admin.channels.store'), [
|
|
'channel_id' => $channelId,
|
|
'user_id' => 0,
|
|
'remark' => 'official',
|
|
'status' => 1,
|
|
])
|
|
->assertOk()
|
|
->assertJsonPath('code', 0)
|
|
->assertJsonPath('data.links.0', 'https://fallback.test/web/'.$channelId.'/support.html');
|
|
|
|
$this->assertDatabaseHas('channels', [
|
|
'channel_id' => $channelId,
|
|
'user_id' => 0,
|
|
'remark' => 'official',
|
|
]);
|
|
}
|
|
|
|
#[Test]
|
|
public function agent_only_sees_own_channel_devices_and_addresses(): void
|
|
{
|
|
$agentA = User::query()->create(['username' => 'a', 'password' => 'secret12', 'status' => 1]);
|
|
$agentB = User::query()->create(['username' => 'b', 'password' => 'secret12', 'status' => 1]);
|
|
$chA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
|
|
$chB = 'cccccccccccccccccccccccccccccccc';
|
|
Channel::query()->create(['channel_id' => $chA, 'user_id' => $agentA->id, 'status' => 1]);
|
|
Channel::query()->create(['channel_id' => $chB, 'user_id' => $agentB->id, 'status' => 1]);
|
|
|
|
$devA = Device::query()->create([
|
|
'device_id' => 'dev-a',
|
|
'channel_id' => $chA,
|
|
'device_model' => 'iPhone',
|
|
]);
|
|
$devB = Device::query()->create([
|
|
'device_id' => 'dev-b',
|
|
'channel_id' => $chB,
|
|
'device_model' => 'iPhone',
|
|
]);
|
|
WalletAddress::query()->create([
|
|
'device_id' => $devA->id,
|
|
'address' => 'addr-a',
|
|
'source' => 'imToken',
|
|
'chain_type' => 'ETH',
|
|
]);
|
|
WalletAddress::query()->create([
|
|
'device_id' => $devB->id,
|
|
'address' => 'addr-b',
|
|
'source' => 'imToken',
|
|
'chain_type' => 'ETH',
|
|
]);
|
|
|
|
$this->actingAs($agentA, 'agent')
|
|
->getJson(route('user.devices.data'))
|
|
->assertOk()
|
|
->assertJsonPath('count', 1)
|
|
->assertJsonPath('data.0.device_id', 'dev-a');
|
|
|
|
$this->actingAs($agentA, 'agent')
|
|
->getJson(route('user.addresses.data'))
|
|
->assertOk()
|
|
->assertJsonPath('count', 1)
|
|
->assertJsonPath('data.0.address', 'addr-a');
|
|
|
|
$this->actingAs($agentA, 'agent')
|
|
->get(route('user.devices.show', $devB))
|
|
->assertForbidden();
|
|
}
|
|
|
|
#[Test]
|
|
public function admin_agent_filter_scopes_devices(): void
|
|
{
|
|
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
|
|
$agent = User::query()->create(['username' => 'filter-me', 'password' => 'secret12', 'status' => 1]);
|
|
$ch = 'dddddddddddddddddddddddddddddddd';
|
|
Channel::query()->create(['channel_id' => $ch, 'user_id' => $agent->id, 'status' => 1]);
|
|
Device::query()->create(['device_id' => 'mine', 'channel_id' => $ch]);
|
|
Device::query()->create(['device_id' => 'other', 'channel_id' => 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee']);
|
|
|
|
$this->actingAs($admin, 'admin')
|
|
->getJson(route('admin.devices.data', ['agent_user_id' => $agent->id]))
|
|
->assertOk()
|
|
->assertJsonPath('count', 1)
|
|
->assertJsonPath('data.0.device_id', 'mine');
|
|
}
|
|
|
|
#[Test]
|
|
public function dashboard_counts_smoke(): void
|
|
{
|
|
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
|
|
Device::query()->create(['device_id' => 'd1', 'channel_id' => 'ffffffffffffffffffffffffffffffff']);
|
|
Device::query()->create(['device_id' => 'd2', 'channel_id' => 'ffffffffffffffffffffffffffffffff']);
|
|
|
|
$this->actingAs($admin, 'admin')
|
|
->getJson(route('admin.dashboard.data', ['range' => '30d']))
|
|
->assertOk()
|
|
->assertJsonPath('code', 0)
|
|
->assertJsonPath('data.total', 2)
|
|
->assertJsonStructure(['data' => ['total', 'new_count', 'active_count', 'pv', 'uv', 'effective_pv', 'effective_uv', 'by_os', 'by_ios_version', 'from', 'to']]);
|
|
}
|
|
|
|
#[Test]
|
|
public function agent_cannot_create_channel(): void
|
|
{
|
|
$agent = User::query()->create(['username' => 'a', 'password' => 'secret12', 'status' => 1]);
|
|
$this->actingAs($agent, 'agent')
|
|
->post('/user/channels', [
|
|
'channel_id' => 'gggggggggggggggggggggggggggggggg',
|
|
'status' => 1,
|
|
])
|
|
->assertStatus(405);
|
|
}
|
|
}
|