Skip to content

Commit d493685

Browse files
committed
Add test coverage for allocation assignment endpoint
1 parent b2be067 commit d493685

File tree

6 files changed

+204
-79
lines changed

6 files changed

+204
-79
lines changed

app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ public function setPrimary(SetPrimaryAllocationRequest $request, Server $server,
122122
*/
123123
public function store(NewAllocationRequest $request, Server $server): array
124124
{
125+
if ($server->allocations()->count() >= $server->allocation_limit) {
126+
throw new DisplayException(
127+
'Cannot assign additional allocations to this server: limit has been reached.'
128+
);
129+
}
130+
125131
$allocation = $this->assignableAllocationService->handle($server);
126132

127133
return $this->fractal->item($allocation)

app/Services/Allocations/FindAssignableAllocationService.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ public function handle(Server $server)
4646
throw new AutoAllocationNotEnabledException;
4747
}
4848

49-
if ($server->allocations()->count() >= $server->allocation_limit) {
50-
throw new DisplayException(
51-
'Cannot assign additional allocations to this server: limit has been reached.'
52-
);
53-
}
54-
5549
// Attempt to find a given available allocation for a server. If one cannot be found
5650
// we will fall back to attempting to create a new allocation that can be used for the
5751
// server.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Integration\Api\Client\Server\Allocation;
4+
5+
use Illuminate\Http\Response;
6+
use Pterodactyl\Models\Permission;
7+
use Pterodactyl\Models\Allocation;
8+
use Pterodactyl\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
9+
10+
class CreateNewAllocationTest extends ClientApiIntegrationTestCase
11+
{
12+
/**
13+
* Setup tests.
14+
*/
15+
public function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
config()->set('pterodactyl.client_features.allocations.enabled', true);
20+
config()->set('pterodactyl.client_features.allocations.range_start', 5000);
21+
config()->set('pterodactyl.client_features.allocations.range_end', 5050);
22+
}
23+
24+
/**
25+
* Tests that a new allocation can be properly assigned to a server.
26+
*
27+
* @param array $permission
28+
* @dataProvider permissionDataProvider
29+
*/
30+
public function testNewAllocationCanBeAssignedToServer(array $permission)
31+
{
32+
/** @var \Pterodactyl\Models\Server $server */
33+
[$user, $server] = $this->generateTestAccount($permission);
34+
$server->update(['allocation_limit' => 2]);
35+
36+
$response = $this->actingAs($user)->postJson($this->link($server, "/network/allocations"));
37+
$response->assertJsonPath('object', Allocation::RESOURCE_NAME);
38+
39+
$matched = Allocation::query()->findOrFail($response->json('attributes.id'));
40+
41+
$this->assertSame($server->id, $matched->server_id);
42+
$this->assertJsonTransformedWith($response->json('attributes'), $matched);
43+
}
44+
45+
/**
46+
* Test that a user without the required permissions cannot create an allocation for
47+
* the server instance.
48+
*/
49+
public function testAllocationCannotBeCreatedIfUserDoesNotHavePermission()
50+
{
51+
/** @var \Pterodactyl\Models\Server $server */
52+
[$user, $server] = $this->generateTestAccount([Permission::ACTION_ALLOCATION_UPDATE]);
53+
$server->update(['allocation_limit' => 2]);
54+
55+
$this->actingAs($user)->postJson($this->link($server, "/network/allocations"))->assertForbidden();
56+
}
57+
58+
/**
59+
* Test that an error is returned to the user if this feature is not enabled on the system.
60+
*/
61+
public function testAllocationCannotBeCreatedIfNotEnabled()
62+
{
63+
config()->set('pterodactyl.client_features.allocations.enabled', false);
64+
65+
/** @var \Pterodactyl\Models\Server $server */
66+
[$user, $server] = $this->generateTestAccount();
67+
$server->update(['allocation_limit' => 2]);
68+
69+
$this->actingAs($user)->postJson($this->link($server, "/network/allocations"))
70+
->assertStatus(Response::HTTP_BAD_REQUEST)
71+
->assertJsonPath('errors.0.code', 'AutoAllocationNotEnabledException')
72+
->assertJsonPath('errors.0.detail', 'Server auto-allocation is not enabled for this instance.');
73+
}
74+
75+
/**
76+
* Test that an allocation cannot be created if the server has reached it's allocation limit.
77+
*/
78+
public function testAllocationCannotBeCreatedIfServerIsAtLimit()
79+
{
80+
/** @var \Pterodactyl\Models\Server $server */
81+
[$user, $server] = $this->generateTestAccount();
82+
$server->update(['allocation_limit' => 1]);
83+
84+
$this->actingAs($user)->postJson($this->link($server, "/network/allocations"))
85+
->assertStatus(Response::HTTP_BAD_REQUEST)
86+
->assertJsonPath('errors.0.code', 'DisplayException')
87+
->assertJsonPath('errors.0.detail', 'Cannot assign additional allocations to this server: limit has been reached.');
88+
}
89+
90+
/**
91+
* @return array
92+
*/
93+
public function permissionDataProvider()
94+
{
95+
return [[[Permission::ACTION_ALLOCATION_CREATE]], [[]]];
96+
}
97+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Integration\Api\Client\Server\Allocation;
4+
5+
use Illuminate\Http\Response;
6+
use Pterodactyl\Models\Permission;
7+
use Pterodactyl\Models\Allocation;
8+
use Pterodactyl\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
9+
10+
class DeleteAllocationTest extends ClientApiIntegrationTestCase
11+
{
12+
/**
13+
* Test that an allocation is deleted from the server and the notes are properly reset
14+
* to an empty value on assignment.
15+
*
16+
* @param array $permission
17+
* @dataProvider permissionDataProvider
18+
*/
19+
public function testAllocationCanBeDeletedFromServer(array $permission)
20+
{
21+
/** @var \Pterodactyl\Models\Server $server */
22+
[$user, $server] = $this->generateTestAccount($permission);
23+
24+
/** @var \Pterodactyl\Models\Allocation $allocation */
25+
$allocation = factory(Allocation::class)->create([
26+
'server_id' => $server->id,
27+
'node_id' => $server->node_id,
28+
'notes' => 'hodor',
29+
]);
30+
31+
$this->actingAs($user)->deleteJson($this->link($allocation))->assertStatus(Response::HTTP_NO_CONTENT);
32+
33+
$this->assertDatabaseHas('allocations', ['id' => $allocation->id, 'server_id' => null, 'notes' => null]);
34+
}
35+
36+
/**
37+
* Test that an error is returned if the user does not have permissiont to delete an allocation.
38+
*/
39+
public function testErrorIsReturnedIfUserDoesNotHavePermission()
40+
{
41+
/** @var \Pterodactyl\Models\Server $server */
42+
[$user, $server] = $this->generateTestAccount([Permission::ACTION_ALLOCATION_CREATE]);
43+
44+
/** @var \Pterodactyl\Models\Allocation $allocation */
45+
$allocation = factory(Allocation::class)->create([
46+
'server_id' => $server->id,
47+
'node_id' => $server->node_id,
48+
'notes' => 'hodor',
49+
]);
50+
51+
$this->actingAs($user)->deleteJson($this->link($allocation))->assertForbidden();
52+
53+
$this->assertDatabaseHas('allocations', ['id' => $allocation->id, 'server_id' => $server->id]);
54+
}
55+
56+
/**
57+
* Test that an allocation is not deleted if it is currently marked as the primary allocation
58+
* for the server.
59+
*/
60+
public function testErrorIsReturnedIfAllocationIsPrimary()
61+
{
62+
/** @var \Pterodactyl\Models\Server $server */
63+
[$user, $server] = $this->generateTestAccount();
64+
65+
$this->actingAs($user)->deleteJson($this->link($server->allocation))
66+
->assertStatus(Response::HTTP_BAD_REQUEST)
67+
->assertJsonPath('errors.0.code', 'DisplayException')
68+
->assertJsonPath('errors.0.detail', 'You cannot delete the primary allocation for this server.');
69+
}
70+
71+
/**
72+
* Test that an allocation cannot be deleted if it does not belong to the server instance.
73+
*/
74+
public function testErrorIsReturnedIfAllocationDoesNotBelongToServer()
75+
{
76+
/** @var \Pterodactyl\Models\Server $server */
77+
[$user, $server] = $this->generateTestAccount();
78+
[, $server2] = $this->generateTestAccount();
79+
80+
$this->actingAs($user)->deleteJson($this->link($server2->allocation))->assertNotFound();
81+
$this->actingAs($user)->deleteJson($this->link($server, "/network/allocations/{$server2->allocation_id}"))->assertNotFound();
82+
}
83+
84+
/**
85+
* @return array
86+
*/
87+
public function permissionDataProvider()
88+
{
89+
return [[[Permission::ACTION_ALLOCATION_DELETE]], [[]]];
90+
}
91+
}

tests/Integration/Api/Client/Server/NetworkAllocationControllerTest.php

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Pterodactyl\Models\User;
66
use Illuminate\Http\Response;
7-
use Pterodactyl\Models\Server;
87
use Pterodactyl\Models\Allocation;
98
use Pterodactyl\Models\Permission;
109
use Pterodactyl\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
@@ -17,15 +16,14 @@ class NetworkAllocationControllerTest extends ClientApiIntegrationTestCase
1716
public function testServerAllocationsAreReturned()
1817
{
1918
[$user, $server] = $this->generateTestAccount();
20-
$allocation = $this->getAllocation($server);
2119

2220
$response = $this->actingAs($user)->getJson($this->link($server, '/network/allocations'));
2321

2422
$response->assertOk();
2523
$response->assertJsonPath('object', 'list');
2624
$response->assertJsonCount(1, 'data');
2725

28-
$this->assertJsonTransformedWith($response->json('data.0.attributes'), $allocation);
26+
$this->assertJsonTransformedWith($response->json('data.0.attributes'), $server->allocation);
2927
}
3028

3129
/**
@@ -57,7 +55,7 @@ public function testServerAllocationsAreNotReturnedWithoutPermission()
5755
public function testAllocationNotesCanBeUpdated(array $permissions)
5856
{
5957
[$user, $server] = $this->generateTestAccount($permissions);
60-
$allocation = $this->getAllocation($server);
58+
$allocation = $server->allocation;
6159

6260
$this->assertNull($allocation->notes);
6361

@@ -92,13 +90,11 @@ public function testAllocationNotesCannotBeUpdatedByInvalidUsers()
9290
$server->owner_id = $user2->id;
9391
$server->save();
9492

95-
$this->actingAs($user)->postJson($this->link($this->getAllocation($server)))
96-
->assertNotFound();
93+
$this->actingAs($user)->postJson($this->link($server->allocation))->assertNotFound();
9794

9895
[$user, $server] = $this->generateTestAccount([Permission::ACTION_ALLOCATION_CREATE]);
9996

100-
$this->actingAs($user)->postJson($this->link($this->getAllocation($server)))
101-
->assertForbidden();
97+
$this->actingAs($user)->postJson($this->link($server->allocation))->assertForbidden();
10298
}
10399

104100
/**
@@ -108,8 +104,8 @@ public function testAllocationNotesCannotBeUpdatedByInvalidUsers()
108104
public function testPrimaryAllocationCanBeModified(array $permissions)
109105
{
110106
[$user, $server] = $this->generateTestAccount($permissions);
111-
$allocation = $this->getAllocation($server);
112-
$allocation2 = $this->getAllocation($server);
107+
$allocation = $server->allocation;
108+
$allocation2 = factory(Allocation::class)->create(['node_id' => $server->node_id, 'server_id' => $server->id]);
113109

114110
$server->allocation_id = $allocation->id;
115111
$server->save();
@@ -130,61 +126,12 @@ public function testPrimaryAllocationCannotBeModifiedByInvalidUser()
130126
$server->owner_id = $user2->id;
131127
$server->save();
132128

133-
$this->actingAs($user)->postJson($this->link($this->getAllocation($server), '/primary'))
129+
$this->actingAs($user)->postJson($this->link($server->allocation, '/primary'))
134130
->assertNotFound();
135131

136132
[$user, $server] = $this->generateTestAccount([Permission::ACTION_ALLOCATION_CREATE]);
137133

138-
$this->actingAs($user)->postJson($this->link($this->getAllocation($server), '/primary'))
139-
->assertForbidden();
140-
}
141-
142-
/**
143-
* @param array $permissions
144-
* @dataProvider deletePermissionsDataProvider
145-
*/
146-
public function testAllocationCanBeDeleted(array $permissions)
147-
{
148-
[$user, $server] = $this->generateTestAccount($permissions);
149-
$allocation = $this->getAllocation($server);
150-
$allocation2 = $this->getAllocation($server);
151-
152-
$allocation2->notes = 'Filled notes';
153-
$allocation2->save();
154-
155-
$server->allocation_id = $allocation->id;
156-
$server->save();
157-
158-
$this->actingAs($user)->deleteJson($this->link($allocation))
159-
->assertStatus(Response::HTTP_BAD_REQUEST)
160-
->assertJsonPath('errors.0.code', 'DisplayException')
161-
->assertJsonPath('errors.0.detail', 'Cannot delete the primary allocation for a server.');
162-
163-
$this->actingAs($user)->deleteJson($this->link($allocation2))
164-
->assertStatus(Response::HTTP_NO_CONTENT);
165-
166-
$server = $server->refresh();
167-
$allocation2 = $allocation2->refresh();
168-
169-
$this->assertSame($allocation->id, $server->allocation_id);
170-
$this->assertNull($allocation2->server_id);
171-
$this->assertNull($allocation2->notes);
172-
}
173-
174-
public function testAllocationCannotBeDeletedByInvalidUser()
175-
{
176-
[$user, $server] = $this->generateTestAccount();
177-
$user2 = factory(User::class)->create();
178-
179-
$server->owner_id = $user2->id;
180-
$server->save();
181-
182-
$this->actingAs($user)->deleteJson($this->link($this->getAllocation($server)))
183-
->assertNotFound();
184-
185-
[$user, $server] = $this->generateTestAccount([Permission::ACTION_ALLOCATION_CREATE]);
186-
187-
$this->actingAs($user)->deleteJson($this->link($this->getAllocation($server)))
134+
$this->actingAs($user)->postJson($this->link($server->allocation, '/primary'))
188135
->assertForbidden();
189136
}
190137

@@ -197,16 +144,4 @@ public function deletePermissionsDataProvider()
197144
{
198145
return [[[]], [[Permission::ACTION_ALLOCATION_DELETE]]];
199146
}
200-
201-
/**
202-
* @param \Pterodactyl\Models\Server $server
203-
* @return \Pterodactyl\Models\Allocation
204-
*/
205-
protected function getAllocation(Server $server): Allocation
206-
{
207-
return factory(Allocation::class)->create([
208-
'server_id' => $server->id,
209-
'node_id' => $server->node_id,
210-
]);
211-
}
212147
}

tests/Traits/Integration/CreatesTestModels.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public function createServerModel(array $attributes = []): Server
7171

7272
$server = $factory->of(Server::class)->create($attributes);
7373

74+
Allocation::query()->where('id', $server->allocation_id)->update(['server_id' => $server->id]);
75+
7476
return Server::with([
7577
'location', 'user', 'node', 'allocation', 'nest', 'egg',
7678
])->findOrFail($server->id);

0 commit comments

Comments
 (0)