Update to Laravel 8

Co-authored-by: Matthew Penner <me@matthewp.io>
This commit is contained in:
Dane Everitt 2021-01-23 12:09:16 -08:00
parent 028921b42a
commit a043071e3c
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
211 changed files with 4394 additions and 2933 deletions

View File

@ -19,9 +19,9 @@ jobs:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: true
fail-fast: false
matrix:
php: [7.3, 7.4]
php: [7.4, 8.0]
name: PHP ${{ matrix.php }}
steps:
- name: checkout
@ -44,7 +44,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: cli, openssl, gd, mysql, pdo, mbstring, tokenizer, bcmath, xml, curl, zip
tools: composer:v1
tools: composer:v2
coverage: none
- name: configure
run: cp .env.ci .env

5
.gitignore vendored
View File

@ -1,6 +1,9 @@
/vendor
*.DS_Store*
.env
!.env.ci
!.env.dusk
!.env.example
.env*
.vagrant/*
.vscode/*
storage/framework/*

View File

@ -17,7 +17,7 @@ class SeedCommand extends BaseSeedCommand
*/
public function handle()
{
if (!$this->hasCompletedMigrations()) {
if (! $this->hasCompletedMigrations()) {
return $this->showMigrationWarning();
}

View File

@ -14,7 +14,7 @@ class UpCommand extends BaseUpCommand
*/
public function handle()
{
if (!$this->hasCompletedMigrations()) {
if (! $this->hasCompletedMigrations()) {
return $this->showMigrationWarning();
}

View File

@ -2,8 +2,8 @@
namespace Pterodactyl\Console\Commands\Schedule;
use Throwable;
use Exception;
use Throwable;
use Illuminate\Console\Command;
use Pterodactyl\Models\Schedule;
use Illuminate\Support\Facades\Log;

View File

@ -99,9 +99,9 @@ class BulkPowerActionCommand extends Command
if (! empty($nodes) && ! empty($servers)) {
$instance->whereIn('id', $servers)->orWhereIn('node_id', $nodes);
} else if (empty($nodes) && ! empty($servers)) {
} elseif (empty($nodes) && ! empty($servers)) {
$instance->whereIn('id', $servers);
} else if (! empty($nodes) && empty($servers)) {
} elseif (! empty($nodes) && empty($servers)) {
$instance->whereIn('node_id', $nodes);
}

View File

@ -9,11 +9,10 @@
namespace Pterodactyl\Console\Commands\User;
use Webmozart\Assert\Assert;
use Pterodactyl\Models\User;
use Webmozart\Assert\Assert;
use Illuminate\Console\Command;
use Pterodactyl\Services\Users\UserDeletionService;
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
class DeleteUserCommand extends Command
{
@ -42,7 +41,8 @@ class DeleteUserCommand extends Command
*
* @param \Pterodactyl\Services\Users\UserDeletionService $deletionService
*/
public function __construct(UserDeletionService $deletionService) {
public function __construct(UserDeletionService $deletionService)
{
parent::__construct();
$this->deletionService = $deletionService;
@ -96,7 +96,5 @@ class DeleteUserCommand extends Command
$this->deletionService->handle($deleteUser);
$this->info(trans('command/messages.user.deleted'));
}
return;
}
}

View File

@ -39,7 +39,7 @@ trait RequiresDatabaseMigrations
*/
protected function showMigrationWarning(): int
{
$this->getOutput()->writeln("<options=bold>
$this->getOutput()->writeln('<options=bold>
| @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| |
| Your database has not been properly migrated! |
@ -52,9 +52,9 @@ You must run the following command to finish migrating your database:
You will not be able to use Pterodactyl Panel as expected without fixing your
database state by running the command above.
");
');
$this->getOutput()->error("You must correct the error above before continuing.");
$this->getOutput()->error('You must correct the error above before continuing.');
return 1;
}

View File

@ -2,8 +2,6 @@
namespace Pterodactyl\Contracts\Repository;
use Illuminate\Support\Collection;
interface AllocationRepositoryInterface extends RepositoryInterface
{
/**

View File

@ -4,9 +4,6 @@ namespace Pterodactyl\Contracts\Repository;
use Pterodactyl\Models\Node;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
interface NodeRepositoryInterface extends RepositoryInterface
{

View File

@ -5,10 +5,14 @@ namespace Pterodactyl\Exceptions;
use Exception;
use Throwable;
use PDOException;
use Psr\Log\LoggerInterface;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Swift_TransportException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Illuminate\Container\Container;
use Illuminate\Database\Connection;
use Illuminate\Foundation\Application;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Validation\ValidationException;
@ -43,17 +47,6 @@ class Handler extends ExceptionHandler
ValidationException::class,
];
/**
* A list of exceptions that should be logged with cleaned stack
* traces to avoid exposing credentials or other sensitive information.
*
* @var array
*/
protected $cleanStacks = [
PDOException::class,
Swift_TransportException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
@ -67,56 +60,40 @@ class Handler extends ExceptionHandler
];
/**
* Report or log an exception. Skips Laravel's internal reporter since we
* don't need or want the user information in our logs by default.
* Registers the exception handling callbacks for the application. This
* will capture specific exception types that we do not want to include
* the detailed stack traces for since they could reveal credentials to
* whoever can read the logs.
*
* If you want to implement logging in a different format to integrate with
* services such as AWS Cloudwatch or other monitoring you can replace the
* contents of this function with a call to the parent reporter.
*
* @param \Throwable $exception
* @return mixed
*
* @throws \Throwable
* @noinspection PhpUnusedLocalVariableInspection
*/
public function report(Throwable $exception)
public function register()
{
if (! config('app.exceptions.report_all', false) && $this->shouldntReport($exception)) {
return null;
if (config('app.exceptions.report_all', false)) {
$this->dontReport = [];
}
if (method_exists($exception, 'report')) {
return $exception->report();
$this->reportable(function (PDOException $ex) {
$ex = $this->generateCleanedExceptionStack($ex);
});
$this->reportable(function (Swift_TransportException $ex) {
$ex = $this->generateCleanedExceptionStack($ex);
});
}
try {
$logger = $this->container->make(LoggerInterface::class);
} catch (Exception $ex) {
throw $exception;
}
foreach ($this->cleanStacks as $class) {
if ($exception instanceof $class) {
$exception = $this->generateCleanedExceptionStack($exception);
break;
}
}
return $logger->error($exception);
}
private function generateCleanedExceptionStack(Throwable $exception)
private function generateCleanedExceptionStack(Throwable $exception): string
{
$cleanedStack = '';
foreach ($exception->getTrace() as $index => $item) {
$cleanedStack .= sprintf(
"#%d %s(%d): %s%s%s\n",
$index,
array_get($item, 'file'),
array_get($item, 'line'),
array_get($item, 'class'),
array_get($item, 'type'),
array_get($item, 'function')
Arr::get($item, 'file'),
Arr::get($item, 'line'),
Arr::get($item, 'class'),
Arr::get($item, 'type'),
Arr::get($item, 'function')
);
}
@ -142,7 +119,7 @@ class Handler extends ExceptionHandler
*/
public function render($request, Throwable $exception)
{
$connections = Container::getInstance()->make(Connection::class);
$connections = $this->container->make(Connection::class);
// If we are currently wrapped up inside a transaction, we will roll all the way
// back to the beginning. This needs to happen, otherwise session data does not
@ -170,21 +147,21 @@ class Handler extends ExceptionHandler
*/
public function invalidJson($request, ValidationException $exception)
{
$codes = collect($exception->validator->failed())->mapWithKeys(function ($reasons, $field) {
$codes = Collection::make($exception->validator->failed())->mapWithKeys(function ($reasons, $field) {
$cleaned = [];
foreach ($reasons as $reason => $attrs) {
$cleaned[] = snake_case($reason);
$cleaned[] = Str::snake($reason);
}
return [str_replace('.', '_', $field) => $cleaned];
})->toArray();
$errors = collect($exception->errors())->map(function ($errors, $field) use ($codes, $exception) {
$errors = Collection::make($exception->errors())->map(function ($errors, $field) use ($codes, $exception) {
$response = [];
foreach ($errors as $key => $error) {
$meta = [
'source_field' => $field,
'rule' => str_replace(self::PTERODACTYL_RULE_STRING, 'p_', array_get(
'rule' => str_replace(self::PTERODACTYL_RULE_STRING, 'p_', Arr::get(
$codes, str_replace('.', '_', $field) . '.' . $key
)),
];
@ -235,7 +212,7 @@ class Handler extends ExceptionHandler
'detail' => $exception->getMessage(),
'source' => [
'line' => $exception->getLine(),
'file' => str_replace(base_path(), '', $exception->getFile()),
'file' => str_replace(Application::getInstance()->basePath(), '', $exception->getFile()),
],
'meta' => [
'trace' => explode("\n", $exception->getTraceAsString()),
@ -262,15 +239,15 @@ class Handler extends ExceptionHandler
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*/
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(self::convertToArray($exception), 401);
return new JsonResponse(self::convertToArray($exception), JsonResponse::HTTP_UNAUTHORIZED);
}
return redirect()->guest(route('auth.login'));
return $this->container->make('redirect')->guest('/auth/login');
}
/**

View File

@ -42,7 +42,7 @@ class DaemonConnectionException extends DisplayException
$body = $response->getBody();
if (is_string($body) || (is_object($body) && method_exists($body, '__toString'))) {
$body = json_decode(is_string($body) ? $body : $body->__toString(), true);
$message = "[Wings Error]: " . Arr::get($body, 'error', $message);
$message = '[Wings Error]: ' . Arr::get($body, 'error', $message);
}
}

View File

@ -16,6 +16,6 @@ class TwoFactorAuthRequiredException extends HttpException implements HttpExcept
*/
public function __construct(Throwable $previous = null)
{
parent::__construct(Response::HTTP_BAD_REQUEST, "Two-factor authentication is required on this account in order to access this endpoint.", $previous);
parent::__construct(Response::HTTP_BAD_REQUEST, 'Two-factor authentication is required on this account in order to access this endpoint.', $previous);
}
}

View File

@ -8,8 +8,8 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Webmozart\Assert\Assert;
use InvalidArgumentException;
use League\Flysystem\AdapterInterface;
use Illuminate\Foundation\Application;
use League\Flysystem\AdapterInterface;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Memory\MemoryAdapter;
use Illuminate\Contracts\Config\Repository;

View File

@ -0,0 +1,33 @@
<?php
namespace Pterodactyl\Extensions\Lcobucci\JWT\Encoding;
use DateTimeImmutable;
use Lcobucci\JWT\ClaimsFormatter;
use Lcobucci\JWT\Token\RegisteredClaims;
final class TimestampDates implements ClaimsFormatter
{
/**
* The default time encoder for JWTs using this library is not supported correctly
* by Wings and will cause a flood of errors and panic conditions because the times
* cannot be parsed correctly. The default is time with microseconds, we just need
* to use the normal unix timestamp here.
*
* @param array $claims
* @return array
*/
public function formatClaims(array $claims): array
{
foreach (RegisteredClaims::DATE_CLAIMS as $claim) {
if (! array_key_exists($claim, $claims)) {
continue;
}
assert($claims[$claim] instanceof DateTimeImmutable);
$claims[$claim] = $claims[$claim]->getTimestamp();
}
return $claims;
}
}

View File

@ -3,17 +3,13 @@
namespace Pterodactyl\Http\Controllers\Admin;
use Ramsey\Uuid\Uuid;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Pterodactyl\Models\Nest;
use Pterodactyl\Models\Mount;
use Pterodactyl\Models\Location;
use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Mounts\MountUpdateService;
use Pterodactyl\Http\Requests\Admin\MountFormRequest;
use Pterodactyl\Services\Mounts\MountCreationService;
use Pterodactyl\Services\Mounts\MountDeletionService;
use Pterodactyl\Repositories\Eloquent\MountRepository;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;

View File

@ -79,7 +79,7 @@ class EggController extends Controller
public function store(EggFormRequest $request): RedirectResponse
{
$data = $request->normalize();
if (!empty($data['docker_images']) && !is_array($data['docker_images'])) {
if (! empty($data['docker_images']) && ! is_array($data['docker_images'])) {
$data['docker_images'] = array_map(function ($value) {
return trim($value);
}, explode("\n", $data['docker_images']));
@ -116,7 +116,7 @@ class EggController extends Controller
public function update(EggFormRequest $request, Egg $egg): RedirectResponse
{
$data = $request->normalize();
if (!empty($data['docker_images']) && !is_array($data['docker_images'])) {
if (! empty($data['docker_images']) && ! is_array($data['docker_images'])) {
$data['docker_images'] = array_map(function ($value) {
return trim($value);
}, explode("\n", $data['docker_images']));

View File

@ -118,7 +118,7 @@ class CreateServerController extends Controller
public function store(ServerFormRequest $request)
{
$data = $request->except(['_token']);
if (!empty($data['custom_image'])) {
if (! empty($data['custom_image'])) {
$data['image'] = $data['custom_image'];
unset($data['custom_image']);
}

View File

@ -89,7 +89,8 @@ class ServerTransferController extends Controller
*
* @throws \Throwable
*/
public function transfer(Request $request, Server $server) {
public function transfer(Request $request, Server $server)
{
$validatedData = $request->validate([
'node_id' => 'required|exists:nodes,id',
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',

View File

@ -9,14 +9,12 @@
namespace Pterodactyl\Http\Controllers\Admin;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Mount;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\MountServer;
use Prologue\Alerts\AlertsMessageBag;
use GuzzleHttp\Exception\RequestException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Validation\ValidationException;
@ -37,7 +35,6 @@ use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest;
@ -338,7 +335,7 @@ class ServersController extends Controller
public function saveStartup(Request $request, Server $server)
{
$data = $request->except('_token');
if (!empty($data['custom_docker_image'])) {
if (! empty($data['custom_docker_image'])) {
$data['docker_image'] = $data['custom_docker_image'];
unset($data['custom_docker_image']);
}

View File

@ -67,7 +67,7 @@ class ClientController extends ClientApiController
? $builder
: $builder->whereNotIn('servers.id', $user->accessibleServers()->pluck('id')->all());
}
} else if ($type === 'owner') {
} elseif ($type === 'owner') {
$builder = $builder->where('servers.owner_id', $user->id);
} else {
$builder = $builder->whereIn('servers.id', $user->accessibleServers()->pluck('id')->all());

View File

@ -61,6 +61,7 @@ class BackupController extends ClientApiController
public function index(GetBackupsRequest $request, Server $server)
{
$limit = min($request->query('per_page') ?? 20, 50);
return $this->fractal->collection($server->backups()->paginate($limit))
->transformWith($this->getTransformer(BackupTransformer::class))
->toArray();

View File

@ -138,7 +138,7 @@ class DownloadBackupController extends ClientApiController
return sprintf(
'%s/download/backup?token=%s',
$server->node->getConnectionAddress(),
$token->__toString()
$token->toString()
);
}
}

View File

@ -6,7 +6,6 @@ use Carbon\CarbonImmutable;
use Illuminate\Http\Response;
use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Pterodactyl\Services\Nodes\NodeJWTService;
use Illuminate\Contracts\Routing\ResponseFactory;
use Pterodactyl\Repositories\Wings\DaemonFileRepository;
@ -15,9 +14,9 @@ use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CopyFileRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\PullFileRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ChmodFilesRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DeleteFileRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ChmodFilesRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CreateFolderRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CompressFilesRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DecompressFilesRequest;
@ -127,7 +126,7 @@ class FileController extends ClientApiController
'url' => sprintf(
'%s/download/file?token=%s',
$server->node->getConnectionAddress(),
$token->__toString()
$token->toString()
),
],
];

View File

@ -67,7 +67,7 @@ class FileUploadController extends ClientApiController
return sprintf(
'%s/upload/file?token=%s',
$server->node->getConnectionAddress(),
$token->__toString()
$token->toString()
);
}
}

View File

@ -112,7 +112,7 @@ class NetworkAllocationController extends ClientApiController
/**
* Set the notes for the allocation for a server.
*s
*s.
*
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\NewAllocationRequest $request
* @param \Pterodactyl\Models\Server $server

View File

@ -10,7 +10,6 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Models\Schedule;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Helpers\Utilities;
use Pterodactyl\Jobs\Schedule\RunTaskJob;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
use Pterodactyl\Services\Schedules\ProcessScheduleService;
@ -173,7 +172,7 @@ class ScheduleController extends ClientApiController
*/
public function execute(TriggerScheduleRequest $request, Server $server, Schedule $schedule)
{
if (!$schedule->is_active) {
if (! $schedule->is_active) {
throw new BadRequestHttpException(
'Cannot trigger schedule exection for a schedule that is not currently active.'
);

View File

@ -2,7 +2,6 @@
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse;
@ -88,7 +87,7 @@ class SettingsController extends ClientApiController
*/
public function dockerImage(SetDockerImageRequest $request, Server $server)
{
if (!in_array($server->image, $server->egg->docker_images)) {
if (! in_array($server->image, $server->egg->docker_images)) {
throw new BadRequestHttpException(
'This server\'s Docker image has been manually set by an administrator and cannot be updated.'
);

View File

@ -86,11 +86,11 @@ class StartupController extends ClientApiController
if (is_null($variable) || ! $variable->user_viewable) {
throw new BadRequestHttpException(
"The environment variable you are trying to edit does not exist."
'The environment variable you are trying to edit does not exist.'
);
} else if (! $variable->user_editable) {
} elseif (! $variable->user_editable) {
throw new BadRequestHttpException(
"The environment variable you are trying to edit is read-only."
'The environment variable you are trying to edit is read-only.'
);
}

View File

@ -85,7 +85,7 @@ class WebsocketController extends ClientApiController
return new JsonResponse([
'data' => [
'token' => $token->__toString(),
'token' => $token->toString(),
'socket' => $socket . sprintf('/api/servers/%s/ws', $server->uuid),
],
]);

View File

@ -6,8 +6,8 @@ use Carbon\CarbonImmutable;
use Pterodactyl\Models\Backup;
use Illuminate\Http\JsonResponse;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Extensions\Backups\BackupManager;
use Pterodactyl\Repositories\Eloquent\BackupRepository;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

View File

@ -85,7 +85,7 @@ class ServerDetailsController extends Controller
->where('node_id', $node->id)
// If you don't cast this to a string you'll end up with a stringified per_page returned in
// the metadata, and then Wings will panic crash as a result.
->paginate((int)$request->input('per_page', 50));
->paginate((int) $request->input('per_page', 50));
return new ServerConfigurationCollection($servers);
}

View File

@ -2,7 +2,7 @@
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
use Cake\Chronos\Chronos;
use Carbon\CarbonImmutable;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
@ -110,11 +110,11 @@ class ServerTransferController extends Controller
Arr::set($data, 'suspended', false);
$this->connection->transaction(function () use ($data, $server) {
// This token is used by the new node the server is being transfered to. It allows
// 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(Chronos::now()->addMinutes(15))
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
->setSubject($server->uuid)
->handle($server->node, $server->uuid, 'sha256');
@ -128,7 +128,7 @@ class ServerTransferController extends Controller
$this->daemonTransferRepository
->setServer($server)
->setNode($server->transfer->newNode)
->notify($server, $data, $server->node, $token->__toString());
->notify($server, $data, $server->node, $token->toString());
});
return new JsonResponse([], Response::HTTP_NO_CONTENT);

View File

@ -12,7 +12,6 @@ use Illuminate\Database\Eloquent\ModelNotFoundException;
use Pterodactyl\Http\Requests\Auth\LoginCheckpointRequest;
use Illuminate\Contracts\Cache\Repository as CacheRepository;
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Repositories\Eloquent\RecoveryTokenRepository;
class LoginCheckpointController extends AbstractLoginController

View File

@ -2,7 +2,7 @@
namespace Pterodactyl\Http\Controllers\Auth;
use Cake\Chronos\Chronos;
use Carbon\CarbonImmutable;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Auth\AuthManager;
@ -101,7 +101,7 @@ class LoginController extends AbstractLoginController
if ($user->use_totp) {
$token = Str::random(64);
$this->cache->put($token, $user->id, Chronos::now()->addMinutes(5));
$this->cache->put($token, $user->id, CarbonImmutable::now()->addMinutes(5));
return new JsonResponse([
'data' => [

View File

@ -3,7 +3,7 @@
namespace Pterodactyl\Http\Middleware\Api;
use Closure;
use Cake\Chronos\Chronos;
use Carbon\CarbonImmutable;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Models\ApiKey;
@ -110,7 +110,7 @@ class AuthenticateKey
throw new AccessDeniedHttpException;
}
$this->repository->withoutFreshModel()->update($model->id, ['last_used_at' => Chronos::now()]);
$this->repository->withoutFreshModel()->update($model->id, ['last_used_at' => CarbonImmutable::now()]);
return $model;
}

View File

@ -8,8 +8,8 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Pterodactyl\Exceptions\Http\Server\ServerTransferringException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class AuthenticateServerAccess
{

View File

@ -7,11 +7,11 @@ use Illuminate\Http\Request;
use Pterodactyl\Models\Task;
use Pterodactyl\Models\User;
use InvalidArgumentException;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Subuser;
use Pterodactyl\Models\Schedule;
use Pterodactyl\Models\Database;
use Pterodactyl\Models\Schedule;
use Pterodactyl\Models\Allocation;
use Illuminate\Database\Eloquent\Model;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

View File

@ -43,7 +43,7 @@ class SubstituteClientApiBindings extends ApiSubstituteBindings
}
});
$this->router->bind('database', function ($value) use ($request) {
$this->router->bind('database', function ($value) {
$id = Container::getInstance()->make(HashidsInterface::class)->decodeFirst($value);
return Database::query()->where('id', $id)->firstOrFail();

View File

@ -59,14 +59,14 @@ class RequireTwoFactorAuthentication
return $next($request);
}
$level = (int)config('pterodactyl.auth.2fa_required');
$level = (int) config('pterodactyl.auth.2fa_required');
// If this setting is not configured, or the user is already using 2FA then we can just
// send them right through, nothing else needs to be checked.
//
// If the level is set as admin and the user is not an admin, pass them through as well.
if ($level === self::LEVEL_NONE || $user->use_totp) {
return $next($request);
} else if ($level === self::LEVEL_ADMIN && ! $user->root_admin) {
} elseif ($level === self::LEVEL_ADMIN && ! $user->root_admin) {
return $next($request);
}

View File

@ -44,7 +44,7 @@ class EggFormRequest extends AdminFormRequest
public function withValidator($validator)
{
$validator->sometimes('config_from', 'exists:eggs,id', function () {
return (int)$this->input('config_from') !== 0;
return (int) $this->input('config_from') !== 0;
});
}
}

View File

@ -8,7 +8,6 @@ use Carbon\CarbonImmutable;
use Pterodactyl\Models\Task;
use InvalidArgumentException;
use Pterodactyl\Models\Schedule;
use Illuminate\Support\Facades\Log;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

View File

@ -18,6 +18,10 @@ use Pterodactyl\Services\Acl\Api\AdminAcl;
*/
class ApiKey extends Model
{
/**
* The resource name for this model when it is transformed into an
* API representation using fractal.
*/
const RESOURCE_NAME = 'api_key';
/**

View File

@ -2,6 +2,18 @@
namespace Pterodactyl\Models;
/**
* @property int $id
* @property string $name
* @property string $host
* @property int $port
* @property string $username
* @property string $password
* @property int|null $max_databases
* @property int|null $node_id
* @property \Carbon\CarbonImmutable $created_at
* @property \Carbon\CarbonImmutable $updated_at
*/
class DatabaseHost extends Model
{
/**
@ -10,6 +22,11 @@ class DatabaseHost extends Model
*/
const RESOURCE_NAME = 'database_host';
/**
* @var bool
*/
protected $immutableDates = true;
/**
* The table associated with the model.
*

View File

@ -42,12 +42,12 @@ class MultiFieldServerFilter implements Filter
$parts = explode(':', $value);
$builder->when(
!Str::startsWith($value, ':'),
! Str::startsWith($value, ':'),
// When the string does not start with a ":" it means we're looking for an IP or IP:Port
// combo, so use a query to handle that.
function (Builder $builder) use ($parts) {
$builder->orWhere('allocations.ip', $parts[0]);
if (!is_null($parts[1] ?? null)) {
if (! is_null($parts[1] ?? null)) {
$builder->where('allocations.port', 'LIKE', "{$parts[1]}%");
}
},

View File

@ -6,11 +6,14 @@ use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\Container\Container;
use Illuminate\Contracts\Validation\Factory;
use Illuminate\Database\Eloquent\Model as IlluminateModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Pterodactyl\Exceptions\Model\DataValidationException;
use Illuminate\Database\Eloquent\Model as IlluminateModel;
abstract class Model extends IlluminateModel
{
use HasFactory;
/**
* Set to true to return immutable Carbon date instances from the model.
*

View File

@ -87,7 +87,7 @@ class Mount extends Model
public $timestamps = false;
/**
* Blacklisted source paths
* Blacklisted source paths.
*
* @var string[]
*/
@ -98,7 +98,7 @@ class Mount extends Model
];
/**
* Blacklisted target paths
* Blacklisted target paths.
*
* @var string[]
*/

View File

@ -202,7 +202,7 @@ class Node extends Model
*/
public function getDecryptedKey(): string
{
return (string)Container::getInstance()->make(Encrypter::class)->decrypt(
return (string) Container::getInstance()->make(Encrypter::class)->decrypt(
$this->daemon_token
);
}

View File

@ -7,6 +7,7 @@ use Cache;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Subuser;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Pterodactyl\Observers\UserObserver;
@ -29,6 +30,8 @@ class AppServiceProvider extends ServiceProvider
View::share('appVersion', $this->versionData()['version'] ?? 'undefined');
View::share('appIsGit', $this->versionData()['is_git'] ?? false);
Paginator::useBootstrap();
}
/**

View File

@ -13,7 +13,7 @@ class BladeServiceProvider extends ServiceProvider
{
$this->app->make('blade.compiler')
->directive('datetimeHuman', function ($expression) {
return "<?php echo \Cake\Chronos\Chronos::createFromFormat(\Cake\Chronos\Chronos::DEFAULT_TO_STRING_FORMAT, $expression)->setTimezone(config('app.timezone'))->toDateTimeString(); ?>";
return "<?php echo \Carbon\CarbonImmutable::createFromFormat(\Carbon\CarbonImmutable::DEFAULT_TO_STRING_FORMAT, $expression)->setTimezone(config('app.timezone'))->toDateTimeString(); ?>";
});
}
}

View File

@ -8,7 +8,6 @@ use Illuminate\Foundation\Application;
use Illuminate\Database\DatabaseManager;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Exceptions\Repository\DuplicateDatabaseNameException;
class DatabaseRepository extends EloquentRepository implements DatabaseRepositoryInterface
{

View File

@ -13,7 +13,6 @@ use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Pterodactyl\Contracts\Repository\RepositoryInterface;
use Pterodactyl\Exceptions\Model\DataValidationException;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
abstract class EloquentRepository extends Repository implements RepositoryInterface
{

View File

@ -4,8 +4,6 @@ namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Node;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
class NodeRepository extends EloquentRepository implements NodeRepositoryInterface

View File

@ -51,7 +51,7 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt
if (! is_null($server) && is_null($node)) {
$instance = $instance->where('id', '=', $server);
} else if (is_null($server) && ! is_null($node)) {
} elseif (is_null($server) && ! is_null($node)) {
$instance = $instance->where('node_id', '=', $node);
}
@ -71,7 +71,7 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt
if (! is_null($server) && is_null($node)) {
$instance = $instance->where('id', '=', $server);
} else if (is_null($server) && ! is_null($node)) {
} elseif (is_null($server) && ! is_null($node)) {
$instance = $instance->where('node_id', '=', $node);
}

View File

@ -2,7 +2,6 @@
namespace Pterodactyl\Repositories\Wings;
use Illuminate\Support\Arr;
use Webmozart\Assert\Assert;
use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Server;

View File

@ -37,7 +37,7 @@ class DaemonFileRepository extends DaemonRepository
throw new DaemonConnectionException($exception);
}
$length = (int)$response->getHeader('Content-Length')[0] ?? 0;
$length = (int) $response->getHeader('Content-Length')[0] ?? 0;
if ($notLargerThan && $length > $notLargerThan) {
throw new FileSizeTooLargeException;

View File

@ -3,7 +3,6 @@
namespace Pterodactyl\Repositories\Wings;
use Webmozart\Assert\Assert;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use GuzzleHttp\Exception\TransferException;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
@ -157,7 +156,7 @@ class DaemonServerRepository extends DaemonRepository
{
Assert::isInstanceOf($this->server, Server::class);
$this->revokeJTIs([ md5($id . $this->server->uuid) ]);
$this->revokeJTIs([md5($id . $this->server->uuid)]);
}
/**

View File

@ -8,7 +8,6 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Models\Database;
use Pterodactyl\Helpers\Utilities;
use Illuminate\Database\ConnectionInterface;
use Symfony\Component\VarDumper\Cloner\Data;
use Illuminate\Contracts\Encryption\Encrypter;
use Pterodactyl\Extensions\DynamicDatabaseConnection;
use Pterodactyl\Repositories\Eloquent\DatabaseRepository;

View File

@ -2,8 +2,8 @@
namespace Pterodactyl\Services\Deployment;
use Webmozart\Assert\Assert;
use Pterodactyl\Models\Node;
use Webmozart\Assert\Assert;
use Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException;
class FindViableNodesService

View File

@ -108,7 +108,7 @@ class EggConfigurationService
// Normalize the output of the configuration for the new Wings Daemon to more
// easily ingest, as well as make things more flexible down the road.
foreach ($configs as $file => $data) {
$append = array_merge((array)$data, ['file' => $file, 'replace' => []]);
$append = array_merge((array) $data, ['file' => $file, 'replace' => []]);
foreach ($this->iterate($data->find, $structure) as $find => $replace) {
if (is_object($replace)) {

View File

@ -119,7 +119,7 @@ class EggImporterService
], true, true);
collect($parsed->variables)->each(function ($variable) use ($egg) {
$this->eggVariableRepository->create(array_merge((array)$variable, [
$this->eggVariableRepository->create(array_merge((array) $variable, [
'egg_id' => $egg->id,
]));
});

View File

@ -2,13 +2,14 @@
namespace Pterodactyl\Services\Nodes;
use DateTimeInterface;
use Lcobucci\JWT\Builder;
use DateTimeImmutable;
use Carbon\CarbonImmutable;
use Illuminate\Support\Str;
use Lcobucci\JWT\Signer\Key;
use Pterodactyl\Models\Node;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Pterodactyl\Extensions\Lcobucci\JWT\Encoding\TimestampDates;
class NodeJWTService
{
@ -18,7 +19,7 @@ class NodeJWTService
private $claims = [];
/**
* @var int|null
* @var \DateTimeImmutable|null
*/
private $expiresAt;
@ -41,12 +42,12 @@ class NodeJWTService
}
/**
* @param \DateTimeInterface $date
* @param \DateTimeImmutable $date
* @return $this
*/
public function setExpiresAt(DateTimeInterface $date)
public function setExpiresAt(DateTimeImmutable $date)
{
$this->expiresAt = $date->getTimestamp();
$this->expiresAt = $date;
return $this;
}
@ -68,24 +69,27 @@ class NodeJWTService
* @param \Pterodactyl\Models\Node $node
* @param string|null $identifiedBy
* @param string $algo
* @return \Lcobucci\JWT\Token
* @return \Lcobucci\JWT\Token\Plain
*/
public function handle(Node $node, string $identifiedBy, string $algo = 'md5')
{
$signer = new Sha256;
$identifier = hash($algo, $identifiedBy);
$config = Configuration::forSymmetricSigner(new Sha256, InMemory::plainText($node->getDecryptedKey()));
$builder = (new Builder)->issuedBy(config('app.url'))
$builder = $config->builder(new TimestampDates)
->issuedBy(config('app.url'))
->permittedFor($node->getConnectionAddress())
->identifiedBy(hash($algo, $identifiedBy), true)
->issuedAt(CarbonImmutable::now()->getTimestamp())
->canOnlyBeUsedAfter(CarbonImmutable::now()->subMinutes(5)->getTimestamp());
->identifiedBy($identifier)
->withHeader('jti', $identifier)
->issuedAt(CarbonImmutable::now())
->canOnlyBeUsedAfter(CarbonImmutable::now()->subMinutes(5));
if ($this->expiresAt) {
$builder = $builder->expiresAt($this->expiresAt);
}
if (!empty($this->subject)) {
$builder = $builder->relatedTo($this->subject, true);
if (! empty($this->subject)) {
$builder = $builder->relatedTo($this->subject)->withHeader('sub', $this->subject);
}
foreach ($this->claims as $key => $value) {
@ -94,6 +98,6 @@ class NodeJWTService
return $builder
->withClaim('unique_id', Str::random(16))
->getToken($signer, new Key($node->getDecryptedKey()));
->getToken($config->signer(), $config->signingKey());
}
}

View File

@ -5,11 +5,9 @@ namespace Pterodactyl\Services\Nodes;
use Illuminate\Support\Str;
use Pterodactyl\Models\Node;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Exception\ConnectException;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Contracts\Encryption\Encrypter;
use Pterodactyl\Repositories\Eloquent\NodeRepository;
use Pterodactyl\Repositories\Daemon\ConfigurationRepository;
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
use Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException;
@ -101,7 +99,7 @@ class NodeUpdateService
// inject their own response pages, causing this logic to get fucked up.
//
// @see https://github.com/pterodactyl/panel/issues/2712
return [ $updated, true ];
return [$updated, true];
}
return [$updated, false];

View File

@ -82,7 +82,7 @@ class BuildModificationService
$updateData = $this->structureService->handle($server);
if (!empty($updateData['build'])) {
if (! empty($updateData['build'])) {
$this->daemonServerRepository->setServer($server)->update([
'build' => $updateData['build'],
]);

View File

@ -4,7 +4,6 @@ namespace Pterodactyl\Services\Servers;
use Pterodactyl\Models\Server;
use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
class ReinstallServerService

View File

@ -38,7 +38,7 @@ class ServerConfigurationStructureService
$clone = $server;
// If any overrides have been set on this call make sure to update them on the
// cloned instance so that the configuration generated uses them.
if (!empty($override)) {
if (! empty($override)) {
$clone = $server->fresh();
foreach ($override as $key => $value) {
$clone->setAttribute($key, $value);
@ -95,10 +95,10 @@ class ServerConfigurationStructureService
'id' => $server->egg->uuid,
'file_denylist' => [
'config.yml',
'**/*.json'
]
'**/*.json',
],
// 'file_denylist' => explode(PHP_EOL, $server->egg->inherit_file_denylist),
]
],
];
}
@ -124,12 +124,12 @@ class ServerConfigurationStructureService
})->toArray(),
'env' => $this->environment->handle($server),
'oom_disabled' => $server->oom_disabled,
'memory' => (int)$server->memory,
'swap' => (int)$server->swap,
'io' => (int)$server->io,
'cpu' => (int)$server->cpu,
'memory' => (int) $server->memory,
'swap' => (int) $server->swap,
'io' => (int) $server->io,
'cpu' => (int) $server->cpu,
'threads' => $server->threads,
'disk' => (int)$server->disk,
'disk' => (int) $server->disk,
'image' => $server->image,
],
'service' => [
@ -137,7 +137,7 @@ class ServerConfigurationStructureService
'skip_scripts' => $server->skip_scripts,
],
'rebuild' => false,
'suspended' => (int)$server->suspended,
'suspended' => (int) $server->suspended,
];
}
}

View File

@ -92,7 +92,7 @@ class ServerDeletionService
try {
$this->databaseManagementService->delete($database);
} catch (Exception $exception) {
if (!$this->force) {
if (! $this->force) {
throw $exception;
}

View File

@ -20,7 +20,7 @@ class StartupCommandService
foreach ($server->variables as $variable) {
$find[] = '{{' . $variable->env_variable . '}}';
$replace[] = ($variable->user_viewable && !$hideAllValues) ? ($variable->server_value ?? $variable->default_value) : '[hidden]';
$replace[] = ($variable->user_viewable && ! $hideAllValues) ? ($variable->server_value ?? $variable->default_value) : '[hidden]';
}
return str_replace($find, $replace, $server->startup);

View File

@ -91,7 +91,7 @@ class StartupModificationService
{
$eggId = Arr::get($data, 'egg_id');
if (is_digit($eggId) && $server->egg_id !== (int)$eggId) {
if (is_digit($eggId) && $server->egg_id !== (int) $eggId) {
/** @var \Pterodactyl\Models\Egg $egg */
$egg = Egg::query()->findOrFail($data['egg_id']);

View File

@ -6,7 +6,6 @@ use Webmozart\Assert\Assert;
use Pterodactyl\Models\Server;
use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
use Pterodactyl\Exceptions\Http\Server\ServerTransferringException;
class SuspensionService

View File

@ -68,7 +68,7 @@ class VariableValidatorService
}
return Collection::make($variables)->map(function ($item) use ($fields) {
return (object)[
return (object) [
'id' => $item->id,
'key' => $item->env_variable,
'value' => $fields[$item->env_variable] ?? null,

View File

@ -2,7 +2,7 @@
namespace Pterodactyl\Transformers\Api\Application;
use Cake\Chronos\Chronos;
use Carbon\CarbonImmutable;
use Pterodactyl\Models\ApiKey;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Model;
@ -107,7 +107,7 @@ abstract class BaseTransformer extends TransformerAbstract
*/
protected function formatTimestamp(string $timestamp): string
{
return Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $timestamp)
return CarbonImmutable::createFromFormat(CarbonImmutable::DEFAULT_TO_STRING_FORMAT, $timestamp)
->setTimezone(self::RESPONSE_TIMEZONE)
->toIso8601String();
}

View File

@ -2,7 +2,6 @@
namespace Pterodactyl\Transformers\Api\Application;
use Cake\Chronos\Chronos;
use Pterodactyl\Models\Database;
use Pterodactyl\Models\DatabaseHost;
use Pterodactyl\Services\Acl\Api\AdminAcl;
@ -41,12 +40,8 @@ class DatabaseHostTransformer extends BaseTransformer
'port' => $model->port,
'username' => $model->username,
'node' => $model->node_id,
'created_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $model->created_at)
->setTimezone(config('app.timezone'))
->toIso8601String(),
'updated_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $model->updated_at)
->setTimezone(config('app.timezone'))
->toIso8601String(),
'created_at' => $model->created_at->toIso8601String(),
'updated_at' => $model->updated_at->toIso8601String(),
];
}

View File

@ -2,7 +2,6 @@
namespace Pterodactyl\Transformers\Api\Application;
use Cake\Chronos\Chronos;
use Pterodactyl\Models\Database;
use Pterodactyl\Models\DatabaseHost;
use Pterodactyl\Services\Acl\Api\AdminAcl;
@ -56,12 +55,8 @@ class ServerDatabaseTransformer extends BaseTransformer
'username' => $model->username,
'remote' => $model->remote,
'max_connections' => $model->max_connections,
'created_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $model->created_at)
->setTimezone(config('app.timezone'))
->toIso8601String(),
'updated_at' => Chronos::createFromFormat(Chronos::DEFAULT_TO_STRING_FORMAT, $model->updated_at)
->setTimezone(config('app.timezone'))
->toIso8601String(),
'created_at' => $model->created_at->toIso8601String(),
'updated_at' => $model->updated_at->toIso8601String(),
];
}

View File

@ -3,7 +3,6 @@
namespace Pterodactyl\Transformers\Api\Application;
use Pterodactyl\Models\Subuser;
use Pterodactyl\Models\Permission;
use Pterodactyl\Services\Acl\Api\AdminAcl;
class SubuserTransformer extends BaseTransformer

View File

@ -3,7 +3,6 @@
namespace Pterodactyl\Transformers\Api\Client;
use BadMethodCallException;
use InvalidArgumentException;
use Pterodactyl\Models\EggVariable;
class EggVariableTransformer extends BaseClientTransformer
@ -25,7 +24,7 @@ class EggVariableTransformer extends BaseClientTransformer
// This guards against someone incorrectly retrieving variables (haha, me) and then passing
// them into the transformer and along to the user. Just throw an exception and break the entire
// pathway since you should never be exposing these types of variables to a client.
if (!$variable->user_viewable) {
if (! $variable->user_viewable) {
throw new BadMethodCallException(
'Cannot transform a hidden egg variable in a client transformer.'
);

View File

@ -12,7 +12,7 @@
*/
$app = new Illuminate\Foundation\Application(
realpath(__DIR__ . '/../')
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
/*

View File

@ -1,5 +1,6 @@
<?php
use NunoMaduro\Collision\Provider;
use Illuminate\Contracts\Console\Kernel;
use Symfony\Component\Console\Output\ConsoleOutput;
@ -15,6 +16,10 @@ $kernel = $app->make(Kernel::class);
*/
$kernel->bootstrap();
// Register the collision service provider so that errors during the test
// setup process are output nicely.
(new Provider)->register();
$output = new ConsoleOutput;
if (config('database.default') !== 'testing') {

View File

@ -11,64 +11,60 @@
}
],
"require": {
"php": "^7.2",
"php": "^7.4 || ^8.0",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo_mysql": "*",
"ext-zip": "*",
"appstract/laravel-blade-directives": "^1.8",
"aws/aws-sdk-php": "^3.134",
"cakephp/chronos": "^1.3",
"doctrine/dbal": "^2.10",
"fideloper/proxy": "^4.2",
"guzzlehttp/guzzle": "^6.5",
"hashids/hashids": "^4.0",
"laracasts/utilities": "^3.1",
"laravel/framework": "^7.17",
"laravel/helpers": "^1.2",
"laravel/tinker": "^2.4",
"laravel/ui": "^2.0",
"lcobucci/jwt": "^3.3",
"aws/aws-sdk-php": "^3.171",
"doctrine/dbal": "^2.12",
"fideloper/proxy": "^4.4",
"guzzlehttp/guzzle": "^7.2",
"hashids/hashids": "^4.1",
"laracasts/utilities": "^3.2",
"laravel/framework": "^8.22",
"laravel/helpers": "^1.4",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.0",
"lcobucci/jwt": "^4.0",
"league/flysystem-aws-s3-v3": "^1.0",
"league/flysystem-memory": "^1.0",
"matriphe/iso-639": "^1.2",
"pragmarx/google2fa": "^5.0",
"predis/predis": "^1.1",
"prologue/alerts": "^0.4",
"psy/psysh": "^0.10.4",
"s1lentium/iptools": "^1.1",
"spatie/laravel-fractal": "^5.7",
"spatie/laravel-query-builder": "^2.8",
"staudenmeir/belongs-to-through": "^2.10",
"spatie/laravel-fractal": "^5.8",
"spatie/laravel-query-builder": "^3.3",
"staudenmeir/belongs-to-through": "^2.11",
"symfony/yaml": "^4.4",
"webmozart/assert": "^1.9"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.3",
"barryvdh/laravel-ide-helper": "^2.7",
"codedungeon/phpunit-result-printer": "^0.28.0",
"friendsofphp/php-cs-fixer": "2.16.1",
"fzaninotto/faker": "^1.9",
"laravel/dusk": "^6.3",
"barryvdh/laravel-debugbar": "^3.5",
"barryvdh/laravel-ide-helper": "^2.9",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.13",
"friendsofphp/php-cs-fixer": "^2.18",
"laravel/dusk": "^6.11",
"mockery/mockery": "^1.4",
"nunomaduro/collision": "^5.2",
"php-mock/php-mock-phpunit": "^2.6",
"phpunit/phpunit": "^8.5"
"phpunit/phpunit": "^9.0"
},
"autoload": {
"classmap": [
"database"
],
"files": [
"app/helpers.php"
],
"psr-4": {
"Pterodactyl\\": "app/"
"Pterodactyl\\": "app/",
"Database\\Factories\\": "database/Factories/",
"Database\\Seeders\\": "database/Seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Pterodactyl\\Tests\\Browser\\": "tests/Browser",
"Pterodactyl\\Tests\\Integration\\": "tests/Integration",
"Tests\\": "tests/"
"Pterodactyl\\Tests\\": "tests/"
}
},
"scripts": {

4814
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,7 @@ return [
'collation' => 'utf8mb4_unicode_ci',
'prefix' => env('DB_PREFIX', ''),
'strict' => env('DB_STRICT_MODE', false),
'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC')))
'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC'))),
],
/*
@ -68,7 +68,7 @@ return [
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => false,
'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC')))
'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC'))),
],
],

View File

@ -10,7 +10,7 @@ return [
| setup on the panel. When set to true, configurations stored in the
| database will not be applied.
*/
'load_environment_only' => (bool)env('APP_ENVIRONMENT_ONLY', false),
'load_environment_only' => (bool) env('APP_ENVIRONMENT_ONLY', false),
/*
|--------------------------------------------------------------------------

View File

@ -0,0 +1,29 @@
<?php
namespace Database\Factories;
use Pterodactyl\Models\Allocation;
use Illuminate\Database\Eloquent\Factories\Factory;
class AllocationFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Allocation::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'ip' => $this->faker->ipv4,
'port' => $this->faker->randomNumber(5),
];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Database\Factories;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Pterodactyl\Models\ApiKey;
use Illuminate\Database\Eloquent\Factories\Factory;
class ApiKeyFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ApiKey::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
static $token;
return [
'key_type' => ApiKey::TYPE_APPLICATION,
'identifier' => Str::random(\Pterodactyl\Models\ApiKey::IDENTIFIER_LENGTH),
'token' => $token ?: $token = encrypt(Str::random(\Pterodactyl\Models\ApiKey::KEY_LENGTH)),
'allowed_ips' => null,
'memo' => 'Test Function Key',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use Ramsey\Uuid\Uuid;
use Pterodactyl\Models\Backup;
use Illuminate\Database\Eloquent\Factories\Factory;
class BackupFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Backup::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'uuid' => Uuid::uuid4()->toString(),
'is_successful' => true,
'name' => $this->faker->sentence,
'disk' => Backup::ADAPTER_WINGS,
];
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Database\Factories;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Pterodactyl\Models\Database;
use Illuminate\Database\Eloquent\Factories\Factory;
class DatabaseFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Database::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
static $password;
return [
'database' => Str::random(10),
'username' => Str::random(10),
'remote' => '%',
'password' => $password ?: encrypt('test123'),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Database\Factories;
use Pterodactyl\Models\DatabaseHost;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Database\Eloquent\Factories\Factory;
class DatabaseHostFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = DatabaseHost::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'name' => $this->faker->colorName,
'host' => $this->faker->unique()->ipv4,
'port' => 3306,
'username' => $this->faker->colorName,
'password' => Crypt::encrypt($this->faker->word),
];
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use Ramsey\Uuid\Uuid;
use Pterodactyl\Models\Egg;
use Illuminate\Database\Eloquent\Factories\Factory;
class EggFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Egg::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'uuid' => Uuid::uuid4()->toString(),
'name' => $this->faker->name,
'description' => implode(' ', $this->faker->sentences()),
'startup' => 'java -jar test.jar',
];
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace Database\Factories;
use Illuminate\Support\Str;
use Pterodactyl\Models\EggVariable;
use Illuminate\Database\Eloquent\Factories\Factory;
class EggVariableFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = EggVariable::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'name' => $this->faker->firstName,
'description' => $this->faker->sentence(),
'env_variable' => Str::upper(Str::replaceArray(' ', ['_'], $this->faker->words(2, true))),
'default_value' => $this->faker->colorName,
'user_viewable' => 0,
'user_editable' => 0,
'rules' => 'required|string',
];
}
/**
* Indicate that the egg variable is viewable.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function viewable(): Factory
{
return $this->state(function (array $attributes) {
return [
'user_viewable' => 1,
];
});
}
/**
* Indicate that the egg variable is editable.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function editable(): Factory
{
return $this->state(function (array $attributes) {
return [
'user_editable' => 1,
];
});
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Database\Factories;
use Illuminate\Support\Str;
use Pterodactyl\Models\Location;
use Illuminate\Database\Eloquent\Factories\Factory;
class LocationFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Location::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'short' => Str::random(8),
'long' => Str::random(32),
];
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use Ramsey\Uuid\Uuid;
use Pterodactyl\Models\Nest;
use Illuminate\Database\Eloquent\Factories\Factory;
class NestFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Nest::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'uuid' => Uuid::uuid4()->toString(),
'author' => 'testauthor@example.com',
'name' => $this->faker->word,
'description' => null,
];
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Database\Factories;
use Ramsey\Uuid\Uuid;
use Illuminate\Support\Str;
use Pterodactyl\Models\Node;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Database\Eloquent\Factories\Factory;
class NodeFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Node::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'uuid' => Uuid::uuid4()->toString(),
'public' => true,
'name' => $this->faker->firstName,
'fqdn' => $this->faker->ipv4,
'scheme' => 'http',
'behind_proxy' => false,
'memory' => 1024,
'memory_overallocate' => 0,
'disk' => 10240,
'disk_overallocate' => 0,
'upload_size' => 100,
'daemon_token_id' => Str::random(Node::DAEMON_TOKEN_ID_LENGTH),
'daemon_token' => Crypt::encrypt(Str::random(Node::DAEMON_TOKEN_LENGTH)),
'daemonListen' => 8080,
'daemonSFTP' => 2022,
'daemonBase' => '/var/lib/pterodactyl/volumes',
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Database\Factories;
use Pterodactyl\Models\Schedule;
use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Schedule::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'name' => $this->faker->firstName(),
];
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace Database\Factories;
use Carbon\Carbon;
use Ramsey\Uuid\Uuid;
use Illuminate\Support\Str;
use Pterodactyl\Models\Server;
use Illuminate\Database\Eloquent\Factories\Factory;
class ServerFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Server::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'uuid' => Uuid::uuid4()->toString(),
'uuidShort' => Str::lower(Str::random(8)),
'name' => $this->faker->firstName,
'description' => implode(' ', $this->faker->sentences()),
'skip_scripts' => 0,
'suspended' => 0,
'memory' => 512,
'swap' => 0,
'disk' => 512,
'io' => 500,
'cpu' => 0,
'threads' => null,
'oom_disabled' => 0,
'installed' => 1,
'allocation_limit' => null,
'database_limit' => null,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Database\Factories;
use Pterodactyl\Models\Subuser;
use Pterodactyl\Models\Permission;
use Illuminate\Database\Eloquent\Factories\Factory;
class SubuserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Subuser::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'permissions' => [
Permission::ACTION_WEBSOCKET_CONNECT,
],
];
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use Pterodactyl\Models\Task;
use Illuminate\Database\Eloquent\Factories\Factory;
class TaskFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Task::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'sequence_id' => $this->faker->randomNumber(1),
'action' => 'command',
'payload' => 'test command',
'time_offset' => 120,
'is_queued' => false,
];
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Database\Factories;
use Carbon\Carbon;
use Ramsey\Uuid\Uuid;
use Pterodactyl\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
static $password;
return [
'external_id' => $this->faker->unique()->isbn10,
'uuid' => Uuid::uuid4()->toString(),
'username' => $this->faker->userName,
'email' => $this->faker->safeEmail,
'name_first' => $this->faker->firstName,
'name_last' => $this->faker->lastName,
'password' => $password ?: $password = bcrypt('password'),
'language' => 'en',
'root_admin' => false,
'use_totp' => false,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
/**
* Indicate that the user is an admin.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function admin(): Factory
{
return $this->state(function (array $attributes) {
return [
'root_admin' => true,
];
});
}
}

View File

@ -1,5 +1,7 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder

View File

@ -1,5 +1,7 @@
<?php
namespace Database\Seeders;
use Pterodactyl\Models\Nest;
use Illuminate\Database\Seeder;
use Illuminate\Http\UploadedFile;
@ -109,7 +111,7 @@ class EggSeeder extends Seeder
*/
private function parseEggFiles(Nest $nest)
{
$files = $this->filesystem->allFiles(database_path('seeds/eggs/' . kebab_case($nest->name)));
$files = $this->filesystem->allFiles(database_path('seeders/eggs/' . kebab_case($nest->name)));
$this->command->alert('Updating Eggs for Nest: ' . $nest->name);
Collection::make($files)->each(function ($file) use ($nest) {

Some files were not shown because too many files have changed in this diff Show More