Merge branch 'develop' into matthewpi/security-keys-backport
This commit is contained in:
commit
f631ac1946
1153 changed files with 25099 additions and 37002 deletions
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\ApiKey;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Api\KeyCreationService;
|
||||
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Api\StoreApplicationApiKeyRequest;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* ApiController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private ApiKeyRepositoryInterface $repository,
|
||||
private KeyCreationService $keyCreationService,
|
||||
private ViewFactory $view,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render view showing all of a user's application API keys.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
return $this->view->make('admin.api.index', [
|
||||
'keys' => $this->repository->getApplicationKeys($request->user()),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render view allowing an admin to create a new application API key.
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
$resources = AdminAcl::getResourceList();
|
||||
sort($resources);
|
||||
|
||||
return $this->view->make('admin.api.new', [
|
||||
'resources' => $resources,
|
||||
'permissions' => [
|
||||
'r' => AdminAcl::READ,
|
||||
'rw' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'n' => AdminAcl::NONE,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the new key and redirect the user back to the application key listing.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function store(StoreApplicationApiKeyRequest $request): RedirectResponse
|
||||
{
|
||||
$this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([
|
||||
'memo' => $request->input('memo'),
|
||||
'user_id' => $request->user()->id,
|
||||
], $request->getKeyPermissions());
|
||||
|
||||
$this->alert->success('A new application API key has been generated for your account.')->flash();
|
||||
|
||||
return redirect()->route('admin.api.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an application API key from the database.
|
||||
*/
|
||||
public function delete(Request $request, string $identifier): Response
|
||||
{
|
||||
$this->repository->deleteApplicationKey($request->user(), $identifier);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
|
@ -3,24 +3,12 @@
|
|||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
|
||||
class BaseController extends Controller
|
||||
{
|
||||
/**
|
||||
* BaseController constructor.
|
||||
*/
|
||||
public function __construct(private SoftwareVersionService $version, private ViewFactory $view)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the admin index view.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.index', ['version' => $this->version]);
|
||||
return view('templates/base.core');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Exception;
|
||||
use PDOException;
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\DatabaseHost;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Databases\Hosts\HostUpdateService;
|
||||
use Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest;
|
||||
use Pterodactyl\Services\Databases\Hosts\HostCreationService;
|
||||
use Pterodactyl\Services\Databases\Hosts\HostDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
||||
|
||||
class DatabaseController extends Controller
|
||||
{
|
||||
/**
|
||||
* DatabaseController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private DatabaseHostRepositoryInterface $repository,
|
||||
private DatabaseRepositoryInterface $databaseRepository,
|
||||
private HostCreationService $creationService,
|
||||
private HostDeletionService $deletionService,
|
||||
private HostUpdateService $updateService,
|
||||
private LocationRepositoryInterface $locationRepository,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Display database host index.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.databases.index', [
|
||||
'locations' => $this->locationRepository->getAllWithNodes(),
|
||||
'hosts' => $this->repository->getWithViewDetails(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display database host to user.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(int $host): View
|
||||
{
|
||||
return $this->view->make('admin.databases.view', [
|
||||
'locations' => $this->locationRepository->getAllWithNodes(),
|
||||
'host' => $this->repository->find($host),
|
||||
'databases' => $this->databaseRepository->getDatabasesForHost($host),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to create a new database host.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function create(DatabaseHostFormRequest $request): RedirectResponse
|
||||
{
|
||||
try {
|
||||
$host = $this->creationService->handle($request->normalize());
|
||||
} catch (Exception $exception) {
|
||||
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||
$this->alert->danger(
|
||||
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||
)->flash();
|
||||
|
||||
return redirect()->route('admin.databases')->withInput($request->validated());
|
||||
} else {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
$this->alert->success('Successfully created a new database host on the system.')->flash();
|
||||
|
||||
return redirect()->route('admin.databases.view', $host->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle updating database host.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(DatabaseHostFormRequest $request, DatabaseHost $host): RedirectResponse
|
||||
{
|
||||
$redirect = redirect()->route('admin.databases.view', $host->id);
|
||||
|
||||
try {
|
||||
$this->updateService->handle($host->id, $request->normalize());
|
||||
$this->alert->success('Database host was updated successfully.')->flash();
|
||||
} catch (Exception $exception) {
|
||||
// Catch any SQL related exceptions and display them back to the user, otherwise just
|
||||
// throw the exception like normal and move on with it.
|
||||
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||
$this->alert->danger(
|
||||
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||
)->flash();
|
||||
|
||||
return $redirect->withInput($request->normalize());
|
||||
} else {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to delete a database host.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function delete(int $host): RedirectResponse
|
||||
{
|
||||
$this->deletionService->handle($host);
|
||||
$this->alert->success('The requested database host has been deleted from the system.')->flash();
|
||||
|
||||
return redirect()->route('admin.databases');
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Http\Requests\Admin\LocationFormRequest;
|
||||
use Pterodactyl\Services\Locations\LocationUpdateService;
|
||||
use Pterodactyl\Services\Locations\LocationCreationService;
|
||||
use Pterodactyl\Services\Locations\LocationDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
|
||||
class LocationController extends Controller
|
||||
{
|
||||
/**
|
||||
* LocationController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected LocationCreationService $creationService,
|
||||
protected LocationDeletionService $deletionService,
|
||||
protected LocationRepositoryInterface $repository,
|
||||
protected LocationUpdateService $updateService,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location overview page.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.locations.index', [
|
||||
'locations' => $this->repository->getAllWithDetails(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location view page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(int $id): View
|
||||
{
|
||||
return $this->view->make('admin.locations.view', [
|
||||
'location' => $this->repository->getWithNodes($id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to create new location.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function create(LocationFormRequest $request): RedirectResponse
|
||||
{
|
||||
$location = $this->creationService->handle($request->normalize());
|
||||
$this->alert->success('Location was created successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.locations.view', $location->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update or delete location.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(LocationFormRequest $request, Location $location): RedirectResponse
|
||||
{
|
||||
if ($request->input('action') === 'delete') {
|
||||
return $this->delete($location);
|
||||
}
|
||||
|
||||
$this->updateService->handle($location->id, $request->normalize());
|
||||
$this->alert->success('Location was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.locations.view', $location->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a location from the system.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete(Location $location): RedirectResponse
|
||||
{
|
||||
try {
|
||||
$this->deletionService->handle($location->id);
|
||||
|
||||
return redirect()->route('admin.locations');
|
||||
} catch (DisplayException $ex) {
|
||||
$this->alert->danger($ex->getMessage())->flash();
|
||||
}
|
||||
|
||||
return redirect()->route('admin.locations.view', $location->id);
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Http\Requests\Admin\MountFormRequest;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
|
||||
class MountController extends Controller
|
||||
{
|
||||
/**
|
||||
* MountController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected NestRepositoryInterface $nestRepository,
|
||||
protected LocationRepositoryInterface $locationRepository,
|
||||
protected MountRepository $repository,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mount overview page.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.mounts.index', [
|
||||
'mounts' => $this->repository->getAllWithDetails(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mount view page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(string $id): View
|
||||
{
|
||||
$nests = Nest::query()->with('eggs')->get();
|
||||
$locations = Location::query()->with('nodes')->get();
|
||||
|
||||
return $this->view->make('admin.mounts.view', [
|
||||
'mount' => $this->repository->getWithRelations($id),
|
||||
'nests' => $nests,
|
||||
'locations' => $locations,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to create new mount.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function create(MountFormRequest $request): RedirectResponse
|
||||
{
|
||||
$model = (new Mount())->fill($request->validated());
|
||||
$model->forceFill(['uuid' => Uuid::uuid4()->toString()]);
|
||||
|
||||
$model->saveOrFail();
|
||||
$mount = $model->fresh();
|
||||
|
||||
$this->alert->success('Mount was created successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update or delete location.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(MountFormRequest $request, Mount $mount): RedirectResponse
|
||||
{
|
||||
if ($request->input('action') === 'delete') {
|
||||
return $this->delete($mount);
|
||||
}
|
||||
|
||||
$mount->forceFill($request->validated())->save();
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a location from the system.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(Mount $mount): RedirectResponse
|
||||
{
|
||||
$mount->delete();
|
||||
|
||||
return redirect()->route('admin.mounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds eggs to the mount's many-to-many relation.
|
||||
*/
|
||||
public function addEggs(Request $request, Mount $mount): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'eggs' => 'required|exists:eggs,id',
|
||||
]);
|
||||
|
||||
$eggs = $validatedData['eggs'] ?? [];
|
||||
if (count($eggs) > 0) {
|
||||
$mount->eggs()->attach($eggs);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds nodes to the mount's many-to-many relation.
|
||||
*/
|
||||
public function addNodes(Request $request, Mount $mount): RedirectResponse
|
||||
{
|
||||
$data = $request->validate(['nodes' => 'required|exists:nodes,id']);
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$mount->nodes()->attach($nodes);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an egg from the mount's many-to-many relation.
|
||||
*/
|
||||
public function deleteEgg(Mount $mount, int $egg_id): Response
|
||||
{
|
||||
$mount->eggs()->detach($egg_id);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a node from the mount's many-to-many relation.
|
||||
*/
|
||||
public function deleteNode(Mount $mount, int $node_id): Response
|
||||
{
|
||||
$mount->nodes()->detach($node_id);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use JavaScript;
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Eggs\EggUpdateService;
|
||||
use Pterodactyl\Services\Eggs\EggCreationService;
|
||||
use Pterodactyl\Services\Eggs\EggDeletionService;
|
||||
use Pterodactyl\Http\Requests\Admin\Egg\EggFormRequest;
|
||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
|
||||
class EggController extends Controller
|
||||
{
|
||||
/**
|
||||
* EggController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected EggCreationService $creationService,
|
||||
protected EggDeletionService $deletionService,
|
||||
protected EggRepositoryInterface $repository,
|
||||
protected EggUpdateService $updateService,
|
||||
protected NestRepositoryInterface $nestRepository,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to display the Egg creation page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
JavaScript::put(['nests' => $nests->keyBy('id')]);
|
||||
|
||||
return $this->view->make('admin.eggs.new', ['nests' => $nests]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to store a new Egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\NoParentConfigurationFoundException
|
||||
*/
|
||||
public function store(EggFormRequest $request): RedirectResponse
|
||||
{
|
||||
$data = $request->validated();
|
||||
$data['docker_images'] = $this->normalizeDockerImages($data['docker_images'] ?? null);
|
||||
|
||||
$egg = $this->creationService->handle($data);
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.egg_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.view', $egg->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to view a single Egg.
|
||||
*/
|
||||
public function view(Egg $egg): View
|
||||
{
|
||||
return $this->view->make('admin.eggs.view', [
|
||||
'egg' => $egg,
|
||||
'images' => array_map(
|
||||
fn ($key, $value) => $key === $value ? $value : "$key|$value",
|
||||
array_keys($egg->docker_images),
|
||||
$egg->docker_images,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update an Egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\NoParentConfigurationFoundException
|
||||
*/
|
||||
public function update(EggFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$data = $request->validated();
|
||||
$data['docker_images'] = $this->normalizeDockerImages($data['docker_images'] ?? null);
|
||||
|
||||
$this->updateService->handle($egg, $data);
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.view', $egg->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to destroy an egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\HasChildrenException
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function destroy(Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->deletionService->handle($egg->id);
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.deleted'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.view', $egg->nest_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a string of docker image data into the expected egg format.
|
||||
*/
|
||||
protected function normalizeDockerImages(string $input = null): array
|
||||
{
|
||||
$data = array_map(fn ($value) => trim($value), explode("\n", $input ?? ''));
|
||||
|
||||
$images = [];
|
||||
// Iterate over the image data provided and convert it into a name => image
|
||||
// pairing that is used to improve the display on the front-end.
|
||||
foreach ($data as $value) {
|
||||
$parts = explode('|', $value, 2);
|
||||
$images[$parts[0]] = empty($parts[1]) ? $parts[0] : $parts[1];
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Eggs\Scripts\InstallScriptService;
|
||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Egg\EggScriptFormRequest;
|
||||
|
||||
class EggScriptController extends Controller
|
||||
{
|
||||
/**
|
||||
* EggScriptController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected EggRepositoryInterface $repository,
|
||||
protected InstallScriptService $installScriptService,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle requests to render installation script for an Egg.
|
||||
*/
|
||||
public function index(int $egg): View
|
||||
{
|
||||
$egg = $this->repository->getWithCopyAttributes($egg);
|
||||
$copy = $this->repository->findWhere([
|
||||
['copy_script_from', '=', null],
|
||||
['nest_id', '=', $egg->nest_id],
|
||||
['id', '!=', $egg],
|
||||
]);
|
||||
|
||||
$rely = $this->repository->findWhere([
|
||||
['copy_script_from', '=', $egg->id],
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.eggs.scripts', [
|
||||
'copyFromOptions' => $copy,
|
||||
'relyOnScript' => $rely,
|
||||
'egg' => $egg,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to update the installation script for an Egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\InvalidCopyFromException
|
||||
*/
|
||||
public function update(EggScriptFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->installScriptService->handle($egg, $request->normalize());
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.script_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.scripts', $egg);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Pterodactyl\Services\Eggs\Sharing\EggExporterService;
|
||||
use Pterodactyl\Services\Eggs\Sharing\EggImporterService;
|
||||
use Pterodactyl\Http\Requests\Admin\Egg\EggImportFormRequest;
|
||||
use Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService;
|
||||
|
||||
class EggShareController extends Controller
|
||||
{
|
||||
/**
|
||||
* EggShareController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected EggExporterService $exporterService,
|
||||
protected EggImporterService $importerService,
|
||||
protected EggUpdateImporterService $updateImporterService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function export(Egg $egg): Response
|
||||
{
|
||||
$filename = trim(preg_replace('/\W/', '-', kebab_case($egg->name)), '-');
|
||||
|
||||
return response($this->exporterService->handle($egg->id), 200, [
|
||||
'Content-Transfer-Encoding' => 'binary',
|
||||
'Content-Description' => 'File Transfer',
|
||||
'Content-Disposition' => 'attachment; filename=egg-' . $filename . '.json',
|
||||
'Content-Type' => 'application/json',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a new service option using an XML file.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
|
||||
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
|
||||
*/
|
||||
public function import(EggImportFormRequest $request): RedirectResponse
|
||||
{
|
||||
$egg = $this->importerService->handle($request->file('import_file'), $request->input('import_to_nest'));
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.imported'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.view', ['egg' => $egg->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing Egg using a new imported file.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
|
||||
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
|
||||
*/
|
||||
public function update(EggImportFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->updateImporterService->handle($egg, $request->file('import_file'));
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.updated_via_import'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.view', ['egg' => $egg]);
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Pterodactyl\Models\EggVariable;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
||||
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
||||
use Pterodactyl\Http\Requests\Admin\Egg\EggVariableFormRequest;
|
||||
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
||||
|
||||
class EggVariableController extends Controller
|
||||
{
|
||||
/**
|
||||
* EggVariableController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected VariableCreationService $creationService,
|
||||
protected VariableUpdateService $updateService,
|
||||
protected EggRepositoryInterface $repository,
|
||||
protected EggVariableRepositoryInterface $variableRepository,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to view the variables attached to an Egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(int $egg): View
|
||||
{
|
||||
$egg = $this->repository->getWithVariables($egg);
|
||||
|
||||
return $this->view->make('admin.eggs.variables', ['egg' => $egg]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to create a new Egg variable.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
||||
*/
|
||||
public function store(EggVariableFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->creationService->handle($egg->id, $request->normalize());
|
||||
$this->alert->success(trans('admin/nests.variables.notices.variable_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.variables', $egg->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to update an existing Egg variable.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
||||
*/
|
||||
public function update(EggVariableFormRequest $request, Egg $egg, EggVariable $variable): RedirectResponse
|
||||
{
|
||||
$this->updateService->handle($variable, $request->normalize());
|
||||
$this->alert->success(trans('admin/nests.variables.notices.variable_updated', [
|
||||
'variable' => $variable->name,
|
||||
]))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.variables', $egg->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to delete an existing Egg variable from the Panel.
|
||||
*/
|
||||
public function destroy(int $egg, EggVariable $variable): RedirectResponse
|
||||
{
|
||||
$this->variableRepository->delete($variable->id);
|
||||
$this->alert->success(trans('admin/nests.variables.notices.variable_deleted', [
|
||||
'variable' => $variable->name,
|
||||
]))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.egg.variables', $egg);
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Nests\NestUpdateService;
|
||||
use Pterodactyl\Services\Nests\NestCreationService;
|
||||
use Pterodactyl\Services\Nests\NestDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Nest\StoreNestFormRequest;
|
||||
|
||||
class NestController extends Controller
|
||||
{
|
||||
/**
|
||||
* NestController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected NestCreationService $nestCreationService,
|
||||
protected NestDeletionService $nestDeletionService,
|
||||
protected NestRepositoryInterface $repository,
|
||||
protected NestUpdateService $nestUpdateService,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render nest listing page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.nests.index', [
|
||||
'nests' => $this->repository->getWithCounts(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render nest creation page.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return $this->view->make('admin.nests.new');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the storage of a new nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function store(StoreNestFormRequest $request): RedirectResponse
|
||||
{
|
||||
$nest = $this->nestCreationService->handle($request->normalize());
|
||||
$this->alert->success(trans('admin/nests.notices.created', ['name' => $nest->name]))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.view', $nest->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details about a nest including all the eggs and servers per egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(int $nest): View
|
||||
{
|
||||
return $this->view->make('admin.nests.view', [
|
||||
'nest' => $this->repository->getWithEggServers($nest),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update a nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(StoreNestFormRequest $request, int $nest): RedirectResponse
|
||||
{
|
||||
$this->nestUpdateService->handle($nest, $request->normalize());
|
||||
$this->alert->success(trans('admin/nests.notices.updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests.view', $nest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to delete a nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function destroy(int $nest): RedirectResponse
|
||||
{
|
||||
$this->nestDeletionService->handle($nest);
|
||||
$this->alert->success(trans('admin/nests.notices.deleted'))->flash();
|
||||
|
||||
return redirect()->route('admin.nests');
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\ApiKey;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Pterodactyl\Services\Api\KeyCreationService;
|
||||
use Pterodactyl\Repositories\Eloquent\ApiKeyRepository;
|
||||
|
||||
class NodeAutoDeployController extends Controller
|
||||
{
|
||||
/**
|
||||
* NodeAutoDeployController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private ApiKeyRepository $repository,
|
||||
private Encrypter $encrypter,
|
||||
private KeyCreationService $keyCreationService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new API key for the logged-in user with only permission to read
|
||||
* nodes, and returns that as the deployment key for a node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function __invoke(Request $request, Node $node): JsonResponse
|
||||
{
|
||||
/** @var \Pterodactyl\Models\ApiKey|null $key */
|
||||
$key = $this->repository->getApplicationKeys($request->user())
|
||||
->filter(function (ApiKey $key) {
|
||||
foreach ($key->getAttributes() as $permission => $value) {
|
||||
if ($permission === 'r_nodes' && $value === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
->first();
|
||||
|
||||
// We couldn't find a key that exists for this user with only permission for
|
||||
// reading nodes. Go ahead and create it now.
|
||||
if (!$key) {
|
||||
$key = $this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([
|
||||
'user_id' => $request->user()->id,
|
||||
'memo' => 'Automatically generated node deployment key.',
|
||||
'allowed_ips' => [],
|
||||
], ['r_nodes' => 1]);
|
||||
}
|
||||
|
||||
return new JsonResponse([
|
||||
'node' => $node->id,
|
||||
'token' => $key->identifier . $this->encrypter->decrypt($key->token),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
|
||||
class NodeController extends Controller
|
||||
{
|
||||
/**
|
||||
* NodeController constructor.
|
||||
*/
|
||||
public function __construct(private ViewFactory $view)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a listing of nodes on the system.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$nodes = QueryBuilder::for(
|
||||
Node::query()->with('location')->withCount('servers')
|
||||
)
|
||||
->allowedFilters(['uuid', 'name'])
|
||||
->allowedSorts(['id'])
|
||||
->paginate(25);
|
||||
|
||||
return $this->view->make('admin.nodes.index', ['nodes' => $nodes]);
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Support\Collection;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
|
||||
|
||||
class NodeViewController extends Controller
|
||||
{
|
||||
use JavascriptInjection;
|
||||
|
||||
/**
|
||||
* NodeViewController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AllocationRepository $allocationRepository,
|
||||
private LocationRepository $locationRepository,
|
||||
private NodeRepository $repository,
|
||||
private ServerRepository $serverRepository,
|
||||
private SoftwareVersionService $versionService,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns index view for a specific node on the system.
|
||||
*/
|
||||
public function index(Request $request, Node $node): View
|
||||
{
|
||||
$node = $this->repository->loadLocationAndServerCount($node);
|
||||
|
||||
return $this->view->make('admin.nodes.view.index', [
|
||||
'node' => $node,
|
||||
'stats' => $this->repository->getUsageStats($node),
|
||||
'version' => $this->versionService,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings page for a specific node.
|
||||
*/
|
||||
public function settings(Request $request, Node $node): View
|
||||
{
|
||||
return $this->view->make('admin.nodes.view.settings', [
|
||||
'node' => $node,
|
||||
'locations' => $this->locationRepository->all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node configuration page for a specific node.
|
||||
*/
|
||||
public function configuration(Request $request, Node $node): View
|
||||
{
|
||||
return $this->view->make('admin.nodes.view.configuration', compact('node'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node allocation management page.
|
||||
*/
|
||||
public function allocations(Request $request, Node $node): View
|
||||
{
|
||||
$node = $this->repository->loadNodeAllocations($node);
|
||||
|
||||
$this->plainInject(['node' => Collection::wrap($node)->only(['id'])]);
|
||||
|
||||
return $this->view->make('admin.nodes.view.allocation', [
|
||||
'node' => $node,
|
||||
'allocations' => Allocation::query()->where('node_id', $node->id)
|
||||
->groupBy('ip')
|
||||
->orderByRaw('INET_ATON(ip) ASC')
|
||||
->get(['ip']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a listing of servers that exist for this specific node.
|
||||
*/
|
||||
public function servers(Request $request, Node $node): View
|
||||
{
|
||||
$this->plainInject([
|
||||
'node' => Collection::wrap($node->makeVisible(['daemon_token_id', 'daemon_token']))
|
||||
->only(['scheme', 'fqdn', 'daemonListen', 'daemon_token_id', 'daemon_token']),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.nodes.view.servers', [
|
||||
'node' => $node,
|
||||
'servers' => $this->serverRepository->loadAllServersForNode($node->id, 25),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
||||
|
||||
class SystemInformationController extends Controller
|
||||
{
|
||||
/**
|
||||
* SystemInformationController constructor.
|
||||
*/
|
||||
public function __construct(private DaemonConfigurationRepository $repository)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns system information from the Daemon.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function __invoke(Request $request, Node $node): JsonResponse
|
||||
{
|
||||
$data = $this->repository->setNode($node)->getSystemInformation();
|
||||
|
||||
return new JsonResponse([
|
||||
'version' => $data['version'] ?? '',
|
||||
'system' => [
|
||||
'type' => Str::title($data['os'] ?? 'Unknown'),
|
||||
'arch' => $data['architecture'] ?? '--',
|
||||
'release' => $data['kernel_version'] ?? '--',
|
||||
'cpus' => $data['cpu_count'] ?? 0,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Nodes\NodeUpdateService;
|
||||
use Illuminate\Cache\Repository as CacheRepository;
|
||||
use Pterodactyl\Services\Nodes\NodeCreationService;
|
||||
use Pterodactyl\Services\Nodes\NodeDeletionService;
|
||||
use Pterodactyl\Services\Allocations\AssignmentService;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
use Pterodactyl\Http\Requests\Admin\Node\NodeFormRequest;
|
||||
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Node\AllocationFormRequest;
|
||||
use Pterodactyl\Services\Allocations\AllocationDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Node\AllocationAliasFormRequest;
|
||||
|
||||
class NodesController extends Controller
|
||||
{
|
||||
/**
|
||||
* NodesController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected AllocationDeletionService $allocationDeletionService,
|
||||
protected AllocationRepositoryInterface $allocationRepository,
|
||||
protected AssignmentService $assignmentService,
|
||||
protected CacheRepository $cache,
|
||||
protected NodeCreationService $creationService,
|
||||
protected NodeDeletionService $deletionService,
|
||||
protected LocationRepositoryInterface $locationRepository,
|
||||
protected NodeRepositoryInterface $repository,
|
||||
protected ServerRepositoryInterface $serverRepository,
|
||||
protected NodeUpdateService $updateService,
|
||||
protected SoftwareVersionService $versionService,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays create new node page.
|
||||
*/
|
||||
public function create(): View|RedirectResponse
|
||||
{
|
||||
$locations = $this->locationRepository->all();
|
||||
if (count($locations) < 1) {
|
||||
$this->alert->warning(trans('admin/node.notices.location_required'))->flash();
|
||||
|
||||
return redirect()->route('admin.locations');
|
||||
}
|
||||
|
||||
return $this->view->make('admin.nodes.new', ['locations' => $locations]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post controller to create a new node on the system.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function store(NodeFormRequest $request): RedirectResponse
|
||||
{
|
||||
$node = $this->creationService->handle($request->normalize());
|
||||
$this->alert->info(trans('admin/node.notices.node_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view.allocation', $node->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates settings for a node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function updateSettings(NodeFormRequest $request, Node $node): RedirectResponse
|
||||
{
|
||||
$this->updateService->handle($node, $request->normalize(), $request->input('reset_secret') === 'on');
|
||||
$this->alert->success(trans('admin/node.notices.node_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view.settings', $node->id)->withInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single allocation from a node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
|
||||
*/
|
||||
public function allocationRemoveSingle(int $node, Allocation $allocation): Response
|
||||
{
|
||||
$this->allocationDeletionService->handle($allocation);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple individual allocations from a node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
|
||||
*/
|
||||
public function allocationRemoveMultiple(Request $request, int $node): Response
|
||||
{
|
||||
$allocations = $request->input('allocations');
|
||||
foreach ($allocations as $rawAllocation) {
|
||||
$allocation = new Allocation();
|
||||
$allocation->id = $rawAllocation['id'];
|
||||
$this->allocationRemoveSingle($node, $allocation);
|
||||
}
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all allocations for a specific IP at once on a node.
|
||||
*/
|
||||
public function allocationRemoveBlock(Request $request, int $node): RedirectResponse
|
||||
{
|
||||
$this->allocationRepository->deleteWhere([
|
||||
['node_id', '=', $node],
|
||||
['server_id', '=', null],
|
||||
['ip', '=', $request->input('ip')],
|
||||
]);
|
||||
|
||||
$this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => $request->input('ip')]))
|
||||
->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view.allocation', $node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alias for a specific allocation on a node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function allocationSetAlias(AllocationAliasFormRequest $request): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$this->allocationRepository->update($request->input('allocation_id'), [
|
||||
'ip_alias' => (empty($request->input('alias'))) ? null : $request->input('alias'),
|
||||
]);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new allocations on a node.
|
||||
*
|
||||
* @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 createAllocation(AllocationFormRequest $request, Node $node): RedirectResponse
|
||||
{
|
||||
$this->assignmentService->handle($node, $request->normalize());
|
||||
$this->alert->success(trans('admin/node.notices.allocations_added'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view.allocation', $node->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a node from the system.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete(int|Node $node): RedirectResponse
|
||||
{
|
||||
$this->deletionService->handle($node);
|
||||
$this->alert->success(trans('admin/node.notices.node_deleted'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes');
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use JavaScript;
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Http\Requests\Admin\ServerFormRequest;
|
||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||
|
||||
class CreateServerController extends Controller
|
||||
{
|
||||
/**
|
||||
* CreateServerController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private NestRepository $nestRepository,
|
||||
private NodeRepository $nodeRepository,
|
||||
private ServerCreationService $creationService,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the create server page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function index(): View|RedirectResponse
|
||||
{
|
||||
$nodes = Node::all();
|
||||
if (count($nodes) < 1) {
|
||||
$this->alert->warning(trans('admin/server.alerts.node_required'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes');
|
||||
}
|
||||
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
|
||||
JavaScript::put([
|
||||
'nodeData' => $this->nodeRepository->getNodesForServerCreation(),
|
||||
'nests' => $nests->map(function ($item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.servers.new', [
|
||||
'locations' => Location::all(),
|
||||
'nests' => $nests,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new server on the remote system.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function store(ServerFormRequest $request): RedirectResponse
|
||||
{
|
||||
$data = $request->except(['_token']);
|
||||
if (!empty($data['custom_image'])) {
|
||||
$data['image'] = $data['custom_image'];
|
||||
unset($data['custom_image']);
|
||||
}
|
||||
|
||||
$server = $this->creationService->handle($data);
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.server_created'))->flash();
|
||||
|
||||
return new RedirectResponse('/admin/servers/view/' . $server->id);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Spatie\QueryBuilder\AllowedFilter;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Models\Filters\AdminServerFilter;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
/**
|
||||
* ServerController constructor.
|
||||
*/
|
||||
public function __construct(private ViewFactory $view)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the servers that exist on the system using a paginated result set. If
|
||||
* a query is passed along in the request it is also passed to the repository function.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$servers = QueryBuilder::for(Server::query()->with('node', 'user', 'allocation'))
|
||||
->allowedFilters([
|
||||
AllowedFilter::exact('owner_id'),
|
||||
AllowedFilter::custom('*', new AdminServerFilter()),
|
||||
])
|
||||
->paginate(config()->get('pterodactyl.paginate.admin.servers'));
|
||||
|
||||
return $this->view->make('admin.servers.index', ['servers' => $servers]);
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Models\ServerTransfer;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Servers\TransferService;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
|
||||
class ServerTransferController extends Controller
|
||||
{
|
||||
/**
|
||||
* ServerTransferController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private AllocationRepositoryInterface $allocationRepository,
|
||||
private NodeRepository $nodeRepository,
|
||||
private TransferService $transferService,
|
||||
private DaemonConfigurationRepository $daemonConfigurationRepository
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a transfer of a server to a new node.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function transfer(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'node_id' => 'required|exists:nodes,id',
|
||||
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
|
||||
'allocation_additional' => 'nullable',
|
||||
]);
|
||||
|
||||
$node_id = $validatedData['node_id'];
|
||||
$allocation_id = intval($validatedData['allocation_id']);
|
||||
$additional_allocations = array_map('intval', $validatedData['allocation_additional'] ?? []);
|
||||
|
||||
// Check if the node is viable for the transfer.
|
||||
$node = $this->nodeRepository->getNodeWithResourceUsage($node_id);
|
||||
if ($node->isViable($server->memory, $server->disk)) {
|
||||
// Check if the selected daemon is online.
|
||||
$this->daemonConfigurationRepository->setNode($node)->getSystemInformation();
|
||||
|
||||
$server->validateTransferState();
|
||||
|
||||
// Create a new ServerTransfer entry.
|
||||
$transfer = new ServerTransfer();
|
||||
|
||||
$transfer->server_id = $server->id;
|
||||
$transfer->old_node = $server->node_id;
|
||||
$transfer->new_node = $node_id;
|
||||
$transfer->old_allocation = $server->allocation_id;
|
||||
$transfer->new_allocation = $allocation_id;
|
||||
$transfer->old_additional_allocations = $server->allocations->where('id', '!=', $server->allocation_id)->pluck('id');
|
||||
$transfer->new_additional_allocations = $additional_allocations;
|
||||
|
||||
$transfer->save();
|
||||
|
||||
// Add the allocations to the server, so they cannot be automatically assigned while the transfer is in progress.
|
||||
$this->assignAllocationsToServer($server, $node_id, $allocation_id, $additional_allocations);
|
||||
|
||||
// Request an archive from the server's current daemon. (this also checks if the daemon is online)
|
||||
$this->transferService->requestArchive($server);
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.transfer_started'))->flash();
|
||||
} else {
|
||||
$this->alert->danger(trans('admin/server.alerts.transfer_not_viable'))->flash();
|
||||
}
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the specified allocations to the specified server.
|
||||
*/
|
||||
private function assignAllocationsToServer(Server $server, int $node_id, int $allocation_id, array $additional_allocations)
|
||||
{
|
||||
$allocations = $additional_allocations;
|
||||
$allocations[] = $allocation_id;
|
||||
|
||||
$unassigned = $this->allocationRepository->getUnassignedAllocationIds($node_id);
|
||||
|
||||
$updateIds = [];
|
||||
foreach ($allocations as $allocation) {
|
||||
if (!in_array($allocation, $unassigned)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$updateIds[] = $allocation;
|
||||
}
|
||||
|
||||
if (!empty($updateIds)) {
|
||||
$this->allocationRepository->updateWhereIn('id', $updateIds, ['server_id' => $server->id]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use JavaScript;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Servers\EnvironmentService;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository;
|
||||
|
||||
class ServerViewController extends Controller
|
||||
{
|
||||
use JavascriptInjection;
|
||||
|
||||
/**
|
||||
* ServerViewController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private DatabaseHostRepository $databaseHostRepository,
|
||||
private LocationRepository $locationRepository,
|
||||
private MountRepository $mountRepository,
|
||||
private NestRepository $nestRepository,
|
||||
private NodeRepository $nodeRepository,
|
||||
private ServerRepository $repository,
|
||||
private EnvironmentService $environmentService,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index view for a server.
|
||||
*/
|
||||
public function index(Request $request, Server $server): View
|
||||
{
|
||||
return $this->view->make('admin.servers.view.index', compact('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server details page.
|
||||
*/
|
||||
public function details(Request $request, Server $server): View
|
||||
{
|
||||
return $this->view->make('admin.servers.view.details', compact('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view of server build settings.
|
||||
*/
|
||||
public function build(Request $request, Server $server): View
|
||||
{
|
||||
$allocations = $server->node->allocations->toBase();
|
||||
|
||||
return $this->view->make('admin.servers.view.build', [
|
||||
'server' => $server,
|
||||
'assigned' => $allocations->where('server_id', $server->id)->sortBy('port')->sortBy('ip'),
|
||||
'unassigned' => $allocations->where('server_id', null)->sortBy('port')->sortBy('ip'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server startup management page.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function startup(Request $request, Server $server): View
|
||||
{
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
$variables = $this->environmentService->handle($server);
|
||||
|
||||
$this->plainInject([
|
||||
'server' => $server,
|
||||
'server_variables' => $variables,
|
||||
'nests' => $nests->map(function (Nest $item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.servers.view.startup', compact('server', 'nests'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the databases that exist for the server.
|
||||
*/
|
||||
public function database(Request $request, Server $server): View
|
||||
{
|
||||
return $this->view->make('admin.servers.view.database', [
|
||||
'hosts' => $this->databaseHostRepository->all(),
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the mounts that exist for the server.
|
||||
*/
|
||||
public function mounts(Request $request, Server $server): View
|
||||
{
|
||||
$server->load('mounts');
|
||||
|
||||
return $this->view->make('admin.servers.view.mounts', [
|
||||
'mounts' => $this->mountRepository->getMountListForServer($server),
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base server management page, or an exception if the server
|
||||
* is in a state that cannot be recovered from.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function manage(Request $request, Server $server): View
|
||||
{
|
||||
if ($server->status === Server::STATUS_INSTALL_FAILED) {
|
||||
throw new DisplayException('This server is in a failed install state and cannot be recovered. Please delete and re-create the server.');
|
||||
}
|
||||
|
||||
// Check if the panel doesn't have at least 2 nodes configured.
|
||||
$nodes = $this->nodeRepository->all();
|
||||
$canTransfer = false;
|
||||
if (count($nodes) >= 2) {
|
||||
$canTransfer = true;
|
||||
}
|
||||
|
||||
JavaScript::put([
|
||||
'nodeData' => $this->nodeRepository->getNodesForServerCreation(),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.servers.view.manage', [
|
||||
'server' => $server,
|
||||
'locations' => $this->locationRepository->all(),
|
||||
'canTransfer' => $canTransfer,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server deletion page.
|
||||
*/
|
||||
public function delete(Request $request, Server $server): View
|
||||
{
|
||||
return $this->view->make('admin.servers.view.delete', compact('server'));
|
||||
}
|
||||
}
|
|
@ -1,273 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Database;
|
||||
use Pterodactyl\Models\MountServer;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Pterodactyl\Services\Servers\SuspensionService;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Services\Servers\ServerDeletionService;
|
||||
use Pterodactyl\Services\Servers\ReinstallServerService;
|
||||
use Pterodactyl\Exceptions\Model\DataValidationException;
|
||||
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
||||
use Pterodactyl\Services\Servers\BuildModificationService;
|
||||
use Pterodactyl\Services\Databases\DatabasePasswordService;
|
||||
use Pterodactyl\Services\Servers\DetailsModificationService;
|
||||
use Pterodactyl\Services\Servers\StartupModificationService;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository;
|
||||
use Pterodactyl\Services\Databases\DatabaseManagementService;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
|
||||
use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest;
|
||||
|
||||
class ServersController extends Controller
|
||||
{
|
||||
/**
|
||||
* ServersController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected AllocationRepositoryInterface $allocationRepository,
|
||||
protected BuildModificationService $buildModificationService,
|
||||
protected ConfigRepository $config,
|
||||
protected DaemonServerRepository $daemonServerRepository,
|
||||
protected DatabaseManagementService $databaseManagementService,
|
||||
protected DatabasePasswordService $databasePasswordService,
|
||||
protected DatabaseRepositoryInterface $databaseRepository,
|
||||
protected DatabaseHostRepository $databaseHostRepository,
|
||||
protected ServerDeletionService $deletionService,
|
||||
protected DetailsModificationService $detailsModificationService,
|
||||
protected ReinstallServerService $reinstallService,
|
||||
protected ServerRepositoryInterface $repository,
|
||||
protected MountRepository $mountRepository,
|
||||
protected NestRepositoryInterface $nestRepository,
|
||||
protected ServerConfigurationStructureService $serverConfigurationStructureService,
|
||||
protected StartupModificationService $startupModificationService,
|
||||
protected SuspensionService $suspensionService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the details for a server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function setDetails(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$this->detailsModificationService->handle($server, $request->only([
|
||||
'owner_id', 'external_id', 'name', 'description',
|
||||
]));
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.details_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.details', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the installation status for a server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function toggleInstall(Server $server): RedirectResponse
|
||||
{
|
||||
if ($server->status === Server::STATUS_INSTALL_FAILED) {
|
||||
throw new DisplayException(trans('admin/server.exceptions.marked_as_failed'));
|
||||
}
|
||||
|
||||
$this->repository->update($server->id, [
|
||||
'status' => $server->isInstalled() ? Server::STATUS_INSTALLING : null,
|
||||
], true, true);
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.install_toggled'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reinstalls the server with the currently assigned service.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function reinstallServer(Server $server): RedirectResponse
|
||||
{
|
||||
$this->reinstallService->handle($server);
|
||||
$this->alert->success(trans('admin/server.alerts.server_reinstalled'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the suspension status for a server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function manageSuspension(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$this->suspensionService->toggle($server, $request->input('action'));
|
||||
$this->alert->success(trans('admin/server.alerts.suspension_toggled', [
|
||||
'status' => $request->input('action') . 'ed',
|
||||
]))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the build configuration for a server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function updateBuild(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
try {
|
||||
$this->buildModificationService->handle($server, $request->only([
|
||||
'allocation_id', 'add_allocations', 'remove_allocations',
|
||||
'memory', 'swap', 'io', 'cpu', 'threads', 'disk',
|
||||
'database_limit', 'allocation_limit', 'backup_limit', 'oom_disabled',
|
||||
]));
|
||||
} catch (DataValidationException $exception) {
|
||||
throw new ValidationException($exception->getValidator());
|
||||
}
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.build_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.build', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the server deletion process.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function delete(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$this->deletionService->withForce($request->filled('force_delete'))->handle($server);
|
||||
$this->alert->success(trans('admin/server.alerts.server_deleted'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the startup command as well as variables.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function saveStartup(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$data = $request->except('_token');
|
||||
if (!empty($data['custom_docker_image'])) {
|
||||
$data['docker_image'] = $data['custom_docker_image'];
|
||||
unset($data['custom_docker_image']);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->startupModificationService
|
||||
->setUserLevel(User::USER_LEVEL_ADMIN)
|
||||
->handle($server, $data);
|
||||
} catch (DataValidationException $exception) {
|
||||
throw new ValidationException($exception->getValidator());
|
||||
}
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.startup_changed'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.startup', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new database assigned to a specific server.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function newDatabase(StoreServerDatabaseRequest $request, Server $server): RedirectResponse
|
||||
{
|
||||
$this->databaseManagementService->create($server, [
|
||||
'database' => DatabaseManagementService::generateUniqueDatabaseName($request->input('database'), $server->id),
|
||||
'remote' => $request->input('remote'),
|
||||
'database_host_id' => $request->input('database_host_id'),
|
||||
'max_connections' => $request->input('max_connections'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.servers.view.database', $server->id)->withInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the database password for a specific database on this server.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function resetDatabasePassword(Request $request, Server $server): Response
|
||||
{
|
||||
/** @var \Pterodactyl\Models\Database $database */
|
||||
$database = $server->databases()->findOrFail($request->input('database'));
|
||||
|
||||
$this->databasePasswordService->handle($database);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a database from a server.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function deleteDatabase(Server $server, Database $database): Response
|
||||
{
|
||||
$this->databaseManagementService->delete($database);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mount to a server.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function addMount(Request $request, Server $server): RedirectResponse
|
||||
{
|
||||
$mountServer = (new MountServer())->forceFill([
|
||||
'mount_id' => $request->input('mount_id'),
|
||||
'server_id' => $server->id,
|
||||
]);
|
||||
|
||||
$mountServer->saveOrFail();
|
||||
|
||||
$this->alert->success('Mount was added successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.mounts', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a mount from a server.
|
||||
*/
|
||||
public function deleteMount(Server $server, Mount $mount): RedirectResponse
|
||||
{
|
||||
MountServer::where('mount_id', $mount->id)->where('server_id', $server->id)->delete();
|
||||
|
||||
$this->alert->success('Mount was removed successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.mounts', $server->id);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Settings;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Settings\AdvancedSettingsFormRequest;
|
||||
|
||||
class AdvancedController extends Controller
|
||||
{
|
||||
/**
|
||||
* AdvancedController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private ConfigRepository $config,
|
||||
private Kernel $kernel,
|
||||
private SettingsRepositoryInterface $settings,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render advanced Panel settings UI.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$showRecaptchaWarning = false;
|
||||
if (
|
||||
$this->config->get('recaptcha._shipped_secret_key') === $this->config->get('recaptcha.secret_key')
|
||||
|| $this->config->get('recaptcha._shipped_website_key') === $this->config->get('recaptcha.website_key')
|
||||
) {
|
||||
$showRecaptchaWarning = true;
|
||||
}
|
||||
|
||||
return $this->view->make('admin.settings.advanced', [
|
||||
'showRecaptchaWarning' => $showRecaptchaWarning,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(AdvancedSettingsFormRequest $request): RedirectResponse
|
||||
{
|
||||
foreach ($request->normalize() as $key => $value) {
|
||||
$this->settings->set('settings::' . $key, $value);
|
||||
}
|
||||
|
||||
$this->kernel->call('queue:restart');
|
||||
$this->alert->success('Advanced settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
|
||||
|
||||
return redirect()->route('admin.settings.advanced');
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Settings;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Traits\Helpers\AvailableLanguages;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Settings\BaseSettingsFormRequest;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
use AvailableLanguages;
|
||||
|
||||
/**
|
||||
* IndexController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private AlertsMessageBag $alert,
|
||||
private Kernel $kernel,
|
||||
private SettingsRepositoryInterface $settings,
|
||||
private SoftwareVersionService $versionService,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the UI for basic Panel settings.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.settings.index', [
|
||||
'version' => $this->versionService,
|
||||
'languages' => $this->getAvailableLanguages(true),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle settings update.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(BaseSettingsFormRequest $request): RedirectResponse
|
||||
{
|
||||
foreach ($request->normalize() as $key => $value) {
|
||||
$this->settings->set('settings::' . $key, $value);
|
||||
}
|
||||
|
||||
$this->kernel->call('queue:restart');
|
||||
$this->alert->success('Panel settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
|
||||
|
||||
return redirect()->route('admin.settings');
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Settings;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Pterodactyl\Notifications\MailTested;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Pterodactyl\Providers\SettingsServiceProvider;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Admin\Settings\MailSettingsFormRequest;
|
||||
|
||||
class MailController extends Controller
|
||||
{
|
||||
/**
|
||||
* MailController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private ConfigRepository $config,
|
||||
private Encrypter $encrypter,
|
||||
private Kernel $kernel,
|
||||
private SettingsRepositoryInterface $settings,
|
||||
private ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render UI for editing mail settings. This UI should only display if
|
||||
* the server is configured to send mail using SMTP.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('admin.settings.mail', [
|
||||
'disabled' => $this->config->get('mail.default') !== 'smtp',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update SMTP mail settings.
|
||||
*
|
||||
* @throws DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(MailSettingsFormRequest $request): Response
|
||||
{
|
||||
if ($this->config->get('mail.default') !== 'smtp') {
|
||||
throw new DisplayException('This feature is only available if SMTP is the selected email driver for the Panel.');
|
||||
}
|
||||
|
||||
$values = $request->normalize();
|
||||
if (array_get($values, 'mail:password') === '!e') {
|
||||
$values['mail:password'] = '';
|
||||
}
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if (in_array($key, SettingsServiceProvider::getEncryptedKeys()) && !empty($value)) {
|
||||
$value = $this->encrypter->encrypt($value);
|
||||
}
|
||||
|
||||
$this->settings->set('settings::' . $key, $value);
|
||||
}
|
||||
|
||||
$this->kernel->call('queue:restart');
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a request to send a test mail message.
|
||||
*/
|
||||
public function test(Request $request): Response
|
||||
{
|
||||
try {
|
||||
Notification::route('mail', $request->user()->email)
|
||||
->notify(new MailTested($request->user()));
|
||||
} catch (Exception $exception) {
|
||||
return response($exception->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Illuminate\View\Factory as ViewFactory;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Translation\Translator;
|
||||
use Pterodactyl\Services\Users\UserUpdateService;
|
||||
use Pterodactyl\Traits\Helpers\AvailableLanguages;
|
||||
use Pterodactyl\Services\Users\UserCreationService;
|
||||
use Pterodactyl\Services\Users\UserDeletionService;
|
||||
use Pterodactyl\Http\Requests\Admin\UserFormRequest;
|
||||
use Pterodactyl\Http\Requests\Admin\NewUserFormRequest;
|
||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
use AvailableLanguages;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
protected AlertsMessageBag $alert,
|
||||
protected UserCreationService $creationService,
|
||||
protected UserDeletionService $deletionService,
|
||||
protected Translator $translator,
|
||||
protected UserUpdateService $updateService,
|
||||
protected UserRepositoryInterface $repository,
|
||||
protected ViewFactory $view
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Display user index page.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$users = QueryBuilder::for(
|
||||
User::query()->select('users.*')
|
||||
->selectRaw('COUNT(DISTINCT(subusers.id)) as subuser_of_count')
|
||||
->selectRaw('COUNT(DISTINCT(servers.id)) as servers_count')
|
||||
->leftJoin('subusers', 'subusers.user_id', '=', 'users.id')
|
||||
->leftJoin('servers', 'servers.owner_id', '=', 'users.id')
|
||||
->groupBy('users.id')
|
||||
)
|
||||
->allowedFilters(['username', 'email', 'uuid'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate(50);
|
||||
|
||||
return $this->view->make('admin.users.index', ['users' => $users]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display new user page.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return $this->view->make('admin.users.new', [
|
||||
'languages' => $this->getAvailableLanguages(true),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display user view page.
|
||||
*/
|
||||
public function view(User $user): View
|
||||
{
|
||||
return $this->view->make('admin.users.view', [
|
||||
'user' => $user,
|
||||
'languages' => $this->getAvailableLanguages(true),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user from the system.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete(Request $request, User $user): RedirectResponse
|
||||
{
|
||||
if ($request->user()->id === $user->id) {
|
||||
throw new DisplayException($this->translator->get('admin/user.exceptions.user_has_servers'));
|
||||
}
|
||||
|
||||
$this->deletionService->handle($user);
|
||||
|
||||
return redirect()->route('admin.users');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a user.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function store(NewUserFormRequest $request): RedirectResponse
|
||||
{
|
||||
$user = $this->creationService->handle($request->normalize());
|
||||
$this->alert->success($this->translator->get('admin/user.notices.account_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.users.view', $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user on the system.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(UserFormRequest $request, User $user): RedirectResponse
|
||||
{
|
||||
$this->updateService
|
||||
->setUserLevel(User::USER_LEVEL_ADMIN)
|
||||
->handle($user, $request->normalize());
|
||||
|
||||
$this->alert->success(trans('admin/user.notices.account_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.users.view', $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a JSON response of users on the system.
|
||||
*/
|
||||
public function json(Request $request): Model|Collection
|
||||
{
|
||||
$users = QueryBuilder::for(User::query())->allowedFilters(['email'])->paginate(25);
|
||||
|
||||
// Handle single user requests.
|
||||
if ($request->query('user_id')) {
|
||||
$user = User::query()->findOrFail($request->input('user_id'));
|
||||
$user->md5 = md5(strtolower($user->email));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
return $users->map(function ($item) {
|
||||
$item->md5 = md5(strtolower($item->email));
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -3,19 +3,16 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Application;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Webmozart\Assert\Assert;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Container\Container;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Extensions\Spatie\Fractalistic\Fractal;
|
||||
use Pterodactyl\Transformers\Api\Application\BaseTransformer;
|
||||
|
||||
abstract class ApplicationApiController extends Controller
|
||||
{
|
||||
protected Request $request;
|
||||
|
||||
protected Fractal $fractal;
|
||||
protected Request $request;
|
||||
|
||||
/**
|
||||
* ApplicationApiController constructor.
|
||||
|
@ -47,21 +44,11 @@ abstract class ApplicationApiController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Return an instance of an application transformer.
|
||||
*
|
||||
* @template T of \Pterodactyl\Transformers\Api\Application\BaseTransformer
|
||||
*
|
||||
* @param class-string<T> $abstract
|
||||
*
|
||||
* @return T
|
||||
*
|
||||
* @noinspection PhpDocSignatureInspection
|
||||
* Return an HTTP/201 response for the API.
|
||||
*/
|
||||
public function getTransformer(string $abstract)
|
||||
protected function returnAccepted(): Response
|
||||
{
|
||||
Assert::subclassOf($abstract, BaseTransformer::class);
|
||||
|
||||
return $abstract::fromRequest($this->request);
|
||||
return new Response('', Response::HTTP_ACCEPTED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Databases;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\DatabaseHost;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Databases\Hosts\HostUpdateService;
|
||||
use Pterodactyl\Services\Databases\Hosts\HostCreationService;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Transformers\Api\Application\DatabaseHostTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\GetDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\GetDatabasesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\StoreDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\DeleteDatabaseRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Databases\UpdateDatabaseRequest;
|
||||
|
||||
class DatabaseController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* DatabaseController constructor.
|
||||
*/
|
||||
public function __construct(private HostCreationService $creationService, private HostUpdateService $updateService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all database hosts.
|
||||
*/
|
||||
public function index(GetDatabasesRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$databases = QueryBuilder::for(DatabaseHost::query())
|
||||
->allowedFilters(['name', 'host'])
|
||||
->allowedSorts(['id', 'name', 'host'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($databases)
|
||||
->transformWith(DatabaseHostTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single database host.
|
||||
*/
|
||||
public function view(GetDatabaseRequest $request, DatabaseHost $databaseHost): array
|
||||
{
|
||||
return $this->fractal->item($databaseHost)
|
||||
->transformWith(DatabaseHostTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new database host.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function store(StoreDatabaseRequest $request): JsonResponse
|
||||
{
|
||||
$databaseHost = $this->creationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($databaseHost)
|
||||
->transformWith(DatabaseHostTransformer::class)
|
||||
->respond(JsonResponse::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a database host.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(UpdateDatabaseRequest $request, DatabaseHost $databaseHost): array
|
||||
{
|
||||
$databaseHost = $this->updateService->handle($databaseHost->id, $request->validated());
|
||||
|
||||
return $this->fractal->item($databaseHost)
|
||||
->transformWith(DatabaseHostTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a database host.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(DeleteDatabaseRequest $request, DatabaseHost $databaseHost): Response
|
||||
{
|
||||
$databaseHost->delete();
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
120
app/Http/Controllers/Api/Application/Eggs/EggController.php
Normal file
120
app/Http/Controllers/Api/Application/Eggs/EggController.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Eggs;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Eggs\Sharing\EggExporterService;
|
||||
use Pterodactyl\Transformers\Api\Application\EggTransformer;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\GetEggRequest;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\GetEggsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\StoreEggRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\DeleteEggRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\ExportEggRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\UpdateEggRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class EggController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* EggController constructor.
|
||||
*/
|
||||
public function __construct(private EggExporterService $eggExporterService)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->eggExporterService = $eggExporterService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of all eggs on a given nest.
|
||||
*/
|
||||
public function index(GetEggsRequest $request, Nest $nest): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$eggs = QueryBuilder::for(Egg::query())
|
||||
->where('nest_id', '=', $nest->id)
|
||||
->allowedFilters(['id', 'name', 'author'])
|
||||
->allowedSorts(['id', 'name', 'author']);
|
||||
if ($perPage > 0) {
|
||||
$eggs = $eggs->paginate($perPage);
|
||||
}
|
||||
|
||||
return $this->fractal->collection($eggs)
|
||||
->transformWith(EggTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single egg.
|
||||
*/
|
||||
public function view(GetEggRequest $request, Egg $egg): array
|
||||
{
|
||||
return $this->fractal->item($egg)
|
||||
->transformWith(EggTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new egg.
|
||||
*/
|
||||
public function store(StoreEggRequest $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validated();
|
||||
$merged = array_merge($validated, [
|
||||
'uuid' => Uuid::uuid4()->toString(),
|
||||
// TODO: allow this to be set in the request, and default to config value if null or not present.
|
||||
'author' => config('pterodactyl.service.author'),
|
||||
]);
|
||||
|
||||
$egg = Egg::query()->create($merged);
|
||||
|
||||
return $this->fractal->item($egg)
|
||||
->transformWith(EggTransformer::class)
|
||||
->respond(Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an egg.
|
||||
*/
|
||||
public function update(UpdateEggRequest $request, Egg $egg): array
|
||||
{
|
||||
$egg->update($request->validated());
|
||||
|
||||
return $this->fractal->item($egg)
|
||||
->transformWith(EggTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an egg.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(DeleteEggRequest $request, Egg $egg): Response
|
||||
{
|
||||
$egg->delete();
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports an egg.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function export(ExportEggRequest $request, int $eggId): JsonResponse
|
||||
{
|
||||
return new JsonResponse($this->eggExporterService->handle($eggId));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Eggs;
|
||||
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\EggVariable;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
||||
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
||||
use Pterodactyl\Transformers\Api\Application\EggVariableTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\Variables\StoreEggVariableRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\Variables\UpdateEggVariablesRequest;
|
||||
|
||||
class EggVariableController extends ApplicationApiController
|
||||
{
|
||||
public function __construct(
|
||||
private ConnectionInterface $connection,
|
||||
private VariableCreationService $variableCreationService,
|
||||
private VariableUpdateService $variableUpdateService
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new egg variable.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
||||
*/
|
||||
public function store(StoreEggVariableRequest $request, Egg $egg): array
|
||||
{
|
||||
$variable = $this->variableCreationService->handle($egg->id, $request->validated());
|
||||
|
||||
return $this->fractal->item($variable)
|
||||
->transformWith(EggVariableTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates multiple egg variables.
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(UpdateEggVariablesRequest $request, Egg $egg): array
|
||||
{
|
||||
$validated = $request->validated();
|
||||
|
||||
$this->connection->transaction(function () use ($egg, $validated) {
|
||||
foreach ($validated as $data) {
|
||||
$this->variableUpdateService->handle($egg, $data);
|
||||
}
|
||||
});
|
||||
|
||||
return $this->fractal->collection($egg->refresh()->variables)
|
||||
->transformWith(EggVariableTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single egg variable.
|
||||
*/
|
||||
public function delete(Request $request, Egg $egg, EggVariable $eggVariable): Response
|
||||
{
|
||||
EggVariable::query()
|
||||
->where('id', $eggVariable->id)
|
||||
->where('egg_id', $egg->id)
|
||||
->delete();
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use Pterodactyl\Services\Locations\LocationUpdateService;
|
|||
use Pterodactyl\Services\Locations\LocationCreationService;
|
||||
use Pterodactyl\Services\Locations\LocationDeletionService;
|
||||
use Pterodactyl\Transformers\Api\Application\LocationTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\GetLocationRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\GetLocationsRequest;
|
||||
|
@ -35,13 +36,18 @@ class LocationController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetLocationsRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$locations = QueryBuilder::for(Location::query())
|
||||
->allowedFilters(['short', 'long'])
|
||||
->allowedSorts(['id'])
|
||||
->paginate($request->query('per_page') ?? 50);
|
||||
->allowedSorts(['id', 'short', 'long'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($locations)
|
||||
->transformWith($this->getTransformer(LocationTransformer::class))
|
||||
->transformWith(LocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -51,7 +57,7 @@ class LocationController extends ApplicationApiController
|
|||
public function view(GetLocationRequest $request, Location $location): array
|
||||
{
|
||||
return $this->fractal->item($location)
|
||||
->transformWith($this->getTransformer(LocationTransformer::class))
|
||||
->transformWith(LocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -66,12 +72,7 @@ class LocationController extends ApplicationApiController
|
|||
$location = $this->creationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($location)
|
||||
->transformWith($this->getTransformer(LocationTransformer::class))
|
||||
->addMeta([
|
||||
'resource' => route('api.application.locations.view', [
|
||||
'location' => $location->id,
|
||||
]),
|
||||
])
|
||||
->transformWith(LocationTransformer::class)
|
||||
->respond(201);
|
||||
}
|
||||
|
||||
|
@ -86,7 +87,7 @@ class LocationController extends ApplicationApiController
|
|||
$location = $this->updateService->handle($location, $request->validated());
|
||||
|
||||
return $this->fractal->item($location)
|
||||
->transformWith($this->getTransformer(LocationTransformer::class))
|
||||
->transformWith(LocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -99,6 +100,6 @@ class LocationController extends ApplicationApiController
|
|||
{
|
||||
$this->deletionService->handle($location);
|
||||
|
||||
return response('', 204);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
163
app/Http/Controllers/Api/Application/Mounts/MountController.php
Normal file
163
app/Http/Controllers/Api/Application/Mounts/MountController.php
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Mounts;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Transformers\Api\Application\MountTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\GetMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\GetMountsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountEggsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\MountNodesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\StoreMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\DeleteMountRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Mounts\UpdateMountRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class MountController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* MountController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all mount.
|
||||
*/
|
||||
public function index(GetMountsRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$mounts = QueryBuilder::for(Mount::query())
|
||||
->allowedFilters(['id', 'name', 'source', 'target'])
|
||||
->allowedSorts(['id', 'name', 'source', 'target'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($mounts)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single mount.
|
||||
*/
|
||||
public function view(GetMountRequest $request, Mount $mount): array
|
||||
{
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new mount.
|
||||
*/
|
||||
public function store(StoreMountRequest $request): JsonResponse
|
||||
{
|
||||
$mount = Mount::query()->create($request->validated());
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->respond(JsonResponse::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a mount.
|
||||
*/
|
||||
public function update(UpdateMountRequest $request, Mount $mount): array
|
||||
{
|
||||
$mount->update($request->validated());
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a mount.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(DeleteMountRequest $request, Mount $mount): Response
|
||||
{
|
||||
$mount->delete();
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches eggs to a mount.
|
||||
*/
|
||||
public function addEggs(MountEggsRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$eggs = $data['eggs'] ?? [];
|
||||
if (count($eggs) > 0) {
|
||||
$mount->eggs()->syncWithoutDetaching($eggs);
|
||||
}
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches nodes to a mount.
|
||||
*/
|
||||
public function addNodes(MountNodesRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$mount->nodes()->syncWithoutDetaching($nodes);
|
||||
}
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches eggs from a mount.
|
||||
*/
|
||||
public function deleteEggs(MountEggsRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$eggs = $data['eggs'] ?? [];
|
||||
if (count($eggs) > 0) {
|
||||
$mount->eggs()->detach($eggs);
|
||||
}
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches nodes from a mount.
|
||||
*/
|
||||
public function deleteNodes(MountNodesRequest $request, Mount $mount): array
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$mount->nodes()->detach($nodes);
|
||||
}
|
||||
|
||||
return $this->fractal->item($mount)
|
||||
->transformWith(MountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Nests;
|
||||
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Pterodactyl\Transformers\Api\Application\EggTransformer;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\Eggs\GetEggRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\Eggs\GetEggsRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class EggController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* Return all eggs that exist for a given nest.
|
||||
*/
|
||||
public function index(GetEggsRequest $request, Nest $nest): array
|
||||
{
|
||||
return $this->fractal->collection($nest->eggs)
|
||||
->transformWith($this->getTransformer(EggTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single egg that exists on the specified nest.
|
||||
*/
|
||||
public function view(GetEggRequest $request, Nest $nest, Egg $egg): array
|
||||
{
|
||||
return $this->fractal->item($egg)
|
||||
->transformWith($this->getTransformer(EggTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
}
|
|
@ -3,9 +3,21 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Application\Nests;
|
||||
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Illuminate\Http\Response;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Nests\NestUpdateService;
|
||||
use Pterodactyl\Services\Nests\NestCreationService;
|
||||
use Pterodactyl\Services\Nests\NestDeletionService;
|
||||
use Pterodactyl\Services\Eggs\Sharing\EggImporterService;
|
||||
use Pterodactyl\Transformers\Api\Application\EggTransformer;
|
||||
use Pterodactyl\Transformers\Api\Application\NestTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\GetNestRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Eggs\ImportEggRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\GetNestsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\StoreNestRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\DeleteNestRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nests\UpdateNestRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class NestController extends ApplicationApiController
|
||||
|
@ -13,8 +25,12 @@ class NestController extends ApplicationApiController
|
|||
/**
|
||||
* NestController constructor.
|
||||
*/
|
||||
public function __construct(private NestRepositoryInterface $repository)
|
||||
{
|
||||
public function __construct(
|
||||
private NestCreationService $nestCreationService,
|
||||
private NestDeletionService $nestDeletionService,
|
||||
private NestUpdateService $nestUpdateService,
|
||||
private EggImporterService $eggImporterService
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
@ -23,20 +39,87 @@ class NestController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetNestsRequest $request): array
|
||||
{
|
||||
$nests = $this->repository->paginated($request->query('per_page') ?? 50);
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$nests = QueryBuilder::for(Nest::query())
|
||||
->allowedFilters(['id', 'name', 'author'])
|
||||
->allowedSorts(['id', 'name', 'author']);
|
||||
if ($perPage > 0) {
|
||||
$nests = $nests->paginate($perPage);
|
||||
}
|
||||
|
||||
return $this->fractal->collection($nests)
|
||||
->transformWith($this->getTransformer(NestTransformer::class))
|
||||
->transformWith(NestTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information about a single Nest model.
|
||||
*/
|
||||
public function view(GetNestsRequest $request, Nest $nest): array
|
||||
public function view(GetNestRequest $request, Nest $nest): array
|
||||
{
|
||||
return $this->fractal->item($nest)
|
||||
->transformWith($this->getTransformer(NestTransformer::class))
|
||||
->transformWith(NestTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function store(StoreNestRequest $request): array
|
||||
{
|
||||
$nest = $this->nestCreationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($nest)
|
||||
->transformWith(NestTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports an egg.
|
||||
*/
|
||||
public function import(ImportEggRequest $request, Nest $nest): array
|
||||
{
|
||||
$egg = $this->eggImporterService->handleContent(
|
||||
$nest->id,
|
||||
$request->getContent(),
|
||||
$request->headers->get('Content-Type'),
|
||||
);
|
||||
|
||||
return $this->fractal->item($egg)
|
||||
->transformWith(EggTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(UpdateNestRequest $request, Nest $nest): array
|
||||
{
|
||||
$this->nestUpdateService->handle($nest->id, $request->validated());
|
||||
|
||||
return $this->fractal->item($nest)
|
||||
->transformWith(NestTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing nest.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function delete(DeleteNestRequest $request, Nest $nest): Response
|
||||
{
|
||||
$this->nestDeletionService->handle($nest->id);
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Spatie\QueryBuilder\AllowedFilter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Pterodactyl\Services\Allocations\AssignmentService;
|
||||
use Pterodactyl\Services\Allocations\AllocationDeletionService;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Transformers\Api\Application\AllocationTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Allocations\GetAllocationsRequest;
|
||||
|
@ -33,23 +34,27 @@ class AllocationController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetAllocationsRequest $request, Node $node): array
|
||||
{
|
||||
$allocations = QueryBuilder::for($node->allocations())
|
||||
->allowedFilters([
|
||||
AllowedFilter::exact('ip'),
|
||||
AllowedFilter::exact('port'),
|
||||
'ip_alias',
|
||||
AllowedFilter::callback('server_id', function (Builder $builder, $value) {
|
||||
if (empty($value) || is_bool($value) || !ctype_digit((string) $value)) {
|
||||
return $builder->whereNull('server_id');
|
||||
}
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
return $builder->where('server_id', $value);
|
||||
$allocations = QueryBuilder::for(Allocation::query()->where('node_id', '=', $node->id))
|
||||
->allowedFilters([
|
||||
'id', 'ip', 'port', 'alias',
|
||||
AllowedFilter::callback('server_id', function (Builder $query, $value) {
|
||||
if ($value === '0') {
|
||||
$query->whereNull('server_id');
|
||||
} else {
|
||||
$query->where('server_id', '=', $value);
|
||||
}
|
||||
}),
|
||||
])
|
||||
->paginate($request->query('per_page') ?? 50);
|
||||
->allowedSorts(['id', 'ip', 'port', 'server_id'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($allocations)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
->transformWith(AllocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -62,11 +67,11 @@ class AllocationController extends ApplicationApiController
|
|||
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
|
||||
*/
|
||||
public function store(StoreAllocationRequest $request, Node $node): JsonResponse
|
||||
public function store(StoreAllocationRequest $request, Node $node): Response
|
||||
{
|
||||
$this->assignmentService->handle($node, $request->validated());
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,10 +79,10 @@ class AllocationController extends ApplicationApiController
|
|||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
|
||||
*/
|
||||
public function delete(DeleteAllocationRequest $request, Node $node, Allocation $allocation): JsonResponse
|
||||
public function delete(DeleteAllocationRequest $request, Node $node, Allocation $allocation): Response
|
||||
{
|
||||
$this->deletionService->handle($allocation);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,12 @@ class NodeConfigurationController extends ApplicationApiController
|
|||
* to remote machines so long as an API key is provided to the machine to make the request
|
||||
* with, and the node is known.
|
||||
*/
|
||||
public function __invoke(GetNodeRequest $request, Node $node): JsonResponse
|
||||
public function __invoke(GetNodeRequest $request, Node $node): JsonResponse|string
|
||||
{
|
||||
if ($request->query('format') === 'yaml') {
|
||||
return $node->getYamlConfiguration();
|
||||
}
|
||||
|
||||
return new JsonResponse($node->getConfiguration());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Nodes\NodeUpdateService;
|
||||
use Pterodactyl\Services\Nodes\NodeCreationService;
|
||||
use Pterodactyl\Services\Nodes\NodeDeletionService;
|
||||
use Pterodactyl\Transformers\Api\Application\NodeTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nodes\GetNodeRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nodes\GetNodesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nodes\StoreNodeRequest;
|
||||
|
@ -34,13 +36,18 @@ class NodeController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetNodesRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$nodes = QueryBuilder::for(Node::query())
|
||||
->allowedFilters(['uuid', 'name', 'fqdn', 'daemon_token_id'])
|
||||
->allowedSorts(['id', 'uuid', 'memory', 'disk'])
|
||||
->paginate($request->query('per_page') ?? 50);
|
||||
->allowedFilters(['id', 'uuid', 'name', 'fqdn', 'daemon_token_id'])
|
||||
->allowedSorts(['id', 'uuid', 'name', 'location_id', 'fqdn', 'memory', 'disk'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($nodes)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->transformWith(NodeTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -50,7 +57,7 @@ class NodeController extends ApplicationApiController
|
|||
public function view(GetNodeRequest $request, Node $node): array
|
||||
{
|
||||
return $this->fractal->item($node)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->transformWith(NodeTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -65,12 +72,7 @@ class NodeController extends ApplicationApiController
|
|||
$node = $this->creationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($node)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->addMeta([
|
||||
'resource' => route('api.application.nodes.view', [
|
||||
'node' => $node->id,
|
||||
]),
|
||||
])
|
||||
->transformWith(NodeTransformer::class)
|
||||
->respond(201);
|
||||
}
|
||||
|
||||
|
@ -84,11 +86,10 @@ class NodeController extends ApplicationApiController
|
|||
$node = $this->updateService->handle(
|
||||
$node,
|
||||
$request->validated(),
|
||||
$request->input('reset_secret') === true
|
||||
);
|
||||
|
||||
return $this->fractal->item($node)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->transformWith(NodeTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -98,10 +99,10 @@ class NodeController extends ApplicationApiController
|
|||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function delete(DeleteNodeRequest $request, Node $node): JsonResponse
|
||||
public function delete(DeleteNodeRequest $request, Node $node): Response
|
||||
{
|
||||
$this->deletionService->handle($node);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class NodeDeploymentController extends ApplicationApiController
|
|||
->handle($request->query('per_page'), $request->query('page'));
|
||||
|
||||
return $this->fractal->collection($nodes)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->transformWith(NodeTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Cache\Repository as CacheRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class NodeInformationController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* NodeInformationController constructor.
|
||||
*/
|
||||
public function __construct(private CacheRepository $cache, private DaemonConfigurationRepository $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns system information from the node.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function __invoke(Request $request, Node $node): JsonResponse
|
||||
{
|
||||
$data = $this->cache
|
||||
->tags(['nodes'])
|
||||
->remember($node->uuid, Carbon::now()->addSeconds(30), function () use ($node) {
|
||||
return $this->repository->setNode($node)->getSystemInformation();
|
||||
});
|
||||
|
||||
return new JsonResponse([
|
||||
'version' => $data['version'] ?? null,
|
||||
'system' => [
|
||||
'type' => Str::title($data['os'] ?? 'Unknown'),
|
||||
'arch' => $data['architecture'] ?? null,
|
||||
'release' => $data['kernel_version'] ?? null,
|
||||
'cpus' => $data['cpu_count'] ?? null,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Roles;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\AdminRole;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Transformers\Api\Application\AdminRoleTransformer;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Roles\GetRoleRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Roles\GetRolesRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Roles\StoreRoleRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Roles\DeleteRoleRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Roles\UpdateRoleRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class RoleController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* RoleController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all roles.
|
||||
*/
|
||||
public function index(GetRolesRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$roles = QueryBuilder::for(AdminRole::query())
|
||||
->allowedFilters(['id', 'name'])
|
||||
->allowedSorts(['id', 'name'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($roles)
|
||||
->transformWith(AdminRoleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single role.
|
||||
*/
|
||||
public function view(GetRoleRequest $request, AdminRole $role): array
|
||||
{
|
||||
return $this->fractal->item($role)
|
||||
->transformWith(AdminRoleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new role.
|
||||
*/
|
||||
public function store(StoreRoleRequest $request): JsonResponse
|
||||
{
|
||||
$data = array_merge($request->validated(), [
|
||||
'sort_id' => 99,
|
||||
]);
|
||||
$role = AdminRole::query()->create($data);
|
||||
|
||||
return $this->fractal->item($role)
|
||||
->transformWith(AdminRoleTransformer::class)
|
||||
->respond(JsonResponse::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a role.
|
||||
*/
|
||||
public function update(UpdateRoleRequest $request, AdminRole $role): array
|
||||
{
|
||||
$role->update($request->validated());
|
||||
|
||||
return $this->fractal->item($role)
|
||||
->transformWith(AdminRoleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a role.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(DeleteRoleRequest $request, AdminRole $role): Response
|
||||
{
|
||||
$role->delete();
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ class DatabaseController extends ApplicationApiController
|
|||
public function index(GetServerDatabasesRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->collection($server->databases)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
->transformWith(ServerDatabaseTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ class DatabaseController extends ApplicationApiController
|
|||
public function view(GetServerDatabaseRequest $request, Server $server, Database $database): array
|
||||
{
|
||||
return $this->fractal->item($database)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
->transformWith(ServerDatabaseTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -53,11 +53,11 @@ class DatabaseController extends ApplicationApiController
|
|||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function resetPassword(ServerDatabaseWriteRequest $request, Server $server, Database $database): JsonResponse
|
||||
public function resetPassword(ServerDatabaseWriteRequest $request, Server $server, Database $database): Response
|
||||
{
|
||||
$this->databasePasswordService->handle($database);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,23 +72,19 @@ class DatabaseController extends ApplicationApiController
|
|||
]));
|
||||
|
||||
return $this->fractal->item($database)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
->addMeta([
|
||||
'resource' => route('api.application.servers.databases.view', [
|
||||
'server' => $server->id,
|
||||
'database' => $database->id,
|
||||
]),
|
||||
])
|
||||
->transformWith(ServerDatabaseTransformer::class)
|
||||
->respond(Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to delete a specific server database from the Panel.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(ServerDatabaseWriteRequest $request, Server $server, Database $database): Response
|
||||
public function delete(ServerDatabaseWriteRequest $request, Database $database): Response
|
||||
{
|
||||
$this->databaseManagementService->delete($database);
|
||||
|
||||
return response('', 204);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ class ExternalServerController extends ApplicationApiController
|
|||
$server = Server::query()->where('external_id', $external_id)->firstOrFail();
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->transformWith(ServerTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,16 @@ use Illuminate\Http\JsonResponse;
|
|||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||
use Pterodactyl\Services\Servers\ServerDeletionService;
|
||||
use Pterodactyl\Services\Servers\BuildModificationService;
|
||||
use Pterodactyl\Services\Servers\DetailsModificationService;
|
||||
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServerRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServersRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\StoreServerRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\UpdateServerRequest;
|
||||
|
||||
class ServerController extends ApplicationApiController
|
||||
{
|
||||
|
@ -21,6 +25,8 @@ class ServerController extends ApplicationApiController
|
|||
* ServerController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private BuildModificationService $buildModificationService,
|
||||
private DetailsModificationService $detailsModificationService,
|
||||
private ServerCreationService $creationService,
|
||||
private ServerDeletionService $deletionService
|
||||
) {
|
||||
|
@ -32,13 +38,18 @@ class ServerController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetServersRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$servers = QueryBuilder::for(Server::query())
|
||||
->allowedFilters(['uuid', 'uuidShort', 'name', 'description', 'image', 'external_id'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate($request->query('per_page') ?? 50);
|
||||
->allowedFilters(['id', 'uuid', 'uuidShort', 'name', 'owner_id', 'node_id', 'external_id'])
|
||||
->allowedSorts(['id', 'uuid', 'uuidShort', 'name', 'owner_id', 'node_id', 'status'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($servers)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->transformWith(ServerTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -48,18 +59,17 @@ class ServerController extends ApplicationApiController
|
|||
* @throws \Throwable
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||
*/
|
||||
public function store(StoreServerRequest $request): JsonResponse
|
||||
{
|
||||
$server = $this->creationService->handle($request->validated(), $request->getDeploymentObject());
|
||||
$server = $this->creationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->respond(201);
|
||||
->transformWith(ServerTransformer::class)
|
||||
->respond(Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +78,7 @@ class ServerController extends ApplicationApiController
|
|||
public function view(GetServerRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->transformWith(ServerTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -76,6 +86,7 @@ class ServerController extends ApplicationApiController
|
|||
* Deletes a server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function delete(ServerWriteRequest $request, Server $server, string $force = ''): Response
|
||||
{
|
||||
|
@ -83,4 +94,24 @@ class ServerController extends ApplicationApiController
|
|||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a server.
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||
*/
|
||||
public function update(UpdateServerRequest $request, Server $server): array
|
||||
{
|
||||
$server = $this->buildModificationService->handle($server, $request->validated());
|
||||
$server = $this->detailsModificationService->returnUpdatedModel()->handle($server, $request->validated());
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith(ServerTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Servers;
|
||||
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Services\Servers\BuildModificationService;
|
||||
use Pterodactyl\Services\Servers\DetailsModificationService;
|
||||
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\UpdateServerDetailsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\UpdateServerBuildConfigurationRequest;
|
||||
|
||||
class ServerDetailsController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* ServerDetailsController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private BuildModificationService $buildModificationService,
|
||||
private DetailsModificationService $detailsModificationService
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the details for a specific server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function details(UpdateServerDetailsRequest $request, Server $server): array
|
||||
{
|
||||
$updated = $this->detailsModificationService->returnUpdatedModel()->handle(
|
||||
$server,
|
||||
$request->validated()
|
||||
);
|
||||
|
||||
return $this->fractal->item($updated)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the build details for a specific server.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function build(UpdateServerBuildConfigurationRequest $request, Server $server): array
|
||||
{
|
||||
$server = $this->buildModificationService->handle($server, $request->validated());
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
|||
class ServerManagementController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* ServerManagementController constructor.
|
||||
* SuspensionController constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
private ReinstallServerService $reinstallServerService,
|
||||
|
@ -48,9 +48,7 @@ class ServerManagementController extends ApplicationApiController
|
|||
/**
|
||||
* Mark a server as needing to be reinstalled.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function reinstall(ServerWriteRequest $request, Server $server): Response
|
||||
{
|
||||
|
|
|
@ -22,10 +22,7 @@ class StartupController extends ApplicationApiController
|
|||
/**
|
||||
* Update the startup and environment settings for a specific server.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function index(UpdateServerStartupRequest $request, Server $server): array
|
||||
{
|
||||
|
@ -34,7 +31,7 @@ class StartupController extends ApplicationApiController
|
|||
->handle($server, $request->validated());
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->transformWith(ServerTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ class ExternalUserController extends ApplicationApiController
|
|||
$user = User::query()->where('external_id', $external_id)->firstOrFail();
|
||||
|
||||
return $this->fractal->item($user)
|
||||
->transformWith($this->getTransformer(UserTransformer::class))
|
||||
->transformWith(UserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,19 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Users;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Pterodactyl\Models\User;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Spatie\QueryBuilder\AllowedFilter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Pterodactyl\Services\Users\UserUpdateService;
|
||||
use Pterodactyl\Services\Users\UserCreationService;
|
||||
use Pterodactyl\Services\Users\UserDeletionService;
|
||||
use Pterodactyl\Transformers\Api\Application\UserTransformer;
|
||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Users\GetUserRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Users\GetUsersRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Users\StoreUserRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Users\DeleteUserRequest;
|
||||
|
@ -35,24 +41,48 @@ class UserController extends ApplicationApiController
|
|||
*/
|
||||
public function index(GetUsersRequest $request): array
|
||||
{
|
||||
$perPage = (int) $request->query('per_page', '10');
|
||||
if ($perPage < 1 || $perPage > 100) {
|
||||
throw new QueryValueOutOfRangeHttpException('per_page', 1, 100);
|
||||
}
|
||||
|
||||
$users = QueryBuilder::for(User::query())
|
||||
->allowedFilters(['email', 'uuid', 'username', 'external_id'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate($request->query('per_page') ?? 50);
|
||||
->allowedFilters([
|
||||
AllowedFilter::exact('id'),
|
||||
AllowedFilter::exact('uuid'),
|
||||
AllowedFilter::exact('external_id'),
|
||||
'username',
|
||||
'email',
|
||||
AllowedFilter::callback('*', function (Builder $builder, $value) {
|
||||
foreach (Arr::wrap($value) as $datum) {
|
||||
$datum = '%' . $datum . '%';
|
||||
$builder->where(function (Builder $builder) use ($datum) {
|
||||
$builder->where('uuid', 'LIKE', $datum)
|
||||
->orWhere('username', 'LIKE', $datum)
|
||||
->orWhere('email', 'LIKE', $datum)
|
||||
->orWhere('external_id', 'LIKE', $datum);
|
||||
});
|
||||
}
|
||||
}),
|
||||
])
|
||||
->allowedSorts(['id', 'uuid', 'username', 'email', 'admin_role_id'])
|
||||
->paginate($perPage);
|
||||
|
||||
return $this->fractal->collection($users)
|
||||
->transformWith($this->getTransformer(UserTransformer::class))
|
||||
->transformWith(UserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request to view a single user. Includes any relations that
|
||||
* were defined in the request.
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function view(GetUsersRequest $request, User $user): array
|
||||
public function view(GetUserRequest $request, User $user): array
|
||||
{
|
||||
return $this->fractal->item($user)
|
||||
->transformWith($this->getTransformer(UserTransformer::class))
|
||||
->transformWith(UserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -64,22 +94,20 @@ class UserController extends ApplicationApiController
|
|||
* Revocation errors are returned under the 'revocation_errors' key in the response
|
||||
* meta. If there are no errors this is an empty array.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function update(UpdateUserRequest $request, User $user): array
|
||||
{
|
||||
$this->updateService->setUserLevel(User::USER_LEVEL_ADMIN);
|
||||
$user = $this->updateService->handle($user, $request->validated());
|
||||
|
||||
$response = $this->fractal->item($user)
|
||||
->transformWith($this->getTransformer(UserTransformer::class));
|
||||
|
||||
return $response->toArray();
|
||||
return $this->fractal->item($user)
|
||||
->transformWith(UserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new user on the system. Returns the created user and an HTTP/201
|
||||
* Store a new user on the system. Returns the created user and a HTTP/201
|
||||
* header on successful creation.
|
||||
*
|
||||
* @throws \Exception
|
||||
|
@ -90,12 +118,7 @@ class UserController extends ApplicationApiController
|
|||
$user = $this->creationService->handle($request->validated());
|
||||
|
||||
return $this->fractal->item($user)
|
||||
->transformWith($this->getTransformer(UserTransformer::class))
|
||||
->addMeta([
|
||||
'resource' => route('api.application.users.view', [
|
||||
'user' => $user->id,
|
||||
]),
|
||||
])
|
||||
->transformWith(UserTransformer::class)
|
||||
->respond(201);
|
||||
}
|
||||
|
||||
|
@ -105,10 +128,10 @@ class UserController extends ApplicationApiController
|
|||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete(DeleteUserRequest $request, User $user): JsonResponse
|
||||
public function delete(DeleteUserRequest $request, User $user): Response
|
||||
{
|
||||
$this->deletionService->handle($user);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
}
|
||||
|
|
25
app/Http/Controllers/Api/Application/VersionController.php
Normal file
25
app/Http/Controllers/Api/Application/VersionController.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
|
||||
class VersionController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* VersionController constructor.
|
||||
*/
|
||||
public function __construct(private SoftwareVersionService $softwareVersionService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version information.
|
||||
*/
|
||||
public function __invoke(): JsonResponse
|
||||
{
|
||||
return new JsonResponse($this->softwareVersionService->getVersionData());
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ class AccountController extends ClientApiController
|
|||
public function index(Request $request): array
|
||||
{
|
||||
return $this->fractal->item($request->user())
|
||||
->transformWith($this->getTransformer(AccountTransformer::class))
|
||||
->transformWith(AccountTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class ActivityLogController extends ClientApiController
|
|||
->appends($request->query());
|
||||
|
||||
return $this->fractal->collection($activity)
|
||||
->transformWith($this->getTransformer(ActivityLogTransformer::class))
|
||||
->transformWith(ActivityLogTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class ApiKeyController extends ClientApiController
|
|||
public function index(ClientApiRequest $request): array
|
||||
{
|
||||
return $this->fractal->collection($request->user()->apiKeys)
|
||||
->transformWith($this->getTransformer(ApiKeyTransformer::class))
|
||||
->transformWith(ApiKeyTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ class ApiKeyController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($token->accessToken)
|
||||
->transformWith($this->getTransformer(ApiKeyTransformer::class))
|
||||
->transformWith(ApiKeyTransformer::class)
|
||||
->addMeta(['secret_token' => $token->plainTextToken])
|
||||
->toArray();
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Client;
|
||||
|
||||
use Webmozart\Assert\Assert;
|
||||
use Pterodactyl\Transformers\Api\Client\BaseClientTransformer;
|
||||
use Pterodactyl\Transformers\Api\Transformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
abstract class ClientApiController extends ApplicationApiController
|
||||
|
@ -11,7 +10,7 @@ abstract class ClientApiController extends ApplicationApiController
|
|||
/**
|
||||
* Returns only the includes which are valid for the given transformer.
|
||||
*/
|
||||
protected function getIncludesForTransformer(BaseClientTransformer $transformer, array $merge = []): array
|
||||
protected function getIncludesForTransformer(Transformer $transformer, array $merge = []): array
|
||||
{
|
||||
$filtered = array_filter($this->parseIncludes(), function ($datum) use ($transformer) {
|
||||
return in_array($datum, $transformer->getAvailableIncludes());
|
||||
|
@ -35,22 +34,4 @@ abstract class ClientApiController extends ApplicationApiController
|
|||
return trim($item);
|
||||
}, explode(',', $includes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of an application transformer.
|
||||
*
|
||||
* @template T of \Pterodactyl\Transformers\Api\Client\BaseClientTransformer
|
||||
*
|
||||
* @param class-string<T> $abstract
|
||||
*
|
||||
* @return T
|
||||
*
|
||||
* @noinspection PhpDocSignatureInspection
|
||||
*/
|
||||
public function getTransformer(string $abstract)
|
||||
{
|
||||
Assert::subclassOf($abstract, BaseClientTransformer::class);
|
||||
|
||||
return $abstract::fromRequest($this->request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class ClientController extends ClientApiController
|
|||
public function index(GetServersRequest $request): array
|
||||
{
|
||||
$user = $request->user();
|
||||
$transformer = $this->getTransformer(ServerTransformer::class);
|
||||
$transformer = new ServerTransformer();
|
||||
|
||||
// Start the query builder and ensure we eager load any requested relationships from the request.
|
||||
$builder = QueryBuilder::for(
|
||||
|
@ -40,6 +40,11 @@ class ClientController extends ClientApiController
|
|||
AllowedFilter::custom('*', new MultiFieldServerFilter()),
|
||||
]);
|
||||
|
||||
$loweredBindings = collect($builder->getBindings())
|
||||
->map(fn ($f, $key) => is_string($f) ? strtolower($f) : $f)
|
||||
->all();
|
||||
$builder->setBindings($loweredBindings);
|
||||
|
||||
$type = $request->input('type');
|
||||
// Either return all the servers the user has access to because they are an admin `?type=admin` or
|
||||
// just return all the servers the user has access to because they are the owner or a subuser of the
|
||||
|
|
|
@ -17,7 +17,7 @@ class SSHKeyController extends ClientApiController
|
|||
public function index(ClientApiRequest $request): array
|
||||
{
|
||||
return $this->fractal->collection($request->user()->sshKeys)
|
||||
->transformWith($this->getTransformer(UserSSHKeyTransformer::class))
|
||||
->transformWith(UserSSHKeyTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class SSHKeyController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($model)
|
||||
->transformWith($this->getTransformer(UserSSHKeyTransformer::class))
|
||||
->transformWith(UserSSHKeyTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class ActivityLogController extends ClientApiController
|
|||
->appends($request->query());
|
||||
|
||||
return $this->fractal->collection($activity)
|
||||
->transformWith($this->getTransformer(ActivityLogTransformer::class))
|
||||
->transformWith(ActivityLogTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class BackupController extends ClientApiController
|
|||
$limit = min($request->query('per_page') ?? 20, 50);
|
||||
|
||||
return $this->fractal->collection($server->backups()->paginate($limit))
|
||||
->transformWith($this->getTransformer(BackupTransformer::class))
|
||||
->transformWith(BackupTransformer::class)
|
||||
->addMeta([
|
||||
'backup_count' => $this->repository->getNonFailedBackups($server)->count(),
|
||||
])
|
||||
|
@ -84,7 +84,7 @@ class BackupController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($backup)
|
||||
->transformWith($this->getTransformer(BackupTransformer::class))
|
||||
->transformWith(BackupTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ class BackupController extends ClientApiController
|
|||
Activity::event($action)->subject($backup)->property('name', $backup->name)->log();
|
||||
|
||||
return $this->fractal->item($backup)
|
||||
->transformWith($this->getTransformer(BackupTransformer::class))
|
||||
->transformWith(BackupTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ class BackupController extends ClientApiController
|
|||
}
|
||||
|
||||
return $this->fractal->item($backup)
|
||||
->transformWith($this->getTransformer(BackupTransformer::class))
|
||||
->transformWith(BackupTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class DatabaseController extends ClientApiController
|
|||
public function index(GetDatabasesRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->collection($server->databases)
|
||||
->transformWith($this->getTransformer(DatabaseTransformer::class))
|
||||
->transformWith(DatabaseTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class DatabaseController extends ClientApiController
|
|||
|
||||
return $this->fractal->item($database)
|
||||
->parseIncludes(['password'])
|
||||
->transformWith($this->getTransformer(DatabaseTransformer::class))
|
||||
->transformWith(DatabaseTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class DatabaseController extends ClientApiController
|
|||
|
||||
return $this->fractal->item($database)
|
||||
->parseIncludes(['password'])
|
||||
->transformWith($this->getTransformer(DatabaseTransformer::class))
|
||||
->transformWith(DatabaseTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ class FileController extends ClientApiController
|
|||
->getDirectory($request->get('directory') ?? '/');
|
||||
|
||||
return $this->fractal->collection($contents)
|
||||
->transformWith($this->getTransformer(FileObjectTransformer::class))
|
||||
->transformWith(FileObjectTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ class FileController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($file)
|
||||
->transformWith($this->getTransformer(FileObjectTransformer::class))
|
||||
->transformWith(FileObjectTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class NetworkAllocationController extends ClientApiController
|
|||
public function index(GetNetworkRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->collection($server->allocations)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
->transformWith(AllocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ class NetworkAllocationController extends ClientApiController
|
|||
}
|
||||
|
||||
return $this->fractal->item($allocation)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
->transformWith(AllocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ class NetworkAllocationController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($allocation)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
->transformWith(AllocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ class NetworkAllocationController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($allocation)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
->transformWith(AllocationTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class ResourceUtilizationController extends ClientApiController
|
|||
});
|
||||
|
||||
return $this->fractal->item($stats)
|
||||
->transformWith($this->getTransformer(StatsTransformer::class))
|
||||
->transformWith(StatsTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
||||
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
@ -41,7 +40,7 @@ class ScheduleController extends ClientApiController
|
|||
$schedules = $server->schedules->loadMissing('tasks');
|
||||
|
||||
return $this->fractal->collection($schedules)
|
||||
->transformWith($this->getTransformer(ScheduleTransformer::class))
|
||||
->transformWith(ScheduleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -73,7 +72,7 @@ class ScheduleController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($model)
|
||||
->transformWith($this->getTransformer(ScheduleTransformer::class))
|
||||
->transformWith(ScheduleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -89,7 +88,7 @@ class ScheduleController extends ClientApiController
|
|||
$schedule->loadMissing('tasks');
|
||||
|
||||
return $this->fractal->item($schedule)
|
||||
->transformWith($this->getTransformer(ScheduleTransformer::class))
|
||||
->transformWith(ScheduleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -132,7 +131,7 @@ class ScheduleController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($schedule->refresh())
|
||||
->transformWith($this->getTransformer(ScheduleTransformer::class))
|
||||
->transformWith(ScheduleTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -178,7 +177,7 @@ class ScheduleController extends ClientApiController
|
|||
$request->input('month'),
|
||||
$request->input('day_of_week')
|
||||
);
|
||||
} catch (Exception $exception) {
|
||||
} catch (\Exception $exception) {
|
||||
throw new DisplayException('The cron data provided does not evaluate to a valid expression.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class ScheduleTaskController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($task)
|
||||
->transformWith($this->getTransformer(TaskTransformer::class))
|
||||
->transformWith(TaskTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ class ScheduleTaskController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($task->refresh())
|
||||
->transformWith($this->getTransformer(TaskTransformer::class))
|
||||
->transformWith(TaskTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class ServerController extends ClientApiController
|
|||
public function index(GetServerRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
->transformWith(ServerTransformer::class)
|
||||
->addMeta([
|
||||
'is_server_owner' => $request->user()->id === $server->owner_id,
|
||||
'user_permissions' => $this->permissionsService->handle($server, $request->user()),
|
||||
|
|
|
@ -34,14 +34,22 @@ class SettingsController extends ClientApiController
|
|||
*/
|
||||
public function rename(RenameServerRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
$name = $request->input('name');
|
||||
$description = $request->input('description') ?? $server->description;
|
||||
$this->repository->update($server->id, [
|
||||
'name' => $request->input('name'),
|
||||
'description' => $request->input('description') ?? '',
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
]);
|
||||
|
||||
if ($server->name !== $request->input('name')) {
|
||||
if ($server->name !== $name) {
|
||||
Activity::event('server:settings.rename')
|
||||
->property(['old' => $server->name, 'new' => $request->input('name')])
|
||||
->property(['old' => $server->name, 'new' => $name])
|
||||
->log();
|
||||
}
|
||||
|
||||
if ($server->description !== $description) {
|
||||
Activity::event('server:settings.description')
|
||||
->property(['old' => $server->description, 'new' => $description])
|
||||
->log();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class StartupController extends ClientApiController
|
|||
return $this->fractal->collection(
|
||||
$server->variables()->where('user_viewable', true)->get()
|
||||
)
|
||||
->transformWith($this->getTransformer(EggVariableTransformer::class))
|
||||
->transformWith(EggVariableTransformer::class)
|
||||
->addMeta([
|
||||
'startup_command' => $startup,
|
||||
'docker_images' => $server->egg->docker_images,
|
||||
|
@ -52,7 +52,6 @@ class StartupController extends ClientApiController
|
|||
*/
|
||||
public function update(UpdateStartupVariableRequest $request, Server $server): array
|
||||
{
|
||||
/** @var \Pterodactyl\Models\EggVariable $variable */
|
||||
$variable = $server->variables()->where('env_variable', $request->input('key'))->first();
|
||||
$original = $variable->server_value;
|
||||
|
||||
|
@ -62,6 +61,8 @@ class StartupController extends ClientApiController
|
|||
throw new BadRequestHttpException('The environment variable you are trying to edit is read-only.');
|
||||
}
|
||||
|
||||
/* @var \Pterodactyl\Models\EggVariable $variable */
|
||||
|
||||
// Revalidate the variable value using the egg variable specific validation rules for it.
|
||||
$this->validate($request, ['value' => $variable->rules]);
|
||||
|
||||
|
@ -89,7 +90,7 @@ class StartupController extends ClientApiController
|
|||
}
|
||||
|
||||
return $this->fractal->item($variable)
|
||||
->transformWith($this->getTransformer(EggVariableTransformer::class))
|
||||
->transformWith(EggVariableTransformer::class)
|
||||
->addMeta([
|
||||
'startup_command' => $startup,
|
||||
'raw_startup_command' => $server->startup,
|
||||
|
|
|
@ -38,7 +38,7 @@ class SubuserController extends ClientApiController
|
|||
public function index(GetSubuserRequest $request, Server $server): array
|
||||
{
|
||||
return $this->fractal->collection($server->subusers)
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->transformWith(SubuserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ class SubuserController extends ClientApiController
|
|||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
return $this->fractal->item($subuser)
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->transformWith(SubuserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ class SubuserController extends ClientApiController
|
|||
->log();
|
||||
|
||||
return $this->fractal->item($response)
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->transformWith(SubuserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ class SubuserController extends ClientApiController
|
|||
$log->reset();
|
||||
|
||||
return $this->fractal->item($subuser->refresh())
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->transformWith(SubuserTransformer::class)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Remote;
|
||||
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Str;
|
||||
use Pterodactyl\Models\User;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
@ -37,11 +35,11 @@ class ActivityProcessingController extends Controller
|
|||
|
||||
try {
|
||||
$when = Carbon::createFromFormat(
|
||||
DateTimeInterface::RFC3339,
|
||||
\DateTimeInterface::RFC3339,
|
||||
preg_replace('/(\.\d+)Z$/', 'Z', $datum['timestamp']),
|
||||
'UTC'
|
||||
);
|
||||
} catch (Exception $exception) {
|
||||
} catch (\Exception $exception) {
|
||||
Log::warning($exception, ['timestamp' => $datum['timestamp']]);
|
||||
|
||||
// If we cannot parse the value for some reason don't blow up this request, just go ahead
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Backup;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Facades\Activity;
|
||||
|
@ -98,9 +99,11 @@ class ServerDetailsController extends Controller
|
|||
if ($subject = $activity->subjects->where('subject_type', 'backup')->first()) {
|
||||
// Just create a new audit entry for this event and update the server state
|
||||
// so that power actions, file management, and backups can resume as normal.
|
||||
/** @var Backup $actualSubject */
|
||||
$actualSubject = $subject->subject;
|
||||
Activity::event('server:backup.restore-failed')
|
||||
->subject($server, $subject->subject)
|
||||
->property('name', $subject->subject->name)
|
||||
->subject($server, $actualSubject)
|
||||
->property('name', $actualSubject->name)
|
||||
->log();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,18 @@ class ServerInstallController extends Controller
|
|||
public function store(InstallationDataRequest $request, string $uuid): JsonResponse
|
||||
{
|
||||
$server = $this->repository->getByUuid($uuid);
|
||||
$status = null;
|
||||
|
||||
$status = $request->boolean('successful') ? null : Server::STATUS_INSTALL_FAILED;
|
||||
// Make sure the type of failure is accurate
|
||||
if (!$request->boolean('successful')) {
|
||||
$status = Server::STATUS_INSTALL_FAILED;
|
||||
|
||||
if ($request->boolean('reinstall')) {
|
||||
$status = Server::STATUS_REINSTALL_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the server suspended if it's already suspended
|
||||
if ($server->status === Server::STATUS_SUSPENDED) {
|
||||
$status = Server::STATUS_SUSPENDED;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
|
@ -11,10 +9,9 @@ use Illuminate\Support\Facades\Log;
|
|||
use Pterodactyl\Models\ServerTransfer;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Nodes\NodeJWTService;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonTransferRepository;
|
||||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
|
||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||
|
||||
class ServerTransferController extends Controller
|
||||
|
@ -25,52 +22,10 @@ class ServerTransferController extends Controller
|
|||
public function __construct(
|
||||
private ConnectionInterface $connection,
|
||||
private ServerRepository $repository,
|
||||
private DaemonServerRepository $daemonServerRepository,
|
||||
private DaemonTransferRepository $daemonTransferRepository,
|
||||
private NodeJWTService $jwtService
|
||||
private DaemonServerRepository $daemonServerRepository
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The daemon notifies us about the archive status.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function archive(Request $request, string $uuid): JsonResponse
|
||||
{
|
||||
$server = $this->repository->getByUuid($uuid);
|
||||
|
||||
// Unsuspend the server and don't continue the transfer.
|
||||
if (!$request->input('successful')) {
|
||||
return $this->processFailedTransfer($server->transfer);
|
||||
}
|
||||
|
||||
$this->connection->transaction(function () use ($server) {
|
||||
// This token is used by the new node the server is being transferred to. It allows
|
||||
// that node to communicate with the old node during the process to initiate the
|
||||
// actual file transfer.
|
||||
$token = $this->jwtService
|
||||
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
|
||||
->setSubject($server->uuid)
|
||||
->handle($server->node, $server->uuid, 'sha256');
|
||||
|
||||
// Update the archived field on the transfer to make clients connect to the websocket
|
||||
// on the new node to be able to receive transfer logs.
|
||||
$server->transfer->forceFill(['archived' => true])->saveOrFail();
|
||||
|
||||
// On the daemon transfer repository, make sure to set the node after the server
|
||||
// because setServer() tells the repository to use the server's node and not the one
|
||||
// we want to specify.
|
||||
$this->daemonTransferRepository
|
||||
->setServer($server)
|
||||
->setNode($server->transfer->newNode)
|
||||
->notify($server, $token);
|
||||
});
|
||||
|
||||
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* The daemon notifies us about a transfer failure.
|
||||
*
|
||||
|
@ -79,8 +34,12 @@ class ServerTransferController extends Controller
|
|||
public function failure(string $uuid): JsonResponse
|
||||
{
|
||||
$server = $this->repository->getByUuid($uuid);
|
||||
$transfer = $server->transfer;
|
||||
if (is_null($transfer)) {
|
||||
throw new ConflictHttpException('Server is not being transferred.');
|
||||
}
|
||||
|
||||
return $this->processFailedTransfer($server->transfer);
|
||||
return $this->processFailedTransfer($transfer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,6 +51,9 @@ class ServerTransferController extends Controller
|
|||
{
|
||||
$server = $this->repository->getByUuid($uuid);
|
||||
$transfer = $server->transfer;
|
||||
if (is_null($transfer)) {
|
||||
throw new ConflictHttpException('Server is not being transferred.');
|
||||
}
|
||||
|
||||
/** @var \Pterodactyl\Models\Server $server */
|
||||
$server = $this->connection->transaction(function () use ($server, $transfer) {
|
||||
|
|
|
@ -48,7 +48,9 @@ abstract class AbstractLoginController extends Controller
|
|||
/**
|
||||
* Get the failed login response instance.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @return never
|
||||
*
|
||||
* @throws DisplayException
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request, Authenticatable $user = null, string $message = null)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Pterodactyl\Http\Controllers\Auth;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Pterodactyl\Models\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Contracts\Hashing\Hasher;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
@ -67,13 +68,12 @@ class ResetPasswordController extends Controller
|
|||
* account do not automatically log them in. In those cases, send the user back to the login
|
||||
* form with a note telling them their password was changed and to log back in.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\CanResetPassword|\Pterodactyl\Models\User $user
|
||||
* @param string $password
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
protected function resetPassword($user, $password)
|
||||
protected function resetPassword(User $user, $password)
|
||||
{
|
||||
$user = $this->userRepository->update($user->id, [
|
||||
'password' => $this->hasher->make($password),
|
||||
|
|
|
@ -23,6 +23,6 @@ class IndexController extends Controller
|
|||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return $this->view->make('templates/base.core');
|
||||
return view('templates/base.core');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue