diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md index 6d69080b1..640d6def5 100644 --- a/.github/ISSUE_TEMPLATE/---bug-report.md +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -1,9 +1,17 @@ --- name: "\U0001F41B Bug Report" -about: Create a report to help us resolve a bug or error +about: For reporting code or design bugs with the software. DO NOT REPORT APACHE/NGINX/PHP CONFIGURATION ISSUES. --- +DO NOT REPORT ISSUES CONFIGURING: SSL, PHP, APACHE, NGINX, YOUR MACHINE, SSH, SFTP, ETC. ON THIS GITHUB TRACKER. + +For assistance installating this software, as well as debugging issues with dependencies, please use our discord server: https://discord.gg/pterodactyl + +You MUST complete all of the below information when reporting a bug, failure to do so will result in closure of your issue. PLEASE stop spamming our tracker with "bugs" that are not related to this project. + +**STOP: READ FIRST, AND THEN DELETE THE ABOVE LINES** + **Background (please complete the following information):** * Panel or Daemon: * Version of Panel/Daemon: diff --git a/.github/ISSUE_TEMPLATE/--installation-help.md b/.github/ISSUE_TEMPLATE/--installation-help.md index fa10ca975..4d5d27e71 100644 --- a/.github/ISSUE_TEMPLATE/--installation-help.md +++ b/.github/ISSUE_TEMPLATE/--installation-help.md @@ -6,3 +6,9 @@ about: 'Visit our Discord for installation help: https://pterodactyl.io/discord' We use GitHub issues only to discuss about Pterodactyl bugs and new features. For this kind of questions about using Pterodactyl, please visit our Discord for assistance: https://pterodactyl.io/discord + +DO NOT REPORT ISSUES CONFIGURING: SSL, PHP, APACHE, NGINX, YOUR MACHINE, SSH, SFTP, ETC. ON THIS GITHUB TRACKER. + +For assistance installating this software, as well as debugging issues with dependencies, please use our discord server: https://discord.gg/pterodactyl + +PLEASE stop spamming our tracker with "bugs" that are not related to this project. diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d42043df..417434183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v0.7.13 (Derelict Dermodactylus) +### Fixed +* Fixes a bug with the location update API endpoint throwing an error due to an unexected response value. +* Fixes bug where node creation API endpoint was not correctly requiring the `disk_overallocate` key. +* Prevents an exception from being thrown when a database with the same name is created on two different hosts. +* Fixes the redis password not saving correctly when setting up the environment from the command line. +* Fixes a bug with transaction handling in many areas of the application that would cause validation error messages +and other session data to not be persisted properly when using the database as the session driver. +* Fix a bug introduced at some point in the past that causes internal data integrity exceptions to not bubble up to +the user correctly, leading to extraneous and confusing exception messages. +* Fixes a bug causing servers to not be marked as having failed installation in some cases. + +### Changed +* `allocation_limit` for servers now defaults to a null value, and is not required in PATCH/POST requests when adding +a server through the API. +* The `PATCH` endpoint for `/api/applications/servers/{server}/build` now accepts an array called `limits` to match +the response from the server `GET` endpoint. + +### Added +* The server listing for a node is now paginated to 25 servers per page to improve performance on large nodes. + ## v0.7.12 (Derelict Dermodactylus) ### Fixed * Fixes an issue with the locations API endpoint referencing an invalid namespace. diff --git a/app/Console/Commands/Environment/AppSettingsCommand.php b/app/Console/Commands/Environment/AppSettingsCommand.php index 6b9bce37d..9a10bfd0d 100644 --- a/app/Console/Commands/Environment/AppSettingsCommand.php +++ b/app/Console/Commands/Environment/AppSettingsCommand.php @@ -178,9 +178,7 @@ class AppSettingsCommand extends Command if ($askForRedisPassword) { $this->output->comment(trans('command/messages.environment.app.redis_pass_help')); $this->variables['REDIS_PASSWORD'] = $this->option('redis-pass') ?? $this->output->askHidden( - trans('command/messages.environment.app.redis_password'), function () { - return ''; - } + trans('command/messages.environment.app.redis_password') ); } diff --git a/app/Contracts/Repository/NodeRepositoryInterface.php b/app/Contracts/Repository/NodeRepositoryInterface.php index c533032c0..aef04e2a9 100644 --- a/app/Contracts/Repository/NodeRepositoryInterface.php +++ b/app/Contracts/Repository/NodeRepositoryInterface.php @@ -55,16 +55,6 @@ interface NodeRepositoryInterface extends RepositoryInterface, SearchableInterfa */ public function loadNodeAllocations(Node $node, bool $refresh = false): Node; - /** - * Return a node with all of the servers attached to that node. - * - * @param int $id - * @return \Pterodactyl\Models\Node - * - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function getNodeServers(int $id): Node; - /** * Return a collection of nodes for all locations to use in server creation UI. * diff --git a/app/Contracts/Repository/ServerRepositoryInterface.php b/app/Contracts/Repository/ServerRepositoryInterface.php index f00d29d8e..ba853398e 100644 --- a/app/Contracts/Repository/ServerRepositoryInterface.php +++ b/app/Contracts/Repository/ServerRepositoryInterface.php @@ -152,4 +152,14 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter * @return int */ public function getSuspendedServersCount(): int; + + /** + * Returns all of the servers that exist for a given node in a paginated response. + * + * @param int $node + * @param int $limit + * + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + */ + public function loadAllServersForNode(int $node, int $limit): LengthAwarePaginator; } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 9be53eb4f..14cef0764 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -6,6 +6,7 @@ use Exception; use PDOException; use Psr\Log\LoggerInterface; use Illuminate\Container\Container; +use Illuminate\Database\Connection; use Illuminate\Auth\AuthenticationException; use Illuminate\Session\TokenMismatchException; use Illuminate\Validation\ValidationException; @@ -14,6 +15,7 @@ use Illuminate\Database\Eloquent\ModelNotFoundException; use Symfony\Component\HttpKernel\Exception\HttpException; use Pterodactyl\Exceptions\Repository\RecordNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class Handler extends ExceptionHandler { @@ -137,6 +139,41 @@ class Handler extends ExceptionHandler */ public function render($request, Exception $exception) { + $connections = Container::getInstance()->make(Connection::class); + + // If we are currently wrapped up inside a transaction, we will roll all the way + // back to the beginning. This needs to happen, otherwise session data does not + // get properly persisted. + // + // This is kind of a hack, and ideally things like this should be handled as + // much as possible at the code level, but there are a lot of spots that do a + // ton of actions and were written before this bug discovery was made. + // + // @see https://github.com/pterodactyl/panel/pull/1468 + if ($connections->transactionLevel()) { + $connections->rollBack(0); + } + + // Because of some breaking change snuck into a Laravel update that didn't get caught + // by any of the tests, exceptions implementing the HttpExceptionInterface get marked + // as being HttpExceptions, but aren't actually implementing the HttpException abstract. + // + // This is incredibly annoying because we can't just temporarily override the handler to + // allow these (at least without taking on a high maintenance cost). Laravel 5.8 fixes this, + // so when we update (or have updated) this code can be removed. + // + // @see https://github.com/laravel/framework/pull/25975 + // @todo remove this code when upgrading to Laravel 5.8 + if ($exception instanceof HttpExceptionInterface && ! $exception instanceof HttpException) { + $exception = new HttpException( + $exception->getStatusCode(), + $exception->getMessage(), + $exception, + $exception->getHeaders(), + $exception->getCode() + ); + } + return parent::render($request, $exception); } diff --git a/app/Exceptions/Repository/RecordNotFoundException.php b/app/Exceptions/Repository/RecordNotFoundException.php index f449faa42..53cfa2222 100644 --- a/app/Exceptions/Repository/RecordNotFoundException.php +++ b/app/Exceptions/Repository/RecordNotFoundException.php @@ -2,19 +2,28 @@ namespace Pterodactyl\Exceptions\Repository; -class RecordNotFoundException extends RepositoryException +use Illuminate\Http\Response; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; + +class RecordNotFoundException extends RepositoryException implements HttpExceptionInterface { /** - * Handle request to render this exception to a user. Returns the default - * 404 page view. + * Returns the status code. * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response + * @return int */ - public function render($request) + public function getStatusCode() { - if (! config('app.debug')) { - return response()->view('errors.404', [], 404); - } + return Response::HTTP_NOT_FOUND; + } + + /** + * Returns response headers. + * + * @return array + */ + public function getHeaders() + { + return []; } } diff --git a/app/Http/Controllers/Admin/NodesController.php b/app/Http/Controllers/Admin/NodesController.php index ab1ce5eb7..28266eac5 100644 --- a/app/Http/Controllers/Admin/NodesController.php +++ b/app/Http/Controllers/Admin/NodesController.php @@ -24,6 +24,7 @@ use Pterodactyl\Services\Allocations\AssignmentService; use Pterodactyl\Services\Helpers\SoftwareVersionService; use Pterodactyl\Http\Requests\Admin\Node\NodeFormRequest; use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; use Pterodactyl\Http\Requests\Admin\Node\AllocationFormRequest; use Pterodactyl\Services\Allocations\AllocationDeletionService; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; @@ -32,6 +33,11 @@ use Pterodactyl\Http\Requests\Admin\Node\AllocationAliasFormRequest; class NodesController extends Controller { + /** + * @var \Pterodactyl\Services\Allocations\AllocationDeletionService + */ + protected $allocationDeletionService; + /** * @var \Prologue\Alerts\AlertsMessageBag */ @@ -72,6 +78,11 @@ class NodesController extends Controller */ protected $repository; + /** + * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface + */ + protected $serverRepository; + /** * @var \Pterodactyl\Services\Nodes\NodeUpdateService */ @@ -81,10 +92,6 @@ class NodesController extends Controller * @var \Pterodactyl\Services\Helpers\SoftwareVersionService */ protected $versionService; - /** - * @var \Pterodactyl\Services\Allocations\AllocationDeletionService - */ - private $allocationDeletionService; /** * NodesController constructor. @@ -98,6 +105,7 @@ class NodesController extends Controller * @param \Pterodactyl\Services\Nodes\NodeDeletionService $deletionService * @param \Pterodactyl\Contracts\Repository\LocationRepositoryInterface $locationRepository * @param \Pterodactyl\Contracts\Repository\NodeRepositoryInterface $repository + * @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $serverRepository * @param \Pterodactyl\Services\Nodes\NodeUpdateService $updateService * @param \Pterodactyl\Services\Helpers\SoftwareVersionService $versionService */ @@ -111,6 +119,7 @@ class NodesController extends Controller NodeDeletionService $deletionService, LocationRepositoryInterface $locationRepository, NodeRepositoryInterface $repository, + ServerRepositoryInterface $serverRepository, NodeUpdateService $updateService, SoftwareVersionService $versionService ) { @@ -123,6 +132,7 @@ class NodesController extends Controller $this->deletionService = $deletionService; $this->locationRepository = $locationRepository; $this->repository = $repository; + $this->serverRepository = $serverRepository; $this->updateService = $updateService; $this->versionService = $versionService; } @@ -178,8 +188,6 @@ class NodesController extends Controller * * @param \Pterodactyl\Models\Node $node * @return \Illuminate\View\View - * - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ public function viewIndex(Node $node) { @@ -235,19 +243,17 @@ class NodesController extends Controller /** * Shows the server listing page for a specific node. * - * @param int $node + * @param \Pterodactyl\Models\Node $node * @return \Illuminate\View\View - * - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - public function viewServers($node) + public function viewServers(Node $node) { - $node = $this->repository->getNodeServers($node); + $servers = $this->serverRepository->loadAllServersForNode($node->id, 25); Javascript::put([ 'node' => collect($node->makeVisible('daemonSecret'))->only(['scheme', 'fqdn', 'daemonListen', 'daemonSecret']), ]); - return view('admin.nodes.view.servers', ['node' => $node]); + return view('admin.nodes.view.servers', ['node' => $node, 'servers' => $servers]); } /** diff --git a/app/Http/Controllers/Daemon/ActionController.php b/app/Http/Controllers/Daemon/ActionController.php index ea4c52533..257d8775a 100644 --- a/app/Http/Controllers/Daemon/ActionController.php +++ b/app/Http/Controllers/Daemon/ActionController.php @@ -5,10 +5,14 @@ namespace Pterodactyl\Http\Controllers\Daemon; use Cache; use Illuminate\Http\Request; use Pterodactyl\Models\Node; +use Illuminate\Http\Response; use Pterodactyl\Models\Server; +use Illuminate\Http\JsonResponse; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Events\Server\Installed as ServerInstalled; use Illuminate\Contracts\Events\Dispatcher as EventDispatcher; +use Pterodactyl\Exceptions\Repository\RecordNotFoundException; class ActionController extends Controller { @@ -16,15 +20,21 @@ class ActionController extends Controller * @var \Illuminate\Contracts\Events\Dispatcher */ private $eventDispatcher; + /** + * @var \Pterodactyl\Repositories\Eloquent\ServerRepository + */ + private $repository; /** * ActionController constructor. * - * @param \Illuminate\Contracts\Events\Dispatcher $eventDispatcher + * @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository + * @param \Illuminate\Contracts\Events\Dispatcher $eventDispatcher */ - public function __construct(EventDispatcher $eventDispatcher) + public function __construct(ServerRepository $repository, EventDispatcher $eventDispatcher) { $this->eventDispatcher = $eventDispatcher; + $this->repository = $repository; } /** @@ -32,34 +42,47 @@ class ActionController extends Controller * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ - public function markInstall(Request $request) + public function markInstall(Request $request): JsonResponse { - $server = Server::where('uuid', $request->input('server'))->with('node')->first(); - if (! $server) { - return response()->json([ + try { + /** @var \Pterodactyl\Models\Server $server */ + $server = $this->repository->findFirstWhere([ + 'uuid' => $request->input('server'), + ]); + } catch (RecordNotFoundException $exception) { + return JsonResponse::create([ 'error' => 'No server by that ID was found on the system.', - ], 422); + ], Response::HTTP_UNPROCESSABLE_ENTITY); + } + + if (! $server->relationLoaded('node')) { + $server->load('node'); } $hmac = $request->input('signed'); $status = $request->input('installed'); - if (! hash_equals(base64_decode($hmac), hash_hmac('sha256', $server->uuid, $server->node->daemonSecret, true))) { - return response()->json([ + if (! hash_equals(base64_decode($hmac), hash_hmac('sha256', $server->uuid, $server->getRelation('node')->daemonSecret, true))) { + return JsonResponse::create([ 'error' => 'Signed HMAC was invalid.', - ], 403); + ], Response::HTTP_FORBIDDEN); } - $server->installed = ($status === 'installed') ? 1 : 2; - $server->save(); + $this->repository->update($server->id, [ + 'installed' => ($status === 'installed') ? 1 : 2, + ], true, true); // Only fire event if server installed successfully. - if ($server->installed === 1) { + if ($status === 'installed') { $this->eventDispatcher->dispatch(new ServerInstalled($server)); } - return response()->json([]); + // Don't use a 204 here, the daemon is hard-checking for a 200 code. + return JsonResponse::create([]); } /** diff --git a/app/Http/Requests/Admin/Servers/Databases/StoreServerDatabaseRequest.php b/app/Http/Requests/Admin/Servers/Databases/StoreServerDatabaseRequest.php index 7f08ecd08..ba8b76a83 100644 --- a/app/Http/Requests/Admin/Servers/Databases/StoreServerDatabaseRequest.php +++ b/app/Http/Requests/Admin/Servers/Databases/StoreServerDatabaseRequest.php @@ -2,6 +2,8 @@ namespace Pterodactyl\Http\Requests\Admin\Servers\Databases; +use Illuminate\Validation\Rule; +use Illuminate\Database\Query\Builder; use Pterodactyl\Http\Requests\Admin\AdminFormRequest; class StoreServerDatabaseRequest extends AdminFormRequest @@ -14,7 +16,15 @@ class StoreServerDatabaseRequest extends AdminFormRequest public function rules(): array { return [ - 'database' => 'required|string|min:1|max:24', + 'database' => [ + 'required', + 'string', + 'min:1', + 'max:24', + Rule::unique('databases')->where(function (Builder $query) { + $query->where('database_host_id', $this->input('database_host_id') ?? 0); + }), + ], 'remote' => 'required|string|regex:/^[0-9%.]{1,15}$/', 'database_host_id' => 'required|integer|exists:database_hosts,id', ]; diff --git a/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php b/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php index 3a8a15c5f..2d83ab08f 100644 --- a/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php +++ b/app/Http/Requests/Api/Application/Locations/UpdateLocationRequest.php @@ -30,6 +30,6 @@ class UpdateLocationRequest extends StoreLocationRequest return collect(Location::getUpdateRulesForId($locationId))->only([ 'short', 'long', - ]); + ])->toArray(); } } diff --git a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php index 0f39fd2f8..37dd32585 100644 --- a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php +++ b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php @@ -36,7 +36,7 @@ class StoreNodeRequest extends ApplicationApiRequest 'memory', 'memory_overallocate', 'disk', - 'disk_overallocation', + 'disk_overallocate', 'upload_size', 'daemonListen', 'daemonSFTP', diff --git a/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php b/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php index ee4264a9d..c2dbfe14a 100644 --- a/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php +++ b/app/Http/Requests/Api/Application/Servers/Databases/StoreServerDatabaseRequest.php @@ -2,6 +2,8 @@ namespace Pterodactyl\Http\Requests\Api\Application\Servers\Databases; +use Illuminate\Validation\Rule; +use Illuminate\Database\Query\Builder; use Pterodactyl\Services\Acl\Api\AdminAcl; use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest; @@ -25,7 +27,15 @@ class StoreServerDatabaseRequest extends ApplicationApiRequest public function rules(): array { return [ - 'database' => 'required|string|min:1|max:24', + 'database' => [ + 'required', + 'string', + 'min:1', + 'max:24', + Rule::unique('databases')->where(function (Builder $query) { + $query->where('database_host_id', $this->input('host') ?? 0); + }), + ], 'remote' => 'required|string|regex:/^[0-9%.]{1,15}$/', 'host' => 'required|integer|exists:database_hosts,id', ]; diff --git a/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php b/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php index d3d4a8b21..07bbc3281 100644 --- a/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php +++ b/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php @@ -3,6 +3,7 @@ namespace Pterodactyl\Http\Requests\Api\Application\Servers; use Pterodactyl\Models\Server; +use Illuminate\Support\Collection; class UpdateServerBuildConfigurationRequest extends ServerWriteRequest { @@ -17,15 +18,29 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest return [ 'allocation' => $rules['allocation_id'], - 'memory' => $rules['memory'], - 'swap' => $rules['swap'], - 'io' => $rules['io'], - 'cpu' => $rules['cpu'], - 'disk' => $rules['disk'], + + 'limits' => 'sometimes|array', + 'limits.memory' => $this->requiredToOptional('memory', $rules['memory'], true), + 'limits.swap' => $this->requiredToOptional('swap', $rules['swap'], true), + 'limits.io' => $this->requiredToOptional('io', $rules['io'], true), + 'limits.cpu' => $this->requiredToOptional('cpu', $rules['cpu'], true), + 'limits.disk' => $this->requiredToOptional('disk', $rules['disk'], true), + + // Legacy rules to maintain backwards compatable API support without requiring + // a major version bump. + // + // @see https://github.com/pterodactyl/panel/issues/1500 + 'memory' => $this->requiredToOptional('memory', $rules['memory']), + 'swap' => $this->requiredToOptional('swap', $rules['swap']), + 'io' => $this->requiredToOptional('io', $rules['io']), + 'cpu' => $this->requiredToOptional('cpu', $rules['cpu']), + 'disk' => $this->requiredToOptional('disk', $rules['disk']), + 'add_allocations' => 'bail|array', 'add_allocations.*' => 'integer', 'remove_allocations' => 'bail|array', 'remove_allocations.*' => 'integer', + 'feature_limits' => 'required|array', 'feature_limits.databases' => $rules['database_limit'], 'feature_limits.allocations' => $rules['allocation_limit'], @@ -46,6 +61,15 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest $data['allocation_limit'] = $data['feature_limits']['allocations']; unset($data['allocation'], $data['feature_limits']); + // Adjust the limits field to match what is expected by the model. + if (! empty($data['limits'])) { + foreach ($data['limits'] as $key => $value) { + $data[$key] = $value; + } + + unset($data['limits']); + } + return $data; } @@ -65,4 +89,30 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest 'feature_limits.allocations' => 'Allocation Limit', ]; } + + /** + * Converts existing rules for certain limits into a format that maintains backwards + * compatability with the old API endpoint while also supporting a more correct API + * call. + * + * @param string $field + * @param array $rules + * @param bool $limits + * @return array + * + * @see https://github.com/pterodactyl/panel/issues/1500 + */ + protected function requiredToOptional(string $field, array $rules, bool $limits = false) + { + if (! in_array('required', $rules)) { + return $rules; + } + + return (new Collection($rules)) + ->filter(function ($value) { + return $value !== 'required'; + }) + ->prepend($limits ? 'required_with:limits' : 'required_without:limits') + ->toArray(); + } } diff --git a/app/Models/Server.php b/app/Models/Server.php index 5d42cf86b..b1a77ead8 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -63,7 +63,7 @@ class Server extends Model implements CleansAttributes, ValidableContract 'image' => 'required', 'startup' => 'required', 'database_limit' => 'present', - 'allocation_limit' => 'present', + 'allocation_limit' => 'sometimes', ]; /** @@ -87,7 +87,7 @@ class Server extends Model implements CleansAttributes, ValidableContract 'startup' => 'string', 'skip_scripts' => 'boolean', 'image' => 'string|max:255', - 'installed' => 'boolean', + 'installed' => 'in:0,1,2', 'database_limit' => 'nullable|integer|min:0', 'allocation_limit' => 'nullable|integer|min:0', ]; diff --git a/app/Repositories/Eloquent/NodeRepository.php b/app/Repositories/Eloquent/NodeRepository.php index 4f59fddce..3b86f2ee1 100644 --- a/app/Repositories/Eloquent/NodeRepository.php +++ b/app/Repositories/Eloquent/NodeRepository.php @@ -6,10 +6,8 @@ use Generator; use Pterodactyl\Models\Node; use Illuminate\Support\Collection; use Pterodactyl\Repositories\Concerns\Searchable; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; -use Pterodactyl\Exceptions\Repository\RecordNotFoundException; class NodeRepository extends EloquentRepository implements NodeRepositoryInterface { @@ -140,25 +138,6 @@ class NodeRepository extends EloquentRepository implements NodeRepositoryInterfa return $node; } - /** - * Return a node with all of the servers attached to that node. - * - * @param int $id - * @return \Pterodactyl\Models\Node - * - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function getNodeServers(int $id): Node - { - try { - return $this->getBuilder()->with([ - 'servers.user', 'servers.nest', 'servers.egg', - ])->findOrFail($id, $this->getColumns()); - } catch (ModelNotFoundException $exception) { - throw new RecordNotFoundException; - } - } - /** * Return a collection of nodes for all locations to use in server creation UI. * diff --git a/app/Repositories/Eloquent/ServerRepository.php b/app/Repositories/Eloquent/ServerRepository.php index 3c0248be1..820093cf4 100644 --- a/app/Repositories/Eloquent/ServerRepository.php +++ b/app/Repositories/Eloquent/ServerRepository.php @@ -2,6 +2,7 @@ namespace Pterodactyl\Repositories\Eloquent; +use Pterodactyl\Models\Node; use Pterodactyl\Models\User; use Webmozart\Assert\Assert; use Pterodactyl\Models\Server; @@ -338,4 +339,20 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt { return $this->getBuilder()->where('suspended', true)->count(); } + + /** + * Returns all of the servers that exist for a given node in a paginated response. + * + * @param int $node + * @param int $limit + * + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + */ + public function loadAllServersForNode(int $node, int $limit): LengthAwarePaginator + { + return $this->getBuilder() + ->with(['user', 'nest', 'egg']) + ->where('node_id', '=', $node) + ->paginate($limit); + } } diff --git a/codecov.yml b/codecov.yml index f173c829e..fdc1d707a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,5 +2,4 @@ coverage: status: project: off patch: off -comment: - layout: "diff" +comment: false diff --git a/composer.json b/composer.json index 14d11cc6b..49a957236 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "doctrine/dbal": "^2.5", "fideloper/proxy": "^4.0", "guzzlehttp/guzzle": "^6.3", - "hashids/hashids": "^2.0", + "hashids/hashids": "^3.0", "igaster/laravel-theme": "^2.0.6", "laracasts/utilities": "^3.0", "laravel/framework": "~5.7.14", @@ -37,8 +37,8 @@ "sofa/eloquence-base": "v5.6.2", "sofa/eloquence-validable": "v5.6", "spatie/laravel-fractal": "^5.4", - "webmozart/assert": "^1.2", - "znck/belongs-to-through": "^2.3" + "staudenmeir/belongs-to-through": "~2.3.0", + "webmozart/assert": "^1.2" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.2", diff --git a/composer.lock b/composer.lock index 93547e2dd..42f0ec2fb 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": "17de367358e9573d913860f1b446e9a7", + "content-hash": "2079d9e659d2f26492c9931277bd1f25", "packages": [ { "name": "appstract/laravel-blade-directives", @@ -2958,6 +2958,58 @@ ], "time": "2018-09-28T16:17:34+00:00" }, + { + "name": "staudenmeir/belongs-to-through", + "version": "v2.3.2", + "source": { + "type": "git", + "url": "https://github.com/staudenmeir/belongs-to-through.git", + "reference": "2ba1ff76353058d2b4d395e725617d97fd103ab0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staudenmeir/belongs-to-through/zipball/2ba1ff76353058d2b4d395e725617d97fd103ab0", + "reference": "2ba1ff76353058d2b4d395e725617d97fd103ab0", + "shasum": "" + }, + "require": { + "illuminate/database": "~5.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "^1.11", + "orchestra/testbench": "~3.0", + "phpunit/php-code-coverage": "^3.3", + "phpunit/phpunit": "~5.0", + "satooshi/php-coveralls": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Znck\\Eloquent\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rahul Kadyan", + "email": "hi@znck.me" + } + ], + "description": "Adds belongsToThrough relation to laravel models", + "homepage": "https://github.com/staudenmeir/belongs-to-through", + "keywords": [ + "belongsToThrough", + "eloquent", + "laravel", + "model", + "models", + "znck" + ], + "time": "2019-02-01T14:33:18+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.1.3", @@ -4143,58 +4195,6 @@ "validate" ], "time": "2018-01-29T19:49:41+00:00" - }, - { - "name": "znck/belongs-to-through", - "version": "v2.3.1", - "source": { - "type": "git", - "url": "https://github.com/znck/belongs-to-through.git", - "reference": "8ac53e9134072902a8d3f3e18c327d4a8fd70d3d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/znck/belongs-to-through/zipball/8ac53e9134072902a8d3f3e18c327d4a8fd70d3d", - "reference": "8ac53e9134072902a8d3f3e18c327d4a8fd70d3d", - "shasum": "" - }, - "require": { - "illuminate/database": "~5.0" - }, - "require-dev": { - "fabpot/php-cs-fixer": "^1.11", - "orchestra/testbench": "~3.0", - "phpunit/php-code-coverage": "^3.3", - "phpunit/phpunit": "~5.0", - "satooshi/php-coveralls": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Znck\\Eloquent\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Rahul Kadyan", - "email": "hi@znck.me" - } - ], - "description": "Adds belongsToThrough relation to laravel models", - "homepage": "https://github.com/znck/belongs-to-through", - "keywords": [ - "belongsToThrough", - "eloquent", - "laravel", - "model", - "models", - "znck" - ], - "time": "2017-07-23T13:11:16+00:00" } ], "packages-dev": [ diff --git a/config/app.php b/config/app.php index 298a9d06d..470022f48 100644 --- a/config/app.php +++ b/config/app.php @@ -9,7 +9,7 @@ return [ | change this value if you are not maintaining your own internal versions. */ - 'version' => '0.7.12', + 'version' => '0.7.13', /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2019_03_02_142328_set_allocation_limit_default_null.php b/database/migrations/2019_03_02_142328_set_allocation_limit_default_null.php new file mode 100644 index 000000000..d91ce6372 --- /dev/null +++ b/database/migrations/2019_03_02_142328_set_allocation_limit_default_null.php @@ -0,0 +1,32 @@ +unsignedInteger('allocation_limit')->nullable()->default(null)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + $table->unsignedInteger('allocation_limit')->nullable()->default(0)->change(); + }); + } +} diff --git a/database/migrations/2019_03_02_151321_fix_unique_index_to_account_for_host.php b/database/migrations/2019_03_02_151321_fix_unique_index_to_account_for_host.php new file mode 100644 index 000000000..fe5f85f88 --- /dev/null +++ b/database/migrations/2019_03_02_151321_fix_unique_index_to_account_for_host.php @@ -0,0 +1,40 @@ +dropUnique(['database']); + $table->dropUnique(['username']); + + $table->unique(['database_host_id', 'database']); + $table->unique(['database_host_id', 'username']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('databases', function (Blueprint $table) { + $table->dropUnique(['database_host_id', 'database']); + $table->dropUnique(['database_host_id', 'username']); + + $table->unique(['database']); + $table->unique(['username']); + }); + } +} diff --git a/database/seeds/eggs/minecraft/egg-bungeecord.json b/database/seeds/eggs/minecraft/egg-bungeecord.json index 1f60064ac..d527024f3 100644 --- a/database/seeds/eggs/minecraft/egg-bungeecord.json +++ b/database/seeds/eggs/minecraft/egg-bungeecord.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\n# Bungeecord Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add curl\n\ncd \/mnt\/server\n\nif [ -z \"${BUNGEE_VERSION}\" ] || [ \"${BUNGEE_VERSION}\" == \"latest\" ]; then\n BUNGEE_VERSION=\"lastStableBuild\"\nfi\n\ncurl -o ${SERVER_JARFILE} https:\/\/ci.md-5.net\/job\/BungeeCord\/${BUNGEE_VERSION}\/artifact\/bootstrap\/target\/BungeeCord.jar", - "container": "alpine:3.4", + "container": "alpine:3.9", "entrypoint": "ash" } }, @@ -42,4 +42,4 @@ "rules": "required|regex:\/^([\\w\\d._-]+)(\\.jar)$\/" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/minecraft/egg-forge-minecraft.json b/database/seeds/eggs/minecraft/egg-forge-minecraft.json index 9f84a06b3..2e8b43bfe 100644 --- a/database/seeds/eggs/minecraft/egg-forge-minecraft.json +++ b/database/seeds/eggs/minecraft/egg-forge-minecraft.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-06-25T15:47:07-04:00", + "exported_at": "2019-02-07T07:47:35-05:00", "name": "Forge Minecraft", "author": "support@pterodactyl.io", "description": "Minecraft Forge Server. Minecraft Forge is a modding API (Application Programming Interface), which makes it easier to create mods, and also make sure mods are compatible with each other.", @@ -17,7 +17,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/ash\r\n# Forge Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl\r\n\r\nif [ -z \"$MC_VERSION\" ] || [ \"$MC_VERSION\" == \"latest\" ]; then\r\n FORGE_VERSION=$(curl -sl https:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/ | grep -A1 Latest | grep -o -e '[1]\\.[0-9][0-9]\\?\\.\\?[0-9]\\?[0-9] - [0-9][0-9]\\.[0-9][0-9]\\.[0-9]\\?[0-9]\\.[0-9][0-9][0-9][0-9]' | sed 's\/ \/\/g')\r\nelse\r\n FORGE_VERSION=$(curl -sl https:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/index_$MC_VERSION.html | grep -A1 Latest | grep -o -e '[1]\\.[0-9][0-9]\\?\\.\\?[0-9]\\?[0-9] - [0-9][0-9]\\.[0-9][0-9]\\.[0-9]\\?[0-9]\\.[0-9][0-9][0-9][0-9]' | sed 's\/ \/\/g')\r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"\\nDownloading Forge Version $FORGE_VERSION\\n\"\r\ncurl -sS https:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-installer.jar -o installer.jar\r\ncurl -sS https:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-universal.jar -o $SERVER_JARFILE\r\n\r\necho -e \"\\nInstalling forge server usint the installer jar file.\\n\"\r\njava -jar installer.jar --installServer\r\n\r\necho -e \"\\nDeleting installer jar file and cleaning up.\\n\"\r\nrm -rf installer.jar", + "script": "#!\/bin\/ash\r\n# Forge Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl\r\n\r\nif [ -z \"$MC_VERSION\" ] || [ \"$MC_VERSION\" == \"latest\" ]; then\r\n FORGE_VERSION=$(echo $(curl -sSl http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/ | grep -A2 Latest | grep small) | grep -o -e '[1].[0-9]*.[0-9]* - [0-9]*.[0-9]*.[0-9]*.[0-9]*' | sed 's\/ \/\/g')\r\nelse\r\n FORGE_VERSION=$(echo $(curl -sl http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/index_$MC_VERSION.html | grep -A2 Latest | grep small) | grep -o -e '[1].[0-9]*.[0-9]* - [0-9]*.[0-9]*.[0-9]*.[0-9]*' | sed 's\/ \/\/g')\r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"\\nDownloading Forge Version $FORGE_VERSION\\n\"\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-installer.jar -o installer.jar\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-universal.jar -o $SERVER_JARFILE\r\n\r\necho -e \"\\nInstalling forge server usint the installer jar file.\\n\"\r\njava -jar installer.jar --installServer\r\n\r\necho -e \"\\nDeleting installer jar file and cleaning up.\\n\"\r\nrm -rf installer.jar", "container": "openjdk:8-alpine", "entrypoint": "ash" } @@ -42,4 +42,4 @@ "rules": "required|string|max:20" } ] -} +} \ No newline at end of file diff --git a/database/seeds/eggs/minecraft/egg-paper.json b/database/seeds/eggs/minecraft/egg-paper.json new file mode 100644 index 000000000..86208f68b --- /dev/null +++ b/database/seeds/eggs/minecraft/egg-paper.json @@ -0,0 +1,63 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v1" + }, + "exported_at": "2019-02-27T22:23:55-05:00", + "name": "Paper", + "author": "parker@pterodactyl.io", + "description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.", + "image": "quay.io\/pterodactyl\/core:java", + "startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}", + "config": { + "files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}", + "startup": "{\r\n \"done\": \")! For help, type \",\r\n \"userInteraction\": [\r\n \"Go to eula.txt for more info.\"\r\n ]\r\n}", + "logs": "{}", + "stop": "stop" + }, + "scripts": { + "installation": { + "script": "#!\/bin\/ash\r\n# Paper Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk add --no-cache --update curl jq\r\n\r\nif [ -n \"${DL_PATH}\" ]; then\r\n echo -e \"using supplied download url\"\r\n DOWNLOAD_URL=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\nelse\r\n VER_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r --arg VERSION $MINECRAFT_VERSION '.versions[] | IN($VERSION)' | grep true`\r\n LATEST_PAPER_VERSION=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r '.versions' | jq -r '.[0]'`\r\n \r\n if [ \"${VER_EXISTS}\" == \"true\" ]; then\r\n echo -e \"Version is valid. Using version ${MINECRAFT_VERSION}\"\r\n else\r\n echo -e \"Using the latest paper version\"\r\n MINECRAFT_VERSION=${LATEST_PAPER_VERSION}\r\n fi\r\n \r\n BUILD_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r --arg BUILD ${BUILD_NUMBER} '.builds.all[] | IN($BUILD)' | grep true`\r\n LATEST_PAPER_BUILD=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r '.builds.latest'`\r\n \r\n if [ \"${BUILD_EXISTS}\" == \"true\" ] || [ ${BUILD_NUMBER} == \"latest\" ]; then\r\n echo -e \"Build is valid. Using version ${BUILD_NUMBER}\"\r\n else\r\n echo -e \"Using the latest paper build\"\r\n BUILD_NUMBER=${LATEST_PAPER_BUILD}\r\n fi\r\n \r\n echo \"Version being downloaded\"\r\n echo -e \"MC Version: ${MINECRAFT_VERSION}\"\r\n echo -e \"Build: ${BUILD_NUMBER}\"\r\n DOWNLOAD_URL=https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION}\/${BUILD_NUMBER}\/download \r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"running curl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\"\r\n\r\ncurl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\r\n\r\necho -e \"Downloading MC server.properties\"\r\ncurl -o server.properties https:\/\/raw.githubusercontent.com\/parkervcp\/eggs\/master\/minecraft_java\/server.properties", + "container": "alpine:3.9", + "entrypoint": "ash" + } + }, + "variables": [ + { + "name": "Minecraft Version", + "description": "The version of minecraft to download. \r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.", + "env_variable": "MINECRAFT_VERSION", + "default_value": "latest", + "user_viewable": 1, + "user_editable": 0, + "rules": "nullable|string|max:20" + }, + { + "name": "Server Jar File", + "description": "The name of the server jarfile to run the server with.", + "env_variable": "SERVER_JARFILE", + "default_value": "server.jar", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|string|max:20" + }, + { + "name": "Download Path", + "description": "A URL to use to download a server.jar rather than the ones in the install script. This is not user viewable.", + "env_variable": "DL_PATH", + "default_value": "", + "user_viewable": 0, + "user_editable": 0, + "rules": "nullable|string" + }, + { + "name": "Build Number", + "description": "The build number for the paper release.\r\n\r\nLeave at latest to always get the latest version. Invalid versions will default to latest.", + "env_variable": "BUILD_NUMBER", + "default_value": "latest", + "user_viewable": 1, + "user_editable": 0, + "rules": "required|string|max:20" + } + ] +} \ No newline at end of file diff --git a/database/seeds/eggs/minecraft/egg-spigot.json b/database/seeds/eggs/minecraft/egg-spigot.json deleted file mode 100644 index fa34e22c5..000000000 --- a/database/seeds/eggs/minecraft/egg-spigot.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", - "meta": { - "version": "PTDL_v1" - }, - "exported_at": "2018-11-16T02:14:51-05:00", - "name": "Spigot", - "author": "support@pterodactyl.io", - "description": "Spigot is the most widely-used modded Minecraft server software in the world. It powers many of the top Minecraft server networks around to ensure they can cope with their huge player base and ensure the satisfaction of their players. Spigot works by reducing and eliminating many causes of lag, as well as adding in handy features and settings that help make your job of server administration easier.", - "image": "quay.io\/pterodactyl\/core:java-glibc", - "startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}", - "config": { - "files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"enable-query\": \"true\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}", - "startup": "{\r\n \"done\": \")! For help, type \",\r\n \"userInteraction\": [\r\n \"Go to eula.txt for more info.\"\r\n ]\r\n}", - "logs": "{\r\n \"custom\": false,\r\n \"location\": \"logs\/latest.log\"\r\n}", - "stop": "stop" - }, - "scripts": { - "installation": { - "script": "#!\/bin\/ash\r\n# Spigot Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n## Only download if a path is provided, otherwise continue.\r\nif [ ! -z \"${DL_PATH}\" ]; then\r\n apk update\r\n apk add curl\r\n\r\n cd \/mnt\/server\r\n\r\n MODIFIED_DOWNLOAD=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\n curl -sSL -o ${SERVER_JARFILE} ${MODIFIED_DOWNLOAD}\r\nelse\r\n apk add --no-cache curl git openjdk8 openssl bash\r\n \r\n cd \/srv\/\r\n \r\n wget https:\/\/hub.spigotmc.org\/jenkins\/job\/BuildTools\/lastSuccessfulBuild\/artifact\/target\/BuildTools.jar\r\n \r\n mv BuildTools.jar \/srv\/\r\n\r\n java -jar BuildTools.jar --rev ${DL_VERSION}\r\n\r\n mv spigot-*.jar \/mnt\/server\/${SERVER_JARFILE}\r\nfi", - "container": "alpine:3.7", - "entrypoint": "ash" - } - }, - "variables": [ - { - "name": "Server Jar File", - "description": "The name of the server jarfile to run the server with.", - "env_variable": "SERVER_JARFILE", - "default_value": "server.jar", - "user_viewable": 1, - "user_editable": 1, - "rules": "required|regex:\/^([\\w\\d._-]+)(\\.jar)$\/" - }, - { - "name": "Spigot Version", - "description": "The version of Spigot to download (using the --rev tag). Use \"latest\" for latest.", - "env_variable": "DL_VERSION", - "default_value": "latest", - "user_viewable": 1, - "user_editable": 1, - "rules": "required|string|between:3,7" - }, - { - "name": "Download Path", - "description": "A URL to use to download Spigot rather than building it on the server. This is not user viewable. Use {{DL_VERSION}}<\/code> in the URL to automatically insert the assigned version into the URL. If you do not enter a URL Spigot will build directly in the container (this will fail on low memory containers).", - "env_variable": "DL_PATH", - "default_value": "", - "user_viewable": 0, - "user_editable": 0, - "rules": "nullable|string" - } - ] -} diff --git a/database/seeds/eggs/minecraft/egg-sponge--sponge-vanilla.json b/database/seeds/eggs/minecraft/egg-sponge--sponge-vanilla.json index 489100284..2bbfba23a 100644 --- a/database/seeds/eggs/minecraft/egg-sponge--sponge-vanilla.json +++ b/database/seeds/eggs/minecraft/egg-sponge--sponge-vanilla.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\n# Sponge Installation Script\n#\n# Server Files: \/mnt\/server\n\napk update\napk add curl\n\ncd \/mnt\/server\n\ncurl -sSL \"https:\/\/repo.spongepowered.org\/maven\/org\/spongepowered\/spongevanilla\/${SPONGE_VERSION}\/spongevanilla-${SPONGE_VERSION}.jar\" -o ${SERVER_JARFILE}", - "container": "alpine:3.4", + "container": "alpine:3.9", "entrypoint": "ash" } }, @@ -42,4 +42,4 @@ "rules": "required|regex:\/^([\\w\\d._-]+)(\\.jar)$\/" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json b/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json index 3c71a6b2b..5937fc176 100644 --- a/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json +++ b/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\r\n# Vanilla MC Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl jq\r\n\r\ncd \/mnt\/server\r\n\r\nLATEST_VERSION=`curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq -r '.latest.release'`\r\n\r\nif [ -z \"$VANILLA_VERSION\" ] || [ \"$VANILLA_VERSION\" == \"latest\" ]; then\r\n MANIFEST_URL=$(curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq .versions | jq -r '.[] | select(.id == \"'$LATEST_VERSION'\") | .url')\r\nelse\r\n MANIFEST_URL=$(curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq .versions | jq -r '.[] | select(.id == \"'$VANILLA_VERSION'\") | .url')\r\nfi\r\n\r\nDOWNLOAD_URL=`curl $MANIFEST_URL | jq .downloads.server | jq -r '. | .url'`\r\n\r\ncurl -o ${SERVER_JARFILE} $DOWNLOAD_URL", - "container": "alpine:3.7", + "container": "alpine:3.9", "entrypoint": "ash" } }, diff --git a/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json b/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json index 4b2ec6356..35028b20c 100644 --- a/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json +++ b/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-07-06T11:27:32+02:00", + "exported_at": "2019-02-13T12:30:54-05:00", "name": "Ark: Survival Evolved", "author": "support@pterodactyl.io", "description": "As a man or woman stranded, naked, freezing, and starving on the unforgiving shores of a mysterious island called ARK, use your skill and cunning to kill or tame and ride the plethora of leviathan dinosaurs and other primeval creatures roaming the land. Hunt, harvest resources, craft items, grow crops, research technologies, and build shelters to withstand the elements and store valuables, all while teaming up with (or preying upon) hundreds of other players to survive, dominate... and escape! \u2014 Gamepedia: ARK", @@ -11,7 +11,7 @@ "startup": ".\/ShooterGame\/Binaries\/Linux\/ShooterGameServer {{SERVER_MAP}}?listen?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?MaxPlayers={{SERVER_MAX_PLAYERS}}", "config": { "files": "{}", - "startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}", + "startup": "{\r\n \"done\": \"Setting breakpad minidump AppID = 346110\",\r\n \"userInteraction\": []\r\n}", "logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}", "stop": "quit" }, @@ -60,4 +60,4 @@ "rules": "required|string|max:20" } ] -} +} \ No newline at end of file diff --git a/database/seeds/eggs/source-engine/egg-garrys-mod.json b/database/seeds/eggs/source-engine/egg-garrys-mod.json index 0bfdc0a07..c0e4f31b4 100644 --- a/database/seeds/eggs/source-engine/egg-garrys-mod.json +++ b/database/seeds/eggs/source-engine/egg-garrys-mod.json @@ -3,12 +3,12 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-06-19T07:46:27-04:00", + "exported_at": "2019-02-16T14:20:52-05:00", "name": "Garrys Mod", "author": "support@pterodactyl.io", "description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.", "image": "quay.io\/pterodactyl\/core:source", - "startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}", + "startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +host_workshop_collection {{WORKSHOP_ID}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}}", "config": { "files": "{}", "startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}", @@ -17,7 +17,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/bash\n# Garry's Mod Installation Script\n#\n# Server Files: \/mnt\/server\napt -y update\napt -y --no-install-recommends install curl lib32gcc1 ca-certificates\n\ncd \/tmp\ncurl -sSL -o steamcmd.tar.gz http:\/\/media.steampowered.com\/installer\/steamcmd_linux.tar.gz\n\nmkdir -p \/mnt\/server\/steamcmd\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\ncd \/mnt\/server\/steamcmd\n\n# SteamCMD fails otherwise for some reason, even running as root.\n# This is changed at the end of the install process anyways.\nchown -R root:root \/mnt\n\nexport HOME=\/mnt\/server\n.\/steamcmd.sh +login anonymous +force_install_dir \/mnt\/server +app_update 4020 +quit\n\nmkdir -p \/mnt\/server\/.steam\/sdk32\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so", + "script": "#!\/bin\/bash\r\n# Garry's Mod Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napt -y update\r\napt -y --no-install-recommends install curl lib32gcc1 ca-certificates\r\n\r\ncd \/tmp\r\ncurl -sSL -o steamcmd.tar.gz http:\/\/media.steampowered.com\/installer\/steamcmd_linux.tar.gz\r\n\r\nmkdir -p \/mnt\/server\/steamcmd\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\n\r\nexport HOME=\/mnt\/server\r\n.\/steamcmd.sh +login anonymous +force_install_dir \/mnt\/server +app_update 4020 +quit\r\n\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n# Creating needed default files for the game\r\ncd \/mnt\/server\/garrysmod\/lua\/autorun\/server\r\necho '\r\n-- Docs: https:\/\/wiki.garrysmod.com\/page\/resource\/AddWorkshop\r\n-- Place the ID of the workshop addon you want to be downloaded to people who join your server, not the collection ID\r\n-- Use https:\/\/beta.configcreator.com\/create\/gmod\/resources.lua to easily create a list based on your collection ID\r\n\r\nresource.AddWorkshop( \"\" )\r\n' > workshop.lua\r\n\r\ncd \/mnt\/server\/garrysmod\/cfg\r\necho '\r\n\/\/ Please do not set RCon in here, use the startup parameters.\r\n\r\nhostname\t\t\"New Gmod Server\"\r\nsv_password\t\t\"\"\r\nsv_loadingurl \"\"\r\n\r\n\/\/ Steam Server List Settings\r\nsv_region \"255\"\r\nsv_lan \"0\"\r\nsv_max_queries_sec_global \"30000\"\r\nsv_max_queries_window \"45\"\r\nsv_max_queries_sec \"5\"\r\n\r\n\/\/ Server Limits\r\nsbox_maxprops\t\t100\r\nsbox_maxragdolls\t5\r\nsbox_maxnpcs\t\t10\r\nsbox_maxballoons\t10\r\nsbox_maxeffects\t\t10\r\nsbox_maxdynamite\t10\r\nsbox_maxlamps\t\t10\r\nsbox_maxthrusters\t10\r\nsbox_maxwheels\t\t10\r\nsbox_maxhoverballs\t10\r\nsbox_maxvehicles\t20\r\nsbox_maxbuttons\t\t10\r\nsbox_maxsents\t\t20\r\nsbox_maxemitters\t5\r\nsbox_godmode\t\t0\r\nsbox_noclip\t\t 0\r\n\r\n\/\/ Network Settings - Please keep these set to default.\r\n\r\nsv_minrate\t\t75000\r\nsv_maxrate\t\t0\r\ngmod_physiterations\t2\r\nnet_splitpacket_maxrate\t45000\r\ndecalfrequency\t\t12 \r\n\r\n\/\/ Execute Ban Files - Please do not edit\r\nexec banned_ip.cfg \r\nexec banned_user.cfg \r\n\r\n\/\/ Add custom lines under here\r\n' > server.cfg", "container": "ubuntu:16.04", "entrypoint": "bash" } @@ -39,7 +39,7 @@ "default_value": "", "user_viewable": 1, "user_editable": 1, - "rules": "required|string|alpha_num|size:32" + "rules": "nullable|string|alpha_num|size:32" }, { "name": "Source AppID", @@ -49,6 +49,42 @@ "user_viewable": 0, "user_editable": 0, "rules": "required|string|max:20" + }, + { + "name": "Workshop ID", + "description": "The ID of your workshop collection (the numbers at the end of the URL)", + "env_variable": "WORKSHOP_ID", + "default_value": "", + "user_viewable": 1, + "user_editable": 1, + "rules": "nullable|integer" + }, + { + "name": "Gamemode", + "description": "The gamemode of your server.", + "env_variable": "GAMEMODE", + "default_value": "sandbox", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|string" + }, + { + "name": "Max Players", + "description": "The maximum amount of players allowed on your game server.", + "env_variable": "MAX_PLAYERS", + "default_value": "32", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|integer|max:128" + }, + { + "name": "Tickrate", + "description": "The tickrate defines how fast the server will update each entities location.", + "env_variable": "TICKRATE", + "default_value": "22", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|integer|max:100" } ] } diff --git a/database/seeds/eggs/terraria/egg-terraria-server--t-shock.json b/database/seeds/eggs/terraria/egg-terraria-server--t-shock.json index 9be0f1142..9381890d1 100644 --- a/database/seeds/eggs/terraria/egg-terraria-server--t-shock.json +++ b/database/seeds/eggs/terraria/egg-terraria-server--t-shock.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\n# TShock Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add curl unzip\n\ncd \/tmp\n\ncurl -sSLO https:\/\/github.com\/NyxStudios\/TShock\/releases\/download\/v${T_VERSION}\/tshock_${T_VERSION}.zip\n\nunzip -o tshock_${T_VERSION}.zip -d \/mnt\/server", - "container": "alpine:3.4", + "container": "alpine:3.9", "entrypoint": "ash" } }, @@ -42,4 +42,4 @@ "rules": "required|numeric|digits_between:1,3" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/voice-servers/egg-mumble-server.json b/database/seeds/eggs/voice-servers/egg-mumble-server.json index 5e6a98e17..e62562597 100644 --- a/database/seeds/eggs/voice-servers/egg-mumble-server.json +++ b/database/seeds/eggs/voice-servers/egg-mumble-server.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\n# Mumble Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add tar curl\n\ncd \/tmp\n\ncurl -sSLO https:\/\/github.com\/mumble-voip\/mumble\/releases\/download\/${MUMBLE_VERSION}\/murmur-static_x86-${MUMBLE_VERSION}.tar.bz2\n\ntar -xjvf murmur-static_x86-${MUMBLE_VERSION}.tar.bz2\ncp -r murmur-static_x86-${MUMBLE_VERSION}\/* \/mnt\/server", - "container": "alpine:3.4", + "container": "alpine:3.9", "entrypoint": "ash" } }, @@ -42,4 +42,4 @@ "rules": "required|regex:\/^([0-9_\\.-]{5,8})$\/" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/voice-servers/egg-teamspeak3-server.json b/database/seeds/eggs/voice-servers/egg-teamspeak3-server.json index 7f89de4f2..c9521cff4 100644 --- a/database/seeds/eggs/voice-servers/egg-teamspeak3-server.json +++ b/database/seeds/eggs/voice-servers/egg-teamspeak3-server.json @@ -18,7 +18,7 @@ "scripts": { "installation": { "script": "#!\/bin\/ash\n# TS3 Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add tar curl\n\ncd \/mnt\/server\n\ncurl http:\/\/dl.4players.de\/ts\/releases\/${TS_VERSION}\/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2 | tar xj --strip-components=1", - "container": "alpine:3.4", + "container": "alpine:3.9", "entrypoint": "ash" } }, diff --git a/resources/themes/pterodactyl/admin/nodes/view/servers.blade.php b/resources/themes/pterodactyl/admin/nodes/view/servers.blade.php index de8ef5dee..5aed0ccb5 100644 --- a/resources/themes/pterodactyl/admin/nodes/view/servers.blade.php +++ b/resources/themes/pterodactyl/admin/nodes/view/servers.blade.php @@ -51,7 +51,7 @@ CPU Status - @foreach($node->servers as $server) + @foreach($servers as $server) {{ $server->uuidShort }} {{ $server->name }} @@ -64,6 +64,11 @@ @endforeach + @if($servers->hasPages()) + + @endif diff --git a/resources/themes/pterodactyl/server/databases/index.blade.php b/resources/themes/pterodactyl/server/databases/index.blade.php index e6004a706..99b1e096b 100644 --- a/resources/themes/pterodactyl/server/databases/index.blade.php +++ b/resources/themes/pterodactyl/server/databases/index.blade.php @@ -108,7 +108,7 @@ diff --git a/storage/app/packs/.githold b/storage/app/packs/.githold old mode 100644 new mode 100755 diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore old mode 100644 new mode 100755