diff --git a/app/Http/Controllers/Api/Application/Servers/ServerManagementController.php b/app/Http/Controllers/Api/Application/Servers/ServerManagementController.php index 3c7e2997e..7a48f4bfd 100644 --- a/app/Http/Controllers/Api/Application/Servers/ServerManagementController.php +++ b/app/Http/Controllers/Api/Application/Servers/ServerManagementController.php @@ -50,15 +50,16 @@ class ServerManagementController extends ApplicationApiController * Suspend a server on the Panel. * * @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request + * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\Response * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - public function suspend(ServerWriteRequest $request): Response + public function suspend(ServerWriteRequest $request, Server $server): Response { - $this->suspensionService->toggle($request->getModel(Server::class), SuspensionService::ACTION_SUSPEND); + $this->suspensionService->toggle($server, SuspensionService::ACTION_SUSPEND); return $this->returnNoContent(); } @@ -67,15 +68,16 @@ class ServerManagementController extends ApplicationApiController * Unsuspend a server on the Panel. * * @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request + * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\Response * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - public function unsuspend(ServerWriteRequest $request): Response + public function unsuspend(ServerWriteRequest $request, Server $server): Response { - $this->suspensionService->toggle($request->getModel(Server::class), SuspensionService::ACTION_UNSUSPEND); + $this->suspensionService->toggle($server, SuspensionService::ACTION_UNSUSPEND); return $this->returnNoContent(); } @@ -84,15 +86,16 @@ class ServerManagementController extends ApplicationApiController * Mark a server as needing to be reinstalled. * * @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request + * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\Response * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - public function reinstall(ServerWriteRequest $request): Response + public function reinstall(ServerWriteRequest $request, Server $server): Response { - $this->reinstallServerService->reinstall($request->getModel(Server::class)); + $this->reinstallServerService->reinstall($server); return $this->returnNoContent(); } @@ -101,13 +104,14 @@ class ServerManagementController extends ApplicationApiController * Mark a server as needing its container rebuilt the next time it is started. * * @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request + * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\Response * * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ - public function rebuild(ServerWriteRequest $request): Response + public function rebuild(ServerWriteRequest $request, Server $server): Response { - $this->rebuildService->handle($request->getModel(Server::class)); + $this->rebuildService->handle($server); return $this->returnNoContent(); } diff --git a/app/Repositories/Wings/DaemonServerRepository.php b/app/Repositories/Wings/DaemonServerRepository.php index ddd4c4d60..676eed6d7 100644 --- a/app/Repositories/Wings/DaemonServerRepository.php +++ b/app/Repositories/Wings/DaemonServerRepository.php @@ -87,13 +87,25 @@ class DaemonServerRepository extends DaemonRepository throw new BadMethodCallException('Method is not implemented.'); } - public function suspend(): void + /** + * By default this function will suspend a server instance on the daemon. However, passing + * "true" as the first argument will unsuspend the server. + * + * @param bool $unsuspend + * + * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException + */ + public function suspend(bool $unsuspend = false): void { - throw new BadMethodCallException('Method is not implemented.'); - } + Assert::isInstanceOf($this->server, Server::class); - public function unsuspend(): void - { - throw new BadMethodCallException('Method is not implemented.'); + try { + $this->getHttpClient()->patch( + '/api/servers/' . $this->server->uuid, + ['json' => ['suspended' => ! $unsuspend]] + ); + } catch (TransferException $exception) { + throw new DaemonConnectionException($exception); + } } } diff --git a/app/Services/Servers/SuspensionService.php b/app/Services/Servers/SuspensionService.php index 3eba0fefd..9fb95645d 100644 --- a/app/Services/Servers/SuspensionService.php +++ b/app/Services/Servers/SuspensionService.php @@ -3,11 +3,9 @@ namespace Pterodactyl\Services\Servers; use Psr\Log\LoggerInterface; -use InvalidArgumentException; +use Webmozart\Assert\Assert; use Pterodactyl\Models\Server; -use GuzzleHttp\Exception\RequestException; use Illuminate\Database\ConnectionInterface; -use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Repositories\Wings\DaemonServerRepository; use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; @@ -19,7 +17,7 @@ class SuspensionService /** * @var \Illuminate\Database\ConnectionInterface */ - private $database; + private $connection; /** * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface @@ -39,18 +37,18 @@ class SuspensionService /** * SuspensionService constructor. * - * @param \Illuminate\Database\ConnectionInterface $database + * @param \Illuminate\Database\ConnectionInterface $connection * @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository * @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository * @param \Psr\Log\LoggerInterface $writer */ public function __construct( - ConnectionInterface $database, + ConnectionInterface $connection, DaemonServerRepository $daemonServerRepository, ServerRepositoryInterface $repository, LoggerInterface $writer ) { - $this->database = $database; + $this->connection = $connection; $this->repository = $repository; $this->writer = $writer; $this->daemonServerRepository = $daemonServerRepository; @@ -61,49 +59,26 @@ class SuspensionService * * @param int|\Pterodactyl\Models\Server $server * @param string $action - * @return bool * - * @throws \Pterodactyl\Exceptions\DisplayException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + * @throws \Throwable */ - public function toggle($server, $action = self::ACTION_SUSPEND) + public function toggle(Server $server, $action = self::ACTION_SUSPEND) { - if (! $server instanceof Server) { - $server = $this->repository->find($server); - } - - if (! in_array($action, [self::ACTION_SUSPEND, self::ACTION_UNSUSPEND])) { - throw new InvalidArgumentException(sprintf( - 'Action must be either ' . self::ACTION_SUSPEND . ' or ' . self::ACTION_UNSUSPEND . ', %s passed.', - $action - )); - } + Assert::oneOf($action, [self::ACTION_SUSPEND, self::ACTION_UNSUSPEND]); if ( $action === self::ACTION_SUSPEND && $server->suspended || $action === self::ACTION_UNSUSPEND && ! $server->suspended ) { - return true; + return; } - $this->database->beginTransaction(); - $this->repository->withoutFreshModel()->update($server->id, [ - 'suspended' => $action === self::ACTION_SUSPEND, - ]); + $this->connection->transaction(function () use ($action, $server) { + $this->repository->withoutFreshModel()->update($server->id, [ + 'suspended' => $action === self::ACTION_SUSPEND, + ]); - try { - $this->daemonServerRepository->setServer($server)->$action(); - $this->database->commit(); - - return true; - } catch (RequestException $exception) { - $response = $exception->getResponse(); - $this->writer->warning($exception); - - throw new DisplayException(trans('admin/server.exceptions.daemon_exception', [ - 'code' => is_null($response) ? 'E_CONN_REFUSED' : $response->getStatusCode(), - ])); - } + $this->daemonServerRepository->setServer($server)->suspend($action === self::ACTION_UNSUSPEND); + }); } }