Merge branch 'develop' into feature/file-uploads
This commit is contained in:
commit
54f9c5f187
136 changed files with 2178 additions and 971 deletions
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Client;
|
||||
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Permission;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
@ -39,31 +38,27 @@ class ClientController extends ClientApiController
|
|||
public function index(GetServersRequest $request): array
|
||||
{
|
||||
$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']));
|
||||
$builder = QueryBuilder::for(
|
||||
Server::query()->with($this->getIncludesForTransformer($transformer, ['node']))
|
||||
)->allowedFilters('uuid', 'name', 'external_id');
|
||||
|
||||
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) {
|
||||
// Either return all of the servers the user has access to because they are an admin `?type=admin` or
|
||||
// just return all of the servers the user has access to because they are the owner or a subuser of the
|
||||
// server.
|
||||
if ($request->input('type') === 'admin') {
|
||||
$builder = $user->root_admin
|
||||
? $builder->whereNotIn('id', $user->accessibleServers()->pluck('id')->all())
|
||||
// If they aren't an admin but want all the admin servers don't fail the request, just
|
||||
// make it a query that will never return any results back.
|
||||
: $builder->whereRaw('1 = 2');
|
||||
} elseif ($request->input('type') === 'owner') {
|
||||
$builder = $builder->where('owner_id', $user->id);
|
||||
} else {
|
||||
$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());
|
||||
}
|
||||
|
||||
$builder = QueryBuilder::for($builder)->allowedFilters(
|
||||
'uuid', 'name', 'external_id'
|
||||
);
|
||||
|
||||
$servers = $builder->paginate(min($request->query('per_page', 50), 100))->appends($request->query());
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
|||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\BadResponseException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Pterodactyl\Repositories\Wings\DaemonCommandRepository;
|
||||
|
@ -45,11 +44,13 @@ class CommandController extends ClientApiController
|
|||
{
|
||||
try {
|
||||
$this->repository->setServer($server)->send($request->input('command'));
|
||||
} catch (RequestException $exception) {
|
||||
if ($exception instanceof BadResponseException) {
|
||||
} catch (DaemonConnectionException $exception) {
|
||||
$previous = $exception->getPrevious();
|
||||
|
||||
if ($previous instanceof BadResponseException) {
|
||||
if (
|
||||
$exception->getResponse() instanceof ResponseInterface
|
||||
&& $exception->getResponse()->getStatusCode() === Response::HTTP_BAD_GATEWAY
|
||||
$previous->getResponse() instanceof ResponseInterface
|
||||
&& $previous->getResponse()->getStatusCode() === Response::HTTP_BAD_GATEWAY
|
||||
) {
|
||||
throw new HttpException(
|
||||
Response::HTTP_BAD_GATEWAY, 'Server must be online in order to send commands.', $exception
|
||||
|
@ -57,7 +58,7 @@ class CommandController extends ClientApiController
|
|||
}
|
||||
}
|
||||
|
||||
throw new DaemonConnectionException($exception);
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $this->returnNoContent();
|
||||
|
|
|
@ -6,19 +6,18 @@ use Carbon\CarbonImmutable;
|
|||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use GuzzleHttp\Exception\TransferException;
|
||||
use Pterodactyl\Services\Nodes\NodeJWTService;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Pterodactyl\Repositories\Wings\DaemonFileRepository;
|
||||
use Pterodactyl\Transformers\Daemon\FileObjectTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CopyFileRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DeleteFileRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CreateFolderRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CompressFilesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DecompressFilesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\GetFileContentsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\WriteFileContentRequest;
|
||||
|
||||
|
@ -69,13 +68,9 @@ class FileController extends ClientApiController
|
|||
*/
|
||||
public function directory(ListFilesRequest $request, Server $server): array
|
||||
{
|
||||
try {
|
||||
$contents = $this->fileRepository
|
||||
->setServer($server)
|
||||
->getDirectory($request->get('directory') ?? '/');
|
||||
} catch (TransferException $exception) {
|
||||
throw new DaemonConnectionException($exception, true);
|
||||
}
|
||||
$contents = $this->fileRepository
|
||||
->setServer($server)
|
||||
->getDirectory($request->get('directory') ?? '/');
|
||||
|
||||
return $this->fractal->collection($contents)
|
||||
->transformWith($this->getTransformer(FileObjectTransformer::class))
|
||||
|
@ -88,7 +83,9 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\GetFileContentsRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Server\FileSizeTooLargeException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function contents(GetFileContentsRequest $request, Server $server): Response
|
||||
{
|
||||
|
@ -139,6 +136,8 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\WriteFileContentRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function write(WriteFileContentRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
|
@ -156,6 +155,8 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\CreateFolderRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function create(CreateFolderRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
|
@ -172,6 +173,8 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function rename(RenameFileRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
|
@ -188,6 +191,8 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\CopyFileRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function copy(CopyFileRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
|
@ -202,9 +207,14 @@ class FileController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\CompressFilesRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function compress(CompressFilesRequest $request, Server $server): array
|
||||
{
|
||||
// Allow up to five minutes for this request to process before timing out.
|
||||
set_time_limit(300);
|
||||
|
||||
$file = $this->fileRepository->setServer($server)
|
||||
->compressFiles(
|
||||
$request->input('root'), $request->input('files')
|
||||
|
@ -215,12 +225,32 @@ class FileController extends ClientApiController
|
|||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\DecompressFilesRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function decompress(DecompressFilesRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
// Allow up to five minutes for this request to process before timing out.
|
||||
set_time_limit(300);
|
||||
|
||||
$this->fileRepository->setServer($server)
|
||||
->decompressFile($request->input('root'), $request->input('file'));
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes files or folders for the server in the given root directory.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\DeleteFileRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function delete(DeleteFileRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
|
|
|
@ -33,6 +33,8 @@ class PowerController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\SendPowerRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function index(SendPowerRequest $request, Server $server): Response
|
||||
{
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Services\Servers\VariableValidatorService;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerVariableRepository;
|
||||
use Pterodactyl\Transformers\Api\Client\EggVariableTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Startup\UpdateStartupVariableRequest;
|
||||
|
||||
class StartupController extends ClientApiController
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\VariableValidatorService
|
||||
*/
|
||||
private $service;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerVariableRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* StartupController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Services\Servers\VariableValidatorService $service
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerVariableRepository $repository
|
||||
*/
|
||||
public function __construct(VariableValidatorService $service, ServerVariableRepository $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->service = $service;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a single variable for a server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Startup\UpdateStartupVariableRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(UpdateStartupVariableRequest $request, Server $server)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\EggVariable $variable */
|
||||
$variable = $server->variables()->where('env_variable', $request->input('key'))->first();
|
||||
|
||||
if (is_null($variable) || !$variable->user_viewable || !$variable->user_editable) {
|
||||
throw new BadRequestHttpException(
|
||||
"The environment variable you are trying to edit [\"{$request->input('key')}\"] does not exist."
|
||||
);
|
||||
}
|
||||
|
||||
// Revalidate the variable value using the egg variable specific validation rules for it.
|
||||
$this->validate($request, ['value' => $variable->rules]);
|
||||
|
||||
$this->repository->updateOrCreate([
|
||||
'server_id' => $server->id,
|
||||
'variable_id' => $variable->id,
|
||||
], [
|
||||
'variable_value' => $request->input('value'),
|
||||
]);
|
||||
|
||||
$variable = $variable->refresh();
|
||||
$variable->server_value = $request->input('value');
|
||||
|
||||
return $this->fractal->item($variable)
|
||||
->transformWith($this->getTransformer(EggVariableTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Subuser;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\Permission;
|
||||
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
|
||||
|
@ -57,6 +59,21 @@ class SubuserController extends ClientApiController
|
|||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single subuser associated with this server instance.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\GetSubuserRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function view(GetSubuserRequest $request)
|
||||
{
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
return $this->fractal->item($subuser)
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subuser for the given server.
|
||||
*
|
||||
|
@ -84,15 +101,16 @@ class SubuserController extends ClientApiController
|
|||
* Update a given subuser in the system for the server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\UpdateSubuserRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(UpdateSubuserRequest $request, Server $server): array
|
||||
public function update(UpdateSubuserRequest $request): array
|
||||
{
|
||||
$subuser = $request->endpointSubuser();
|
||||
/** @var \Pterodactyl\Models\Subuser $subuser */
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
$this->repository->update($subuser->id, [
|
||||
'permissions' => $this->getDefaultPermissions($request),
|
||||
]);
|
||||
|
@ -106,14 +124,16 @@ class SubuserController extends ClientApiController
|
|||
* Removes a subusers from a server's assignment.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\DeleteSubuserRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function delete(DeleteSubuserRequest $request, Server $server)
|
||||
public function delete(DeleteSubuserRequest $request)
|
||||
{
|
||||
$this->repository->delete($request->endpointSubuser()->id);
|
||||
/** @var \Pterodactyl\Models\Subuser $subuser */
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
return JsonResponse::create([], JsonResponse::HTTP_NO_CONTENT);
|
||||
$this->repository->delete($subuser->id);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Remote\Backups;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\BackupRepository;
|
||||
|
@ -31,25 +32,16 @@ class BackupStatusController extends Controller
|
|||
* @param \Pterodactyl\Http\Requests\Api\Remote\ReportBackupCompleteRequest $request
|
||||
* @param string $backup
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function __invoke(ReportBackupCompleteRequest $request, string $backup)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\Backup $backup */
|
||||
$backup = $this->repository->findFirstWhere([['uuid', '=', $backup]]);
|
||||
$this->repository->updateWhere([['uuid', '=', $backup]], [
|
||||
'is_successful' => $request->input('successful') ? true : false,
|
||||
'sha256_hash' => $request->input('checksum'),
|
||||
'bytes' => $request->input('size'),
|
||||
'completed_at' => CarbonImmutable::now(),
|
||||
]);
|
||||
|
||||
if ($request->input('successful')) {
|
||||
$this->repository->update($backup->id, [
|
||||
'sha256_hash' => $request->input('checksum'),
|
||||
'bytes' => $request->input('size'),
|
||||
'completed_at' => Carbon::now(),
|
||||
], true, true);
|
||||
} else {
|
||||
$this->repository->delete($backup->id);
|
||||
}
|
||||
|
||||
return JsonResponse::create([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue