Merge branch 'develop' into feature/server-mounts

This commit is contained in:
Matthew Penner 2020-07-11 12:29:30 -06:00 committed by GitHub
commit 295f09ca43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
195 changed files with 5395 additions and 5417 deletions

View file

@ -3,11 +3,10 @@
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
use Pterodactyl\Models\Node;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Models\Allocation;
use Pterodactyl\Services\Allocations\AssignmentService;
use Pterodactyl\Services\Allocations\AllocationDeletionService;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Transformers\Api\Application\AllocationTransformer;
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
use Pterodactyl\Http\Requests\Api\Application\Allocations\GetAllocationsRequest;
@ -26,41 +25,32 @@ class AllocationController extends ApplicationApiController
*/
private $deletionService;
/**
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface
*/
private $repository;
/**
* AllocationController constructor.
*
* @param \Pterodactyl\Services\Allocations\AssignmentService $assignmentService
* @param \Pterodactyl\Services\Allocations\AllocationDeletionService $deletionService
* @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $repository
*/
public function __construct(
AssignmentService $assignmentService,
AllocationDeletionService $deletionService,
AllocationRepositoryInterface $repository
AllocationDeletionService $deletionService
) {
parent::__construct();
$this->assignmentService = $assignmentService;
$this->deletionService = $deletionService;
$this->repository = $repository;
}
/**
* Return all of the allocations that exist for a given node.
*
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\GetAllocationsRequest $request
* @param \Pterodactyl\Models\Node $node
* @return array
*/
public function index(GetAllocationsRequest $request): array
public function index(GetAllocationsRequest $request, Node $node): array
{
$allocations = $this->repository->getPaginatedAllocationsForNode(
$request->getModel(Node::class)->id, 50
);
$allocations = $node->allocations()->paginate(50);
return $this->fractal->collection($allocations)
->transformWith($this->getTransformer(AllocationTransformer::class))
@ -71,32 +61,35 @@ class AllocationController extends ApplicationApiController
* Store new allocations for a given node.
*
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\StoreAllocationRequest $request
* @return \Illuminate\Http\Response
* @param \Pterodactyl\Models\Node $node
* @return \Illuminate\Http\JsonResponse
*
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
*/
public function store(StoreAllocationRequest $request): Response
public function store(StoreAllocationRequest $request, Node $node): JsonResponse
{
$this->assignmentService->handle($request->getModel(Node::class), $request->validated());
$this->assignmentService->handle($node, $request->validated());
return response('', 204);
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
}
/**
* Delete a specific allocation from the Panel.
*
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\DeleteAllocationRequest $request
* @return \Illuminate\Http\Response
* @param \Pterodactyl\Models\Node $node
* @param \Pterodactyl\Models\Allocation $allocation
* @return \Illuminate\Http\JsonResponse
*
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
*/
public function delete(DeleteAllocationRequest $request): Response
public function delete(DeleteAllocationRequest $request, Node $node, Allocation $allocation): JsonResponse
{
$this->deletionService->handle($request->getModel(Allocation::class));
$this->deletionService->handle($allocation);
return response('', 204);
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
}
}

View file

@ -10,6 +10,40 @@ use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
abstract class ClientApiController extends ApplicationApiController
{
/**
* Returns only the includes which are valid for the given transformer.
*
* @param \Pterodactyl\Transformers\Api\Client\BaseClientTransformer $transformer
* @param array $merge
* @return string[]
*/
protected function getIncludesForTransformer(BaseClientTransformer $transformer, array $merge = [])
{
$filtered = array_filter($this->parseIncludes(), function ($datum) use ($transformer) {
return in_array($datum, $transformer->getAvailableIncludes());
});
return array_merge($filtered, $merge);
}
/**
* Returns the parsed includes for this request.
*
* @return string[]
*/
protected function parseIncludes()
{
$includes = $this->request->query('include') ?? [];
if (! is_string($includes)) {
return $includes;
}
return array_map(function ($item) {
return trim($item);
}, explode(',', $includes));
}
/**
* Return an instance of an application transformer.
*

View file

@ -3,7 +3,9 @@
namespace Pterodactyl\Http\Controllers\Api\Client;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Permission;
use Spatie\QueryBuilder\QueryBuilder;
use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Transformers\Api\Client\ServerTransformer;
use Pterodactyl\Http\Requests\Api\Client\GetServersRequest;
@ -36,32 +38,36 @@ class ClientController extends ClientApiController
*/
public function index(GetServersRequest $request): array
{
// Check for the filter parameter on the request.
switch ($request->input('filter')) {
case 'all':
$filter = User::FILTER_LEVEL_ALL;
break;
case 'admin':
$filter = User::FILTER_LEVEL_ADMIN;
break;
case 'owner':
$filter = User::FILTER_LEVEL_OWNER;
break;
case 'subuser-of':
default:
$filter = User::FILTER_LEVEL_SUBUSER;
break;
$user = $request->user();
$level = $request->getFilterLevel();
$transformer = $this->getTransformer(ServerTransformer::class);
// Start the query builder and ensure we eager load any requested relationships from the request.
$builder = Server::query()->with($this->getIncludesForTransformer($transformer, ['node']));
if ($level === User::FILTER_LEVEL_OWNER) {
$builder = $builder->where('owner_id', $request->user()->id);
}
// If set to all, display all servers they can access, including those they access as an
// admin. If set to subuser, only return the servers they can access because they are owner,
// or marked as a subuser of the server.
elseif (($level === User::FILTER_LEVEL_ALL && ! $user->root_admin) || $level === User::FILTER_LEVEL_SUBUSER) {
$builder = $builder->whereIn('id', $user->accessibleServers()->pluck('id')->all());
}
// If set to admin, only display the servers a user can access because they are an administrator.
// This means only servers the user would not have access to if they were not an admin (because they
// are not an owner or subuser) are returned.
elseif ($level === User::FILTER_LEVEL_ADMIN && $user->root_admin) {
$builder = $builder->whereNotIn('id', $user->accessibleServers()->pluck('id')->all());
}
$servers = $this->repository
->setSearchTerm($request->input('query'))
->filterUserAccessServers(
$request->user(), $filter, config('pterodactyl.paginate.frontend.servers')
);
$builder = QueryBuilder::for($builder)->allowedFilters(
'uuid', 'name', 'external_id'
);
return $this->fractal->collection($servers)
->transformWith($this->getTransformer(ServerTransformer::class))
->toArray();
$servers = $builder->paginate(min($request->query('per_page', 50), 100))->appends($request->query());
return $this->fractal->transformWith($transformer)->collection($servers)->toArray();
}
/**

View file

@ -159,7 +159,7 @@ class FileController extends ClientApiController
{
$this->fileRepository
->setServer($server)
->createDirectory($request->input('name'), $request->input('directory', '/'));
->createDirectory($request->input('name'), $request->input('root', '/'));
return Response::create('', Response::HTTP_NO_CONTENT);
}

View file

@ -0,0 +1,127 @@
<?php
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Models\Allocation;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
use Pterodactyl\Transformers\Api\Client\AllocationTransformer;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
use Pterodactyl\Http\Requests\Api\Client\Servers\Network\GetNetworkRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Network\DeleteAllocationRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Network\UpdateAllocationRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Network\SetPrimaryAllocationRequest;
class NetworkAllocationController extends ClientApiController
{
/**
* @var \Pterodactyl\Repositories\Eloquent\AllocationRepository
*/
private $repository;
/**
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
*/
private $serverRepository;
/**
* NetworkController constructor.
*
* @param \Pterodactyl\Repositories\Eloquent\AllocationRepository $repository
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $serverRepository
*/
public function __construct(
AllocationRepository $repository,
ServerRepository $serverRepository
) {
parent::__construct();
$this->repository = $repository;
$this->serverRepository = $serverRepository;
}
/**
* Lists all of the allocations available to a server and wether or
* not they are currently assigned as the primary for this server.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\GetNetworkRequest $request
* @param \Pterodactyl\Models\Server $server
* @return array
*/
public function index(GetNetworkRequest $request, Server $server): array
{
return $this->fractal->collection($server->allocations)
->transformWith($this->getTransformer(AllocationTransformer::class))
->toArray();
}
/**
* Set the primary allocation for a server.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\UpdateAllocationRequest $request
* @param \Pterodactyl\Models\Server $server
* @param \Pterodactyl\Models\Allocation $allocation
* @return array
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function update(UpdateAllocationRequest $request, Server $server, Allocation $allocation): array
{
$allocation = $this->repository->update($allocation->id, [
'notes' => $request->input('notes'),
]);
return $this->fractal->item($allocation)
->transformWith($this->getTransformer(AllocationTransformer::class))
->toArray();
}
/**
* Set the primary allocation for a server.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\SetPrimaryAllocationRequest $request
* @param \Pterodactyl\Models\Server $server
* @param \Pterodactyl\Models\Allocation $allocation
* @return array
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function setPrimary(SetPrimaryAllocationRequest $request, Server $server, Allocation $allocation): array
{
$this->serverRepository->update($server->id, ['allocation_id' => $allocation->id]);
return $this->fractal->item($allocation)
->transformWith($this->getTransformer(AllocationTransformer::class))
->toArray();
}
/**
* Delete an allocation from a server.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\DeleteAllocationRequest $request
* @param \Pterodactyl\Models\Server $server
* @param \Pterodactyl\Models\Allocation $allocation
* @return \Illuminate\Http\JsonResponse
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/
public function delete(DeleteAllocationRequest $request, Server $server, Allocation $allocation)
{
if ($allocation->id === $server->allocation_id) {
throw new DisplayException(
'Cannot delete the primary allocation for a server.'
);
}
$this->repository->update($allocation->id, ['server_id' => null, 'notes' => null]);
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
}
}

View file

@ -1,48 +0,0 @@
<?php
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
use Pterodactyl\Models\Server;
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
use Pterodactyl\Transformers\Api\Client\AllocationTransformer;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
use Pterodactyl\Http\Requests\Api\Client\Servers\Network\GetNetworkRequest;
class NetworkController extends ClientApiController
{
/**
* @var \Pterodactyl\Repositories\Eloquent\AllocationRepository
*/
private $repository;
/**
* NetworkController constructor.
*
* @param \Pterodactyl\Repositories\Eloquent\AllocationRepository $repository
*/
public function __construct(AllocationRepository $repository)
{
parent::__construct();
$this->repository = $repository;
}
/**
* Lists all of the allocations available to a server and wether or
* not they are currently assigned as the primary for this server.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\GetNetworkRequest $request
* @param \Pterodactyl\Models\Server $server
* @return array
*/
public function index(GetNetworkRequest $request, Server $server): array
{
$allocations = $this->repository->findWhere([
['server_id', '=', $server->id],
]);
return $this->fractal->collection($allocations)
->transformWith($this->getTransformer(AllocationTransformer::class))
->toArray();
}
}

View file

@ -2,8 +2,6 @@
namespace Pterodactyl\Http\Controllers\Base;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
@ -27,15 +25,10 @@ class IndexController extends Controller
/**
* Returns listing of user's servers.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\View
*/
public function index(Request $request)
public function index()
{
$servers = $this->repository->setSearchTerm($request->input('query'))->filterUserAccessServers(
$request->user(), User::FILTER_LEVEL_ALL, config('pterodactyl.paginate.frontend.servers')
);
return view('templates/base.core', ['servers' => $servers]);
return view('templates/base.core');
}
}