Skip to content

Commit 1754448

Browse files
committed
More server management via the API
1 parent 3724559 commit 1754448

File tree

6 files changed

+193
-26
lines changed

6 files changed

+193
-26
lines changed

app/Http/Controllers/Api/Application/ApplicationApiController.php

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Pterodactyl\Http\Controllers\Api\Application;
44

55
use Illuminate\Http\Request;
6+
use Illuminate\Http\Response;
67
use Illuminate\Container\Container;
78
use Pterodactyl\Http\Controllers\Controller;
89
use Pterodactyl\Extensions\Spatie\Fractalistic\Fractal;
@@ -21,24 +22,33 @@ abstract class ApplicationApiController extends Controller
2122

2223
/**
2324
* ApplicationApiController constructor.
24-
*
25-
* @param \Pterodactyl\Extensions\Spatie\Fractalistic\Fractal $fractal
26-
* @param \Illuminate\Http\Request $request
2725
*/
28-
public function __construct(Fractal $fractal, Request $request)
26+
public function __construct()
2927
{
30-
$this->fractal = $fractal;
31-
$this->request = $request;
28+
Container::getInstance()->call([$this, 'loadDependencies']);
3229

3330
// Parse all of the includes to use on this request.
34-
$includes = collect(explode(',', $request->input('include', '')))->map(function ($value) {
31+
$includes = collect(explode(',', $this->request->input('include', '')))->map(function ($value) {
3532
return trim($value);
3633
})->filter()->toArray();
3734

3835
$this->fractal->parseIncludes($includes);
3936
$this->fractal->limitRecursion(2);
4037
}
4138

39+
/**
40+
* Perform dependency injection of certain classes needed for core functionality
41+
* without littering the constructors of classes that extend this abstract.
42+
*
43+
* @param \Pterodactyl\Extensions\Spatie\Fractalistic\Fractal $fractal
44+
* @param \Illuminate\Http\Request $request
45+
*/
46+
public function loadDependencies(Fractal $fractal, Request $request)
47+
{
48+
$this->fractal = $fractal;
49+
$this->request = $request;
50+
}
51+
4252
/**
4353
* Return an instance of an application transformer.
4454
*
@@ -53,4 +63,14 @@ public function getTransformer(string $abstract)
5363

5464
return $transformer;
5565
}
66+
67+
/**
68+
* Return a HTTP/204 response for the API.
69+
*
70+
* @return \Illuminate\Http\Response
71+
*/
72+
protected function returnNoContent(): Response
73+
{
74+
return new Response('', Response::HTTP_NO_CONTENT);
75+
}
5676
}

app/Http/Controllers/Api/Application/Servers/ServerController.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22

33
namespace Pterodactyl\Http\Controllers\Api\Application\Servers;
44

5-
use Illuminate\Http\Request;
5+
use Illuminate\Http\Response;
66
use Pterodactyl\Models\Server;
7-
use Pterodactyl\Extensions\Spatie\Fractalistic\Fractal;
7+
use Pterodactyl\Services\Servers\ServerDeletionService;
88
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
99
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
10-
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServerRequest;
1110
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServersRequest;
11+
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
1212
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
1313

1414
class ServerController extends ApplicationApiController
1515
{
16+
/**
17+
* @var \Pterodactyl\Services\Servers\ServerDeletionService
18+
*/
19+
private $deletionService;
20+
1621
/**
1722
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
1823
*/
@@ -21,14 +26,14 @@ class ServerController extends ApplicationApiController
2126
/**
2227
* ServerController constructor.
2328
*
24-
* @param \Pterodactyl\Extensions\Spatie\Fractalistic\Fractal $fractal
25-
* @param \Illuminate\Http\Request $request
29+
* @param \Pterodactyl\Services\Servers\ServerDeletionService $deletionService
2630
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
2731
*/
28-
public function __construct(Fractal $fractal, Request $request, ServerRepositoryInterface $repository)
32+
public function __construct(ServerDeletionService $deletionService, ServerRepositoryInterface $repository)
2933
{
30-
parent::__construct($fractal, $request);
34+
parent::__construct();
3135

36+
$this->deletionService = $deletionService;
3237
$this->repository = $repository;
3338
}
3439

@@ -50,14 +55,30 @@ public function index(GetServersRequest $request): array
5055
/**
5156
* Show a single server transformed for the application API.
5257
*
53-
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\GetServerRequest $request
54-
* @param \Pterodactyl\Models\Server $server
58+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
59+
* @param \Pterodactyl\Models\Server $server
5560
* @return array
5661
*/
57-
public function view(GetServerRequest $request, Server $server): array
62+
public function view(ServerWriteRequest $request, Server $server): array
5863
{
5964
return $this->fractal->item($server)
6065
->transformWith($this->getTransformer(ServerTransformer::class))
6166
->toArray();
6267
}
68+
69+
/**
70+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
71+
* @param \Pterodactyl\Models\Server $server
72+
* @param string $force
73+
* @return \Illuminate\Http\Response
74+
*
75+
* @throws \Pterodactyl\Exceptions\DisplayException
76+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
77+
*/
78+
public function delete(ServerWriteRequest $request, Server $server, string $force = ''): Response
79+
{
80+
$this->deletionService->withForce($force === 'force')->handle($server);
81+
82+
return $this->returnNoContent();
83+
}
6384
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\Api\Application\Servers;
4+
5+
use Illuminate\Http\Response;
6+
use Pterodactyl\Models\Server;
7+
use Pterodactyl\Services\Servers\SuspensionService;
8+
use Pterodactyl\Services\Servers\ReinstallServerService;
9+
use Pterodactyl\Services\Servers\ContainerRebuildService;
10+
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
11+
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
12+
13+
class ServerManagementController extends ApplicationApiController
14+
{
15+
/**
16+
* @var \Pterodactyl\Services\Servers\ContainerRebuildService
17+
*/
18+
private $rebuildService;
19+
20+
/**
21+
* @var \Pterodactyl\Services\Servers\ReinstallServerService
22+
*/
23+
private $reinstallServerService;
24+
25+
/**
26+
* @var \Pterodactyl\Services\Servers\SuspensionService
27+
*/
28+
private $suspensionService;
29+
30+
/**
31+
* SuspensionController constructor.
32+
*
33+
* @param \Pterodactyl\Services\Servers\ContainerRebuildService $rebuildService
34+
* @param \Pterodactyl\Services\Servers\ReinstallServerService $reinstallServerService
35+
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
36+
*/
37+
public function __construct(ContainerRebuildService $rebuildService, ReinstallServerService $reinstallServerService, SuspensionService $suspensionService)
38+
{
39+
parent::__construct();
40+
41+
$this->rebuildService = $rebuildService;
42+
$this->reinstallServerService = $reinstallServerService;
43+
$this->suspensionService = $suspensionService;
44+
}
45+
46+
/**
47+
* Suspend a server on the Panel.
48+
*
49+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
50+
* @param \Pterodactyl\Models\Server $server
51+
* @return \Illuminate\Http\Response
52+
*
53+
* @throws \Pterodactyl\Exceptions\DisplayException
54+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
55+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
56+
*/
57+
public function suspend(ServerWriteRequest $request, Server $server): Response
58+
{
59+
$this->suspensionService->toggle($server, SuspensionService::ACTION_SUSPEND);
60+
61+
return $this->returnNoContent();
62+
}
63+
64+
/**
65+
* Unsuspend a server on the Panel.
66+
*
67+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
68+
* @param \Pterodactyl\Models\Server $server
69+
* @return \Illuminate\Http\Response
70+
*
71+
* @throws \Pterodactyl\Exceptions\DisplayException
72+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
73+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
74+
*/
75+
public function unsuspend(ServerWriteRequest $request, Server $server): Response
76+
{
77+
$this->suspensionService->toggle($server, SuspensionService::ACTION_UNSUSPEND);
78+
79+
return $this->returnNoContent();
80+
}
81+
82+
/**
83+
* Mark a server as needing to be reinstalled.
84+
*
85+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
86+
* @param \Pterodactyl\Models\Server $server
87+
* @return \Illuminate\Http\Response
88+
*
89+
* @throws \Pterodactyl\Exceptions\DisplayException
90+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
91+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
92+
*/
93+
public function reinstall(ServerWriteRequest $request, Server $server): Response
94+
{
95+
$this->reinstallServerService->reinstall($server);
96+
97+
return $this->returnNoContent();
98+
}
99+
100+
/**
101+
* Mark a server as needing its container rebuilt the next time it is started.
102+
*
103+
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
104+
* @param \Pterodactyl\Models\Server $server
105+
* @return \Illuminate\Http\Response
106+
*
107+
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
108+
*/
109+
public function rebuild(ServerWriteRequest $request, Server $server): Response
110+
{
111+
$this->rebuildService->handle($server);
112+
113+
return $this->returnNoContent();
114+
}
115+
}

app/Http/Requests/Api/Application/Servers/GetServerRequest.php renamed to app/Http/Requests/Api/Application/Servers/ServerWriteRequest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use Pterodactyl\Services\Acl\Api\AdminAcl;
77
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
88

9-
class GetServerRequest extends ApplicationApiRequest
9+
class ServerWriteRequest extends ApplicationApiRequest
1010
{
1111
/**
1212
* @var string
@@ -16,7 +16,7 @@ class GetServerRequest extends ApplicationApiRequest
1616
/**
1717
* @var int
1818
*/
19-
protected $permission = AdminAcl::READ;
19+
protected $permission = AdminAcl::WRITE;
2020

2121
/**
2222
* Determine if the requested server exists on the Panel.

app/Services/Servers/SuspensionService.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
class SuspensionService
2121
{
22+
const ACTION_SUSPEND = 'suspend';
23+
const ACTION_UNSUSPEND = 'unsuspend';
24+
2225
/**
2326
* @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface
2427
*/
@@ -70,29 +73,29 @@ public function __construct(
7073
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
7174
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
7275
*/
73-
public function toggle($server, $action = 'suspend')
76+
public function toggle($server, $action = self::ACTION_SUSPEND)
7477
{
7578
if (! $server instanceof Server) {
7679
$server = $this->repository->find($server);
7780
}
7881

79-
if (! in_array($action, ['suspend', 'unsuspend'])) {
82+
if (! in_array($action, [self::ACTION_SUSPEND, self::ACTION_UNSUSPEND])) {
8083
throw new \InvalidArgumentException(sprintf(
81-
'Action must be either suspend or unsuspend, %s passed.',
84+
'Action must be either ' . self::ACTION_SUSPEND . ' or ' . self::ACTION_UNSUSPEND . ', %s passed.',
8285
$action
8386
));
8487
}
8588

8689
if (
87-
$action === 'suspend' && $server->suspended ||
88-
$action === 'unsuspend' && ! $server->suspended
90+
$action === self::ACTION_SUSPEND && $server->suspended ||
91+
$action === self::ACTION_UNSUSPEND && ! $server->suspended
8992
) {
9093
return true;
9194
}
9295

9396
$this->database->beginTransaction();
9497
$this->repository->withoutFreshModel()->update($server->id, [
95-
'suspended' => $action === 'suspend',
98+
'suspended' => $action === self::ACTION_SUSPEND,
9699
]);
97100

98101
try {

routes/api-application.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,13 @@
9696
});
9797

9898
Route::get('/', 'Servers\ServerController@index')->name('api.application.servers');
99-
Route::get('/{server}', 'Servers\ServerController@view')->name('api.application.servers');
99+
Route::get('/{server}', 'Servers\ServerController@view')->name('api.application.servers.view');
100+
101+
Route::post('/{server}/suspend', 'Servers\ServerManagementController@suspend')->name('api.application.servers.suspend');
102+
Route::post('/{server}/unsuspend', 'Servers\ServerManagementController@unsuspend')->name('api.application.servers.unsuspend');
103+
Route::post('/{server}/reinstall', 'Servers\ServerManagementController@reinstall')->name('api.application.servers.reinstall');
104+
Route::post('/{server}/rebuild', 'Servers\ServerManagementController@rebuild')->name('api.application.servers.rebuild');
105+
106+
Route::delete('/{server}', 'Servers\ServerController@delete');
107+
Route::delete('/{server}/{force?}', 'Servers\ServerController@delete');
100108
});

0 commit comments

Comments
 (0)