diff --git a/resources/scripts/components/server/files/NewDirectoryButton.tsx b/resources/scripts/components/server/files/NewDirectoryButton.tsx
index 0056cf68..dc91377b 100644
--- a/resources/scripts/components/server/files/NewDirectoryButton.tsx
+++ b/resources/scripts/components/server/files/NewDirectoryButton.tsx
@@ -92,9 +92,7 @@ export default ({ className }: WithClassname) => {
This directory will be created as
/home/container/
- {decodeURIComponent(encodeURIComponent(
- join(directory, values.directoryName).replace(/^(\.\.\/|\/)+/, ''),
- ))}
+ {join(directory, values.directoryName).replace(/^(\.\.\/|\/)+/, '')}
From f99ac0ecdec86184c39c5f124f7a3659dc61375e Mon Sep 17 00:00:00 2001
From: Dane Everitt
Date: Fri, 6 Nov 2020 22:33:39 -0800
Subject: [PATCH 7/8] Fix some failing test cases
---
.../Api/Client/Servers/SubuserController.php | 2 +-
.../Api/Client/Server/Subuser/DeleteSubuserTest.php | 12 ++++++++++--
.../Api/Client/Server/WebsocketControllerTest.php | 2 +-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/app/Http/Controllers/Api/Client/Servers/SubuserController.php b/app/Http/Controllers/Api/Client/Servers/SubuserController.php
index f51503d0..d2806a65 100644
--- a/app/Http/Controllers/Api/Client/Servers/SubuserController.php
+++ b/app/Http/Controllers/Api/Client/Servers/SubuserController.php
@@ -163,7 +163,7 @@ class SubuserController extends ClientApiController
$this->repository->delete($subuser->id);
try {
- $this->serverRepository->revokeJTIs([md5($subuser->user_id . $server->uuid)]);
+ $this->serverRepository->setServer($server)->revokeJTIs([md5($subuser->user_id . $server->uuid)]);
} catch (DaemonConnectionException $exception) {
// Don't block this request if we can't connect to the Wings instance.
Log::warning($exception, ['user_id' => $subuser->user_id, 'server_id' => $server->id]);
diff --git a/tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php b/tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php
index 3118baa2..144db42d 100644
--- a/tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php
+++ b/tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php
@@ -2,10 +2,12 @@
namespace Pterodactyl\Tests\Integration\Api\Client\Server\Subuser;
+use Mockery;
use Ramsey\Uuid\Uuid;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Subuser;
use Pterodactyl\Models\Permission;
+use Pterodactyl\Repositories\Wings\DaemonServerRepository;
use Pterodactyl\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
class DeleteSubuserTest extends ClientApiIntegrationTestCase
@@ -23,6 +25,8 @@ class DeleteSubuserTest extends ClientApiIntegrationTestCase
*/
public function testCorrectSubuserIsDeletedFromServer()
{
+ $this->swap(DaemonServerRepository::class, $mock = Mockery::mock(DaemonServerRepository::class));
+
[$user, $server] = $this->generateTestAccount();
/** @var \Pterodactyl\Models\User $differentUser */
@@ -37,9 +41,11 @@ class DeleteSubuserTest extends ClientApiIntegrationTestCase
Subuser::query()->forceCreate([
'user_id' => $subuser->id,
'server_id' => $server->id,
- 'permissions' => [ Permission::ACTION_WEBSOCKET_CONNECT ],
+ 'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
]);
+ $mock->expects('setServer->revokeJTIs')->with([md5($subuser->id . $server->uuid)])->andReturnUndefined();
+
$this->actingAs($user)->deleteJson($this->link($server) . "/users/{$subuser->uuid}")->assertNoContent();
// Try the same test, but this time with a UUID that if cast to an int (shouldn't) line up with
@@ -51,9 +57,11 @@ class DeleteSubuserTest extends ClientApiIntegrationTestCase
Subuser::query()->forceCreate([
'user_id' => $subuser->id,
'server_id' => $server->id,
- 'permissions' => [ Permission::ACTION_WEBSOCKET_CONNECT ],
+ 'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
]);
+ $mock->expects('setServer->revokeJTIs')->with([md5($subuser->id . $server->uuid)])->andReturnUndefined();
+
$this->actingAs($user)->deleteJson($this->link($server) . "/users/{$subuser->uuid}")->assertNoContent();
}
}
diff --git a/tests/Integration/Api/Client/Server/WebsocketControllerTest.php b/tests/Integration/Api/Client/Server/WebsocketControllerTest.php
index 0d8851d3..734dfcf2 100644
--- a/tests/Integration/Api/Client/Server/WebsocketControllerTest.php
+++ b/tests/Integration/Api/Client/Server/WebsocketControllerTest.php
@@ -63,7 +63,7 @@ class WebsocketControllerTest extends ClientApiIntegrationTestCase
$this->assertSame($server->node->getConnectionAddress(), $token->getClaim('aud'));
$this->assertSame(CarbonImmutable::now()->getTimestamp(), $token->getClaim('iat'));
$this->assertSame(CarbonImmutable::now()->subMinutes(5)->getTimestamp(), $token->getClaim('nbf'));
- $this->assertSame(CarbonImmutable::now()->addMinutes(15)->getTimestamp(), $token->getClaim('exp'));
+ $this->assertSame(CarbonImmutable::now()->addMinutes(10)->getTimestamp(), $token->getClaim('exp'));
$this->assertSame($user->id, $token->getClaim('user_id'));
$this->assertSame($server->uuid, $token->getClaim('server_uuid'));
$this->assertSame(['*'], $token->getClaim('permissions'));
From c20d53bb174539c9ca6bf6ed77b44a9cd0b3fe37 Mon Sep 17 00:00:00 2001
From: Dane Everitt
Date: Sat, 7 Nov 2020 09:57:53 -0800
Subject: [PATCH 8/8] Always return the primary allocation for a server, even
without the allocation permissions
---
app/Models/Permission.php | 2 +-
.../Api/Client/ServerTransformer.php | 20 +++++++++----
.../Api/Client/ClientControllerTest.php | 28 +++++++++++++++++++
3 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/app/Models/Permission.php b/app/Models/Permission.php
index 96429f31..d18e7200 100644
--- a/app/Models/Permission.php
+++ b/app/Models/Permission.php
@@ -163,7 +163,7 @@ class Permission extends Model
'allocation' => [
'description' => 'Permissions that control a user\'s ability to modify the port allocations for this server.',
'keys' => [
- 'read' => 'Allows a user to view the allocations assigned to this server.',
+ 'read' => 'Allows a user to view all allocations currently assigned to this server. Users with any level of access to this server can always view the primary allocation.',
'create' => 'Allows a user to assign additional allocations to the server.',
'update' => 'Allows a user to change the primary server allocation and attach notes to each allocation.',
'delete' => 'Allows a user to delete an allocation from the server.',
diff --git a/app/Transformers/Api/Client/ServerTransformer.php b/app/Transformers/Api/Client/ServerTransformer.php
index a787246b..ac3ab26b 100644
--- a/app/Transformers/Api/Client/ServerTransformer.php
+++ b/app/Transformers/Api/Client/ServerTransformer.php
@@ -83,15 +83,23 @@ class ServerTransformer extends BaseClientTransformer
*/
public function includeAllocations(Server $server)
{
+ $transformer = $this->makeTransformer(AllocationTransformer::class);
+
+ // While we include this permission, we do need to actually handle it slightly different here
+ // for the purpose of keeping things functionally working. If the user doesn't have read permissions
+ // for the allocations we'll only return the primary server allocation, and any notes associated
+ // with it will be hidden.
+ //
+ // This allows us to avoid too much permission regression, without also hiding information that
+ // is generally needed for the frontend to make sense when browsing or searching results.
if (! $this->getUser()->can(Permission::ACTION_ALLOCATION_READ, $server)) {
- return $this->null();
+ $primary = clone $server->allocation;
+ $primary->notes = null;
+
+ return $this->collection([$primary], $transformer, Allocation::RESOURCE_NAME);
}
- return $this->collection(
- $server->allocations,
- $this->makeTransformer(AllocationTransformer::class),
- Allocation::RESOURCE_NAME
- );
+ return $this->collection($server->allocations, $transformer, Allocation::RESOURCE_NAME);
}
/**
diff --git a/tests/Integration/Api/Client/ClientControllerTest.php b/tests/Integration/Api/Client/ClientControllerTest.php
index 30d83781..fc8c2c1e 100644
--- a/tests/Integration/Api/Client/ClientControllerTest.php
+++ b/tests/Integration/Api/Client/ClientControllerTest.php
@@ -304,6 +304,34 @@ class ClientControllerTest extends ClientApiIntegrationTestCase
$response->assertJsonCount(0, 'data');
}
+ /**
+ * Test that a subuser without the allocation.read permission is only able to see the primary
+ * allocation for the server.
+ */
+ public function testOnlyPrimaryAllocationIsReturnedToSubuser()
+ {
+ /** @var \Pterodactyl\Models\Server $server */
+ [$user, $server] = $this->generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT]);
+ $server->allocation->notes = 'Test notes';
+ $server->allocation->save();
+
+ factory(Allocation::class)->times(2)->create([
+ 'node_id' => $server->node_id,
+ 'server_id' => $server->id,
+ ]);
+
+ $server->refresh();
+ $response = $this->actingAs($user)->getJson('/api/client');
+
+ $response->assertOk();
+ $response->assertJsonCount(1, 'data');
+ $response->assertJsonPath('data.0.attributes.server_owner', false);
+ $response->assertJsonPath('data.0.attributes.uuid', $server->uuid);
+ $response->assertJsonCount(1, 'data.0.attributes.relationships.allocations.data');
+ $response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.id', $server->allocation->id);
+ $response->assertJsonPath('data.0.attributes.relationships.allocations.data.0.attributes.notes', null);
+ }
+
/**
* @return array
*/