Path: blob/1.0-develop/tests/Integration/Api/Client/ClientControllerTest.php
7459 views
<?php12namespace Pterodactyl\Tests\Integration\Api\Client;34use Pterodactyl\Models\User;5use Pterodactyl\Models\Server;6use Pterodactyl\Models\Subuser;7use Pterodactyl\Models\Allocation;8use Pterodactyl\Models\Permission;910class ClientControllerTest extends ClientApiIntegrationTestCase11{12/**13* Test that only the servers a logged-in user is assigned to are returned by the14* API endpoint. Obviously there are cases such as being an administrator or being15* a subuser, but for this test we just want to test a basic scenario and pretend16* subusers do not exist at all.17*/18public function testOnlyLoggedInUsersServersAreReturned()19{20/** @var \Pterodactyl\Models\User[] $users */21$users = User::factory()->times(3)->create();2223/** @var \Pterodactyl\Models\Server[] $servers */24$servers = [25$this->createServerModel(['user_id' => $users[0]->id]),26$this->createServerModel(['user_id' => $users[1]->id]),27$this->createServerModel(['user_id' => $users[2]->id]),28];2930$response = $this->actingAs($users[0])->getJson('/api/client');3132$response->assertOk();33$response->assertJsonPath('object', 'list');34$response->assertJsonPath('data.0.object', Server::RESOURCE_NAME);35$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);36$response->assertJsonPath('data.0.attributes.server_owner', true);37$response->assertJsonPath('meta.pagination.total', 1);38$response->assertJsonPath('meta.pagination.per_page', 50);39}4041/**42* Test that using ?filter[*]=name|uuid returns any server matching that name or UUID43* with the search filters.44*/45public function testServersAreFilteredUsingNameAndUuidInformation()46{47/** @var \Pterodactyl\Models\User[] $users */48$users = User::factory()->times(2)->create();49$users[0]->update(['root_admin' => true]);5051/** @var \Pterodactyl\Models\Server[] $servers */52$servers = [53$this->createServerModel(['user_id' => $users[0]->id, 'name' => 'Julia']),54$this->createServerModel(['user_id' => $users[1]->id, 'uuidShort' => '12121212', 'name' => 'Janice']),55$this->createServerModel(['user_id' => $users[1]->id, 'uuid' => '88788878-12356789', 'external_id' => 'ext123', 'name' => 'Julia']),56$this->createServerModel(['user_id' => $users[1]->id, 'uuid' => '88788878-abcdefgh', 'name' => 'Jennifer']),57];5859$this->actingAs($users[1])->getJson('/api/client?filter[*]=Julia')60->assertOk()61->assertJsonCount(1, 'data')62->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);6364$this->actingAs($users[1])->getJson('/api/client?filter[*]=ext123')65->assertOk()66->assertJsonCount(1, 'data')67->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);6869$this->actingAs($users[1])->getJson('/api/client?filter[*]=ext123')70->assertOk()71->assertJsonCount(1, 'data')72->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);7374$this->actingAs($users[1])->getJson('/api/client?filter[*]=12121212')75->assertOk()76->assertJsonCount(1, 'data')77->assertJsonPath('data.0.attributes.identifier', $servers[1]->uuidShort);7879$this->actingAs($users[1])->getJson('/api/client?filter[*]=88788878')80->assertOk()81->assertJsonCount(2, 'data')82->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort)83->assertJsonPath('data.1.attributes.identifier', $servers[3]->uuidShort);8485$this->actingAs($users[1])->getJson('/api/client?filter[*]=88788878-abcd')86->assertOk()87->assertJsonCount(1, 'data')88->assertJsonPath('data.0.attributes.identifier', $servers[3]->uuidShort);8990$this->actingAs($users[0])->getJson('/api/client?filter[*]=Julia&type=admin-all')91->assertOk()92->assertJsonCount(2, 'data')93->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort)94->assertJsonPath('data.1.attributes.identifier', $servers[2]->uuidShort);95}9697/**98* Test that using ?filter[*]=:25565 or ?filter[*]=192.168.1.1:25565 returns only those servers99* with the same allocation for the given user.100*/101public function testServersAreFilteredUsingAllocationInformation()102{103/** @var User $user */104/** @var Server $server */105[$user, $server] = $this->generateTestAccount();106$server2 = $this->createServerModel(['user_id' => $user->id, 'node_id' => $server->node_id]);107108$allocation = Allocation::factory()->create(['node_id' => $server->node_id, 'server_id' => $server->id, 'ip' => '192.168.1.1', 'port' => 25565]);109$allocation2 = Allocation::factory()->create(['node_id' => $server->node_id, 'server_id' => $server2->id, 'ip' => '192.168.1.1', 'port' => 25570]);110111$server->update(['allocation_id' => $allocation->id]);112$server2->update(['allocation_id' => $allocation2->id]);113114$server->refresh();115$server2->refresh();116117$this->actingAs($user)->getJson('/api/client?filter[*]=192.168.1.1')118->assertOk()119->assertJsonCount(2, 'data')120->assertJsonPath('data.0.attributes.identifier', $server->uuidShort)121->assertJsonPath('data.1.attributes.identifier', $server2->uuidShort);122123$this->actingAs($user)->getJson('/api/client?filter[*]=192.168.1.1:25565')124->assertOk()125->assertJsonCount(1, 'data')126->assertJsonPath('data.0.attributes.identifier', $server->uuidShort);127128$this->actingAs($user)->getJson('/api/client?filter[*]=:25570')129->assertOk()130->assertJsonCount(1, 'data')131->assertJsonPath('data.0.attributes.identifier', $server2->uuidShort);132133$this->actingAs($user)->getJson('/api/client?filter[*]=:255')134->assertOk()135->assertJsonCount(2, 'data')136->assertJsonPath('data.0.attributes.identifier', $server->uuidShort)137->assertJsonPath('data.1.attributes.identifier', $server2->uuidShort);138}139140/**141* Test that servers where the user is a subuser are returned by default in the API call.142*/143public function testServersUserIsASubuserOfAreReturned()144{145/** @var \Pterodactyl\Models\User[] $users */146$users = User::factory()->times(3)->create();147$servers = [148$this->createServerModel(['user_id' => $users[0]->id]),149$this->createServerModel(['user_id' => $users[1]->id]),150$this->createServerModel(['user_id' => $users[2]->id]),151];152153// Set user 0 as a subuser of server 1. Thus, we should get two servers154// back in the response when making the API call as user 0.155Subuser::query()->create([156'user_id' => $users[0]->id,157'server_id' => $servers[1]->id,158'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],159]);160161$response = $this->actingAs($users[0])->getJson('/api/client');162163$response->assertOk();164$response->assertJsonCount(2, 'data');165$response->assertJsonPath('data.0.attributes.server_owner', true);166$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);167$response->assertJsonPath('data.1.attributes.server_owner', false);168$response->assertJsonPath('data.1.attributes.identifier', $servers[1]->uuidShort);169}170171/**172* Returns only servers that the user owns, not servers they are a subuser of.173*/174public function testFilterOnlyOwnerServers()175{176/** @var \Pterodactyl\Models\User[] $users */177$users = User::factory()->times(3)->create();178$servers = [179$this->createServerModel(['user_id' => $users[0]->id]),180$this->createServerModel(['user_id' => $users[1]->id]),181$this->createServerModel(['user_id' => $users[2]->id]),182];183184// Set user 0 as a subuser of server 1. Thus, we should get two servers185// back in the response when making the API call as user 0.186Subuser::query()->create([187'user_id' => $users[0]->id,188'server_id' => $servers[1]->id,189'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],190]);191192$response = $this->actingAs($users[0])->getJson('/api/client?type=owner');193194$response->assertOk();195$response->assertJsonCount(1, 'data');196$response->assertJsonPath('data.0.attributes.server_owner', true);197$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);198}199200/**201* Tests that the permissions from the Panel are returned correctly.202*/203public function testPermissionsAreReturned()204{205/** @var User $user */206$user = User::factory()->create();207208$this->actingAs($user)209->getJson('/api/client/permissions')210->assertOk()211->assertJson([212'object' => 'system_permissions',213'attributes' => [214'permissions' => Permission::permissions()->toArray(),215],216]);217}218219/**220* Test that only servers a user can access because they are an administrator are returned. This221* will always exclude any servers they can see because they're the owner or a subuser of the server.222*/223public function testOnlyAdminLevelServersAreReturned()224{225/** @var \Pterodactyl\Models\User[] $users */226$users = User::factory()->times(4)->create();227$users[0]->update(['root_admin' => true]);228229$servers = [230$this->createServerModel(['user_id' => $users[0]->id]),231$this->createServerModel(['user_id' => $users[1]->id]),232$this->createServerModel(['user_id' => $users[2]->id]),233$this->createServerModel(['user_id' => $users[3]->id]),234];235236Subuser::query()->create([237'user_id' => $users[0]->id,238'server_id' => $servers[1]->id,239'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],240]);241242// Only servers 2 & 3 (0 indexed) should be returned by the API at this point. The user making243// the request is the owner of server 0, and a subuser of server 1, so they should be excluded.244$response = $this->actingAs($users[0])->getJson('/api/client?type=admin');245246$response->assertOk();247$response->assertJsonCount(2, 'data');248249$response->assertJsonPath('data.0.attributes.server_owner', false);250$response->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);251$response->assertJsonPath('data.1.attributes.server_owner', false);252$response->assertJsonPath('data.1.attributes.identifier', $servers[3]->uuidShort);253}254255/**256* Test that all servers a user can access as an admin are returned if using ?filter=admin-all.257*/258public function testAllServersAreReturnedToAdmin()259{260/** @var \Pterodactyl\Models\User[] $users */261$users = User::factory()->times(4)->create();262$users[0]->update(['root_admin' => true]);263264$servers = [265$this->createServerModel(['user_id' => $users[0]->id]),266$this->createServerModel(['user_id' => $users[1]->id]),267$this->createServerModel(['user_id' => $users[2]->id]),268$this->createServerModel(['user_id' => $users[3]->id]),269];270271Subuser::query()->create([272'user_id' => $users[0]->id,273'server_id' => $servers[1]->id,274'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],275]);276277// All servers should be returned.278$response = $this->actingAs($users[0])->getJson('/api/client?type=admin-all');279280$response->assertOk();281$response->assertJsonCount(4, 'data');282}283284/**285* Test that no servers get returned if the user requests all admin level servers by using286* ?type=admin or ?type=admin-all in the request.287*/288#[\PHPUnit\Framework\Attributes\DataProvider('filterTypeDataProvider')]289public function testNoServersAreReturnedIfAdminFilterIsPassedByRegularUser(string $type)290{291/** @var \Pterodactyl\Models\User[] $users */292$users = User::factory()->times(3)->create();293294$this->createServerModel(['user_id' => $users[0]->id]);295$this->createServerModel(['user_id' => $users[1]->id]);296$this->createServerModel(['user_id' => $users[2]->id]);297298$response = $this->actingAs($users[0])->getJson('/api/client?type=' . $type);299300$response->assertOk();301$response->assertJsonCount(0, 'data');302}303304/**305* Test that a subuser without the allocation.read permission is only able to see the primary306* allocation for the server.307*/308public function testOnlyPrimaryAllocationIsReturnedToSubuser()309{310/** @var Server $server */311[$user, $server] = $this->generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT]);312$server->allocation->notes = 'Test notes';313$server->allocation->save();314315Allocation::factory()->times(2)->create([316'node_id' => $server->node_id,317'server_id' => $server->id,318]);319320$server->refresh();321$response = $this->actingAs($user)->getJson('/api/client');322323$response->assertOk();324$response->assertJsonCount(1, 'data');325$response->assertJsonPath('data.0.attributes.server_owner', false);326$response->assertJsonPath('data.0.attributes.uuid', $server->uuid);327$response->assertJsonCount(1, 'data.0.attributes.relationships.allocations.data');328$response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.id', $server->allocation->id);329$response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.notes', null);330}331332public static function filterTypeDataProvider(): array333{334return [['admin'], ['admin-all']];335}336}337338339