Merge branch 'develop' into develop

This commit is contained in:
Dane Everitt 2020-10-31 13:47:12 -07:00 committed by GitHub
commit 665a4dd8a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 3434 additions and 1970 deletions

View file

@ -5,6 +5,8 @@ namespace Pterodactyl\Http\Controllers\Api\Client;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Permission;
use Spatie\QueryBuilder\QueryBuilder;
use Spatie\QueryBuilder\AllowedFilter;
use Pterodactyl\Models\Filters\MultiFieldServerFilter;
use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Transformers\Api\Client\ServerTransformer;
use Pterodactyl\Http\Requests\Api\Client\GetServersRequest;
@ -43,21 +45,32 @@ class ClientController extends ClientApiController
// Start the query builder and ensure we eager load any requested relationships from the request.
$builder = QueryBuilder::for(
Server::query()->with($this->getIncludesForTransformer($transformer, ['node']))
)->allowedFilters('uuid', 'name', 'external_id');
)->allowedFilters([
'uuid',
'name',
'external_id',
AllowedFilter::custom('*', new MultiFieldServerFilter),
]);
$type = $request->input('type');
// 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);
// server. If ?type=admin-all is passed all servers on the system will be returned to the user, rather
// than only servers they can see because they are an admin.
if (in_array($type, ['admin', 'admin-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.
if (! $user->root_admin) {
$builder->whereRaw('1 = 2');
} else {
$builder = $type === 'admin-all'
? $builder
: $builder->whereNotIn('servers.id', $user->accessibleServers()->pluck('id')->all());
}
} else if ($type === 'owner') {
$builder = $builder->where('servers.owner_id', $user->id);
} else {
$builder = $builder->whereIn('id', $user->accessibleServers()->pluck('id')->all());
$builder = $builder->whereIn('servers.id', $user->accessibleServers()->pluck('id')->all());
}
$servers = $builder->paginate(min($request->query('per_page', 50), 100))->appends($request->query());

View file

@ -10,15 +10,19 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Models\Schedule;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Helpers\Utilities;
use Pterodactyl\Jobs\Schedule\RunTaskJob;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
use Pterodactyl\Services\Schedules\ProcessScheduleService;
use Pterodactyl\Transformers\Api\Client\ScheduleTransformer;
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\Schedules\ViewScheduleRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\StoreScheduleRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\DeleteScheduleRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\UpdateScheduleRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest;
class ScheduleController extends ClientApiController
{
@ -27,16 +31,23 @@ class ScheduleController extends ClientApiController
*/
private $repository;
/**
* @var \Pterodactyl\Services\Schedules\ProcessScheduleService
*/
private $service;
/**
* ScheduleController constructor.
*
* @param \Pterodactyl\Repositories\Eloquent\ScheduleRepository $repository
* @param \Pterodactyl\Services\Schedules\ProcessScheduleService $service
*/
public function __construct(ScheduleRepository $repository)
public function __construct(ScheduleRepository $repository, ProcessScheduleService $service)
{
parent::__construct();
$this->repository = $repository;
$this->service = $service;
}
/**
@ -147,6 +158,30 @@ class ScheduleController extends ClientApiController
->toArray();
}
/**
* Executes a given schedule immediately rather than waiting on it's normally scheduled time
* to pass. This does not care about the schedule state.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest $request
* @param \Pterodactyl\Models\Server $server
* @param \Pterodactyl\Models\Schedule $schedule
* @return \Illuminate\Http\JsonResponse
*
* @throws \Throwable
*/
public function execute(TriggerScheduleRequest $request, Server $server, Schedule $schedule)
{
if (!$schedule->is_active) {
throw new BadRequestHttpException(
'Cannot trigger schedule exection for a schedule that is not currently active.'
);
}
$this->service->handle($schedule, true);
return new JsonResponse([], JsonResponse::HTTP_ACCEPTED);
}
/**
* Deletes a schedule and it's associated tasks.
*

View file

@ -56,7 +56,8 @@ class ScheduleTaskController extends ClientApiController
);
}
$lastTask = $schedule->tasks->last();
/** @var \Pterodactyl\Models\Task|null $lastTask */
$lastTask = $schedule->tasks()->orderByDesc('sequence_id')->first();
/** @var \Pterodactyl\Models\Task $task */
$task = $this->repository->create([
@ -102,13 +103,16 @@ class ScheduleTaskController extends ClientApiController
}
/**
* Determines if a user can delete the task for a given server.
* Delete a given task for a schedule. If there are subsequent tasks stored in the database
* for this schedule their sequence IDs are decremented properly.
*
* @param \Pterodactyl\Http\Requests\Api\Client\ClientApiRequest $request
* @param \Pterodactyl\Models\Server $server
* @param \Pterodactyl\Models\Schedule $schedule
* @param \Pterodactyl\Models\Task $task
* @return \Illuminate\Http\JsonResponse
*
* @throws \Exception
*/
public function delete(ClientApiRequest $request, Server $server, Schedule $schedule, Task $task)
{
@ -120,8 +124,12 @@ class ScheduleTaskController extends ClientApiController
throw new HttpForbiddenException('You do not have permission to perform this action.');
}
$this->repository->delete($task->id);
$schedule->tasks()->where('sequence_id', '>', $task->sequence_id)->update([
'sequence_id' => $schedule->tasks()->getConnection()->raw('(sequence_id - 1)'),
]);
return JsonResponse::create(null, Response::HTTP_NO_CONTENT);
$task->delete();
return new JsonResponse(null, Response::HTTP_NO_CONTENT);
}
}

View file

@ -3,11 +3,14 @@
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
use Illuminate\Http\Request;
use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\Eloquent\NodeRepository;
use Pterodactyl\Services\Eggs\EggConfigurationService;
use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Http\Resources\Wings\ServerConfigurationCollection;
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
class ServerDetailsController extends Controller
@ -27,11 +30,6 @@ class ServerDetailsController extends Controller
*/
private $configurationStructureService;
/**
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
*/
private $nodeRepository;
/**
* ServerConfigurationController constructor.
*
@ -49,7 +47,6 @@ class ServerDetailsController extends Controller
$this->eggConfigurationService = $eggConfigurationService;
$this->repository = $repository;
$this->configurationStructureService = $configurationStructureService;
$this->nodeRepository = $nodeRepository;
}
/**
@ -66,7 +63,7 @@ class ServerDetailsController extends Controller
{
$server = $this->repository->getByUuid($uuid);
return JsonResponse::create([
return new JsonResponse([
'settings' => $this->configurationStructureService->handle($server),
'process_configuration' => $this->eggConfigurationService->handle($server),
]);
@ -76,25 +73,19 @@ class ServerDetailsController extends Controller
* Lists all servers with their configurations that are assigned to the requesting node.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @return \Pterodactyl\Http\Resources\Wings\ServerConfigurationCollection
*/
public function list(Request $request)
{
/** @var \Pterodactyl\Models\Node $node */
$node = $request->attributes->get('node');
$servers = $this->repository->loadEveryServerForNode($node->id);
$configurations = [];
// Avoid run-away N+1 SQL queries by pre-loading the relationships that are used
// within each of the services called below.
$servers = Server::query()->with('allocations', 'egg', 'mounts', 'variables', 'location')
->where('node_id', $node->id)
->paginate($request->input('per_page', 50));
foreach ($servers as $server) {
$configurations[$server->uuid] = [
'settings' => $this->configurationStructureService->handle($server),
'process_configuration' => $this->eggConfigurationService->handle($server),
];
}
return JsonResponse::create($configurations);
return new ServerConfigurationCollection($servers);
}
}