Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/tests/Integration/Api/Client/ClientControllerTest.php
7459 views
1
<?php
2
3
namespace Pterodactyl\Tests\Integration\Api\Client;
4
5
use Pterodactyl\Models\User;
6
use Pterodactyl\Models\Server;
7
use Pterodactyl\Models\Subuser;
8
use Pterodactyl\Models\Allocation;
9
use Pterodactyl\Models\Permission;
10
11
class ClientControllerTest extends ClientApiIntegrationTestCase
12
{
13
/**
14
* Test that only the servers a logged-in user is assigned to are returned by the
15
* API endpoint. Obviously there are cases such as being an administrator or being
16
* a subuser, but for this test we just want to test a basic scenario and pretend
17
* subusers do not exist at all.
18
*/
19
public function testOnlyLoggedInUsersServersAreReturned()
20
{
21
/** @var \Pterodactyl\Models\User[] $users */
22
$users = User::factory()->times(3)->create();
23
24
/** @var \Pterodactyl\Models\Server[] $servers */
25
$servers = [
26
$this->createServerModel(['user_id' => $users[0]->id]),
27
$this->createServerModel(['user_id' => $users[1]->id]),
28
$this->createServerModel(['user_id' => $users[2]->id]),
29
];
30
31
$response = $this->actingAs($users[0])->getJson('/api/client');
32
33
$response->assertOk();
34
$response->assertJsonPath('object', 'list');
35
$response->assertJsonPath('data.0.object', Server::RESOURCE_NAME);
36
$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);
37
$response->assertJsonPath('data.0.attributes.server_owner', true);
38
$response->assertJsonPath('meta.pagination.total', 1);
39
$response->assertJsonPath('meta.pagination.per_page', 50);
40
}
41
42
/**
43
* Test that using ?filter[*]=name|uuid returns any server matching that name or UUID
44
* with the search filters.
45
*/
46
public function testServersAreFilteredUsingNameAndUuidInformation()
47
{
48
/** @var \Pterodactyl\Models\User[] $users */
49
$users = User::factory()->times(2)->create();
50
$users[0]->update(['root_admin' => true]);
51
52
/** @var \Pterodactyl\Models\Server[] $servers */
53
$servers = [
54
$this->createServerModel(['user_id' => $users[0]->id, 'name' => 'Julia']),
55
$this->createServerModel(['user_id' => $users[1]->id, 'uuidShort' => '12121212', 'name' => 'Janice']),
56
$this->createServerModel(['user_id' => $users[1]->id, 'uuid' => '88788878-12356789', 'external_id' => 'ext123', 'name' => 'Julia']),
57
$this->createServerModel(['user_id' => $users[1]->id, 'uuid' => '88788878-abcdefgh', 'name' => 'Jennifer']),
58
];
59
60
$this->actingAs($users[1])->getJson('/api/client?filter[*]=Julia')
61
->assertOk()
62
->assertJsonCount(1, 'data')
63
->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);
64
65
$this->actingAs($users[1])->getJson('/api/client?filter[*]=ext123')
66
->assertOk()
67
->assertJsonCount(1, 'data')
68
->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);
69
70
$this->actingAs($users[1])->getJson('/api/client?filter[*]=ext123')
71
->assertOk()
72
->assertJsonCount(1, 'data')
73
->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);
74
75
$this->actingAs($users[1])->getJson('/api/client?filter[*]=12121212')
76
->assertOk()
77
->assertJsonCount(1, 'data')
78
->assertJsonPath('data.0.attributes.identifier', $servers[1]->uuidShort);
79
80
$this->actingAs($users[1])->getJson('/api/client?filter[*]=88788878')
81
->assertOk()
82
->assertJsonCount(2, 'data')
83
->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort)
84
->assertJsonPath('data.1.attributes.identifier', $servers[3]->uuidShort);
85
86
$this->actingAs($users[1])->getJson('/api/client?filter[*]=88788878-abcd')
87
->assertOk()
88
->assertJsonCount(1, 'data')
89
->assertJsonPath('data.0.attributes.identifier', $servers[3]->uuidShort);
90
91
$this->actingAs($users[0])->getJson('/api/client?filter[*]=Julia&type=admin-all')
92
->assertOk()
93
->assertJsonCount(2, 'data')
94
->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort)
95
->assertJsonPath('data.1.attributes.identifier', $servers[2]->uuidShort);
96
}
97
98
/**
99
* Test that using ?filter[*]=:25565 or ?filter[*]=192.168.1.1:25565 returns only those servers
100
* with the same allocation for the given user.
101
*/
102
public function testServersAreFilteredUsingAllocationInformation()
103
{
104
/** @var User $user */
105
/** @var Server $server */
106
[$user, $server] = $this->generateTestAccount();
107
$server2 = $this->createServerModel(['user_id' => $user->id, 'node_id' => $server->node_id]);
108
109
$allocation = Allocation::factory()->create(['node_id' => $server->node_id, 'server_id' => $server->id, 'ip' => '192.168.1.1', 'port' => 25565]);
110
$allocation2 = Allocation::factory()->create(['node_id' => $server->node_id, 'server_id' => $server2->id, 'ip' => '192.168.1.1', 'port' => 25570]);
111
112
$server->update(['allocation_id' => $allocation->id]);
113
$server2->update(['allocation_id' => $allocation2->id]);
114
115
$server->refresh();
116
$server2->refresh();
117
118
$this->actingAs($user)->getJson('/api/client?filter[*]=192.168.1.1')
119
->assertOk()
120
->assertJsonCount(2, 'data')
121
->assertJsonPath('data.0.attributes.identifier', $server->uuidShort)
122
->assertJsonPath('data.1.attributes.identifier', $server2->uuidShort);
123
124
$this->actingAs($user)->getJson('/api/client?filter[*]=192.168.1.1:25565')
125
->assertOk()
126
->assertJsonCount(1, 'data')
127
->assertJsonPath('data.0.attributes.identifier', $server->uuidShort);
128
129
$this->actingAs($user)->getJson('/api/client?filter[*]=:25570')
130
->assertOk()
131
->assertJsonCount(1, 'data')
132
->assertJsonPath('data.0.attributes.identifier', $server2->uuidShort);
133
134
$this->actingAs($user)->getJson('/api/client?filter[*]=:255')
135
->assertOk()
136
->assertJsonCount(2, 'data')
137
->assertJsonPath('data.0.attributes.identifier', $server->uuidShort)
138
->assertJsonPath('data.1.attributes.identifier', $server2->uuidShort);
139
}
140
141
/**
142
* Test that servers where the user is a subuser are returned by default in the API call.
143
*/
144
public function testServersUserIsASubuserOfAreReturned()
145
{
146
/** @var \Pterodactyl\Models\User[] $users */
147
$users = User::factory()->times(3)->create();
148
$servers = [
149
$this->createServerModel(['user_id' => $users[0]->id]),
150
$this->createServerModel(['user_id' => $users[1]->id]),
151
$this->createServerModel(['user_id' => $users[2]->id]),
152
];
153
154
// Set user 0 as a subuser of server 1. Thus, we should get two servers
155
// back in the response when making the API call as user 0.
156
Subuser::query()->create([
157
'user_id' => $users[0]->id,
158
'server_id' => $servers[1]->id,
159
'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
160
]);
161
162
$response = $this->actingAs($users[0])->getJson('/api/client');
163
164
$response->assertOk();
165
$response->assertJsonCount(2, 'data');
166
$response->assertJsonPath('data.0.attributes.server_owner', true);
167
$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);
168
$response->assertJsonPath('data.1.attributes.server_owner', false);
169
$response->assertJsonPath('data.1.attributes.identifier', $servers[1]->uuidShort);
170
}
171
172
/**
173
* Returns only servers that the user owns, not servers they are a subuser of.
174
*/
175
public function testFilterOnlyOwnerServers()
176
{
177
/** @var \Pterodactyl\Models\User[] $users */
178
$users = User::factory()->times(3)->create();
179
$servers = [
180
$this->createServerModel(['user_id' => $users[0]->id]),
181
$this->createServerModel(['user_id' => $users[1]->id]),
182
$this->createServerModel(['user_id' => $users[2]->id]),
183
];
184
185
// Set user 0 as a subuser of server 1. Thus, we should get two servers
186
// back in the response when making the API call as user 0.
187
Subuser::query()->create([
188
'user_id' => $users[0]->id,
189
'server_id' => $servers[1]->id,
190
'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
191
]);
192
193
$response = $this->actingAs($users[0])->getJson('/api/client?type=owner');
194
195
$response->assertOk();
196
$response->assertJsonCount(1, 'data');
197
$response->assertJsonPath('data.0.attributes.server_owner', true);
198
$response->assertJsonPath('data.0.attributes.identifier', $servers[0]->uuidShort);
199
}
200
201
/**
202
* Tests that the permissions from the Panel are returned correctly.
203
*/
204
public function testPermissionsAreReturned()
205
{
206
/** @var User $user */
207
$user = User::factory()->create();
208
209
$this->actingAs($user)
210
->getJson('/api/client/permissions')
211
->assertOk()
212
->assertJson([
213
'object' => 'system_permissions',
214
'attributes' => [
215
'permissions' => Permission::permissions()->toArray(),
216
],
217
]);
218
}
219
220
/**
221
* Test that only servers a user can access because they are an administrator are returned. This
222
* will always exclude any servers they can see because they're the owner or a subuser of the server.
223
*/
224
public function testOnlyAdminLevelServersAreReturned()
225
{
226
/** @var \Pterodactyl\Models\User[] $users */
227
$users = User::factory()->times(4)->create();
228
$users[0]->update(['root_admin' => true]);
229
230
$servers = [
231
$this->createServerModel(['user_id' => $users[0]->id]),
232
$this->createServerModel(['user_id' => $users[1]->id]),
233
$this->createServerModel(['user_id' => $users[2]->id]),
234
$this->createServerModel(['user_id' => $users[3]->id]),
235
];
236
237
Subuser::query()->create([
238
'user_id' => $users[0]->id,
239
'server_id' => $servers[1]->id,
240
'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
241
]);
242
243
// Only servers 2 & 3 (0 indexed) should be returned by the API at this point. The user making
244
// the request is the owner of server 0, and a subuser of server 1, so they should be excluded.
245
$response = $this->actingAs($users[0])->getJson('/api/client?type=admin');
246
247
$response->assertOk();
248
$response->assertJsonCount(2, 'data');
249
250
$response->assertJsonPath('data.0.attributes.server_owner', false);
251
$response->assertJsonPath('data.0.attributes.identifier', $servers[2]->uuidShort);
252
$response->assertJsonPath('data.1.attributes.server_owner', false);
253
$response->assertJsonPath('data.1.attributes.identifier', $servers[3]->uuidShort);
254
}
255
256
/**
257
* Test that all servers a user can access as an admin are returned if using ?filter=admin-all.
258
*/
259
public function testAllServersAreReturnedToAdmin()
260
{
261
/** @var \Pterodactyl\Models\User[] $users */
262
$users = User::factory()->times(4)->create();
263
$users[0]->update(['root_admin' => true]);
264
265
$servers = [
266
$this->createServerModel(['user_id' => $users[0]->id]),
267
$this->createServerModel(['user_id' => $users[1]->id]),
268
$this->createServerModel(['user_id' => $users[2]->id]),
269
$this->createServerModel(['user_id' => $users[3]->id]),
270
];
271
272
Subuser::query()->create([
273
'user_id' => $users[0]->id,
274
'server_id' => $servers[1]->id,
275
'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
276
]);
277
278
// All servers should be returned.
279
$response = $this->actingAs($users[0])->getJson('/api/client?type=admin-all');
280
281
$response->assertOk();
282
$response->assertJsonCount(4, 'data');
283
}
284
285
/**
286
* Test that no servers get returned if the user requests all admin level servers by using
287
* ?type=admin or ?type=admin-all in the request.
288
*/
289
#[\PHPUnit\Framework\Attributes\DataProvider('filterTypeDataProvider')]
290
public function testNoServersAreReturnedIfAdminFilterIsPassedByRegularUser(string $type)
291
{
292
/** @var \Pterodactyl\Models\User[] $users */
293
$users = User::factory()->times(3)->create();
294
295
$this->createServerModel(['user_id' => $users[0]->id]);
296
$this->createServerModel(['user_id' => $users[1]->id]);
297
$this->createServerModel(['user_id' => $users[2]->id]);
298
299
$response = $this->actingAs($users[0])->getJson('/api/client?type=' . $type);
300
301
$response->assertOk();
302
$response->assertJsonCount(0, 'data');
303
}
304
305
/**
306
* Test that a subuser without the allocation.read permission is only able to see the primary
307
* allocation for the server.
308
*/
309
public function testOnlyPrimaryAllocationIsReturnedToSubuser()
310
{
311
/** @var Server $server */
312
[$user, $server] = $this->generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT]);
313
$server->allocation->notes = 'Test notes';
314
$server->allocation->save();
315
316
Allocation::factory()->times(2)->create([
317
'node_id' => $server->node_id,
318
'server_id' => $server->id,
319
]);
320
321
$server->refresh();
322
$response = $this->actingAs($user)->getJson('/api/client');
323
324
$response->assertOk();
325
$response->assertJsonCount(1, 'data');
326
$response->assertJsonPath('data.0.attributes.server_owner', false);
327
$response->assertJsonPath('data.0.attributes.uuid', $server->uuid);
328
$response->assertJsonCount(1, 'data.0.attributes.relationships.allocations.data');
329
$response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.id', $server->allocation->id);
330
$response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.notes', null);
331
}
332
333
public static function filterTypeDataProvider(): array
334
{
335
return [['admin'], ['admin-all']];
336
}
337
}
338
339