diff --git a/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php b/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php index 855cb6780..a24dcab91 100644 --- a/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php +++ b/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php @@ -120,6 +120,12 @@ class NetworkAllocationController extends ClientApiController */ public function delete(DeleteAllocationRequest $request, Server $server, Allocation $allocation) { + // Don't allow the deletion of allocations if the server does not have an + // allocation limit set. + if (empty($server->allocation_limit)) { + throw new DisplayException('You cannot delete allocations for this server: no allocation limit is set.'); + } + if ($allocation->id === $server->allocation_id) { throw new DisplayException('You cannot delete the primary allocation for this server.'); } diff --git a/app/Models/Allocation.php b/app/Models/Allocation.php index 9363b4063..49673921b 100644 --- a/app/Models/Allocation.php +++ b/app/Models/Allocation.php @@ -3,6 +3,8 @@ namespace Pterodactyl\Models; /** + * Pterodactyl\Models\Allocation. + * * @property int $id * @property int $node_id * @property string $ip @@ -16,6 +18,22 @@ namespace Pterodactyl\Models; * @property bool $has_alias * @property \Pterodactyl\Models\Server|null $server * @property \Pterodactyl\Models\Node $node + * @property string $hashid + * + * @method static \Database\Factories\AllocationFactory factory(...$parameters) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Allocation newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|Allocation query() + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereIp($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereIpAlias($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereNodeId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereNotes($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation wherePort($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereServerId($value) + * @method static \Illuminate\Database\Eloquent\Builder|Allocation whereUpdatedAt($value) + * @mixin \Eloquent */ class Allocation extends Model { diff --git a/database/Factories/AllocationFactory.php b/database/Factories/AllocationFactory.php index 679c8c03e..9ed42e3ef 100644 --- a/database/Factories/AllocationFactory.php +++ b/database/Factories/AllocationFactory.php @@ -2,6 +2,7 @@ namespace Database\Factories; +use Pterodactyl\Models\Server; use Pterodactyl\Models\Allocation; use Illuminate\Database\Eloquent\Factories\Factory; @@ -24,4 +25,12 @@ class AllocationFactory extends Factory 'port' => $this->faker->unique()->randomNumber(5), ]; } + + /** + * Attaches the allocation to a specific server model. + */ + public function forServer(Server $server): self + { + return $this->for($server)->for($server->node); + } } diff --git a/resources/scripts/components/server/network/NetworkContainer.tsx b/resources/scripts/components/server/network/NetworkContainer.tsx index 0bb6bd42a..ec4406da1 100644 --- a/resources/scripts/components/server/network/NetworkContainer.tsx +++ b/resources/scripts/components/server/network/NetworkContainer.tsx @@ -66,20 +66,22 @@ const NetworkContainer = () => { /> )) } - - -
-

- You are currently using {data.length} of {allocationLimit} allowed allocations for this - server. -

- {allocationLimit > data.length && - - } -
-
+ {allocationLimit > 0 && + + +
+

+ You are currently using {data.length} of {allocationLimit} allowed allocations for + this server. +

+ {allocationLimit > data.length && + + } +
+
+ } } diff --git a/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php b/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php index 80b397ca8..22f941807 100644 --- a/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php +++ b/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php @@ -89,6 +89,7 @@ abstract class ClientApiIntegrationTestCase extends IntegrationTestCase * is assumed that the user is actually a subuser of the server. * * @param string[] $permissions + * @return array{\Pterodactyl\Models\User, \Pterodactyl\Models\Server} */ protected function generateTestAccount(array $permissions = []): array { diff --git a/tests/Integration/Api/Client/Server/Allocation/DeleteAllocationTest.php b/tests/Integration/Api/Client/Server/Allocation/DeleteAllocationTest.php index c986de784..42db6eef7 100644 --- a/tests/Integration/Api/Client/Server/Allocation/DeleteAllocationTest.php +++ b/tests/Integration/Api/Client/Server/Allocation/DeleteAllocationTest.php @@ -19,6 +19,7 @@ class DeleteAllocationTest extends ClientApiIntegrationTestCase { /** @var \Pterodactyl\Models\Server $server */ [$user, $server] = $this->generateTestAccount($permission); + $server->update(['allocation_limit' => 2]); /** @var \Pterodactyl\Models\Allocation $allocation */ $allocation = Allocation::factory()->create([ @@ -60,6 +61,7 @@ class DeleteAllocationTest extends ClientApiIntegrationTestCase { /** @var \Pterodactyl\Models\Server $server */ [$user, $server] = $this->generateTestAccount(); + $server->update(['allocation_limit' => 2]); $this->actingAs($user)->deleteJson($this->link($server->allocation)) ->assertStatus(Response::HTTP_BAD_REQUEST) @@ -67,6 +69,22 @@ class DeleteAllocationTest extends ClientApiIntegrationTestCase ->assertJsonPath('errors.0.detail', 'You cannot delete the primary allocation for this server.'); } + public function testAllocationCannotBeDeletedIfServerLimitIsNotDefined() + { + [$user, $server] = $this->generateTestAccount(); + + /** @var \Pterodactyl\Models\Allocation $allocation */ + $allocation = Allocation::factory()->forServer($server)->create(['notes' => 'Test notes']); + + $this->actingAs($user)->deleteJson($this->link($allocation)) + ->assertStatus(400) + ->assertJsonPath('errors.0.detail', 'You cannot delete allocations for this server: no allocation limit is set.'); + + $allocation->refresh(); + $this->assertNotNull($allocation->notes); + $this->assertEquals($server->id, $allocation->server_id); + } + /** * Test that an allocation cannot be deleted if it does not belong to the server instance. */ diff --git a/tests/Integration/Api/Client/Server/NetworkAllocationControllerTest.php b/tests/Integration/Api/Client/Server/NetworkAllocationControllerTest.php index 9741af974..336b4e037 100644 --- a/tests/Integration/Api/Client/Server/NetworkAllocationControllerTest.php +++ b/tests/Integration/Api/Client/Server/NetworkAllocationControllerTest.php @@ -137,9 +137,4 @@ class NetworkAllocationControllerTest extends ClientApiIntegrationTestCase { return [[[]], [[Permission::ACTION_ALLOCATION_UPDATE]]]; } - - public function deletePermissionsDataProvider() - { - return [[[]], [[Permission::ACTION_ALLOCATION_DELETE]]]; - } }