From a1a52754ad1dab4f2713e034fa60d02e2240e388 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Mon, 28 Nov 2022 11:56:03 -0500 Subject: [PATCH] chore: add phpstan static analysis minimum (#4511) --- .github/workflows/docker.yaml | 12 +- .github/workflows/{ci.yaml => laravel.yaml} | 96 ++++++-- .github/workflows/lint.yaml | 33 --- .github/workflows/release.yaml | 12 +- .github/workflows/ui.yaml | 35 ++- app/Exceptions/Handler.php | 2 +- app/Http/Controllers/Admin/ApiController.php | 8 +- app/Http/Controllers/Admin/BaseController.php | 5 +- .../Controllers/Admin/DatabaseController.php | 8 +- .../Controllers/Admin/LocationController.php | 4 +- .../Controllers/Admin/MountController.php | 4 +- .../Controllers/Admin/Nests/EggController.php | 4 +- .../Admin/Nests/EggScriptController.php | 2 +- .../Admin/Nests/EggVariableController.php | 2 +- .../Admin/Nests/NestController.php | 6 +- .../Admin/Nodes/NodeController.php | 10 +- .../Admin/Nodes/NodeViewController.php | 16 +- .../Controllers/Admin/NodesController.php | 2 +- .../Admin/Servers/CreateServerController.php | 9 +- .../Admin/Servers/ServerController.php | 10 +- .../Servers/ServerTransferController.php | 10 +- .../Admin/Servers/ServerViewController.php | 22 +- .../Admin/Settings/AdvancedController.php | 6 +- .../Admin/Settings/IndexController.php | 6 +- .../Admin/Settings/MailController.php | 6 +- app/Http/Controllers/Admin/UserController.php | 23 +- .../Api/Client/Servers/StartupController.php | 3 +- .../Servers/ServerDetailsController.php | 7 +- .../Auth/AbstractLoginController.php | 4 +- .../Auth/LoginCheckpointController.php | 2 +- app/Http/Controllers/Auth/LoginController.php | 11 +- .../Auth/ResetPasswordController.php | 4 +- app/Http/Controllers/Base/IndexController.php | 2 +- .../Client/Server/ResourceBelongsToServer.php | 6 +- .../RequireTwoFactorAuthentication.php | 10 +- .../Requests/Admin/LocationFormRequest.php | 5 +- app/Http/Requests/Admin/MountFormRequest.php | 5 +- .../Api/Application/ApplicationApiRequest.php | 4 +- .../Locations/UpdateLocationRequest.php | 4 +- .../Application/Nodes/UpdateNodeRequest.php | 5 +- .../Databases/StoreServerDatabaseRequest.php | 2 + .../Databases/StoreDatabaseRequest.php | 1 + .../Servers/Subusers/SubuserRequest.php | 1 - app/Models/Egg.php | 6 +- app/Models/EggVariable.php | 5 +- app/Models/Model.php | 1 + app/Models/Node.php | 25 +- app/Models/Setting.php | 1 + app/Models/User.php | 12 + app/Notifications/ServerInstalled.php | 10 +- .../Eloquent/EloquentRepository.php | 2 + app/Repositories/Eloquent/NodeRepository.php | 28 +-- .../Eloquent/SettingsRepository.php | 1 + app/Rules/Fqdn.php | 8 +- .../Allocations/AssignmentService.php | 9 +- app/Services/Backups/DeleteBackupService.php | 5 +- .../Backups/InitiateBackupService.php | 4 +- .../Databases/DatabaseManagementService.php | 1 + .../Deployment/FindViableNodesService.php | 2 +- .../Schedules/ProcessScheduleService.php | 2 +- .../Servers/BuildModificationService.php | 5 +- .../Servers/ServerCreationService.php | 6 +- app/Services/Users/UserDeletionService.php | 4 +- .../Application/ServerVariableTransformer.php | 1 + composer.json | 1 + composer.lock | 231 +++++++++++++++++- phpstan.neon | 35 +++ 67 files changed, 558 insertions(+), 276 deletions(-) rename .github/workflows/{ci.yaml => laravel.yaml} (70%) delete mode 100644 .github/workflows/lint.yaml create mode 100644 phpstan.neon diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index bd44fecd0d..65cef226d3 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -1,4 +1,4 @@ -name: Publish Docker Image +name: Docker on: push: @@ -8,16 +8,16 @@ on: jobs: push: - name: Push Image to GitHub Packages + name: Push runs-on: ubuntu-20.04 # Always run against a tag, even if the commit into the tag has [docker skip] # within the commit message. if: "!contains(github.ref, 'develop') || (!contains(github.event.head_commit.message, 'skip docker') && !contains(github.event.head_commit.message, 'docker skip'))" steps: - - name: Code Checkout + - name: Code checkout uses: actions/checkout@v3 - - name: Docker Metadata + - name: Docker metadata uses: docker/metadata-action@v4 id: docker_meta with: @@ -26,10 +26,10 @@ jobs: - name: Setup QEMU uses: docker/setup-qemu-action@v2 - - name: Setup Docker Buildx + - name: Setup Docker buildx uses: docker/setup-buildx-action@v2 - - name: Docker Login + - name: Docker login uses: docker/login-action@v2 with: registry: ghcr.io diff --git a/.github/workflows/ci.yaml b/.github/workflows/laravel.yaml similarity index 70% rename from .github/workflows/ci.yaml rename to .github/workflows/laravel.yaml index 28ce63e4a7..56a597b480 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/laravel.yaml @@ -1,4 +1,4 @@ -name: Tests +name: Laravel on: push: @@ -11,8 +11,58 @@ on: - "1.0-develop" jobs: + analysis: + name: Static Analysis + runs-on: ubuntu-20.04 + env: + APP_ENV: testing + APP_DEBUG: "true" + APP_KEY: SomeRandomString3232RandomString + CACHE_DRIVER: array + MAIL_MAILER: array + SESSION_DRIVER: array + QUEUE_CONNECTION: sync + steps: + - name: Code checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + extensions: bcmath, cli, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --no-progress --no-suggest --prefer-dist + + - name: Analyze + run: vendor/bin/phpstan analyse + + lint: + name: Lint + runs-on: ubuntu-20.04 + steps: + - name: Code checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --no-progress --no-suggest --prefer-dist + + - name: PHP CS Fixer + run: vendor/bin/php-cs-fixer fix --dry-run --diff + mysql: - name: MySQL + name: Tests (MySQL) runs-on: ubuntu-20.04 strategy: fail-fast: false @@ -36,20 +86,17 @@ jobs: APP_TIMEZONE: UTC APP_URL: http://localhost/ APP_ENVIRONMENT_ONLY: "true" - - DB_CONNECTION: mysql - DB_HOST: 127.0.0.1 - DB_DATABASE: testing - DB_USERNAME: root - CACHE_DRIVER: array MAIL_MAILER: array SESSION_DRIVER: array QUEUE_CONNECTION: sync - HASHIDS_SALT: test123 + DB_CONNECTION: mysql + DB_HOST: 127.0.0.1 + DB_DATABASE: testing + DB_USERNAME: root steps: - - name: Code Checkout + - name: Code checkout uses: actions/checkout@v3 - name: Get cache directory @@ -78,7 +125,6 @@ jobs: - name: Unit tests run: vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit - if: ${{ always() }} env: DB_HOST: UNIT_NO_DB @@ -88,7 +134,7 @@ jobs: DB_PORT: ${{ job.services.database.ports[3306] }} postgres: - name: PostgreSQL + name: Tests (PostgreSQL) runs-on: ubuntu-20.04 if: "!contains(github.event.head_commit.message, 'skip ci') && !contains(github.event.head_commit.message, 'ci skip')" strategy: @@ -114,35 +160,32 @@ jobs: APP_TIMEZONE: UTC APP_URL: http://localhost/ APP_ENVIRONMENT_ONLY: "true" - - DB_CONNECTION: pgsql - DB_HOST: 127.0.0.1 - DB_DATABASE: testing - DB_USERNAME: postgres - DB_PASSWORD: postgres - CACHE_DRIVER: array MAIL_MAILER: array SESSION_DRIVER: array QUEUE_CONNECTION: sync - HASHIDS_SALT: test123 + DB_CONNECTION: pgsql + DB_HOST: 127.0.0.1 + DB_DATABASE: testing + DB_USERNAME: postgres + DB_PASSWORD: postgres steps: - - name: Code Checkout + - name: Code checkout uses: actions/checkout@v3 - name: Get cache directory id: composer-cache run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache uses: actions/cache@v3 with: - path: | - ~/.php_cs.cache - ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-cache-${{ matrix.php }}-${{ hashFiles('**.composer.lock') }} + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.php }}- - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -157,7 +200,6 @@ jobs: - name: Unit tests run: vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit - if: ${{ always() }} env: DB_HOST: UNIT_NO_DB diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index a48c6b14ed..0000000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: Lint - -on: - push: - branches: - - "develop" - - "1.0-develop" - pull_request: - branches: - - "develop" - - "1.0-develop" - -jobs: - lint: - name: Lint - runs-on: ubuntu-20.04 - steps: - - name: Code Checkout - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "8.1" - extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip - tools: composer:v2 - coverage: none - - - name: Install dependencies - run: composer install --no-interaction --no-progress --no-suggest --prefer-dist - - - name: PHP CS Fixer - run: vendor/bin/php-cs-fixer fix --dry-run --diff diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 09ab86410a..7c4a72bffb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,20 +10,20 @@ jobs: name: Release runs-on: ubuntu-20.04 steps: - - name: Code Checkout + - name: Code checkout uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: - node-version: 16 - cache: "yarn" + node-version: 18 + cache: yarn - name: Install dependencies run: yarn install --frozen-lockfile - name: Build - run: yarn build:production + run: yarn build - name: Create release branch and bump version env: @@ -41,7 +41,7 @@ jobs: - name: Create release archive run: | - rm -rf node_modules/ test/ codecov.yml CODE_OF_CONDUCT.md CONTRIBUTING.md phpunit.xml Vagrantfile + rm -rf node_modules/ tests/ CODE_OF_CONDUCT.md CONTRIBUTING.md phpstan.neon phpunit.xml tar -czf panel.tar.gz * .env.example .eslintignore .eslintrc.js - name: Extract changelog @@ -58,7 +58,7 @@ jobs: echo -e "\n#### SHA256 Checksum\n\n\`\`\`\n$SUM\n\`\`\`\n" >> ./RELEASE_CHANGELOG echo $SUM > checksum.txt - - name: Create Release + - name: Create release id: create_release uses: actions/create-release@v1 env: diff --git a/.github/workflows/ui.yaml b/.github/workflows/ui.yaml index e743de4667..e61696c1ce 100644 --- a/.github/workflows/ui.yaml +++ b/.github/workflows/ui.yaml @@ -11,28 +11,47 @@ on: - "1.0-develop" jobs: - build-and-test: - name: Build and Test + lint: + name: Lint + runs-on: ubuntu-20.04 + steps: + - name: Code checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: yarn + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Lint + run: yarn run lint + + tests: + name: Tests runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: - node-version: [16, 18] + node: [16, 18] steps: - - name: Code Checkout + - name: Code checkout uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} - cache: "yarn" + node-version: ${{ matrix.node }} + cache: yarn - name: Install dependencies run: yarn install --frozen-lockfile - name: Build - run: yarn build + run: yarn run build - name: Tests - run: yarn test + run: yarn run test diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index bcc636b5c7..00cc8615ed 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -25,7 +25,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -class Handler extends ExceptionHandler +final class Handler extends ExceptionHandler { /** * The validation parser in Laravel formats custom rules using the class name diff --git a/app/Http/Controllers/Admin/ApiController.php b/app/Http/Controllers/Admin/ApiController.php index 02ad6e540d..247aaee00b 100644 --- a/app/Http/Controllers/Admin/ApiController.php +++ b/app/Http/Controllers/Admin/ApiController.php @@ -9,7 +9,6 @@ use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; use Pterodactyl\Services\Acl\Api\AdminAcl; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Api\KeyCreationService; use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface; @@ -23,8 +22,7 @@ class ApiController extends Controller public function __construct( private AlertsMessageBag $alert, private ApiKeyRepositoryInterface $repository, - private KeyCreationService $keyCreationService, - private ViewFactory $view, + private KeyCreationService $keyCreationService ) { } @@ -33,7 +31,7 @@ public function __construct( */ public function index(Request $request): View { - return $this->view->make('admin.api.index', [ + return view('admin.api.index', [ 'keys' => $this->repository->getApplicationKeys($request->user()), ]); } @@ -48,7 +46,7 @@ public function create(): View $resources = AdminAcl::getResourceList(); sort($resources); - return $this->view->make('admin.api.new', [ + return view('admin.api.new', [ 'resources' => $resources, 'permissions' => [ 'r' => AdminAcl::READ, diff --git a/app/Http/Controllers/Admin/BaseController.php b/app/Http/Controllers/Admin/BaseController.php index 53f53ce54c..2b69330740 100644 --- a/app/Http/Controllers/Admin/BaseController.php +++ b/app/Http/Controllers/Admin/BaseController.php @@ -3,7 +3,6 @@ namespace Pterodactyl\Http\Controllers\Admin; use Illuminate\View\View; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Helpers\SoftwareVersionService; @@ -12,7 +11,7 @@ class BaseController extends Controller /** * BaseController constructor. */ - public function __construct(private SoftwareVersionService $version, private ViewFactory $view) + public function __construct(private SoftwareVersionService $version) { } @@ -21,6 +20,6 @@ public function __construct(private SoftwareVersionService $version, private Vie */ public function index(): View { - return $this->view->make('admin.index', ['version' => $this->version]); + return view('admin.index', ['version' => $this->version]); } } diff --git a/app/Http/Controllers/Admin/DatabaseController.php b/app/Http/Controllers/Admin/DatabaseController.php index e0dc0dc577..dc436ffaa1 100644 --- a/app/Http/Controllers/Admin/DatabaseController.php +++ b/app/Http/Controllers/Admin/DatabaseController.php @@ -8,7 +8,6 @@ use Pterodactyl\Models\DatabaseHost; use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Databases\Hosts\HostUpdateService; use Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest; @@ -30,8 +29,7 @@ public function __construct( private HostCreationService $creationService, private HostDeletionService $deletionService, private HostUpdateService $updateService, - private LocationRepositoryInterface $locationRepository, - private ViewFactory $view + private LocationRepositoryInterface $locationRepository ) { } @@ -40,7 +38,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.databases.index', [ + return view('admin.databases.index', [ 'locations' => $this->locationRepository->getAllWithNodes(), 'hosts' => $this->repository->getWithViewDetails(), ]); @@ -53,7 +51,7 @@ public function index(): View */ public function view(int $host): View { - return $this->view->make('admin.databases.view', [ + return view('admin.databases.view', [ 'locations' => $this->locationRepository->getAllWithNodes(), 'host' => $this->repository->find($host), 'databases' => $this->databaseRepository->getDatabasesForHost($host), diff --git a/app/Http/Controllers/Admin/LocationController.php b/app/Http/Controllers/Admin/LocationController.php index ea01cbaa90..41ed581db7 100644 --- a/app/Http/Controllers/Admin/LocationController.php +++ b/app/Http/Controllers/Admin/LocationController.php @@ -35,7 +35,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.locations.index', [ + return view('admin.locations.index', [ 'locations' => $this->repository->getAllWithDetails(), ]); } @@ -47,7 +47,7 @@ public function index(): View */ public function view(int $id): View { - return $this->view->make('admin.locations.view', [ + return view('admin.locations.view', [ 'location' => $this->repository->getWithNodes($id), ]); } diff --git a/app/Http/Controllers/Admin/MountController.php b/app/Http/Controllers/Admin/MountController.php index 097ad6690b..8f4138989a 100644 --- a/app/Http/Controllers/Admin/MountController.php +++ b/app/Http/Controllers/Admin/MountController.php @@ -37,7 +37,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.mounts.index', [ + return view('admin.mounts.index', [ 'mounts' => $this->repository->getAllWithDetails(), ]); } @@ -52,7 +52,7 @@ public function view(string $id): View $nests = Nest::query()->with('eggs')->get(); $locations = Location::query()->with('nodes')->get(); - return $this->view->make('admin.mounts.view', [ + return view('admin.mounts.view', [ 'mount' => $this->repository->getWithRelations($id), 'nests' => $nests, 'locations' => $locations, diff --git a/app/Http/Controllers/Admin/Nests/EggController.php b/app/Http/Controllers/Admin/Nests/EggController.php index 010c28af00..1efccfd5d0 100644 --- a/app/Http/Controllers/Admin/Nests/EggController.php +++ b/app/Http/Controllers/Admin/Nests/EggController.php @@ -42,7 +42,7 @@ public function create(): View $nests = $this->nestRepository->getWithEggs(); JavaScript::put(['nests' => $nests->keyBy('id')]); - return $this->view->make('admin.eggs.new', ['nests' => $nests]); + return view('admin.eggs.new', ['nests' => $nests]); } /** @@ -67,7 +67,7 @@ public function store(EggFormRequest $request): RedirectResponse */ public function view(Egg $egg): View { - return $this->view->make('admin.eggs.view', [ + return view('admin.eggs.view', [ 'egg' => $egg, 'images' => array_map( fn ($key, $value) => $key === $value ? $value : "$key|$value", diff --git a/app/Http/Controllers/Admin/Nests/EggScriptController.php b/app/Http/Controllers/Admin/Nests/EggScriptController.php index 4f997e5a86..b68a211ac1 100644 --- a/app/Http/Controllers/Admin/Nests/EggScriptController.php +++ b/app/Http/Controllers/Admin/Nests/EggScriptController.php @@ -41,7 +41,7 @@ public function index(int $egg): View ['copy_script_from', '=', $egg->id], ]); - return $this->view->make('admin.eggs.scripts', [ + return view('admin.eggs.scripts', [ 'copyFromOptions' => $copy, 'relyOnScript' => $rely, 'egg' => $egg, diff --git a/app/Http/Controllers/Admin/Nests/EggVariableController.php b/app/Http/Controllers/Admin/Nests/EggVariableController.php index 40274b3239..c94a8dc284 100644 --- a/app/Http/Controllers/Admin/Nests/EggVariableController.php +++ b/app/Http/Controllers/Admin/Nests/EggVariableController.php @@ -39,7 +39,7 @@ public function view(int $egg): View { $egg = $this->repository->getWithVariables($egg); - return $this->view->make('admin.eggs.variables', ['egg' => $egg]); + return view('admin.eggs.variables', ['egg' => $egg]); } /** diff --git a/app/Http/Controllers/Admin/Nests/NestController.php b/app/Http/Controllers/Admin/Nests/NestController.php index 037dd09430..fb24f10693 100644 --- a/app/Http/Controllers/Admin/Nests/NestController.php +++ b/app/Http/Controllers/Admin/Nests/NestController.php @@ -35,7 +35,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.nests.index', [ + return view('admin.nests.index', [ 'nests' => $this->repository->getWithCounts(), ]); } @@ -45,7 +45,7 @@ public function index(): View */ public function create(): View { - return $this->view->make('admin.nests.new'); + return view('admin.nests.new'); } /** @@ -68,7 +68,7 @@ public function store(StoreNestFormRequest $request): RedirectResponse */ public function view(int $nest): View { - return $this->view->make('admin.nests.view', [ + return view('admin.nests.view', [ 'nest' => $this->repository->getWithEggServers($nest), ]); } diff --git a/app/Http/Controllers/Admin/Nodes/NodeController.php b/app/Http/Controllers/Admin/Nodes/NodeController.php index d80df6c80d..7936772406 100644 --- a/app/Http/Controllers/Admin/Nodes/NodeController.php +++ b/app/Http/Controllers/Admin/Nodes/NodeController.php @@ -7,17 +7,9 @@ use Pterodactyl\Models\Node; use Spatie\QueryBuilder\QueryBuilder; use Pterodactyl\Http\Controllers\Controller; -use Illuminate\Contracts\View\Factory as ViewFactory; class NodeController extends Controller { - /** - * NodeController constructor. - */ - public function __construct(private ViewFactory $view) - { - } - /** * Returns a listing of nodes on the system. */ @@ -30,6 +22,6 @@ public function index(Request $request): View ->allowedSorts(['id']) ->paginate(25); - return $this->view->make('admin.nodes.index', ['nodes' => $nodes]); + return view('admin.nodes.index', ['nodes' => $nodes]); } } diff --git a/app/Http/Controllers/Admin/Nodes/NodeViewController.php b/app/Http/Controllers/Admin/Nodes/NodeViewController.php index 6738903230..0ec60a7a03 100644 --- a/app/Http/Controllers/Admin/Nodes/NodeViewController.php +++ b/app/Http/Controllers/Admin/Nodes/NodeViewController.php @@ -8,13 +8,11 @@ use Illuminate\Support\Collection; use Pterodactyl\Models\Allocation; use Pterodactyl\Http\Controllers\Controller; -use Illuminate\Contracts\View\Factory as ViewFactory; use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Traits\Controllers\JavascriptInjection; use Pterodactyl\Services\Helpers\SoftwareVersionService; use Pterodactyl\Repositories\Eloquent\LocationRepository; -use Pterodactyl\Repositories\Eloquent\AllocationRepository; class NodeViewController extends Controller { @@ -24,12 +22,10 @@ class NodeViewController extends Controller * NodeViewController constructor. */ public function __construct( - private AllocationRepository $allocationRepository, private LocationRepository $locationRepository, private NodeRepository $repository, private ServerRepository $serverRepository, - private SoftwareVersionService $versionService, - private ViewFactory $view + private SoftwareVersionService $versionService ) { } @@ -40,7 +36,7 @@ public function index(Request $request, Node $node): View { $node = $this->repository->loadLocationAndServerCount($node); - return $this->view->make('admin.nodes.view.index', [ + return view('admin.nodes.view.index', [ 'node' => $node, 'stats' => $this->repository->getUsageStats($node), 'version' => $this->versionService, @@ -52,7 +48,7 @@ public function index(Request $request, Node $node): View */ public function settings(Request $request, Node $node): View { - return $this->view->make('admin.nodes.view.settings', [ + return view('admin.nodes.view.settings', [ 'node' => $node, 'locations' => $this->locationRepository->all(), ]); @@ -63,7 +59,7 @@ public function settings(Request $request, Node $node): View */ public function configuration(Request $request, Node $node): View { - return $this->view->make('admin.nodes.view.configuration', compact('node')); + return view('admin.nodes.view.configuration', compact('node')); } /** @@ -75,7 +71,7 @@ public function allocations(Request $request, Node $node): View $this->plainInject(['node' => Collection::wrap($node)->only(['id'])]); - return $this->view->make('admin.nodes.view.allocation', [ + return view('admin.nodes.view.allocation', [ 'node' => $node, 'allocations' => Allocation::query()->where('node_id', $node->id) ->groupBy('ip') @@ -94,7 +90,7 @@ public function servers(Request $request, Node $node): View ->only(['scheme', 'fqdn', 'daemonListen', 'daemon_token_id', 'daemon_token']), ]); - return $this->view->make('admin.nodes.view.servers', [ + return view('admin.nodes.view.servers', [ 'node' => $node, 'servers' => $this->serverRepository->loadAllServersForNode($node->id, 25), ]); diff --git a/app/Http/Controllers/Admin/NodesController.php b/app/Http/Controllers/Admin/NodesController.php index 573a1d9f8d..6d7cba7ffd 100644 --- a/app/Http/Controllers/Admin/NodesController.php +++ b/app/Http/Controllers/Admin/NodesController.php @@ -60,7 +60,7 @@ public function create(): View|RedirectResponse return redirect()->route('admin.locations'); } - return $this->view->make('admin.nodes.new', ['locations' => $locations]); + return view('admin.nodes.new', ['locations' => $locations]); } /** diff --git a/app/Http/Controllers/Admin/Servers/CreateServerController.php b/app/Http/Controllers/Admin/Servers/CreateServerController.php index c7a1653ad4..4ba37411bf 100644 --- a/app/Http/Controllers/Admin/Servers/CreateServerController.php +++ b/app/Http/Controllers/Admin/Servers/CreateServerController.php @@ -4,11 +4,11 @@ use JavaScript; use Illuminate\View\View; +use Pterodactyl\Models\Nest; use Pterodactyl\Models\Node; use Pterodactyl\Models\Location; use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Repositories\Eloquent\NestRepository; use Pterodactyl\Repositories\Eloquent\NodeRepository; @@ -24,8 +24,7 @@ public function __construct( private AlertsMessageBag $alert, private NestRepository $nestRepository, private NodeRepository $nodeRepository, - private ServerCreationService $creationService, - private ViewFactory $view + private ServerCreationService $creationService ) { } @@ -47,14 +46,14 @@ public function index(): View|RedirectResponse JavaScript::put([ 'nodeData' => $this->nodeRepository->getNodesForServerCreation(), - 'nests' => $nests->map(function ($item) { + 'nests' => $nests->map(function (Nest $item) { return array_merge($item->toArray(), [ 'eggs' => $item->eggs->keyBy('id')->toArray(), ]); })->keyBy('id'), ]); - return $this->view->make('admin.servers.new', [ + return view('admin.servers.new', [ 'locations' => Location::all(), 'nests' => $nests, ]); diff --git a/app/Http/Controllers/Admin/Servers/ServerController.php b/app/Http/Controllers/Admin/Servers/ServerController.php index 430c3f2b91..80de68ef93 100644 --- a/app/Http/Controllers/Admin/Servers/ServerController.php +++ b/app/Http/Controllers/Admin/Servers/ServerController.php @@ -9,17 +9,9 @@ use Spatie\QueryBuilder\AllowedFilter; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Models\Filters\AdminServerFilter; -use Illuminate\Contracts\View\Factory as ViewFactory; class ServerController extends Controller { - /** - * ServerController constructor. - */ - public function __construct(private ViewFactory $view) - { - } - /** * Returns all the servers that exist on the system using a paginated result set. If * a query is passed along in the request it is also passed to the repository function. @@ -33,6 +25,6 @@ public function index(Request $request): View ]) ->paginate(config()->get('pterodactyl.paginate.admin.servers')); - return $this->view->make('admin.servers.index', ['servers' => $servers]); + return view('admin.servers.index', ['servers' => $servers]); } } diff --git a/app/Http/Controllers/Admin/Servers/ServerTransferController.php b/app/Http/Controllers/Admin/Servers/ServerTransferController.php index 8941ce10c5..6d94963500 100644 --- a/app/Http/Controllers/Admin/Servers/ServerTransferController.php +++ b/app/Http/Controllers/Admin/Servers/ServerTransferController.php @@ -4,6 +4,7 @@ use Carbon\CarbonImmutable; use Illuminate\Http\Request; +use Pterodactyl\Models\Node; use Pterodactyl\Models\Server; use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; @@ -11,7 +12,6 @@ use Illuminate\Database\ConnectionInterface; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Nodes\NodeJWTService; -use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Wings\DaemonTransferRepository; use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; @@ -25,8 +25,7 @@ public function __construct( private AllocationRepositoryInterface $allocationRepository, private ConnectionInterface $connection, private DaemonTransferRepository $daemonTransferRepository, - private NodeJWTService $nodeJWTService, - private NodeRepository $nodeRepository + private NodeJWTService $nodeJWTService ) { } @@ -48,7 +47,7 @@ public function transfer(Request $request, Server $server): RedirectResponse $additional_allocations = array_map('intval', $validatedData['allocation_additional'] ?? []); // Check if the node is viable for the transfer. - $node = $this->nodeRepository->getNodeWithResourceUsage($node_id); + $node = Node::query()->findOrFail($node_id); if (!$node->isViable($server->memory, $server->disk)) { $this->alert->danger(trans('admin/server.alerts.transfer_not_viable'))->flash(); @@ -58,7 +57,6 @@ public function transfer(Request $request, Server $server): RedirectResponse $server->validateTransferState(); $this->connection->transaction(function () use ($server, $node_id, $allocation_id, $additional_allocations) { - // Create a new ServerTransfer entry. $transfer = new ServerTransfer(); $transfer->server_id = $server->id; @@ -66,7 +64,7 @@ public function transfer(Request $request, Server $server): RedirectResponse $transfer->new_node = $node_id; $transfer->old_allocation = $server->allocation_id; $transfer->new_allocation = $allocation_id; - $transfer->old_additional_allocations = $server->allocations->where('id', '!=', $server->allocation_id)->pluck('id'); + $transfer->old_additional_allocations = $server->allocations->where('id', '!=', $server->allocation_id)->pluck('id')->all(); $transfer->new_additional_allocations = $additional_allocations; $transfer->save(); diff --git a/app/Http/Controllers/Admin/Servers/ServerViewController.php b/app/Http/Controllers/Admin/Servers/ServerViewController.php index 7cf64a2f57..3e662d479d 100644 --- a/app/Http/Controllers/Admin/Servers/ServerViewController.php +++ b/app/Http/Controllers/Admin/Servers/ServerViewController.php @@ -10,11 +10,9 @@ use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Servers\EnvironmentService; -use Illuminate\Contracts\View\Factory as ViewFactory; use Pterodactyl\Repositories\Eloquent\NestRepository; use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Eloquent\MountRepository; -use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Traits\Controllers\JavascriptInjection; use Pterodactyl\Repositories\Eloquent\LocationRepository; use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository; @@ -32,9 +30,7 @@ public function __construct( private MountRepository $mountRepository, private NestRepository $nestRepository, private NodeRepository $nodeRepository, - private ServerRepository $repository, - private EnvironmentService $environmentService, - private ViewFactory $view + private EnvironmentService $environmentService ) { } @@ -43,7 +39,7 @@ public function __construct( */ public function index(Request $request, Server $server): View { - return $this->view->make('admin.servers.view.index', compact('server')); + return view('admin.servers.view.index', compact('server')); } /** @@ -51,7 +47,7 @@ public function index(Request $request, Server $server): View */ public function details(Request $request, Server $server): View { - return $this->view->make('admin.servers.view.details', compact('server')); + return view('admin.servers.view.details', compact('server')); } /** @@ -61,7 +57,7 @@ public function build(Request $request, Server $server): View { $allocations = $server->node->allocations->toBase(); - return $this->view->make('admin.servers.view.build', [ + return view('admin.servers.view.build', [ 'server' => $server, 'assigned' => $allocations->where('server_id', $server->id)->sortBy('port')->sortBy('ip'), 'unassigned' => $allocations->where('server_id', null)->sortBy('port')->sortBy('ip'), @@ -88,7 +84,7 @@ public function startup(Request $request, Server $server): View })->keyBy('id'), ]); - return $this->view->make('admin.servers.view.startup', compact('server', 'nests')); + return view('admin.servers.view.startup', compact('server', 'nests')); } /** @@ -96,7 +92,7 @@ public function startup(Request $request, Server $server): View */ public function database(Request $request, Server $server): View { - return $this->view->make('admin.servers.view.database', [ + return view('admin.servers.view.database', [ 'hosts' => $this->databaseHostRepository->all(), 'server' => $server, ]); @@ -109,7 +105,7 @@ public function mounts(Request $request, Server $server): View { $server->load('mounts'); - return $this->view->make('admin.servers.view.mounts', [ + return view('admin.servers.view.mounts', [ 'mounts' => $this->mountRepository->getMountListForServer($server), 'server' => $server, ]); @@ -138,7 +134,7 @@ public function manage(Request $request, Server $server): View 'nodeData' => $this->nodeRepository->getNodesForServerCreation(), ]); - return $this->view->make('admin.servers.view.manage', [ + return view('admin.servers.view.manage', [ 'server' => $server, 'locations' => $this->locationRepository->all(), 'canTransfer' => $canTransfer, @@ -150,6 +146,6 @@ public function manage(Request $request, Server $server): View */ public function delete(Request $request, Server $server): View { - return $this->view->make('admin.servers.view.delete', compact('server')); + return view('admin.servers.view.delete', compact('server')); } } diff --git a/app/Http/Controllers/Admin/Settings/AdvancedController.php b/app/Http/Controllers/Admin/Settings/AdvancedController.php index bf68832325..20f8f3c036 100644 --- a/app/Http/Controllers/Admin/Settings/AdvancedController.php +++ b/app/Http/Controllers/Admin/Settings/AdvancedController.php @@ -6,7 +6,6 @@ use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; use Illuminate\Contracts\Console\Kernel; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; @@ -21,8 +20,7 @@ public function __construct( private AlertsMessageBag $alert, private ConfigRepository $config, private Kernel $kernel, - private SettingsRepositoryInterface $settings, - private ViewFactory $view + private SettingsRepositoryInterface $settings ) { } @@ -39,7 +37,7 @@ public function index(): View $showRecaptchaWarning = true; } - return $this->view->make('admin.settings.advanced', [ + return view('admin.settings.advanced', [ 'showRecaptchaWarning' => $showRecaptchaWarning, ]); } diff --git a/app/Http/Controllers/Admin/Settings/IndexController.php b/app/Http/Controllers/Admin/Settings/IndexController.php index eabede932c..ca92e7d033 100644 --- a/app/Http/Controllers/Admin/Settings/IndexController.php +++ b/app/Http/Controllers/Admin/Settings/IndexController.php @@ -6,7 +6,6 @@ use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; use Illuminate\Contracts\Console\Kernel; -use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Traits\Helpers\AvailableLanguages; use Pterodactyl\Services\Helpers\SoftwareVersionService; @@ -24,8 +23,7 @@ public function __construct( private AlertsMessageBag $alert, private Kernel $kernel, private SettingsRepositoryInterface $settings, - private SoftwareVersionService $versionService, - private ViewFactory $view + private SoftwareVersionService $versionService ) { } @@ -34,7 +32,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.settings.index', [ + return view('admin.settings.index', [ 'version' => $this->versionService, 'languages' => $this->getAvailableLanguages(true), ]); diff --git a/app/Http/Controllers/Admin/Settings/MailController.php b/app/Http/Controllers/Admin/Settings/MailController.php index 2db87fd58f..8c9365641a 100644 --- a/app/Http/Controllers/Admin/Settings/MailController.php +++ b/app/Http/Controllers/Admin/Settings/MailController.php @@ -8,7 +8,6 @@ use Illuminate\Http\Response; use Illuminate\Contracts\Console\Kernel; use Pterodactyl\Notifications\MailTested; -use Illuminate\View\Factory as ViewFactory; use Illuminate\Support\Facades\Notification; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; @@ -27,8 +26,7 @@ public function __construct( private ConfigRepository $config, private Encrypter $encrypter, private Kernel $kernel, - private SettingsRepositoryInterface $settings, - private ViewFactory $view + private SettingsRepositoryInterface $settings ) { } @@ -38,7 +36,7 @@ public function __construct( */ public function index(): View { - return $this->view->make('admin.settings.mail', [ + return view('admin.settings.mail', [ 'disabled' => $this->config->get('mail.default') !== 'smtp', ]); } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 1d6db65691..ef22189d4a 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -6,13 +6,13 @@ use Illuminate\Http\Request; use Pterodactyl\Models\User; use Pterodactyl\Models\Model; -use Illuminate\Support\Collection; use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; use Spatie\QueryBuilder\QueryBuilder; use Illuminate\View\Factory as ViewFactory; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Contracts\Translation\Translator; use Pterodactyl\Services\Users\UserUpdateService; use Pterodactyl\Traits\Helpers\AvailableLanguages; @@ -57,7 +57,7 @@ public function index(Request $request): View ->allowedSorts(['id', 'uuid']) ->paginate(50); - return $this->view->make('admin.users.index', ['users' => $users]); + return view('admin.users.index', ['users' => $users]); } /** @@ -65,7 +65,7 @@ public function index(Request $request): View */ public function create(): View { - return $this->view->make('admin.users.new', [ + return view('admin.users.new', [ 'languages' => $this->getAvailableLanguages(true), ]); } @@ -75,7 +75,7 @@ public function create(): View */ public function view(User $user): View { - return $this->view->make('admin.users.view', [ + return view('admin.users.view', [ 'user' => $user, 'languages' => $this->getAvailableLanguages(true), ]); @@ -132,22 +132,13 @@ public function update(UserFormRequest $request, User $user): RedirectResponse /** * Get a JSON response of users on the system. */ - public function json(Request $request): Model|Collection + public function json(Request $request): Model|LengthAwarePaginator { - $users = QueryBuilder::for(User::query())->allowedFilters(['email'])->paginate(25); - // Handle single user requests. if ($request->query('user_id')) { - $user = User::query()->findOrFail($request->input('user_id')); - $user->md5 = md5(strtolower($user->email)); - - return $user; + return User::query()->findOrFail($request->input('user_id')); } - return $users->map(function ($item) { - $item->md5 = md5(strtolower($item->email)); - - return $item; - }); + return QueryBuilder::for(User::query())->allowedFilters(['email'])->paginate(25); } } diff --git a/app/Http/Controllers/Api/Client/Servers/StartupController.php b/app/Http/Controllers/Api/Client/Servers/StartupController.php index 9548be25e9..b674145ff2 100644 --- a/app/Http/Controllers/Api/Client/Servers/StartupController.php +++ b/app/Http/Controllers/Api/Client/Servers/StartupController.php @@ -52,7 +52,6 @@ public function index(GetStartupRequest $request, Server $server): array */ public function update(UpdateStartupVariableRequest $request, Server $server): array { - /** @var \Pterodactyl\Models\EggVariable $variable */ $variable = $server->variables()->where('env_variable', $request->input('key'))->first(); $original = $variable->server_value; @@ -62,6 +61,8 @@ public function update(UpdateStartupVariableRequest $request, Server $server): a throw new BadRequestHttpException('The environment variable you are trying to edit is read-only.'); } + /* @var \Pterodactyl\Models\EggVariable $variable */ + // Revalidate the variable value using the egg variable specific validation rules for it. $this->validate($request, ['value' => $variable->rules]); diff --git a/app/Http/Controllers/Api/Remote/Servers/ServerDetailsController.php b/app/Http/Controllers/Api/Remote/Servers/ServerDetailsController.php index 8ce88e89ee..8d8b0de92a 100644 --- a/app/Http/Controllers/Api/Remote/Servers/ServerDetailsController.php +++ b/app/Http/Controllers/Api/Remote/Servers/ServerDetailsController.php @@ -3,6 +3,7 @@ namespace Pterodactyl\Http\Controllers\Api\Remote\Servers; use Illuminate\Http\Request; +use Pterodactyl\Models\Backup; use Pterodactyl\Models\Server; use Illuminate\Http\JsonResponse; use Pterodactyl\Facades\Activity; @@ -98,9 +99,11 @@ public function resetState(Request $request): JsonResponse if ($subject = $activity->subjects->where('subject_type', 'backup')->first()) { // Just create a new audit entry for this event and update the server state // so that power actions, file management, and backups can resume as normal. + /** @var Backup $actualSubject */ + $actualSubject = $subject->subject; Activity::event('server:backup.restore-failed') - ->subject($server, $subject->subject) - ->property('name', $subject->subject->name) + ->subject($server, $actualSubject) + ->property('name', $actualSubject->name) ->log(); } } diff --git a/app/Http/Controllers/Auth/AbstractLoginController.php b/app/Http/Controllers/Auth/AbstractLoginController.php index f07282fbac..74e7a9aa3a 100644 --- a/app/Http/Controllers/Auth/AbstractLoginController.php +++ b/app/Http/Controllers/Auth/AbstractLoginController.php @@ -49,7 +49,9 @@ public function __construct() /** * Get the failed login response instance. * - * @throws \Pterodactyl\Exceptions\DisplayException + * @return never + * + * @throws DisplayException */ protected function sendFailedLoginResponse(Request $request, Authenticatable $user = null, string $message = null) { diff --git a/app/Http/Controllers/Auth/LoginCheckpointController.php b/app/Http/Controllers/Auth/LoginCheckpointController.php index af05c55ef7..82580edc0b 100644 --- a/app/Http/Controllers/Auth/LoginCheckpointController.php +++ b/app/Http/Controllers/Auth/LoginCheckpointController.php @@ -72,7 +72,7 @@ public function __invoke(LoginCheckpointRequest $request): JsonResponse } else { $decrypted = $this->encrypter->decrypt($user->totp_secret); - if ($this->google2FA->verifyKey($decrypted, (string) $request->input('authentication_code') ?? '', config('pterodactyl.auth.2fa.window'))) { + if ($this->google2FA->verifyKey($decrypted, $request->input('authentication_code') ?? '', config('pterodactyl.auth.2fa.window'))) { Event::dispatch(new ProvidedAuthenticationToken($user)); return $this->sendLoginResponse($user, $request); diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 2dbb34ee36..49a17378da 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -9,19 +9,10 @@ use Illuminate\Http\JsonResponse; use Pterodactyl\Facades\Activity; use Illuminate\Contracts\View\View; -use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Database\Eloquent\ModelNotFoundException; class LoginController extends AbstractLoginController { - /** - * LoginController constructor. - */ - public function __construct(private ViewFactory $view) - { - parent::__construct(); - } - /** * Handle all incoming requests for the authentication routes and render the * base authentication view component. React will take over at this point and @@ -29,7 +20,7 @@ public function __construct(private ViewFactory $view) */ public function index(): View { - return $this->view->make('templates/auth.core'); + return view('templates/auth.core'); } /** diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 3325a1e6b3..9b22f6f988 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -3,6 +3,7 @@ namespace Pterodactyl\Http\Controllers\Auth; use Illuminate\Support\Str; +use Pterodactyl\Models\User; use Illuminate\Http\JsonResponse; use Illuminate\Contracts\Hashing\Hasher; use Illuminate\Support\Facades\Password; @@ -67,13 +68,12 @@ function ($user, $password) { * account do not automatically log them in. In those cases, send the user back to the login * form with a note telling them their password was changed and to log back in. * - * @param \Illuminate\Contracts\Auth\CanResetPassword|\Pterodactyl\Models\User $user * @param string $password * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - protected function resetPassword($user, $password) + protected function resetPassword(User $user, $password) { $user = $this->userRepository->update($user->id, [ 'password' => $this->hasher->make($password), diff --git a/app/Http/Controllers/Base/IndexController.php b/app/Http/Controllers/Base/IndexController.php index fecaa91a3e..ffa278b63b 100644 --- a/app/Http/Controllers/Base/IndexController.php +++ b/app/Http/Controllers/Base/IndexController.php @@ -23,6 +23,6 @@ public function __construct( */ public function index(): View { - return $this->view->make('templates/base.core'); + return view('templates/base.core'); } } diff --git a/app/Http/Middleware/Api/Client/Server/ResourceBelongsToServer.php b/app/Http/Middleware/Api/Client/Server/ResourceBelongsToServer.php index 5d3530d865..337f4af713 100644 --- a/app/Http/Middleware/Api/Client/Server/ResourceBelongsToServer.php +++ b/app/Http/Middleware/Api/Client/Server/ResourceBelongsToServer.php @@ -29,11 +29,11 @@ class ResourceBelongsToServer public function handle(Request $request, Closure $next): mixed { $params = $request->route()->parameters(); - if (is_null($params) || !$params['server'] instanceof Server) { + if (!$params['server'] instanceof Server) { throw new InvalidArgumentException('This middleware cannot be used in a context that is missing a server in the parameters.'); } - /** @var \Pterodactyl\Models\Server $server */ + /** @var Server $server */ $server = $request->route()->parameter('server'); $exception = new NotFoundHttpException('The requested resource was not found for this server.'); foreach ($params as $key => $model) { @@ -45,6 +45,7 @@ public function handle(Request $request, Closure $next): mixed continue; } + /** @var Allocation|Backup|Database|Schedule|Subuser $model */ switch (get_class($model)) { // All of these models use "server_id" as the field key for the server // they are assigned to, so the logic is identical for them all. @@ -71,6 +72,7 @@ public function handle(Request $request, Closure $next): mixed // Tasks are special since they're (currently) the only item in the API // that requires something in addition to the server in order to be accessed. case Task::class: + /** @var Schedule $schedule */ $schedule = $request->route()->parameter('schedule'); if ($model->schedule_id !== $schedule->id || $schedule->server_id !== $server->id) { throw $exception; diff --git a/app/Http/Middleware/RequireTwoFactorAuthentication.php b/app/Http/Middleware/RequireTwoFactorAuthentication.php index e3307727f2..cffcc50116 100644 --- a/app/Http/Middleware/RequireTwoFactorAuthentication.php +++ b/app/Http/Middleware/RequireTwoFactorAuthentication.php @@ -5,6 +5,7 @@ use Closure; use Illuminate\Support\Str; use Illuminate\Http\Request; +use Pterodactyl\Models\User; use Prologue\Alerts\AlertsMessageBag; use Pterodactyl\Exceptions\Http\TwoFactorAuthRequiredException; @@ -36,12 +37,17 @@ public function __construct(private AlertsMessageBag $alert) */ public function handle(Request $request, Closure $next): mixed { - /** @var \Pterodactyl\Models\User $user */ + /** @var User $user */ $user = $request->user(); $uri = rtrim($request->getRequestUri(), '/') . '/'; $current = $request->route()->getName(); - if (!$user || Str::startsWith($uri, ['/auth/']) || Str::startsWith($current, ['auth.', 'account.'])) { + // Must be logged in + if (!$user instanceof User) { + return $next($request); + } + + if (Str::startsWith($uri, ['/auth/']) || Str::startsWith($current, ['auth.', 'account.'])) { return $next($request); } diff --git a/app/Http/Requests/Admin/LocationFormRequest.php b/app/Http/Requests/Admin/LocationFormRequest.php index b10e304a07..57fa0310b8 100644 --- a/app/Http/Requests/Admin/LocationFormRequest.php +++ b/app/Http/Requests/Admin/LocationFormRequest.php @@ -12,7 +12,10 @@ class LocationFormRequest extends AdminFormRequest public function rules(): array { if ($this->method() === 'PATCH') { - return Location::getRulesForUpdate($this->route()->parameter('location')->id); + /** @var Location $location */ + $location = $this->route()->parameter('location'); + + return Location::getRulesForUpdate($location->id); } return Location::getRules(); diff --git a/app/Http/Requests/Admin/MountFormRequest.php b/app/Http/Requests/Admin/MountFormRequest.php index 074ea4a503..22b2475f4c 100644 --- a/app/Http/Requests/Admin/MountFormRequest.php +++ b/app/Http/Requests/Admin/MountFormRequest.php @@ -12,7 +12,10 @@ class MountFormRequest extends AdminFormRequest public function rules(): array { if ($this->method() === 'PATCH') { - return Mount::getRulesForUpdate($this->route()->parameter('mount')->id); + /** @var Mount $mount */ + $mount = $this->route()->parameter('mount'); + + return Mount::getRulesForUpdate($mount->id); } return Mount::getRules(); diff --git a/app/Http/Requests/Api/Application/ApplicationApiRequest.php b/app/Http/Requests/Api/Application/ApplicationApiRequest.php index 2e0ed133a5..082bc6921f 100644 --- a/app/Http/Requests/Api/Application/ApplicationApiRequest.php +++ b/app/Http/Requests/Api/Application/ApplicationApiRequest.php @@ -29,7 +29,7 @@ abstract class ApplicationApiRequest extends FormRequest * Determine if the current user is authorized to perform * the requested action against the API. * - * @throws \Pterodactyl\Exceptions\PterodactylException + * @throws PterodactylException */ public function authorize(): bool { @@ -42,6 +42,7 @@ public function authorize(): bool return true; } + /** @var ApiKey $token */ if ($token->key_type === ApiKey::TYPE_ACCOUNT) { return true; } @@ -81,6 +82,7 @@ public function withValidator(Validator $validator): void */ public function parameter(string $key, string $expect) { + /** @var ApiKey $value */ $value = $this->route()->parameter($key); Assert::isInstanceOf($value, $expect); diff --git a/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php b/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php index ce42e6f051..b7acac9781 100644 --- a/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php +++ b/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php @@ -11,7 +11,9 @@ class UpdateLocationRequest extends StoreLocationRequest */ public function rules(): array { - $locationId = $this->route()->parameter('location')->id; + /** @var Location $location */ + $location = $this->route()->parameter('location'); + $locationId = $location->id; return collect(Location::getRulesForUpdate($locationId))->only([ 'short', diff --git a/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php index 7133bd0b52..de6b7b45c9 100644 --- a/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php +++ b/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php @@ -12,8 +12,9 @@ class UpdateNodeRequest extends StoreNodeRequest */ public function rules(array $rules = null): array { - $node = $this->route()->parameter('node')->id; + /** @var Node $node */ + $node = $this->route()->parameter('node'); - return parent::rules(Node::getRulesForUpdate($node)); + return parent::rules(Node::getRulesForUpdate($node->id)); } } diff --git a/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php b/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php index d53a0a75ef..f52bed805d 100644 --- a/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php +++ b/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php @@ -21,6 +21,7 @@ class StoreServerDatabaseRequest extends ApplicationApiRequest */ public function rules(): array { + /** @var Server $server */ $server = $this->route()->parameter('server'); return [ @@ -67,6 +68,7 @@ public function attributes(): array */ public function databaseName(): string { + /** @var Server $server */ $server = $this->route()->parameter('server'); Assert::isInstanceOf($server, Server::class); diff --git a/app/Http/Requests/Api/Client/Servers/Databases/StoreDatabaseRequest.php b/app/Http/Requests/Api/Client/Servers/Databases/StoreDatabaseRequest.php index be4f4a719d..41569cfabf 100644 --- a/app/Http/Requests/Api/Client/Servers/Databases/StoreDatabaseRequest.php +++ b/app/Http/Requests/Api/Client/Servers/Databases/StoreDatabaseRequest.php @@ -21,6 +21,7 @@ public function permission(): string public function rules(): array { + /** @var Server $server */ $server = $this->route()->parameter('server'); Assert::isInstanceOf($server, Server::class); diff --git a/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php b/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php index 7c4fab9d22..1381e5cb92 100644 --- a/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php +++ b/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php @@ -63,7 +63,6 @@ protected function validatePermissionsCanBeAssigned(array $permissions) // Otherwise, get the current subuser's permission set, and ensure that the // permissions they are trying to assign are not _more_ than the ones they // already have. - /** @var \Pterodactyl\Models\Subuser|null $subuser */ /** @var \Pterodactyl\Services\Servers\GetUserPermissionsService $service */ $service = $this->container->make(GetUserPermissionsService::class); diff --git a/app/Models/Egg.php b/app/Models/Egg.php index 31c3e34200..c33e5b194c 100644 --- a/app/Models/Egg.php +++ b/app/Models/Egg.php @@ -26,9 +26,9 @@ * @property string|null $startup * @property bool $script_is_privileged * @property string|null $script_install - * @property string $script_entry - * @property string $script_container - * @property int|null $copy_script_from + * @property ?string $script_entry + * @property ?string $script_container + * @property ?int $copy_script_from * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at * @property string|null $copy_script_install diff --git a/app/Models/EggVariable.php b/app/Models/EggVariable.php index 8c34bb3980..dbbf8e0bd0 100644 --- a/app/Models/EggVariable.php +++ b/app/Models/EggVariable.php @@ -18,8 +18,9 @@ * @property \Carbon\CarbonImmutable $created_at * @property \Carbon\CarbonImmutable $updated_at * @property bool $required - * @property \Pterodactyl\Models\Egg $egg - * @property \Pterodactyl\Models\ServerVariable $serverVariable + * @property Egg $egg + * @property ServerVariable $serverVariable + * @property string $field_type * * The "server_value" variable is only present on the object if you've loaded this model * using the server relationship. diff --git a/app/Models/Model.php b/app/Models/Model.php index 2e371d9d9c..34b856c385 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -155,6 +155,7 @@ public function validate(): void return; } + /** @var \Illuminate\Validation\Validator $validator */ $validator = $this->getValidator(); $validator->setData( // Trying to do self::toArray() here will leave out keys based on the whitelist/blacklist diff --git a/app/Models/Node.php b/app/Models/Node.php index 504a28c248..a1d9688f67 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -6,6 +6,7 @@ use Symfony\Component\Yaml\Yaml; use Illuminate\Container\Container; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -24,20 +25,24 @@ * @property bool $maintenance_mode * @property int $memory * @property int $memory_overallocate + * @property int $sum_memory * @property int $disk * @property int $disk_overallocate + * @property int $sum_disk * @property int $upload_size * @property string $daemon_token_id * @property string $daemon_token * @property int $daemonListen * @property int $daemonSFTP * @property string $daemonBase + * @property int $servers_count * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at - * @property \Pterodactyl\Models\Location $location - * @property \Pterodactyl\Models\Mount[]|\Illuminate\Database\Eloquent\Collection $mounts - * @property \Pterodactyl\Models\Server[]|\Illuminate\Database\Eloquent\Collection $servers - * @property \Pterodactyl\Models\Allocation[]|\Illuminate\Database\Eloquent\Collection $allocations + * @property Location $location + * @property int[]|\Illuminate\Support\Collection $ports + * @property Mount[]|Collection $mounts + * @property Server[]|Collection $servers + * @property Allocation[]|Collection $allocations */ class Node extends Model { @@ -220,11 +225,21 @@ public function allocations(): HasMany return $this->hasMany(Allocation::class); } + public function loadServerSums(): self + { + $this->loadSum('servers as sum_memory', 'memory'); + $this->loadSum('servers as sum_disk', 'disk'); + + return $this; + } + /** * Returns a boolean if the node is viable for an additional server to be placed on it. */ - public function isViable(int $memory, int $disk): bool + public function isViable(int $memory = 0, int $disk = 0): bool { + $this->loadServerSums(); + $memoryLimit = $this->memory * (1.0 + ($this->memory_overallocate / 100.0)); $diskLimit = $this->disk * (1.0 + ($this->disk_overallocate / 100.0)); diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 52c7f1cffb..ec85a2ecf6 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -2,6 +2,7 @@ namespace Pterodactyl\Models; +/** @property string $value */ class Setting extends Model { /** diff --git a/app/Models/User.php b/app/Models/User.php index eb3c15d220..bef6da7817 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Builder; use Pterodactyl\Models\Traits\HasAccessTokens; use Illuminate\Auth\Passwords\CanResetPassword; +use Illuminate\Database\Eloquent\Casts\Attribute; use Pterodactyl\Traits\Helpers\AvailableLanguages; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\Access\Authorizable; @@ -129,6 +130,10 @@ class User extends Model implements 'root_admin', ]; + protected $appends = [ + 'md5', + ]; + /** * Cast values to correct type. */ @@ -259,6 +264,13 @@ public function activity(): MorphToMany return $this->morphToMany(ActivityLog::class, 'subject', 'activity_log_subjects'); } + public function md5(): Attribute + { + return Attribute::make( + get: fn () => md5(strtolower($this->email)), + ); + } + /** * Returns all the servers that a user can access by way of being the owner of the * server, or because they are assigned as a subuser for that server. diff --git a/app/Notifications/ServerInstalled.php b/app/Notifications/ServerInstalled.php index 46f38ff84e..3eb93e79db 100644 --- a/app/Notifications/ServerInstalled.php +++ b/app/Notifications/ServerInstalled.php @@ -26,12 +26,14 @@ class ServerInstalled extends Notification implements ShouldQueue, ReceivesEvent * Handle a direct call to this notification from the server installed event. This is configured * in the event service provider. */ - public function handle(Event|Installed $event): void + public function handle(Event|Installed $notification): void { - $event->server->loadMissing('user'); + abort_unless($notification instanceof Installed, 500); + /* @var Installed $notification */ + $notification->server->loadMissing('user'); - $this->server = $event->server; - $this->user = $event->server->user; + $this->server = $notification->server; + $this->user = $notification->server->user; // Since we are calling this notification directly from an event listener we need to fire off the dispatcher // to send the email now. Don't use send() or you'll end up firing off two different events. diff --git a/app/Repositories/Eloquent/EloquentRepository.php b/app/Repositories/Eloquent/EloquentRepository.php index a78295be46..ea636ce9ce 100644 --- a/app/Repositories/Eloquent/EloquentRepository.php +++ b/app/Repositories/Eloquent/EloquentRepository.php @@ -78,6 +78,7 @@ public function getBuilder(): Builder */ public function create(array $fields, bool $validate = true, bool $force = false): Model|bool { + /** @var \Pterodactyl\Models\Model $instance */ $instance = $this->getBuilder()->newModelInstance(); ($force) ? $instance->forceFill($fields) : $instance->fill($fields); @@ -163,6 +164,7 @@ public function deleteWhere(array $attributes, bool $force = false): int public function update(int $id, array $fields, bool $validate = true, bool $force = false): Model|bool { try { + /** @var \Pterodactyl\Models\Model $instance */ $instance = $this->getBuilder()->where('id', $id)->firstOrFail(); } catch (ModelNotFoundException) { throw new RecordNotFoundException(); diff --git a/app/Repositories/Eloquent/NodeRepository.php b/app/Repositories/Eloquent/NodeRepository.php index d7a3818f3d..0ee703a795 100644 --- a/app/Repositories/Eloquent/NodeRepository.php +++ b/app/Repositories/Eloquent/NodeRepository.php @@ -21,11 +21,7 @@ public function model(): string */ public function getUsageStats(Node $node): array { - $stats = $this->getBuilder() - ->selectRaw('COALESCE(SUM(servers.memory), 0) as sum_memory, COALESCE(SUM(servers.disk), 0) as sum_disk') - ->join('servers', 'servers.node_id', '=', 'nodes.id') - ->where('node_id', '=', $node->id) - ->first(); + $stats = $node->loadServerSums(); return Collection::make(['disk' => $stats->sum_disk, 'memory' => $stats->sum_memory]) ->mapWithKeys(function ($value, $key) use ($node) { @@ -53,9 +49,7 @@ public function getUsageStats(Node $node): array */ public function getUsageStatsRaw(Node $node): array { - $stats = $this->getBuilder()->select( - $this->getBuilder()->raw('COALESCE(SUM(servers.memory), 0) as sum_memory, COALESCE(SUM(servers.disk), 0) as sum_disk') - )->join('servers', 'servers.node_id', '=', 'nodes.id')->where('node_id', $node->id)->first(); + $stats = $node->loadServerSums(); return collect(['disk' => $stats->sum_disk, 'memory' => $stats->sum_memory])->mapWithKeys(function ($value, $key) use ($node) { $maxUsage = $node->{$key}; @@ -84,9 +78,7 @@ public function loadLocationAndServerCount(Node $node, bool $refresh = false): N // This is quite ugly and can probably be improved down the road. // And by probably, I mean it should. if (is_null($node->servers_count) || $refresh) { - $node->load('servers'); - $node->setRelation('servers_count', count($node->getRelation('servers'))); - unset($node->servers); + $node->loadCount('servers'); } return $node; @@ -135,18 +127,4 @@ public function getNodesForServerCreation(): Collection ]; })->values(); } - - /** - * Returns a node with the given id with the Node's resource usage. - */ - public function getNodeWithResourceUsage(int $node_id): Node - { - $instance = $this->getBuilder() - ->select(['nodes.id', 'nodes.fqdn', 'nodes.scheme', 'nodes.daemon_token', 'nodes.daemonListen', 'nodes.memory', 'nodes.disk', 'nodes.memory_overallocate', 'nodes.disk_overallocate']) - ->selectRaw('COALESCE(SUM(servers.memory), 0) as sum_memory, COALESCE(SUM(servers.disk), 0) as sum_disk') - ->leftJoin('servers', 'servers.node_id', '=', 'nodes.id') - ->where('nodes.id', $node_id); - - return $instance->first(); - } } diff --git a/app/Repositories/Eloquent/SettingsRepository.php b/app/Repositories/Eloquent/SettingsRepository.php index df22fce595..e8003129a1 100644 --- a/app/Repositories/Eloquent/SettingsRepository.php +++ b/app/Repositories/Eloquent/SettingsRepository.php @@ -46,6 +46,7 @@ public function get(string $key, mixed $default = null): mixed return value($default); } + /** @var Setting $instance */ $instance = $this->getBuilder()->where('key', $key)->first(); if (is_null($instance)) { self::$databaseMiss[$key] = true; diff --git a/app/Rules/Fqdn.php b/app/Rules/Fqdn.php index 47baf510d7..915ca40158 100644 --- a/app/Rules/Fqdn.php +++ b/app/Rules/Fqdn.php @@ -6,11 +6,11 @@ use Illuminate\Contracts\Validation\Rule; use Illuminate\Contracts\Validation\DataAwareRule; -class Fqdn implements Rule, DataAwareRule +final class Fqdn implements Rule, DataAwareRule { - protected array $data = []; - protected string $message = ''; - protected ?string $schemeField = null; + private array $data = []; + private string $message = ''; + private ?string $schemeField = null; /** * @param array $data diff --git a/app/Services/Allocations/AssignmentService.php b/app/Services/Allocations/AssignmentService.php index ec79d18f18..11d3013224 100644 --- a/app/Services/Allocations/AssignmentService.php +++ b/app/Services/Allocations/AssignmentService.php @@ -40,23 +40,24 @@ public function __construct(protected AllocationRepositoryInterface $repository, */ public function handle(Node $node, array $data): void { - $explode = explode('/', $data['allocation_ip']); + $allocationIp = $data['allocation_ip']; + $explode = explode('/', $allocationIp); if (count($explode) !== 1) { if (!ctype_digit($explode[1]) || ($explode[1] > self::CIDR_MIN_BITS || $explode[1] < self::CIDR_MAX_BITS)) { throw new CidrOutOfRangeException(); } } + $underlying = 'Unknown IP'; try { // TODO: how should we approach supporting IPv6 with this? // gethostbyname only supports IPv4, but the alternative (dns_get_record) returns // an array of records, which is not ideal for this use case, we need a SINGLE // IP to use, not multiple. - $underlying = gethostbyname($data['allocation_ip']); + $underlying = gethostbyname($allocationIp); $parsed = Network::parse($underlying); } catch (Exception $exception) { - /* @noinspection PhpUndefinedVariableInspection */ - throw new DisplayException("Could not parse provided allocation IP address ({$underlying}): {$exception->getMessage()}", $exception); + throw new DisplayException("Could not parse provided allocation IP address for $allocationIp ($underlying): {$exception->getMessage()}", $exception); } $this->connection->beginTransaction(); diff --git a/app/Services/Backups/DeleteBackupService.php b/app/Services/Backups/DeleteBackupService.php index fd65969c17..bbb54ce6a9 100644 --- a/app/Services/Backups/DeleteBackupService.php +++ b/app/Services/Backups/DeleteBackupService.php @@ -73,7 +73,10 @@ protected function deleteFromS3(Backup $backup): void /** @var \Pterodactyl\Extensions\Filesystem\S3Filesystem $adapter */ $adapter = $this->manager->adapter(Backup::ADAPTER_AWS_S3); - $adapter->getClient()->deleteObject([ + /** @var \Aws\S3\S3Client $client */ + $client = $adapter->getClient(); + + $client->deleteObject([ 'Bucket' => $adapter->getBucket(), 'Key' => sprintf('%s/%s.tar.gz', $backup->server->uuid, $backup->uuid), ]); diff --git a/app/Services/Backups/InitiateBackupService.php b/app/Services/Backups/InitiateBackupService.php index be8f966326..f142754031 100644 --- a/app/Services/Backups/InitiateBackupService.php +++ b/app/Services/Backups/InitiateBackupService.php @@ -98,17 +98,17 @@ public function handle(Server $server, string $name = null, bool $override = fal // Get the oldest backup the server has that is not "locked" (indicating a backup that should // never be automatically purged). If we find a backup we will delete it and then continue with // this process. If no backup is found that can be used an exception is thrown. - /** @var \Pterodactyl\Models\Backup $oldest */ $oldest = $successful->where('is_locked', false)->orderBy('created_at')->first(); if (!$oldest) { throw new TooManyBackupsException($server->backup_limit); } + /* @var Backup $oldest */ $this->deleteBackupService->handle($oldest); } return $this->connection->transaction(function () use ($server, $name) { - /** @var \Pterodactyl\Models\Backup $backup */ + /** @var Backup $backup */ $backup = $this->repository->create([ 'server_id' => $server->id, 'uuid' => Uuid::uuid4()->toString(), diff --git a/app/Services/Databases/DatabaseManagementService.php b/app/Services/Databases/DatabaseManagementService.php index b70cb8b4dc..0635c1c70c 100644 --- a/app/Services/Databases/DatabaseManagementService.php +++ b/app/Services/Databases/DatabaseManagementService.php @@ -119,6 +119,7 @@ public function create(Server $server, array $data): Database }); } catch (Exception $exception) { try { + /** @var ?Database $database */ if ($database instanceof Database) { $this->repository->dropDatabase($database->database); $this->repository->dropUser($database->username, $database->remote); diff --git a/app/Services/Deployment/FindViableNodesService.php b/app/Services/Deployment/FindViableNodesService.php index a95211c3f9..bd2acfdd24 100644 --- a/app/Services/Deployment/FindViableNodesService.php +++ b/app/Services/Deployment/FindViableNodesService.php @@ -78,7 +78,7 @@ public function handle(int $perPage = null, int $page = null): LengthAwarePagina ->where('nodes.public', 1); if (!empty($this->locations)) { - $query = $query->whereIn('nodes.location_id', $this->locations); + $query = $query->whereIn('location_id', $this->locations); } $results = $query->groupBy('nodes.id') diff --git a/app/Services/Schedules/ProcessScheduleService.php b/app/Services/Schedules/ProcessScheduleService.php index cfbc7e5cad..d1b5811a88 100644 --- a/app/Services/Schedules/ProcessScheduleService.php +++ b/app/Services/Schedules/ProcessScheduleService.php @@ -27,13 +27,13 @@ public function __construct(private ConnectionInterface $connection, private Dis */ public function handle(Schedule $schedule, bool $now = false): void { - /** @var \Pterodactyl\Models\Task $task */ $task = $schedule->tasks()->orderBy('sequence_id')->first(); if (is_null($task)) { throw new DisplayException('Cannot process schedule for task execution: no tasks are registered.'); } + /* @var \Pterodactyl\Models\Task $task */ $this->connection->transaction(function () use ($schedule, $task) { $schedule->forceFill([ 'is_processing' => true, diff --git a/app/Services/Servers/BuildModificationService.php b/app/Services/Servers/BuildModificationService.php index 05553d7f10..b7a22fdaae 100644 --- a/app/Services/Servers/BuildModificationService.php +++ b/app/Services/Servers/BuildModificationService.php @@ -88,14 +88,13 @@ private function processAllocations(Server $server, array &$data): void // Handle the addition of allocations to this server. Only assign allocations that are not currently // assigned to a different server, and only allocations on the same node as the server. if (!empty($data['add_allocations'])) { - $query = Allocation::query() - ->where('node_id', $server->node_id) + $query = $server->node->allocations() ->whereIn('id', $data['add_allocations']) ->whereNull('server_id'); // Keep track of all the allocations we're just now adding so that we can use the first // one to reset the default allocation to. - $freshlyAllocated = $query->pluck('id')->first(); + $freshlyAllocated = $query->first()->id ?? null; $query->update(['server_id' => $server->id, 'notes' => null]); } diff --git a/app/Services/Servers/ServerCreationService.php b/app/Services/Servers/ServerCreationService.php index 2c9b4cf844..62e848aa0a 100644 --- a/app/Services/Servers/ServerCreationService.php +++ b/app/Services/Servers/ServerCreationService.php @@ -82,7 +82,7 @@ public function handle(array $data, DeploymentObject $deployment = null): Server // // If that connection fails out we will attempt to perform a cleanup by just // deleting the server itself from the system. - /** @var \Pterodactyl\Models\Server $server */ + /** @var Server $server */ $server = $this->connection->transaction(function () use ($data, $eggVariableData) { // Create the server and assign any additional allocations to it. $server = $this->createModel($data); @@ -115,7 +115,7 @@ public function handle(array $data, DeploymentObject $deployment = null): Server */ private function configureDeployment(array $data, DeploymentObject $deployment): Allocation { - /** @var \Illuminate\Support\Collection $nodes */ + /** @var Collection $nodes */ $nodes = $this->findViableNodesService->setLocations($deployment->getLocations()) ->setDisk(Arr::get($data, 'disk')) ->setMemory(Arr::get($data, 'memory')) @@ -136,7 +136,7 @@ private function createModel(array $data): Server { $uuid = $this->generateUniqueUuidCombo(); - /** @var \Pterodactyl\Models\Server $model */ + /** @var Server $model */ $model = $this->repository->create([ 'external_id' => Arr::get($data, 'external_id'), 'uuid' => $uuid, diff --git a/app/Services/Users/UserDeletionService.php b/app/Services/Users/UserDeletionService.php index f7f060cee4..0f373240f9 100644 --- a/app/Services/Users/UserDeletionService.php +++ b/app/Services/Users/UserDeletionService.php @@ -25,7 +25,7 @@ public function __construct( * * @throws \Pterodactyl\Exceptions\DisplayException */ - public function handle(int|User $user): ?bool + public function handle(int|User $user): void { if ($user instanceof User) { $user = $user->id; @@ -36,6 +36,6 @@ public function handle(int|User $user): ?bool throw new DisplayException($this->translator->get('admin/user.exceptions.user_has_servers')); } - return $this->repository->delete($user); + $this->repository->delete($user); } } diff --git a/app/Transformers/Api/Application/ServerVariableTransformer.php b/app/Transformers/Api/Application/ServerVariableTransformer.php index 25e8f879bd..e27d1e0135 100644 --- a/app/Transformers/Api/Application/ServerVariableTransformer.php +++ b/app/Transformers/Api/Application/ServerVariableTransformer.php @@ -4,6 +4,7 @@ use League\Fractal\Resource\Item; use Pterodactyl\Models\EggVariable; +use Pterodactyl\Models\ServerVariable; use League\Fractal\Resource\NullResource; use Pterodactyl\Services\Acl\Api\AdminAcl; diff --git a/composer.json b/composer.json index 160537b6bb..a03a9dcfc1 100644 --- a/composer.json +++ b/composer.json @@ -61,6 +61,7 @@ "laravel/sail": "~1.16", "mockery/mockery": "~1.5", "nunomaduro/collision": "~6.3", + "nunomaduro/larastan": "^2.0", "php-mock/php-mock-phpunit": "~2.6", "phpunit/phpunit": "~9.5", "spatie/laravel-ignition": "~1.5" diff --git a/composer.lock b/composer.lock index 9f4b73f6f9..381b321ae5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ae61e7d6e405e3a59c8a54f3eefa2c50", + "content-hash": "88999658a97429a6840f4da57ea115b1", "packages": [ { "name": "aws/aws-crt-php", @@ -9004,6 +9004,103 @@ ], "time": "2022-09-29T12:29:49+00:00" }, + { + "name": "nunomaduro/larastan", + "version": "2.2.7", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/larastan.git", + "reference": "a3f67a4a668e477751557b0b19ad2c870e1e4e56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/larastan/zipball/a3f67a4a668e477751557b0b19ad2c870e1e4e56", + "reference": "a3f67a4a668e477751557b0b19ad2c870e1e4e56", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9", + "illuminate/container": "^9", + "illuminate/contracts": "^9", + "illuminate/database": "^9", + "illuminate/http": "^9", + "illuminate/pipeline": "^9", + "illuminate/support": "^9", + "mockery/mockery": "^1.4.4", + "php": "^8.0.2", + "phpmyadmin/sql-parser": "^5.5", + "phpstan/phpstan": "^1.8.7" + }, + "require-dev": { + "nikic/php-parser": "^4.13.2", + "orchestra/testbench": "^7.0.0", + "phpunit/phpunit": "^9.5.11" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "NunoMaduro\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan wrapper for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/nunomaduro/larastan/issues", + "source": "https://github.com/nunomaduro/larastan/tree/2.2.7" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/canvural", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2022-10-30T15:02:40+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -9422,6 +9519,138 @@ }, "time": "2022-10-14T12:47:21+00:00" }, + { + "name": "phpmyadmin/sql-parser", + "version": "5.5.0", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/sql-parser.git", + "reference": "8ab99cd0007d880f49f5aa1807033dbfa21b1cb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/8ab99cd0007d880f49f5aa1807033dbfa21b1cb5", + "reference": "8ab99cd0007d880f49f5aa1807033dbfa21b1cb5", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "symfony/polyfill-mbstring": "^1.3" + }, + "conflict": { + "phpmyadmin/motranslator": "<3.0" + }, + "require-dev": { + "phpmyadmin/coding-standard": "^3.0", + "phpmyadmin/motranslator": "^4.0 || ^5.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.2", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/php-code-coverage": "*", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.16.1", + "vimeo/psalm": "^4.11", + "zumba/json-serializer": "^3.0" + }, + "suggest": { + "ext-mbstring": "For best performance", + "phpmyadmin/motranslator": "Translate messages to your favorite locale" + }, + "bin": [ + "bin/highlight-query", + "bin/lint-query", + "bin/tokenize-query" + ], + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\SqlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", + "homepage": "https://github.com/phpmyadmin/sql-parser", + "keywords": [ + "analysis", + "lexer", + "parser", + "sql" + ], + "support": { + "issues": "https://github.com/phpmyadmin/sql-parser/issues", + "source": "https://github.com/phpmyadmin/sql-parser" + }, + "time": "2021-12-09T04:31:52+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.8.11", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "46e223dd68a620da18855c23046ddb00940b4014" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014", + "reference": "46e223dd68a620da18855c23046ddb00940b4014", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.8.11" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-10-24T15:45:13+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.17", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000000..e12e72eb50 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,35 @@ +includes: + - ./vendor/nunomaduro/larastan/extension.neon + +parameters: + + paths: + - app/ + + # Level 9 is the highest level + level: 4 + + ignoreErrors: + # Ignore dynamic methods from 3rd Party Vendor + - '#Call to an undefined method Prologue\\Alerts\\AlertsMessageBag::(success|info|warning|danger)\(\)#' + + # Ignore repository interface missing methods + - '#Call to an undefined method Pterodactyl\\Repositories\\Wings\\DaemonRepository::(\w+)\(\)#' + + # Ignore magic spatie calls + - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder::allowed(\w+)\(\)#' + + # This should be replaced with resources instead of a magic transformer factory, robots in disguise + - '#Method Pterodactyl\\Http\\Controllers\\Api\\Client\\ClientApiController::getTransformer\(\) should return T#' + + excludePaths: + - app/Repositories + + # Bug in Laravel Framework #44807 + - app/Console/Commands/Overrides/UpCommand.php + + # More magic spatie to be replaced + - app/Extensions/Spatie/Fractalistic/Fractal.php + +# +# checkMissingIterableValueType: false