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

5
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,10 +5,14 @@ namespace Pterodactyl\Exceptions;
use Exception; use Exception;
use Throwable; use Throwable;
use PDOException; use PDOException;
use Psr\Log\LoggerInterface; use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Swift_TransportException; use Swift_TransportException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Illuminate\Container\Container; use Illuminate\Container\Container;
use Illuminate\Database\Connection; use Illuminate\Database\Connection;
use Illuminate\Foundation\Application;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Session\TokenMismatchException; use Illuminate\Session\TokenMismatchException;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
@ -43,17 +47,6 @@ class Handler extends ExceptionHandler
ValidationException::class, 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. * 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 * Registers the exception handling callbacks for the application. This
* don't need or want the user information in our logs by default. * 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 * @noinspection PhpUnusedLocalVariableInspection
* 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
*/ */
public function report(Throwable $exception) public function register()
{ {
if (! config('app.exceptions.report_all', false) && $this->shouldntReport($exception)) { if (config('app.exceptions.report_all', false)) {
return null; $this->dontReport = [];
} }
if (method_exists($exception, 'report')) { $this->reportable(function (PDOException $ex) {
return $exception->report(); $ex = $this->generateCleanedExceptionStack($ex);
});
$this->reportable(function (Swift_TransportException $ex) {
$ex = $this->generateCleanedExceptionStack($ex);
});
} }
try { private function generateCleanedExceptionStack(Throwable $exception): string
$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)
{ {
$cleanedStack = ''; $cleanedStack = '';
foreach ($exception->getTrace() as $index => $item) { foreach ($exception->getTrace() as $index => $item) {
$cleanedStack .= sprintf( $cleanedStack .= sprintf(
"#%d %s(%d): %s%s%s\n", "#%d %s(%d): %s%s%s\n",
$index, $index,
array_get($item, 'file'), Arr::get($item, 'file'),
array_get($item, 'line'), Arr::get($item, 'line'),
array_get($item, 'class'), Arr::get($item, 'class'),
array_get($item, 'type'), Arr::get($item, 'type'),
array_get($item, 'function') Arr::get($item, 'function')
); );
} }
@ -142,7 +119,7 @@ class Handler extends ExceptionHandler
*/ */
public function render($request, Throwable $exception) 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 // 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 // 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) 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 = []; $cleaned = [];
foreach ($reasons as $reason => $attrs) { foreach ($reasons as $reason => $attrs) {
$cleaned[] = snake_case($reason); $cleaned[] = Str::snake($reason);
} }
return [str_replace('.', '_', $field) => $cleaned]; return [str_replace('.', '_', $field) => $cleaned];
})->toArray(); })->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 = []; $response = [];
foreach ($errors as $key => $error) { foreach ($errors as $key => $error) {
$meta = [ $meta = [
'source_field' => $field, '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 $codes, str_replace('.', '_', $field) . '.' . $key
)), )),
]; ];
@ -235,7 +212,7 @@ class Handler extends ExceptionHandler
'detail' => $exception->getMessage(), 'detail' => $exception->getMessage(),
'source' => [ 'source' => [
'line' => $exception->getLine(), 'line' => $exception->getLine(),
'file' => str_replace(base_path(), '', $exception->getFile()), 'file' => str_replace(Application::getInstance()->basePath(), '', $exception->getFile()),
], ],
'meta' => [ 'meta' => [
'trace' => explode("\n", $exception->getTraceAsString()), 'trace' => explode("\n", $exception->getTraceAsString()),
@ -262,15 +239,15 @@ class Handler extends ExceptionHandler
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception * @param \Illuminate\Auth\AuthenticationException $exception
* @return \Illuminate\Http\Response * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*/ */
protected function unauthenticated($request, AuthenticationException $exception) protected function unauthenticated($request, AuthenticationException $exception)
{ {
if ($request->expectsJson()) { 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(); $body = $response->getBody();
if (is_string($body) || (is_object($body) && method_exists($body, '__toString'))) { if (is_string($body) || (is_object($body) && method_exists($body, '__toString'))) {
$body = json_decode(is_string($body) ? $body : $body->__toString(), true); $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) 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 Illuminate\Support\Str;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
use InvalidArgumentException; use InvalidArgumentException;
use League\Flysystem\AdapterInterface;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use League\Flysystem\AdapterInterface;
use League\Flysystem\AwsS3v3\AwsS3Adapter; use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Memory\MemoryAdapter; use League\Flysystem\Memory\MemoryAdapter;
use Illuminate\Contracts\Config\Repository; 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; namespace Pterodactyl\Http\Controllers\Admin;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use Illuminate\Support\Str;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\Nest; use Pterodactyl\Models\Nest;
use Pterodactyl\Models\Mount; use Pterodactyl\Models\Mount;
use Pterodactyl\Models\Location; use Pterodactyl\Models\Location;
use Prologue\Alerts\AlertsMessageBag; use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Mounts\MountUpdateService;
use Pterodactyl\Http\Requests\Admin\MountFormRequest; use Pterodactyl\Http\Requests\Admin\MountFormRequest;
use Pterodactyl\Services\Mounts\MountCreationService;
use Pterodactyl\Services\Mounts\MountDeletionService;
use Pterodactyl\Repositories\Eloquent\MountRepository; use Pterodactyl\Repositories\Eloquent\MountRepository;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;

View File

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

View File

@ -9,14 +9,12 @@
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Illuminate\Support\Arr;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\User; use Pterodactyl\Models\User;
use Pterodactyl\Models\Mount; use Pterodactyl\Models\Mount;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Pterodactyl\Models\MountServer; use Pterodactyl\Models\MountServer;
use Prologue\Alerts\AlertsMessageBag; use Prologue\Alerts\AlertsMessageBag;
use GuzzleHttp\Exception\RequestException;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
@ -37,7 +35,6 @@ use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
use Pterodactyl\Services\Servers\ServerConfigurationStructureService; use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest; use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest;

View File

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

View File

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

View File

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

View File

@ -67,7 +67,7 @@ class FileUploadController extends ClientApiController
return sprintf( return sprintf(
'%s/upload/file?token=%s', '%s/upload/file?token=%s',
$server->node->getConnectionAddress(), $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. * Set the notes for the allocation for a server.
*s *s.
* *
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\NewAllocationRequest $request * @param \Pterodactyl\Http\Requests\Api\Client\Servers\Network\NewAllocationRequest $request
* @param \Pterodactyl\Models\Server $server * @param \Pterodactyl\Models\Server $server

View File

@ -10,7 +10,6 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Models\Schedule; use Pterodactyl\Models\Schedule;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Pterodactyl\Helpers\Utilities; use Pterodactyl\Helpers\Utilities;
use Pterodactyl\Jobs\Schedule\RunTaskJob;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\Eloquent\ScheduleRepository; use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
use Pterodactyl\Services\Schedules\ProcessScheduleService; use Pterodactyl\Services\Schedules\ProcessScheduleService;

View File

@ -2,7 +2,6 @@
namespace Pterodactyl\Http\Controllers\Api\Client\Servers; namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;

View File

@ -86,11 +86,11 @@ class StartupController extends ClientApiController
if (is_null($variable) || ! $variable->user_viewable) { if (is_null($variable) || ! $variable->user_viewable) {
throw new BadRequestHttpException( 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.'
); );
} elseif (! $variable->user_editable) { } elseif (! $variable->user_editable) {
throw new BadRequestHttpException( 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([ return new JsonResponse([
'data' => [ 'data' => [
'token' => $token->__toString(), 'token' => $token->toString(),
'socket' => $socket . sprintf('/api/servers/%s/ws', $server->uuid), 'socket' => $socket . sprintf('/api/servers/%s/ws', $server->uuid),
], ],
]); ]);

View File

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

View File

@ -2,7 +2,7 @@
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers; namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
use Cake\Chronos\Chronos; use Carbon\CarbonImmutable;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
@ -110,11 +110,11 @@ class ServerTransferController extends Controller
Arr::set($data, 'suspended', false); Arr::set($data, 'suspended', false);
$this->connection->transaction(function () use ($data, $server) { $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 // that node to communicate with the old node during the process to initiate the
// actual file transfer. // actual file transfer.
$token = $this->jwtService $token = $this->jwtService
->setExpiresAt(Chronos::now()->addMinutes(15)) ->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
->setSubject($server->uuid) ->setSubject($server->uuid)
->handle($server->node, $server->uuid, 'sha256'); ->handle($server->node, $server->uuid, 'sha256');
@ -128,7 +128,7 @@ class ServerTransferController extends Controller
$this->daemonTransferRepository $this->daemonTransferRepository
->setServer($server) ->setServer($server)
->setNode($server->transfer->newNode) ->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); 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 Pterodactyl\Http\Requests\Auth\LoginCheckpointRequest;
use Illuminate\Contracts\Cache\Repository as CacheRepository; use Illuminate\Contracts\Cache\Repository as CacheRepository;
use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Repositories\Eloquent\RecoveryTokenRepository; use Pterodactyl\Repositories\Eloquent\RecoveryTokenRepository;
class LoginCheckpointController extends AbstractLoginController class LoginCheckpointController extends AbstractLoginController

View File

@ -2,7 +2,7 @@
namespace Pterodactyl\Http\Controllers\Auth; namespace Pterodactyl\Http\Controllers\Auth;
use Cake\Chronos\Chronos; use Carbon\CarbonImmutable;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Auth\AuthManager; use Illuminate\Auth\AuthManager;
@ -101,7 +101,7 @@ class LoginController extends AbstractLoginController
if ($user->use_totp) { if ($user->use_totp) {
$token = Str::random(64); $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([ return new JsonResponse([
'data' => [ 'data' => [

View File

@ -3,7 +3,7 @@
namespace Pterodactyl\Http\Middleware\Api; namespace Pterodactyl\Http\Middleware\Api;
use Closure; use Closure;
use Cake\Chronos\Chronos; use Carbon\CarbonImmutable;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\User; use Pterodactyl\Models\User;
use Pterodactyl\Models\ApiKey; use Pterodactyl\Models\ApiKey;
@ -110,7 +110,7 @@ class AuthenticateKey
throw new AccessDeniedHttpException; 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; return $model;
} }

View File

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

View File

@ -7,11 +7,11 @@ use Illuminate\Http\Request;
use Pterodactyl\Models\Task; use Pterodactyl\Models\Task;
use Pterodactyl\Models\User; use Pterodactyl\Models\User;
use InvalidArgumentException; use InvalidArgumentException;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Backup; use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Subuser; use Pterodactyl\Models\Subuser;
use Pterodactyl\Models\Schedule;
use Pterodactyl\Models\Database; use Pterodactyl\Models\Database;
use Pterodactyl\Models\Schedule;
use Pterodactyl\Models\Allocation; use Pterodactyl\Models\Allocation;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 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); $id = Container::getInstance()->make(HashidsInterface::class)->decodeFirst($value);
return Database::query()->where('id', $id)->firstOrFail(); return Database::query()->where('id', $id)->firstOrFail();

View File

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

View File

@ -18,6 +18,10 @@ use Pterodactyl\Services\Acl\Api\AdminAcl;
*/ */
class ApiKey extends Model 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'; const RESOURCE_NAME = 'api_key';
/** /**

View File

@ -2,6 +2,18 @@
namespace Pterodactyl\Models; 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 class DatabaseHost extends Model
{ {
/** /**
@ -10,6 +22,11 @@ class DatabaseHost extends Model
*/ */
const RESOURCE_NAME = 'database_host'; const RESOURCE_NAME = 'database_host';
/**
* @var bool
*/
protected $immutableDates = true;
/** /**
* The table associated with the model. * The table associated with the model.
* *

View File

@ -6,11 +6,14 @@ use Illuminate\Support\Str;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Illuminate\Container\Container; use Illuminate\Container\Container;
use Illuminate\Contracts\Validation\Factory; use Illuminate\Contracts\Validation\Factory;
use Illuminate\Database\Eloquent\Model as IlluminateModel; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Pterodactyl\Exceptions\Model\DataValidationException; use Pterodactyl\Exceptions\Model\DataValidationException;
use Illuminate\Database\Eloquent\Model as IlluminateModel;
abstract class Model extends IlluminateModel abstract class Model extends IlluminateModel
{ {
use HasFactory;
/** /**
* Set to true to return immutable Carbon date instances from the model. * 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; public $timestamps = false;
/** /**
* Blacklisted source paths * Blacklisted source paths.
* *
* @var string[] * @var string[]
*/ */
@ -98,7 +98,7 @@ class Mount extends Model
]; ];
/** /**
* Blacklisted target paths * Blacklisted target paths.
* *
* @var string[] * @var string[]
*/ */

View File

@ -7,6 +7,7 @@ use Cache;
use Pterodactyl\Models\User; use Pterodactyl\Models\User;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Pterodactyl\Models\Subuser; use Pterodactyl\Models\Subuser;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Pterodactyl\Observers\UserObserver; use Pterodactyl\Observers\UserObserver;
@ -29,6 +30,8 @@ class AppServiceProvider extends ServiceProvider
View::share('appVersion', $this->versionData()['version'] ?? 'undefined'); View::share('appVersion', $this->versionData()['version'] ?? 'undefined');
View::share('appIsGit', $this->versionData()['is_git'] ?? false); 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') $this->app->make('blade.compiler')
->directive('datetimeHuman', function ($expression) { ->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\Database\DatabaseManager;
use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Exceptions\Repository\DuplicateDatabaseNameException;
class DatabaseRepository extends EloquentRepository implements DatabaseRepositoryInterface class DatabaseRepository extends EloquentRepository implements DatabaseRepositoryInterface
{ {

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@
namespace Pterodactyl\Repositories\Wings; namespace Pterodactyl\Repositories\Wings;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use GuzzleHttp\Exception\TransferException; use GuzzleHttp\Exception\TransferException;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;

View File

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

View File

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

View File

@ -2,13 +2,14 @@
namespace Pterodactyl\Services\Nodes; namespace Pterodactyl\Services\Nodes;
use DateTimeInterface; use DateTimeImmutable;
use Lcobucci\JWT\Builder;
use Carbon\CarbonImmutable; use Carbon\CarbonImmutable;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Lcobucci\JWT\Signer\Key;
use Pterodactyl\Models\Node; use Pterodactyl\Models\Node;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Pterodactyl\Extensions\Lcobucci\JWT\Encoding\TimestampDates;
class NodeJWTService class NodeJWTService
{ {
@ -18,7 +19,7 @@ class NodeJWTService
private $claims = []; private $claims = [];
/** /**
* @var int|null * @var \DateTimeImmutable|null
*/ */
private $expiresAt; private $expiresAt;
@ -41,12 +42,12 @@ class NodeJWTService
} }
/** /**
* @param \DateTimeInterface $date * @param \DateTimeImmutable $date
* @return $this * @return $this
*/ */
public function setExpiresAt(DateTimeInterface $date) public function setExpiresAt(DateTimeImmutable $date)
{ {
$this->expiresAt = $date->getTimestamp(); $this->expiresAt = $date;
return $this; return $this;
} }
@ -68,24 +69,27 @@ class NodeJWTService
* @param \Pterodactyl\Models\Node $node * @param \Pterodactyl\Models\Node $node
* @param string|null $identifiedBy * @param string|null $identifiedBy
* @param string $algo * @param string $algo
* @return \Lcobucci\JWT\Token * @return \Lcobucci\JWT\Token\Plain
*/ */
public function handle(Node $node, string $identifiedBy, string $algo = 'md5') 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()) ->permittedFor($node->getConnectionAddress())
->identifiedBy(hash($algo, $identifiedBy), true) ->identifiedBy($identifier)
->issuedAt(CarbonImmutable::now()->getTimestamp()) ->withHeader('jti', $identifier)
->canOnlyBeUsedAfter(CarbonImmutable::now()->subMinutes(5)->getTimestamp()); ->issuedAt(CarbonImmutable::now())
->canOnlyBeUsedAfter(CarbonImmutable::now()->subMinutes(5));
if ($this->expiresAt) { if ($this->expiresAt) {
$builder = $builder->expiresAt($this->expiresAt); $builder = $builder->expiresAt($this->expiresAt);
} }
if (! empty($this->subject)) { if (! empty($this->subject)) {
$builder = $builder->relatedTo($this->subject, true); $builder = $builder->relatedTo($this->subject)->withHeader('sub', $this->subject);
} }
foreach ($this->claims as $key => $value) { foreach ($this->claims as $key => $value) {
@ -94,6 +98,6 @@ class NodeJWTService
return $builder return $builder
->withClaim('unique_id', Str::random(16)) ->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 Illuminate\Support\Str;
use Pterodactyl\Models\Node; use Pterodactyl\Models\Node;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use GuzzleHttp\Exception\ConnectException;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Contracts\Encryption\Encrypter;
use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Eloquent\NodeRepository;
use Pterodactyl\Repositories\Daemon\ConfigurationRepository;
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository; use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
use Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException; use Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException;

View File

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

View File

@ -95,10 +95,10 @@ class ServerConfigurationStructureService
'id' => $server->egg->uuid, 'id' => $server->egg->uuid,
'file_denylist' => [ 'file_denylist' => [
'config.yml', 'config.yml',
'**/*.json' '**/*.json',
] ],
// 'file_denylist' => explode(PHP_EOL, $server->egg->inherit_file_denylist), // 'file_denylist' => explode(PHP_EOL, $server->egg->inherit_file_denylist),
] ],
]; ];
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@
namespace Pterodactyl\Transformers\Api\Client; namespace Pterodactyl\Transformers\Api\Client;
use BadMethodCallException; use BadMethodCallException;
use InvalidArgumentException;
use Pterodactyl\Models\EggVariable; use Pterodactyl\Models\EggVariable;
class EggVariableTransformer extends BaseClientTransformer class EggVariableTransformer extends BaseClientTransformer

View File

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

View File

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

View File

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

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 <?php
namespace Database\Seeders;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder

View File

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

View File

@ -1,5 +1,7 @@
<?php <?php
namespace Database\Seeders;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Pterodactyl\Services\Nests\NestCreationService; use Pterodactyl\Services\Nests\NestCreationService;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface;

View File

@ -1,211 +0,0 @@
<?php
use Carbon\Carbon;
use Ramsey\Uuid\Uuid;
use Cake\Chronos\Chronos;
use Illuminate\Support\Str;
use Pterodactyl\Models\Node;
use Faker\Generator as Faker;
use Pterodactyl\Models\ApiKey;
use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Permission;
/** @var \Illuminate\Database\Eloquent\Factory $factory */
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
$factory->define(Pterodactyl\Models\Server::class, function (Faker $faker) {
return [
'uuid' => Uuid::uuid4()->toString(),
'uuidShort' => str_random(8),
'name' => $faker->firstName,
'description' => implode(' ', $faker->sentences()),
'skip_scripts' => 0,
'suspended' => 0,
'memory' => 512,
'swap' => 0,
'disk' => 512,
'io' => 500,
'cpu' => 0,
'oom_disabled' => 0,
'installed' => 1,
'database_limit' => null,
'allocation_limit' => null,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
});
$factory->define(Pterodactyl\Models\User::class, function (Faker $faker) {
static $password;
return [
'external_id' => $faker->unique()->isbn10,
'uuid' => $faker->uuid,
'username' => $faker->userName,
'email' => $faker->safeEmail,
'name_first' => $faker->firstName,
'name_last' => $faker->lastName,
'password' => $password ?: $password = bcrypt('password'),
'language' => 'en',
'root_admin' => false,
'use_totp' => false,
'created_at' => Chronos::now(),
'updated_at' => Chronos::now(),
];
});
$factory->state(Pterodactyl\Models\User::class, 'admin', function () {
return [
'root_admin' => true,
];
});
$factory->define(Pterodactyl\Models\Location::class, function (Faker $faker) {
return [
'short' => Str::random(8),
'long' => $faker->catchPhrase,
];
});
$factory->define(Pterodactyl\Models\Node::class, function (Faker $faker) {
return [
'uuid' => Uuid::uuid4()->toString(),
'public' => true,
'name' => $faker->firstName,
'fqdn' => $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' => encrypt(Str::random(Node::DAEMON_TOKEN_LENGTH)),
'daemonListen' => 8080,
'daemonSFTP' => 2022,
'daemonBase' => '/var/lib/pterodactyl/volumes',
];
});
$factory->define(Pterodactyl\Models\Nest::class, function (Faker $faker) {
return [
'uuid' => $faker->unique()->uuid,
'author' => 'testauthor@example.com',
'name' => $faker->word,
'description' => null,
];
});
$factory->define(Pterodactyl\Models\Egg::class, function (Faker $faker) {
return [
'uuid' => $faker->unique()->uuid,
'name' => $faker->name,
'description' => implode(' ', $faker->sentences(3)),
'startup' => 'java -jar test.jar',
];
});
$factory->define(Pterodactyl\Models\EggVariable::class, function (Faker $faker) {
return [
'name' => $faker->firstName,
'description' => $faker->sentence(),
'env_variable' => strtoupper(str_replace(' ', '_', $faker->words(2, true))),
'default_value' => $faker->colorName,
'user_viewable' => 0,
'user_editable' => 0,
'rules' => 'required|string',
];
});
$factory->state(Pterodactyl\Models\EggVariable::class, 'viewable', function () {
return ['user_viewable' => 1];
});
$factory->state(Pterodactyl\Models\EggVariable::class, 'editable', function () {
return ['user_editable' => 1];
});
$factory->define(Pterodactyl\Models\Subuser::class, function (Faker $faker) {
return [
'permissions' => [Permission::ACTION_WEBSOCKET_CONNECT],
];
});
$factory->define(Pterodactyl\Models\Allocation::class, function (Faker $faker) {
return [
'ip' => $faker->ipv4,
'port' => $faker->randomNumber(5),
];
});
$factory->define(Pterodactyl\Models\DatabaseHost::class, function (Faker $faker) {
return [
'name' => $faker->colorName,
'host' => $faker->unique()->ipv4,
'port' => 3306,
'username' => $faker->colorName,
'password' => Crypt::encrypt($faker->word),
];
});
$factory->define(Pterodactyl\Models\Database::class, function (Faker $faker) {
static $password;
return [
'database' => str_random(10),
'username' => str_random(10),
'remote' => '%',
'password' => $password ?: encrypt('test123'),
'created_at' => Carbon::now()->toDateTimeString(),
'updated_at' => Carbon::now()->toDateTimeString(),
];
});
$factory->define(Pterodactyl\Models\Schedule::class, function (Faker $faker) {
return [
'name' => $faker->firstName(),
];
});
$factory->define(Pterodactyl\Models\Task::class, function (Faker $faker) {
return [
'sequence_id' => $faker->randomNumber(1),
'action' => 'command',
'payload' => 'test command',
'time_offset' => 120,
'is_queued' => false,
];
});
$factory->define(Pterodactyl\Models\ApiKey::class, function (Faker $faker) {
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()->toDateTimeString(),
'updated_at' => Carbon::now()->toDateTimeString(),
];
});
$factory->define(Pterodactyl\Models\Backup::class, function (Faker $faker) {
return [
'uuid' => Uuid::uuid4()->toString(),
'is_successful' => true,
'name' => $faker->sentence,
'disk' => Backup::ADAPTER_WINGS,
];
});

View File

@ -11,14 +11,12 @@ class DeleteServiceExecutableOption extends Migration
*/ */
public function up() public function up()
{ {
DB::transaction(function () {
Schema::table('services', function (Blueprint $table) { Schema::table('services', function (Blueprint $table) {
$table->renameColumn('file', 'folder'); $table->renameColumn('file', 'folder');
$table->dropColumn('executable'); $table->dropColumn('executable');
$table->text('description')->nullable()->change(); $table->text('description')->nullable()->change();
$table->text('startup')->nullable()->change(); $table->text('startup')->nullable()->change();
}); });
});
} }
/** /**

View File

@ -22,7 +22,7 @@ class MigrateToNewServiceSystem extends Migration
} }
$options = DB::table('service_options')->where('service_id', $service->id)->get(); $options = DB::table('service_options')->where('service_id', $service->id)->get();
$options->each(function ($item) use ($options) { $options->each(function ($item) {
if ($item->tag === 'srcds' && $item->name === 'Insurgency') { if ($item->tag === 'srcds' && $item->name === 'Insurgency') {
$item->tag = 'insurgency'; $item->tag = 'insurgency';
} elseif ($item->tag === 'srcds' && $item->name === 'Team Fortress 2') { } elseif ($item->tag === 'srcds' && $item->name === 'Team Fortress 2') {

View File

@ -1,7 +1,7 @@
<?php <?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Pterodactyl\Models\Permission as P; use Pterodactyl\Models\Permission as P;

View File

@ -20,7 +20,7 @@ class CreateBackupsTable extends Migration
// to use. For now, just rename them to maintain the data. // to use. For now, just rename them to maintain the data.
$results = DB::select('SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = ? AND table_name LIKE ? AND table_name NOT LIKE \'%_plugin_bak\'', [ $results = DB::select('SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = ? AND table_name LIKE ? AND table_name NOT LIKE \'%_plugin_bak\'', [
config("database.connections.{$db}.database"), config("database.connections.{$db}.database"),
'backup%' 'backup%',
]); ]);
// Take any of the results, most likely "backups" and "backup_logs" and rename them to have a // Take any of the results, most likely "backups" and "backup_logs" and rename them to have a

View File

@ -19,7 +19,7 @@ class AddBackupLimitToServers extends Migration
// here. If we find a result we'll actually keep the column around since we can maintain that backup // here. If we find a result we'll actually keep the column around since we can maintain that backup
// limit, but we need to correct the column definition a bit. // limit, but we need to correct the column definition a bit.
$results = DB::select('SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = \'servers\' AND COLUMN_NAME = \'backup_limit\'', [ $results = DB::select('SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = \'servers\' AND COLUMN_NAME = \'backup_limit\'', [
config("database.connections.{$db}.database") config("database.connections.{$db}.database"),
]); ]);
if (count($results) === 1) { if (count($results) === 1) {

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