From 87b96bdfc86045135ba74a7439aa7c7bced13930 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 1 Mar 2018 20:08:27 -0600 Subject: [PATCH 1/4] Add core logic to allow for limited databases and allocations --- .../UpdateServerBuildConfigurationRequest.php | 11 +- app/Models/Server.php | 6 + .../Servers/BuildModificationService.php | 2 + .../Api/Application/ServerTransformer.php | 4 + .../Api/Client/ServerTransformer.php | 4 + ...nd_port_limit_columns_to_servers_table.php | 33 ++++++ .../pterodactyl/admin/servers/new.blade.php | 2 +- .../admin/servers/view/build.blade.php | 109 +++++++++++------- 8 files changed, 128 insertions(+), 43 deletions(-) create mode 100644 database/migrations/2018_03_01_192831_add_database_and_port_limit_columns_to_servers_table.php diff --git a/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php b/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php index 893ff5ff7..076abdf4a 100644 --- a/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php +++ b/app/Http/Requests/Api/Application/Servers/UpdateServerBuildConfigurationRequest.php @@ -13,7 +13,7 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest */ public function rules(): array { - $rules = Server::getUpdateRulesForId($this->route()->parameter('server')->id); + $rules = Server::getUpdateRulesForId($this->getModel(Server::class)->id); return [ 'allocation' => $rules['allocation_id'], @@ -26,6 +26,9 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest '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'], ]; } @@ -39,7 +42,9 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest $data = parent::validated(); $data['allocation_id'] = $data['allocation']; - unset($data['allocation']); + $data['database_limit'] = $data['feature_limits']['databases']; + $data['allocation_limit'] = $data['feature_limits']['allocations']; + unset($data['allocation'], $data['feature_limits']); return $data; } @@ -56,6 +61,8 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest 'remove_allocations' => 'allocations to remove', 'add_allocations.*' => 'allocation to add', 'remove_allocations.*' => 'allocation to remove', + 'feature_limits.databases' => 'Database Limit', + 'feature_limits.allocations' => 'Allocation Limit', ]; } } diff --git a/app/Models/Server.php b/app/Models/Server.php index 458bff1d6..d5c6b3a8d 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -69,6 +69,8 @@ class Server extends Model implements CleansAttributes, ValidableContract 'skip_scripts' => 'sometimes', 'image' => 'required', 'startup' => 'required', + 'database_limit' => 'present', + 'allocation_limit' => 'present', ]; /** @@ -93,6 +95,8 @@ class Server extends Model implements CleansAttributes, ValidableContract 'skip_scripts' => 'boolean', 'image' => 'string|max:255', 'installed' => 'boolean', + 'database_limit' => 'nullable|integer|min:0', + 'allocation_limit' => 'nullable|integer|min:0', ]; /** @@ -116,6 +120,8 @@ class Server extends Model implements CleansAttributes, ValidableContract 'egg_id' => 'integer', 'pack_id' => 'integer', 'installed' => 'integer', + 'database_limit' => 'integer', + 'allocation_limit' => 'integer', ]; /** diff --git a/app/Services/Servers/BuildModificationService.php b/app/Services/Servers/BuildModificationService.php index 8924b2a04..5d36b4c5c 100644 --- a/app/Services/Servers/BuildModificationService.php +++ b/app/Services/Servers/BuildModificationService.php @@ -91,6 +91,8 @@ class BuildModificationService 'cpu' => array_get($data, 'cpu'), 'disk' => array_get($data, 'disk'), 'allocation_id' => array_get($data, 'allocation_id'), + 'database_limit' => array_get($data, 'database_limit'), + 'allocation_limit' => array_get($data, 'allocation_limit'), ]); $allocations = $this->allocationRepository->findWhere([['server_id', '=', $server->id]]); diff --git a/app/Transformers/Api/Application/ServerTransformer.php b/app/Transformers/Api/Application/ServerTransformer.php index 6a003b4dc..2a542dbcd 100644 --- a/app/Transformers/Api/Application/ServerTransformer.php +++ b/app/Transformers/Api/Application/ServerTransformer.php @@ -75,6 +75,10 @@ class ServerTransformer extends BaseTransformer 'io' => $server->io, 'cpu' => $server->cpu, ], + 'feature_limits' => [ + 'databases' => $server->database_limit, + 'allocations' => $server->allocation_limit, + ], 'user' => $server->owner_id, 'node' => $server->node_id, 'allocation' => $server->allocation_id, diff --git a/app/Transformers/Api/Client/ServerTransformer.php b/app/Transformers/Api/Client/ServerTransformer.php index 4f08c208d..6816d6d74 100644 --- a/app/Transformers/Api/Client/ServerTransformer.php +++ b/app/Transformers/Api/Client/ServerTransformer.php @@ -36,6 +36,10 @@ class ServerTransformer extends BaseClientTransformer 'io' => $server->io, 'cpu' => $server->cpu, ], + 'feature_limits' => [ + 'databases' => $server->database_limit, + 'allocations' => $server->allocation_limit, + ], ]; } } diff --git a/database/migrations/2018_03_01_192831_add_database_and_port_limit_columns_to_servers_table.php b/database/migrations/2018_03_01_192831_add_database_and_port_limit_columns_to_servers_table.php new file mode 100644 index 000000000..4e85e8aeb --- /dev/null +++ b/database/migrations/2018_03_01_192831_add_database_and_port_limit_columns_to_servers_table.php @@ -0,0 +1,33 @@ +unsignedInteger('database_limit')->after('installed')->nullable()->default(0); + $table->unsignedInteger('allocation_limit')->after('installed')->nullable()->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + $table->dropColumn(['database_limit', 'allocation_limit']); + }); + } +} diff --git a/resources/themes/pterodactyl/admin/servers/new.blade.php b/resources/themes/pterodactyl/admin/servers/new.blade.php index bfb6760b4..bad452312 100644 --- a/resources/themes/pterodactyl/admin/servers/new.blade.php +++ b/resources/themes/pterodactyl/admin/servers/new.blade.php @@ -111,7 +111,7 @@
- + MB
diff --git a/resources/themes/pterodactyl/admin/servers/view/build.blade.php b/resources/themes/pterodactyl/admin/servers/view/build.blade.php index f6e9e607b..8900bf90a 100644 --- a/resources/themes/pterodactyl/admin/servers/view/build.blade.php +++ b/resources/themes/pterodactyl/admin/servers/view/build.blade.php @@ -89,50 +89,79 @@
-
-
-

Allocation Management

-
-
-
- - -

The default connection address that will be used for this game server.

-
-
- -
- +
+
+
+
+

Application Feature Limits

-

Please note that due to software limitations you cannot assign identical ports on different IPs to the same server.

-
-
- -
- +
+
+
+ +
+ +
+

The total number of databases a user is allowed to create for this server. Leave blank to allow unlimmited.

+
+
+ +
+ +
+

This feature is not currently implemented. The total number of allocations a user is allowed to create for this server. Leave blank to allow unlimited.

+
+
-

Simply select which ports you would like to remove from the list above. If you want to assign a port on a different IP that is already in use you can select it from the left and delete it here.

-
From 07893effa3aa40994da06eb03110205e296c791e Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 1 Mar 2018 21:27:37 -0600 Subject: [PATCH 2/4] Add initial go at user created databases for servers, still needs cleaning --- ...tabaseClientFeatureNotEnabledException.php | 13 +++ .../NoSuitableDatabaseHostException.php | 16 ++++ .../Database/TooManyDatabasesException.php | 13 +++ .../Controllers/Server/DatabaseController.php | 76 ++++++++++++++-- .../Database/StoreServerDatabaseRequest.php | 43 +++++++++ .../Requests/Server/ServerFormRequest.php | 8 +- .../Databases/DatabaseManagementService.php | 15 ++-- .../Databases/DeployServerDatabaseService.php | 87 +++++++++++++++++++ config/pterodactyl.php | 15 ++++ .../server/databases/index.blade.php | 51 ++++++++--- routes/server.php | 2 + 11 files changed, 314 insertions(+), 25 deletions(-) create mode 100644 app/Exceptions/Service/Database/DatabaseClientFeatureNotEnabledException.php create mode 100644 app/Exceptions/Service/Database/NoSuitableDatabaseHostException.php create mode 100644 app/Exceptions/Service/Database/TooManyDatabasesException.php create mode 100644 app/Http/Requests/Server/Database/StoreServerDatabaseRequest.php create mode 100644 app/Services/Databases/DeployServerDatabaseService.php diff --git a/app/Exceptions/Service/Database/DatabaseClientFeatureNotEnabledException.php b/app/Exceptions/Service/Database/DatabaseClientFeatureNotEnabledException.php new file mode 100644 index 000000000..809cb4fbf --- /dev/null +++ b/app/Exceptions/Service/Database/DatabaseClientFeatureNotEnabledException.php @@ -0,0 +1,13 @@ +alert = $alert; + $this->databaseHostRepository = $databaseHostRepository; + $this->deployServerDatabaseService = $deployServerDatabaseService; $this->passwordService = $passwordService; $this->repository = $repository; } @@ -50,11 +81,42 @@ class DatabaseController extends Controller $this->authorize('view-databases', $server); $this->setRequest($request)->injectJavascript(); + $canCreateDatabase = config('pterodactyl.client_features.databases.enabled'); + $allowRandom = config('pterodactyl.client_features.databases.allow_random'); + + if ($this->databaseHostRepository->findCountWhere([['node_id', '=', $server->node_id]]) === 0) { + if ($canCreateDatabase && ! $allowRandom) { + $canCreateDatabase = false; + } + } + + $databases = $this->repository->getDatabasesForServer($server->id); + return view('server.databases.index', [ - 'databases' => $this->repository->getDatabasesForServer($server->id), + 'allowCreation' => $canCreateDatabase, + 'overLimit' => ! is_null($server->database_limit) && count($databases) >= $server->database_limit, + 'databases' => $databases, ]); } + /** + * Handle a request from a user to create a new database for the server. + * + * @param \Pterodactyl\Http\Requests\Server\Database\StoreServerDatabaseRequest $request + * @return \Illuminate\Http\RedirectResponse + * + * @throws \Exception + * @throws \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException + */ + public function store(StoreServerDatabaseRequest $request): RedirectResponse + { + $this->deployServerDatabaseService->handle($request->getServer(), $request->validated()); + + $this->alert->success('Successfully created a new database.')->flash(); + + return redirect()->route('server.databases.index', $request->getServer()->uuidShort); + } + /** * Handle a request to update the password for a specific database. * diff --git a/app/Http/Requests/Server/Database/StoreServerDatabaseRequest.php b/app/Http/Requests/Server/Database/StoreServerDatabaseRequest.php new file mode 100644 index 000000000..2af23a914 --- /dev/null +++ b/app/Http/Requests/Server/Database/StoreServerDatabaseRequest.php @@ -0,0 +1,43 @@ + 'required|string|min:1', + 'remote' => 'required|string|regex:/^[0-9%.]{1,15}$/', + ]; + } +} diff --git a/app/Http/Requests/Server/ServerFormRequest.php b/app/Http/Requests/Server/ServerFormRequest.php index b796a21e0..f59ea3ae3 100644 --- a/app/Http/Requests/Server/ServerFormRequest.php +++ b/app/Http/Requests/Server/ServerFormRequest.php @@ -2,6 +2,7 @@ namespace Pterodactyl\Http\Requests\Server; +use Pterodactyl\Models\Server; use Pterodactyl\Http\Requests\FrontendUserFormRequest; abstract class ServerFormRequest extends FrontendUserFormRequest @@ -24,6 +25,11 @@ abstract class ServerFormRequest extends FrontendUserFormRequest return false; } - return $this->user()->can($this->permission(), $this->attributes->get('server')); + return $this->user()->can($this->permission(), $this->getServer()); + } + + public function getServer(): Server + { + return $this->attributes->get('server'); } } diff --git a/app/Services/Databases/DatabaseManagementService.php b/app/Services/Databases/DatabaseManagementService.php index b05ddc3ff..dc91e11f9 100644 --- a/app/Services/Databases/DatabaseManagementService.php +++ b/app/Services/Databases/DatabaseManagementService.php @@ -13,22 +13,27 @@ class DatabaseManagementService /** * @var \Illuminate\Database\DatabaseManager */ - protected $database; + private $database; /** * @var \Pterodactyl\Extensions\DynamicDatabaseConnection */ - protected $dynamic; + private $dynamic; /** * @var \Illuminate\Contracts\Encryption\Encrypter */ - protected $encrypter; + private $encrypter; /** * @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface */ - protected $repository; + private $repository; + + /** + * @var bool + */ + protected $useRandomHost = false; /** * CreationService constructor. @@ -55,7 +60,7 @@ class DatabaseManagementService * * @param int $server * @param array $data - * @return \Illuminate\Database\Eloquent\Model + * @return \Pterodactyl\Models\Database * * @throws \Exception */ diff --git a/app/Services/Databases/DeployServerDatabaseService.php b/app/Services/Databases/DeployServerDatabaseService.php new file mode 100644 index 000000000..2932b87f2 --- /dev/null +++ b/app/Services/Databases/DeployServerDatabaseService.php @@ -0,0 +1,87 @@ +databaseHostRepository = $databaseHostRepository; + $this->managementService = $managementService; + $this->repository = $repository; + } + + /** + * @param \Pterodactyl\Models\Server $server + * @param array $data + * @return \Pterodactyl\Models\Database + * + * @throws \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException + * @throws \Exception + */ + public function handle(Server $server, array $data): Database + { + if (! config('pterodactyl.client_features.databases.enabled')) { + throw new DatabaseClientFeatureNotEnabledException; + } + + $databases = $this->repository->findCountWhere([['server_id', '=', $server->id]]); + if (! is_null($server->database_limit) && $databases >= $server->database_limit) { + throw new TooManyDatabasesException; + } + + $allowRandom = config('pterodactyl.client_features.databases.allow_random'); + $host = $this->databaseHostRepository->setColumns(['id'])->findWhere([ + ['node_id', '=', $server->node_id], + ])->random(); + + if (empty($host) && ! $allowRandom) { + throw new NoSuitableDatabaseHostException; + } + + if (empty($host)) { + $host = $this->databaseHostRepository->setColumns(['id'])->all()->random(); + if (empty($host)) { + throw new NoSuitableDatabaseHostException; + } + } + + return $this->managementService->create($server->id, [ + 'database_host_id' => $host->id, + 'database' => array_get($data, 'database'), + 'remote' => array_get($data, 'remote'), + ]); + } +} diff --git a/config/pterodactyl.php b/config/pterodactyl.php index 523080ae3..e06c709ef 100644 --- a/config/pterodactyl.php +++ b/config/pterodactyl.php @@ -163,6 +163,21 @@ return [ 'in_context' => env('PHRASE_IN_CONTEXT', false), ], + /* + |-------------------------------------------------------------------------- + | Language Editor + |-------------------------------------------------------------------------- + | + | Set `PHRASE_IN_CONTEXT` to true to enable the PhaseApp in-context editor + | on this site which allows you to translate the panel, from the panel. + */ + 'client_features' => [ + 'databases' => [ + 'enabled' => env('PTERODACTYL_CLIENT_DATABASES_ENABLED', true), + 'allow_random' => env('PTERODACTYL_CLIENT_DATABASES_ALLOW_RANDOM', true), + ], + ], + /* |-------------------------------------------------------------------------- | File Editor diff --git a/resources/themes/pterodactyl/server/databases/index.blade.php b/resources/themes/pterodactyl/server/databases/index.blade.php index 6ba24c1ad..b8e01db84 100644 --- a/resources/themes/pterodactyl/server/databases/index.blade.php +++ b/resources/themes/pterodactyl/server/databases/index.blade.php @@ -21,15 +21,10 @@ @section('content')
-
+

@lang('server.config.database.your_dbs')

- @if(auth()->user()->root_admin) - - @endif
@if(count($databases) > 0)
@@ -69,17 +64,49 @@
@lang('server.config.database.no_dbs') - @if(Auth::user()->root_admin === 1) - @lang('server.config.database.add_db') - @endif
@endif
+ @if($allowCreation) +
+
+
+

Create New Database

+
+ @if($overLimit) +
+
+ You are currently using {{ count($databases) }} of your {{ $server->database_limit ?? '∞' }} allowed databases. +
+
+ @else +
+
+
+ +
+ s{{ $server->id }}_ + +
+
+
+ + +

This should reflect the IP address that connections are allowed from. Uses standard MySQL notation. If unsure leave as %.

+
+
+ +
+ @endif +
+
+ @endif
@endsection diff --git a/routes/server.php b/routes/server.php index 85283df9e..93005aaec 100644 --- a/routes/server.php +++ b/routes/server.php @@ -38,6 +38,8 @@ Route::group(['prefix' => 'settings'], function () { Route::group(['prefix' => 'databases'], function () { Route::get('/', 'DatabaseController@index')->name('server.databases.index'); + Route::post('/new', 'DatabaseController@store')->name('server.databases.new'); + Route::patch('/password', 'DatabaseController@update')->middleware('server..database')->name('server.databases.password'); }); From bcb69603ad5769a623cf813f0fb89dbfe77f225d Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 2 Mar 2018 19:03:55 -0600 Subject: [PATCH 3/4] Add support for user management of databases --- CHANGELOG.md | 1 + .../Controllers/Server/DatabaseController.php | 26 ++++++++++ .../Server/DatabaseBelongsToServer.php | 7 ++- .../Database/DeleteServerDatabaseRequest.php | 40 +++++++++++++++ app/Models/Permission.php | 2 + public/js/laroute.js | 2 +- resources/lang/en/server.php | 8 +++ .../server/databases/index.blade.php | 51 +++++++++++++++++-- routes/server.php | 2 + 9 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 app/Http/Requests/Server/Database/DeleteServerDatabaseRequest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index fef00d908..d182ef4a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines. * Adds back client API for sending commands or power toggles to a server though the Panel API: `/api/client/servers/` * Added proper transformer for Packs and re-enabled missing includes on server. * Added support for using Filesystem as a caching driver, although not recommended. +* Added support for user management of server databases. ## v0.7.3 (Derelict Dermodactylus) ### Fixed diff --git a/app/Http/Controllers/Server/DatabaseController.php b/app/Http/Controllers/Server/DatabaseController.php index 1c2875a02..be7d501ba 100644 --- a/app/Http/Controllers/Server/DatabaseController.php +++ b/app/Http/Controllers/Server/DatabaseController.php @@ -4,16 +4,19 @@ namespace Pterodactyl\Http\Controllers\Server; use Illuminate\View\View; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Prologue\Alerts\AlertsMessageBag; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Traits\Controllers\JavascriptInjection; use Pterodactyl\Services\Databases\DatabasePasswordService; +use Pterodactyl\Services\Databases\DatabaseManagementService; use Pterodactyl\Services\Databases\DeployServerDatabaseService; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface; use Pterodactyl\Http\Requests\Server\Database\StoreServerDatabaseRequest; +use Pterodactyl\Http\Requests\Server\Database\DeleteServerDatabaseRequest; class DatabaseController extends Controller { @@ -34,6 +37,11 @@ class DatabaseController extends Controller */ private $databaseHostRepository; + /** + * @var \Pterodactyl\Services\Databases\DatabaseManagementService + */ + private $managementService; + /** * @var \Pterodactyl\Services\Databases\DatabasePasswordService */ @@ -50,6 +58,7 @@ class DatabaseController extends Controller * @param \Prologue\Alerts\AlertsMessageBag $alert * @param \Pterodactyl\Services\Databases\DeployServerDatabaseService $deployServerDatabaseService * @param \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface $databaseHostRepository + * @param \Pterodactyl\Services\Databases\DatabaseManagementService $managementService * @param \Pterodactyl\Services\Databases\DatabasePasswordService $passwordService * @param \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface $repository */ @@ -57,12 +66,14 @@ class DatabaseController extends Controller AlertsMessageBag $alert, DeployServerDatabaseService $deployServerDatabaseService, DatabaseHostRepositoryInterface $databaseHostRepository, + DatabaseManagementService $managementService, DatabasePasswordService $passwordService, DatabaseRepositoryInterface $repository ) { $this->alert = $alert; $this->databaseHostRepository = $databaseHostRepository; $this->deployServerDatabaseService = $deployServerDatabaseService; + $this->managementService = $managementService; $this->passwordService = $passwordService; $this->repository = $repository; } @@ -136,4 +147,19 @@ class DatabaseController extends Controller return response()->json(['password' => $password]); } + + /** + * Delete a database for this server from the SQL server and Panel database. + * + * @param \Pterodactyl\Http\Requests\Server\Database\DeleteServerDatabaseRequest $request + * @return \Illuminate\Http\Response + * + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + */ + public function delete(DeleteServerDatabaseRequest $request): Response + { + $this->managementService->delete($request->attributes->get('database')->id); + + return response('', Response::HTTP_NO_CONTENT); + } } diff --git a/app/Http/Middleware/Server/DatabaseBelongsToServer.php b/app/Http/Middleware/Server/DatabaseBelongsToServer.php index d7e34d211..1617a8520 100644 --- a/app/Http/Middleware/Server/DatabaseBelongsToServer.php +++ b/app/Http/Middleware/Server/DatabaseBelongsToServer.php @@ -38,8 +38,13 @@ class DatabaseBelongsToServer public function handle(Request $request, Closure $next) { $server = $request->attributes->get('server'); + $database = $request->input('database') ?? $request->route()->parameter('database'); - $database = $this->repository->find($request->input('database')); + if (! is_digit($database)) { + throw new NotFoundHttpException; + } + + $database = $this->repository->find($database); if (is_null($database) || $database->server_id !== $server->id) { throw new NotFoundHttpException; } diff --git a/app/Http/Requests/Server/Database/DeleteServerDatabaseRequest.php b/app/Http/Requests/Server/Database/DeleteServerDatabaseRequest.php new file mode 100644 index 000000000..f2c81d9c8 --- /dev/null +++ b/app/Http/Requests/Server/Database/DeleteServerDatabaseRequest.php @@ -0,0 +1,40 @@ + [ 'view-databases' => null, 'reset-db-password' => null, + 'delete-database' => null, + 'create-database' => null, ], 'file' => [ 'access-sftp' => null, diff --git a/public/js/laroute.js b/public/js/laroute.js index c0e77614d..1ffbc7b1f 100644 --- a/public/js/laroute.js +++ b/public/js/laroute.js @@ -6,7 +6,7 @@ absolute: false, rootUrl: 'http://pterodactyl.local', - routes : [{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/open","name":"debugbar.openhandler","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@handle"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/clockwork\/{id}","name":"debugbar.clockwork","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@clockwork"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/stylesheets","name":"debugbar.assets.css","action":"Barryvdh\Debugbar\Controllers\AssetController@css"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/javascript","name":"debugbar.assets.js","action":"Barryvdh\Debugbar\Controllers\AssetController@js"},{"host":null,"methods":["DELETE"],"uri":"_debugbar\/cache\/{key}\/{tags?}","name":"debugbar.cache.delete","action":"Barryvdh\Debugbar\Controllers\CacheController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"\/","name":"index","action":"Pterodactyl\Http\Controllers\Base\IndexController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"status\/{server}","name":"index.status","action":"Pterodactyl\Http\Controllers\Base\IndexController@status"},{"host":null,"methods":["GET","HEAD"],"uri":"account","name":"account","action":"Pterodactyl\Http\Controllers\Base\AccountController@index"},{"host":null,"methods":["POST"],"uri":"account","name":null,"action":"Pterodactyl\Http\Controllers\Base\AccountController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api","name":"account.api","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api\/new","name":"account.api.new","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@create"},{"host":null,"methods":["POST"],"uri":"account\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Base\ClientApiController@store"},{"host":null,"methods":["DELETE"],"uri":"account\/api\/revoke\/{identifier}","name":"account.api.revoke","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security","name":"account.security","action":"Pterodactyl\Http\Controllers\Base\SecurityController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security\/revoke\/{id}","name":"account.security.revoke","action":"Pterodactyl\Http\Controllers\Base\SecurityController@revoke"},{"host":null,"methods":["PUT"],"uri":"account\/security\/totp","name":"account.security.totp","action":"Pterodactyl\Http\Controllers\Base\SecurityController@generateTotp"},{"host":null,"methods":["POST"],"uri":"account\/security\/totp","name":"account.security.totp.set","action":"Pterodactyl\Http\Controllers\Base\SecurityController@setTotp"},{"host":null,"methods":["DELETE"],"uri":"account\/security\/totp","name":"account.security.totp.disable","action":"Pterodactyl\Http\Controllers\Base\SecurityController@disableTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"admin","name":"admin.index","action":"Pterodactyl\Http\Controllers\Admin\BaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/api","name":"admin.api.index","action":"Pterodactyl\Http\Controllers\Admin\ApiController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/api\/new","name":"admin.api.new","action":"Pterodactyl\Http\Controllers\Admin\ApiController@create"},{"host":null,"methods":["POST"],"uri":"admin\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ApiController@store"},{"host":null,"methods":["DELETE"],"uri":"admin\/api\/revoke\/{identifier}","name":"admin.api.delete","action":"Pterodactyl\Http\Controllers\Admin\ApiController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations","name":"admin.locations","action":"Pterodactyl\Http\Controllers\Admin\LocationController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations\/view\/{location}","name":"admin.locations.view","action":"Pterodactyl\Http\Controllers\Admin\LocationController@view"},{"host":null,"methods":["POST"],"uri":"admin\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationController@create"},{"host":null,"methods":["PATCH"],"uri":"admin\/locations\/view\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases","name":"admin.databases","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases\/view\/{host}","name":"admin.databases.view","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@view"},{"host":null,"methods":["POST"],"uri":"admin\/databases","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@create"},{"host":null,"methods":["PATCH"],"uri":"admin\/databases\/view\/{host}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/view\/{host}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings","name":"admin.settings","action":"Pterodactyl\Http\Controllers\Admin\Settings\IndexController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings\/mail","name":"admin.settings.mail","action":"Pterodactyl\Http\Controllers\Admin\Settings\MailController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings\/advanced","name":"admin.settings.advanced","action":"Pterodactyl\Http\Controllers\Admin\Settings\AdvancedController@index"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\IndexController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings\/mail","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\MailController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings\/advanced","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\AdvancedController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users","name":"admin.users","action":"Pterodactyl\Http\Controllers\Admin\UserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/accounts.json","name":"admin.users.json","action":"Pterodactyl\Http\Controllers\Admin\UserController@json"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/new","name":"admin.users.new","action":"Pterodactyl\Http\Controllers\Admin\UserController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/view\/{user}","name":"admin.users.view","action":"Pterodactyl\Http\Controllers\Admin\UserController@view"},{"host":null,"methods":["POST"],"uri":"admin\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@store"},{"host":null,"methods":["PATCH"],"uri":"admin\/users\/view\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/users\/view\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers","name":"admin.servers","action":"Pterodactyl\Http\Controllers\Admin\ServersController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/new","name":"admin.servers.new","action":"Pterodactyl\Http\Controllers\Admin\ServersController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}","name":"admin.servers.view","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/details","name":"admin.servers.view.details","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDetails"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/build","name":"admin.servers.view.build","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewBuild"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/startup","name":"admin.servers.view.startup","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewStartup"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/database","name":"admin.servers.view.database","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDatabase"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/manage","name":"admin.servers.view.manage","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewManage"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/delete","name":"admin.servers.view.delete","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDelete"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@store"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/build","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@updateBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@saveStartup"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/database","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@newDatabase"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/toggle","name":"admin.servers.view.manage.toggle","action":"Pterodactyl\Http\Controllers\Admin\ServersController@toggleInstall"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/rebuild","name":"admin.servers.view.manage.rebuild","action":"Pterodactyl\Http\Controllers\Admin\ServersController@rebuildContainer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/suspension","name":"admin.servers.view.manage.suspension","action":"Pterodactyl\Http\Controllers\Admin\ServersController@manageSuspension"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/reinstall","name":"admin.servers.view.manage.reinstall","action":"Pterodactyl\Http\Controllers\Admin\ServersController@reinstallServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/delete","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@delete"},{"host":null,"methods":["PATCH"],"uri":"admin\/servers\/view\/{server}\/details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@setDetails"},{"host":null,"methods":["PATCH"],"uri":"admin\/servers\/view\/{server}\/database","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@resetDatabasePassword"},{"host":null,"methods":["DELETE"],"uri":"admin\/servers\/view\/{server}\/database\/{database}\/delete","name":"admin.servers.view.database.delete","action":"Pterodactyl\Http\Controllers\Admin\ServersController@deleteDatabase"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes","name":"admin.nodes","action":"Pterodactyl\Http\Controllers\Admin\NodesController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/new","name":"admin.nodes.new","action":"Pterodactyl\Http\Controllers\Admin\NodesController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}","name":"admin.nodes.view","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/settings","name":"admin.nodes.view.settings","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/configuration","name":"admin.nodes.view.configuration","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/allocation","name":"admin.nodes.view.allocation","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewAllocation"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/servers","name":"admin.nodes.view.servers","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewServers"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/settings\/token","name":"admin.nodes.view.configuration.token","action":"Pterodactyl\Http\Controllers\Admin\NodesController@setToken"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@createAllocation"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation\/remove","name":"admin.nodes.view.allocation.removeBlock","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationRemoveBlock"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation\/alias","name":"admin.nodes.view.allocation.setAlias","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationSetAlias"},{"host":null,"methods":["PATCH"],"uri":"admin\/nodes\/view\/{node}\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@updateSettings"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{node}\/delete","name":"admin.nodes.view.delete","action":"Pterodactyl\Http\Controllers\Admin\NodesController@delete"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{node}\/allocation\/remove\/{allocation}","name":"admin.nodes.view.allocation.removeSingle","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationRemoveSingle"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests","name":"admin.nests","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/new","name":"admin.nests.new","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/view\/{nest}","name":"admin.nests.view","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/new","name":"admin.nests.egg.new","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}","name":"admin.nests.egg.view","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/export","name":"admin.nests.egg.export","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@export"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/variables","name":"admin.nests.egg.variables","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/scripts","name":"admin.nests.egg.scripts","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggScriptController@index"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/import","name":"admin.nests.egg.import","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@import"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/egg\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/egg\/{egg}\/variables","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@store"},{"host":null,"methods":["PUT"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/view\/{nest}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}\/scripts","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggScriptController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","name":"admin.nests.egg.variables.edit","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/view\/{nest}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@destroy"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@destroy"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@destroy"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs","name":"admin.packs","action":"Pterodactyl\Http\Controllers\Admin\PackController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/new","name":"admin.packs.new","action":"Pterodactyl\Http\Controllers\Admin\PackController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/new\/template","name":"admin.packs.new.template","action":"Pterodactyl\Http\Controllers\Admin\PackController@newTemplate"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/view\/{pack}","name":"admin.packs.view","action":"Pterodactyl\Http\Controllers\Admin\PackController@view"},{"host":null,"methods":["POST"],"uri":"admin\/packs\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@store"},{"host":null,"methods":["POST"],"uri":"admin\/packs\/view\/{pack}\/export\/{files?}","name":"admin.packs.view.export","action":"Pterodactyl\Http\Controllers\Admin\PackController@export"},{"host":null,"methods":["PATCH"],"uri":"admin\/packs\/view\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/packs\/view\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@destroy"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login","name":"auth.login","action":"Pterodactyl\Http\Controllers\Auth\LoginController@showLoginForm"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login\/totp","name":"auth.totp","action":"Pterodactyl\Http\Controllers\Auth\LoginController@totp"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password","name":"auth.password","action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password\/reset\/{token}","name":"auth.reset","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@showResetForm"},{"host":null,"methods":["POST"],"uri":"auth\/login","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@login"},{"host":null,"methods":["POST"],"uri":"auth\/login\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@loginUsingTotp"},{"host":null,"methods":["POST"],"uri":"auth\/password","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset","name":"auth.reset.post","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@reset"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset\/{token}","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/logout","name":"auth.logout","action":"Pterodactyl\Http\Controllers\Auth\LoginController@logout"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}","name":"server.index","action":"Pterodactyl\Http\Controllers\Server\ConsoleController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/console","name":"server.console","action":"Pterodactyl\Http\Controllers\Server\ConsoleController@console"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/allocation","name":"server.settings.allocation","action":"Pterodactyl\Http\Controllers\Server\Settings\AllocationController@index"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/settings\/allocation","name":null,"action":"Pterodactyl\Http\Controllers\Server\Settings\AllocationController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/sftp","name":"server.settings.sftp","action":"Pterodactyl\Http\Controllers\Server\Settings\SftpController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/startup","name":"server.settings.startup","action":"Pterodactyl\Http\Controllers\Server\Settings\StartupController@index"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/settings\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Server\Settings\StartupController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/databases","name":"server.databases.index","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@index"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/databases\/password","name":"server.databases.password","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files","name":"server.files.index","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/add","name":"server.files.add","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/edit\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/download\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\Files\DownloadController@index"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/directory-list","name":"server.files.directory-list","action":"Pterodactyl\Http\Controllers\Server\Files\RemoteRequestController@directory"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/save","name":"server.files.save","action":"Pterodactyl\Http\Controllers\Server\Files\RemoteRequestController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users","name":"server.subusers","action":"Pterodactyl\Http\Controllers\Server\SubuserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/new","name":"server.subusers.new","action":"Pterodactyl\Http\Controllers\Server\SubuserController@create"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/view\/{subuser}","name":"server.subusers.view","action":"Pterodactyl\Http\Controllers\Server\SubuserController@view"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/users\/view\/{subuser}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@update"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/users\/view\/{subuser}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules","name":"server.schedules","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules\/new","name":"server.schedules.new","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@create"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":"server.schedules.view","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@view"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@update"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/view\/{schedule}\/toggle","name":"server.schedules.toggle","action":"Pterodactyl\Http\Controllers\Server\Tasks\ActionController@toggle"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/view\/{schedule}\/trigger","name":"server.schedules.trigger","action":"Pterodactyl\Http\Controllers\Server\Tasks\ActionController@trigger"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users","name":"api.application.users","action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users\/{user}","name":"api.application.users.view","action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users\/external\/{external_id}","name":"api.application.users.external","action":"Pterodactyl\Http\Controllers\Api\Application\Users\ExternalUserController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/users","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/users\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/users\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes","name":"api.application.nodes","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes\/{node}","name":"api.application.nodes.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/nodes","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/nodes\/{node}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/nodes\/{node}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes\/{node}\/allocations","name":"api.application.allocations","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/nodes\/{node}\/allocations","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@store"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/nodes\/{node}\/allocations\/{allocation}","name":"api.application.allocations.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/locations","name":"api.applications.locations","action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/locations\/{location}","name":"api.application.locations.view","action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/locations\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/locations\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers","name":"api.application.servers","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}","name":"api.application.servers.view","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/external\/{external_id}","name":"api.application.servers.external","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ExternalServerController@index"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/details","name":"api.application.servers.details","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController@details"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/build","name":"api.application.servers.build","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController@build"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/startup","name":"api.application.servers.startup","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\StartupController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@store"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/suspend","name":"api.application.servers.suspend","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@suspend"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/unsuspend","name":"api.application.servers.unsuspend","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@unsuspend"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/reinstall","name":"api.application.servers.reinstall","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@reinstall"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/rebuild","name":"api.application.servers.rebuild","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@rebuild"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@delete"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}\/{force?}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}\/databases","name":"api.application.servers.databases","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}\/databases\/{database}","name":"api.application.servers.databases.view","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/databases","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@store"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/databases\/{database}\/reset-password","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@resetPassword"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}\/databases\/{database}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests","name":"api.application.nests","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\NestController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}","name":"api.application.nests.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\NestController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}\/eggs","name":"api.application.nests.eggs","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\EggController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}\/eggs\/{egg}","name":"api.application.nests.eggs.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\EggController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/client","name":"api.client.index","action":"Pterodactyl\Http\Controllers\Api\Client\ClientController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/client\/servers\/{server}","name":"api.client.servers.view","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\ServerController@index"},{"host":null,"methods":["POST"],"uri":"api\/client\/servers\/{server}\/command","name":"api.client.servers.command","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\CommandController@index"},{"host":null,"methods":["POST"],"uri":"api\/client\/servers\/{server}\/power","name":"api.client.servers.power","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\PowerController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/authenticate\/{token}","name":"api.remote.authenticate","action":"Pterodactyl\Http\Controllers\Api\Remote\ValidateKeyController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/eggs","name":"api.remote.eggs","action":"Pterodactyl\Http\Controllers\Api\Remote\EggRetrievalController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/eggs\/{uuid}","name":"api.remote.eggs.download","action":"Pterodactyl\Http\Controllers\Api\Remote\EggRetrievalController@download"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/scripts\/{uuid}","name":"api.remote.scripts","action":"Pterodactyl\Http\Controllers\Api\Remote\EggInstallController@index"},{"host":null,"methods":["POST"],"uri":"api\/remote\/sftp","name":"api.remote.sftp","action":"Pterodactyl\Http\Controllers\Api\Remote\SftpController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/packs\/pull\/{uuid}","name":"daemon.pack.pull","action":"Pterodactyl\Http\Controllers\Daemon\PackController@pull"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/packs\/pull\/{uuid}\/hash","name":"daemon.pack.hash","action":"Pterodactyl\Http\Controllers\Daemon\PackController@hash"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/configure\/{token}","name":"daemon.configuration","action":"Pterodactyl\Http\Controllers\Daemon\ActionController@configuration"},{"host":null,"methods":["POST"],"uri":"daemon\/download","name":"daemon.download","action":"Pterodactyl\Http\Controllers\Daemon\ActionController@authenticateDownload"},{"host":null,"methods":["POST"],"uri":"daemon\/install","name":"daemon.install","action":"Pterodactyl\Http\Controllers\Daemon\ActionController@markInstall"}], + routes : [{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/open","name":"debugbar.openhandler","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@handle"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/clockwork\/{id}","name":"debugbar.clockwork","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@clockwork"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/stylesheets","name":"debugbar.assets.css","action":"Barryvdh\Debugbar\Controllers\AssetController@css"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/javascript","name":"debugbar.assets.js","action":"Barryvdh\Debugbar\Controllers\AssetController@js"},{"host":null,"methods":["DELETE"],"uri":"_debugbar\/cache\/{key}\/{tags?}","name":"debugbar.cache.delete","action":"Barryvdh\Debugbar\Controllers\CacheController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"\/","name":"index","action":"Pterodactyl\Http\Controllers\Base\IndexController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"status\/{server}","name":"index.status","action":"Pterodactyl\Http\Controllers\Base\IndexController@status"},{"host":null,"methods":["GET","HEAD"],"uri":"account","name":"account","action":"Pterodactyl\Http\Controllers\Base\AccountController@index"},{"host":null,"methods":["POST"],"uri":"account","name":null,"action":"Pterodactyl\Http\Controllers\Base\AccountController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api","name":"account.api","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api\/new","name":"account.api.new","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@create"},{"host":null,"methods":["POST"],"uri":"account\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Base\ClientApiController@store"},{"host":null,"methods":["DELETE"],"uri":"account\/api\/revoke\/{identifier}","name":"account.api.revoke","action":"Pterodactyl\Http\Controllers\Base\ClientApiController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security","name":"account.security","action":"Pterodactyl\Http\Controllers\Base\SecurityController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security\/revoke\/{id}","name":"account.security.revoke","action":"Pterodactyl\Http\Controllers\Base\SecurityController@revoke"},{"host":null,"methods":["PUT"],"uri":"account\/security\/totp","name":"account.security.totp","action":"Pterodactyl\Http\Controllers\Base\SecurityController@generateTotp"},{"host":null,"methods":["POST"],"uri":"account\/security\/totp","name":"account.security.totp.set","action":"Pterodactyl\Http\Controllers\Base\SecurityController@setTotp"},{"host":null,"methods":["DELETE"],"uri":"account\/security\/totp","name":"account.security.totp.disable","action":"Pterodactyl\Http\Controllers\Base\SecurityController@disableTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"admin","name":"admin.index","action":"Pterodactyl\Http\Controllers\Admin\BaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/api","name":"admin.api.index","action":"Pterodactyl\Http\Controllers\Admin\ApiController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/api\/new","name":"admin.api.new","action":"Pterodactyl\Http\Controllers\Admin\ApiController@create"},{"host":null,"methods":["POST"],"uri":"admin\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ApiController@store"},{"host":null,"methods":["DELETE"],"uri":"admin\/api\/revoke\/{identifier}","name":"admin.api.delete","action":"Pterodactyl\Http\Controllers\Admin\ApiController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations","name":"admin.locations","action":"Pterodactyl\Http\Controllers\Admin\LocationController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations\/view\/{location}","name":"admin.locations.view","action":"Pterodactyl\Http\Controllers\Admin\LocationController@view"},{"host":null,"methods":["POST"],"uri":"admin\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationController@create"},{"host":null,"methods":["PATCH"],"uri":"admin\/locations\/view\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases","name":"admin.databases","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases\/view\/{host}","name":"admin.databases.view","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@view"},{"host":null,"methods":["POST"],"uri":"admin\/databases","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@create"},{"host":null,"methods":["PATCH"],"uri":"admin\/databases\/view\/{host}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/view\/{host}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings","name":"admin.settings","action":"Pterodactyl\Http\Controllers\Admin\Settings\IndexController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings\/mail","name":"admin.settings.mail","action":"Pterodactyl\Http\Controllers\Admin\Settings\MailController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings\/advanced","name":"admin.settings.advanced","action":"Pterodactyl\Http\Controllers\Admin\Settings\AdvancedController@index"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\IndexController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings\/mail","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\MailController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/settings\/advanced","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Settings\AdvancedController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users","name":"admin.users","action":"Pterodactyl\Http\Controllers\Admin\UserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/accounts.json","name":"admin.users.json","action":"Pterodactyl\Http\Controllers\Admin\UserController@json"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/new","name":"admin.users.new","action":"Pterodactyl\Http\Controllers\Admin\UserController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/view\/{user}","name":"admin.users.view","action":"Pterodactyl\Http\Controllers\Admin\UserController@view"},{"host":null,"methods":["POST"],"uri":"admin\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@store"},{"host":null,"methods":["PATCH"],"uri":"admin\/users\/view\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/users\/view\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers","name":"admin.servers","action":"Pterodactyl\Http\Controllers\Admin\ServersController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/new","name":"admin.servers.new","action":"Pterodactyl\Http\Controllers\Admin\ServersController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}","name":"admin.servers.view","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/details","name":"admin.servers.view.details","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDetails"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/build","name":"admin.servers.view.build","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewBuild"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/startup","name":"admin.servers.view.startup","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewStartup"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/database","name":"admin.servers.view.database","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDatabase"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/manage","name":"admin.servers.view.manage","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewManage"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{server}\/delete","name":"admin.servers.view.delete","action":"Pterodactyl\Http\Controllers\Admin\ServersController@viewDelete"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@store"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/build","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@updateBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@saveStartup"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/database","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@newDatabase"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/toggle","name":"admin.servers.view.manage.toggle","action":"Pterodactyl\Http\Controllers\Admin\ServersController@toggleInstall"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/rebuild","name":"admin.servers.view.manage.rebuild","action":"Pterodactyl\Http\Controllers\Admin\ServersController@rebuildContainer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/suspension","name":"admin.servers.view.manage.suspension","action":"Pterodactyl\Http\Controllers\Admin\ServersController@manageSuspension"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/manage\/reinstall","name":"admin.servers.view.manage.reinstall","action":"Pterodactyl\Http\Controllers\Admin\ServersController@reinstallServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{server}\/delete","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@delete"},{"host":null,"methods":["PATCH"],"uri":"admin\/servers\/view\/{server}\/details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@setDetails"},{"host":null,"methods":["PATCH"],"uri":"admin\/servers\/view\/{server}\/database","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@resetDatabasePassword"},{"host":null,"methods":["DELETE"],"uri":"admin\/servers\/view\/{server}\/database\/{database}\/delete","name":"admin.servers.view.database.delete","action":"Pterodactyl\Http\Controllers\Admin\ServersController@deleteDatabase"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes","name":"admin.nodes","action":"Pterodactyl\Http\Controllers\Admin\NodesController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/new","name":"admin.nodes.new","action":"Pterodactyl\Http\Controllers\Admin\NodesController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}","name":"admin.nodes.view","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/settings","name":"admin.nodes.view.settings","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/configuration","name":"admin.nodes.view.configuration","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/allocation","name":"admin.nodes.view.allocation","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewAllocation"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/servers","name":"admin.nodes.view.servers","action":"Pterodactyl\Http\Controllers\Admin\NodesController@viewServers"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{node}\/settings\/token","name":"admin.nodes.view.configuration.token","action":"Pterodactyl\Http\Controllers\Admin\NodesController@setToken"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@createAllocation"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation\/remove","name":"admin.nodes.view.allocation.removeBlock","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationRemoveBlock"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{node}\/allocation\/alias","name":"admin.nodes.view.allocation.setAlias","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationSetAlias"},{"host":null,"methods":["PATCH"],"uri":"admin\/nodes\/view\/{node}\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@updateSettings"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{node}\/delete","name":"admin.nodes.view.delete","action":"Pterodactyl\Http\Controllers\Admin\NodesController@delete"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{node}\/allocation\/remove\/{allocation}","name":"admin.nodes.view.allocation.removeSingle","action":"Pterodactyl\Http\Controllers\Admin\NodesController@allocationRemoveSingle"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests","name":"admin.nests","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/new","name":"admin.nests.new","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/view\/{nest}","name":"admin.nests.view","action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/new","name":"admin.nests.egg.new","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}","name":"admin.nests.egg.view","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/export","name":"admin.nests.egg.export","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@export"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/variables","name":"admin.nests.egg.variables","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nests\/egg\/{egg}\/scripts","name":"admin.nests.egg.scripts","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggScriptController@index"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/import","name":"admin.nests.egg.import","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@import"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/egg\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@store"},{"host":null,"methods":["POST"],"uri":"admin\/nests\/egg\/{egg}\/variables","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@store"},{"host":null,"methods":["PUT"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggShareController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/view\/{nest}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}\/scripts","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggScriptController@update"},{"host":null,"methods":["PATCH"],"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","name":"admin.nests.egg.variables.edit","action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/view\/{nest}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\NestController@destroy"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/egg\/{egg}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggController@destroy"},{"host":null,"methods":["DELETE"],"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\Nests\EggVariableController@destroy"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs","name":"admin.packs","action":"Pterodactyl\Http\Controllers\Admin\PackController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/new","name":"admin.packs.new","action":"Pterodactyl\Http\Controllers\Admin\PackController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/new\/template","name":"admin.packs.new.template","action":"Pterodactyl\Http\Controllers\Admin\PackController@newTemplate"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/packs\/view\/{pack}","name":"admin.packs.view","action":"Pterodactyl\Http\Controllers\Admin\PackController@view"},{"host":null,"methods":["POST"],"uri":"admin\/packs\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@store"},{"host":null,"methods":["POST"],"uri":"admin\/packs\/view\/{pack}\/export\/{files?}","name":"admin.packs.view.export","action":"Pterodactyl\Http\Controllers\Admin\PackController@export"},{"host":null,"methods":["PATCH"],"uri":"admin\/packs\/view\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@update"},{"host":null,"methods":["DELETE"],"uri":"admin\/packs\/view\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@destroy"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login","name":"auth.login","action":"Pterodactyl\Http\Controllers\Auth\LoginController@showLoginForm"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login\/totp","name":"auth.totp","action":"Pterodactyl\Http\Controllers\Auth\LoginController@totp"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password","name":"auth.password","action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password\/reset\/{token}","name":"auth.reset","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@showResetForm"},{"host":null,"methods":["POST"],"uri":"auth\/login","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@login"},{"host":null,"methods":["POST"],"uri":"auth\/login\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@loginUsingTotp"},{"host":null,"methods":["POST"],"uri":"auth\/password","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset","name":"auth.reset.post","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@reset"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset\/{token}","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/logout","name":"auth.logout","action":"Pterodactyl\Http\Controllers\Auth\LoginController@logout"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}","name":"server.index","action":"Pterodactyl\Http\Controllers\Server\ConsoleController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/console","name":"server.console","action":"Pterodactyl\Http\Controllers\Server\ConsoleController@console"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/allocation","name":"server.settings.allocation","action":"Pterodactyl\Http\Controllers\Server\Settings\AllocationController@index"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/settings\/allocation","name":null,"action":"Pterodactyl\Http\Controllers\Server\Settings\AllocationController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/sftp","name":"server.settings.sftp","action":"Pterodactyl\Http\Controllers\Server\Settings\SftpController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/startup","name":"server.settings.startup","action":"Pterodactyl\Http\Controllers\Server\Settings\StartupController@index"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/settings\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Server\Settings\StartupController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/databases","name":"server.databases.index","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@index"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/databases\/new","name":"server.databases.new","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@store"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/databases\/password","name":"server.databases.password","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@update"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/databases\/delete\/{database}","name":"server.databases.delete","action":"Pterodactyl\Http\Controllers\Server\DatabaseController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files","name":"server.files.index","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/add","name":"server.files.add","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/edit\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\Files\FileActionsController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/download\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\Files\DownloadController@index"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/directory-list","name":"server.files.directory-list","action":"Pterodactyl\Http\Controllers\Server\Files\RemoteRequestController@directory"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/save","name":"server.files.save","action":"Pterodactyl\Http\Controllers\Server\Files\RemoteRequestController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users","name":"server.subusers","action":"Pterodactyl\Http\Controllers\Server\SubuserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/new","name":"server.subusers.new","action":"Pterodactyl\Http\Controllers\Server\SubuserController@create"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/view\/{subuser}","name":"server.subusers.view","action":"Pterodactyl\Http\Controllers\Server\SubuserController@view"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/users\/view\/{subuser}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@update"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/users\/view\/{subuser}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules","name":"server.schedules","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules\/new","name":"server.schedules.new","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@create"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@store"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":"server.schedules.view","action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@view"},{"host":null,"methods":["PATCH"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@update"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/view\/{schedule}\/toggle","name":"server.schedules.toggle","action":"Pterodactyl\Http\Controllers\Server\Tasks\ActionController@toggle"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/schedules\/view\/{schedule}\/trigger","name":"server.schedules.trigger","action":"Pterodactyl\Http\Controllers\Server\Tasks\ActionController@trigger"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/schedules\/view\/{schedule}","name":null,"action":"Pterodactyl\Http\Controllers\Server\Tasks\TaskManagementController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users","name":"api.application.users","action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users\/{user}","name":"api.application.users.view","action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/users\/external\/{external_id}","name":"api.application.users.external","action":"Pterodactyl\Http\Controllers\Api\Application\Users\ExternalUserController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/users","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/users\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/users\/{user}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Users\UserController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes","name":"api.application.nodes","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes\/{node}","name":"api.application.nodes.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/nodes","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/nodes\/{node}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/nodes\/{node}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\NodeController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nodes\/{node}\/allocations","name":"api.application.allocations","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/nodes\/{node}\/allocations","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@store"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/nodes\/{node}\/allocations\/{allocation}","name":"api.application.allocations.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nodes\AllocationController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/locations","name":"api.applications.locations","action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/locations\/{location}","name":"api.application.locations.view","action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@store"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/locations\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@update"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/locations\/{location}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Locations\LocationController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers","name":"api.application.servers","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}","name":"api.application.servers.view","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/external\/{external_id}","name":"api.application.servers.external","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ExternalServerController@index"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/details","name":"api.application.servers.details","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController@details"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/build","name":"api.application.servers.build","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController@build"},{"host":null,"methods":["PATCH"],"uri":"api\/application\/servers\/{server}\/startup","name":"api.application.servers.startup","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\StartupController@index"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@store"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/suspend","name":"api.application.servers.suspend","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@suspend"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/unsuspend","name":"api.application.servers.unsuspend","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@unsuspend"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/reinstall","name":"api.application.servers.reinstall","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@reinstall"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/rebuild","name":"api.application.servers.rebuild","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerManagementController@rebuild"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@delete"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}\/{force?}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}\/databases","name":"api.application.servers.databases","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/servers\/{server}\/databases\/{database}","name":"api.application.servers.databases.view","action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@view"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/databases","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@store"},{"host":null,"methods":["POST"],"uri":"api\/application\/servers\/{server}\/databases\/{database}\/reset-password","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@resetPassword"},{"host":null,"methods":["DELETE"],"uri":"api\/application\/servers\/{server}\/databases\/{database}","name":null,"action":"Pterodactyl\Http\Controllers\Api\Application\Servers\DatabaseController@delete"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests","name":"api.application.nests","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\NestController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}","name":"api.application.nests.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\NestController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}\/eggs","name":"api.application.nests.eggs","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\EggController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/application\/nests\/{nest}\/eggs\/{egg}","name":"api.application.nests.eggs.view","action":"Pterodactyl\Http\Controllers\Api\Application\Nests\EggController@view"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/client","name":"api.client.index","action":"Pterodactyl\Http\Controllers\Api\Client\ClientController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/client\/servers\/{server}","name":"api.client.servers.view","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\ServerController@index"},{"host":null,"methods":["POST"],"uri":"api\/client\/servers\/{server}\/command","name":"api.client.servers.command","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\CommandController@index"},{"host":null,"methods":["POST"],"uri":"api\/client\/servers\/{server}\/power","name":"api.client.servers.power","action":"Pterodactyl\Http\Controllers\Api\Client\Servers\PowerController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/authenticate\/{token}","name":"api.remote.authenticate","action":"Pterodactyl\Http\Controllers\Api\Remote\ValidateKeyController@index"},{"host":null,"methods":["POST"],"uri":"api\/remote\/download-file","name":"api.remote.download_file","action":"Pterodactyl\Http\Controllers\Api\Remote\FileDownloadController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/eggs","name":"api.remote.eggs","action":"Pterodactyl\Http\Controllers\Api\Remote\EggRetrievalController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/eggs\/{uuid}","name":"api.remote.eggs.download","action":"Pterodactyl\Http\Controllers\Api\Remote\EggRetrievalController@download"},{"host":null,"methods":["GET","HEAD"],"uri":"api\/remote\/scripts\/{uuid}","name":"api.remote.scripts","action":"Pterodactyl\Http\Controllers\Api\Remote\EggInstallController@index"},{"host":null,"methods":["POST"],"uri":"api\/remote\/sftp","name":"api.remote.sftp","action":"Pterodactyl\Http\Controllers\Api\Remote\SftpController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/packs\/pull\/{uuid}","name":"daemon.pack.pull","action":"Pterodactyl\Http\Controllers\Daemon\PackController@pull"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/packs\/pull\/{uuid}\/hash","name":"daemon.pack.hash","action":"Pterodactyl\Http\Controllers\Daemon\PackController@hash"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/configure\/{token}","name":"daemon.configuration","action":"Pterodactyl\Http\Controllers\Daemon\ActionController@configuration"},{"host":null,"methods":["POST"],"uri":"daemon\/install","name":"daemon.install","action":"Pterodactyl\Http\Controllers\Daemon\ActionController@markInstall"}], prefix: '', route : function (name, parameters, route) { diff --git a/resources/lang/en/server.php b/resources/lang/en/server.php index cd89e1f85..8941c4793 100644 --- a/resources/lang/en/server.php +++ b/resources/lang/en/server.php @@ -248,6 +248,14 @@ return [ 'title' => 'Reset Database Password', 'description' => 'Allows a user to reset passwords for databases.', ], + 'delete_database' => [ + 'title' => 'Delete Databases', + 'description' => 'Allows a user to delete databases for this server from the Panel.', + ], + 'create_database' => [ + 'title' => 'Create Database', + 'description' => 'Allows a user to create additional databases for this server.', + ], ], ], 'files' => [ diff --git a/resources/themes/pterodactyl/server/databases/index.blade.php b/resources/themes/pterodactyl/server/databases/index.blade.php index b8e01db84..fb618b64c 100644 --- a/resources/themes/pterodactyl/server/databases/index.blade.php +++ b/resources/themes/pterodactyl/server/databases/index.blade.php @@ -21,7 +21,7 @@ @section('content')
-
+

@lang('server.config.database.your_dbs')

@@ -50,11 +50,20 @@ {{ $database->host->host }}:{{ $database->host->port }} - @can('reset-db-password', $server) + @if(Gate::allows('reset-db-password', $server) || Gate::allows('delete-database', $server)) - + @can('delete-database', $server) + + @endcan + @can('reset-db-password', $server) + + @endcan - @endcan + @endif @endforeach @@ -69,7 +78,7 @@ @endif
- @if($allowCreation) + @if($allowCreation && Gate::allows('create-database', $server))
@@ -153,5 +162,37 @@ }); }); @endcan + @can('delete-database', $server) + $('[data-action="delete-database"]').click(function (event) { + event.preventDefault(); + var self = $(this); + swal({ + title: '', + type: 'warning', + text: 'Are you sure that you want to delete this database? There is no going back, all data will immediately be removed.', + showCancelButton: true, + confirmButtonText: 'Delete', + confirmButtonColor: '#d9534f', + closeOnConfirm: false, + showLoaderOnConfirm: true, + }, function () { + $.ajax({ + method: 'DELETE', + url: Router.route('server.databases.delete', { server: '{{ $server->uuidShort }}', database: self.data('id') }), + headers: { 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content') }, + }).done(function () { + self.parent().parent().slideUp(); + swal.close(); + }).fail(function (jqXHR) { + console.error(jqXHR); + swal({ + type: 'error', + title: 'Whoops!', + text: (typeof jqXHR.responseJSON.error !== 'undefined') ? jqXHR.responseJSON.error : 'An error occured while processing this request.' + }); + }); + }); + }); + @endcan @endsection diff --git a/routes/server.php b/routes/server.php index 93005aaec..a05f4b00b 100644 --- a/routes/server.php +++ b/routes/server.php @@ -41,6 +41,8 @@ Route::group(['prefix' => 'databases'], function () { Route::post('/new', 'DatabaseController@store')->name('server.databases.new'); Route::patch('/password', 'DatabaseController@update')->middleware('server..database')->name('server.databases.password'); + + Route::delete('/delete/{database}', 'DatabaseController@delete')->middleware('server..database')->name('server.databases.delete'); }); /* From e39353a18db134452cdb50502e47aa030282fc19 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 2 Mar 2018 19:37:21 -0600 Subject: [PATCH 4/4] Add tests for new service --- .../Databases/DeployServerDatabaseService.php | 15 +- .../Server/Files/DownloadControllerTest.php | 25 +- .../DeployServerDatabaseServiceTest.php | 236 ++++++++++++++++++ 3 files changed, 256 insertions(+), 20 deletions(-) create mode 100644 tests/Unit/Services/Databases/DeployServerDatabaseServiceTest.php diff --git a/app/Services/Databases/DeployServerDatabaseService.php b/app/Services/Databases/DeployServerDatabaseService.php index 2932b87f2..c8b5ed179 100644 --- a/app/Services/Databases/DeployServerDatabaseService.php +++ b/app/Services/Databases/DeployServerDatabaseService.php @@ -21,6 +21,7 @@ class DeployServerDatabaseService * @var \Pterodactyl\Services\Databases\DatabaseManagementService */ private $managementService; + /** * @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface */ @@ -63,21 +64,23 @@ class DeployServerDatabaseService } $allowRandom = config('pterodactyl.client_features.databases.allow_random'); - $host = $this->databaseHostRepository->setColumns(['id'])->findWhere([ + $hosts = $this->databaseHostRepository->setColumns(['id'])->findWhere([ ['node_id', '=', $server->node_id], - ])->random(); + ]); - if (empty($host) && ! $allowRandom) { + if ($hosts->isEmpty() && ! $allowRandom) { throw new NoSuitableDatabaseHostException; } - if (empty($host)) { - $host = $this->databaseHostRepository->setColumns(['id'])->all()->random(); - if (empty($host)) { + if ($hosts->isEmpty()) { + $hosts = $this->databaseHostRepository->setColumns(['id'])->all(); + if ($hosts->isEmpty()) { throw new NoSuitableDatabaseHostException; } } + $host = $hosts->random(); + return $this->managementService->create($server->id, [ 'database_host_id' => $host->id, 'database' => array_get($data, 'database'), diff --git a/tests/Unit/Http/Controllers/Server/Files/DownloadControllerTest.php b/tests/Unit/Http/Controllers/Server/Files/DownloadControllerTest.php index d44481c1b..b76cbfb86 100644 --- a/tests/Unit/Http/Controllers/Server/Files/DownloadControllerTest.php +++ b/tests/Unit/Http/Controllers/Server/Files/DownloadControllerTest.php @@ -1,17 +1,10 @@ . - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ namespace Tests\Unit\Http\Controllers\Server\Files; use Mockery as m; -use phpmock\phpunit\PHPMock; use Pterodactyl\Models\Node; +use Tests\Traits\MocksUuids; use Pterodactyl\Models\Server; use Illuminate\Cache\Repository; use Tests\Unit\Http\Controllers\ControllerTestCase; @@ -19,7 +12,7 @@ use Pterodactyl\Http\Controllers\Server\Files\DownloadController; class DownloadControllerTest extends ControllerTestCase { - use PHPMock; + use MocksUuids; /** * @var \Illuminate\Cache\Repository|\Mockery\Mock @@ -48,16 +41,20 @@ class DownloadControllerTest extends ControllerTestCase $this->setRequestAttribute('server', $server); $controller->shouldReceive('authorize')->with('download-files', $server)->once()->andReturnNull(); - $this->getFunctionMock('\\Pterodactyl\\Http\\Controllers\\Server\\Files', 'str_random') - ->expects($this->once())->willReturn('randomString'); - $this->cache->shouldReceive('tags')->with(['Server:Downloads'])->once()->andReturnSelf(); - $this->cache->shouldReceive('put')->with('randomString', ['server' => $server->uuid, 'path' => '/my/file.txt'], 5)->once()->andReturnNull(); + $this->cache->shouldReceive('put') + ->once() + ->with('Server:Downloads:' . $this->getKnownUuid(), ['server' => $server->uuid, 'path' => '/my/file.txt'], 5) + ->andReturnNull(); $response = $controller->index($this->request, $server->uuidShort, '/my/file.txt'); $this->assertIsRedirectResponse($response); $this->assertRedirectUrlEquals(sprintf( - '%s://%s:%s/v1/server/file/download/%s', $server->node->scheme, $server->node->fqdn, $server->node->daemonListen, 'randomString' + '%s://%s:%s/v1/server/file/download/%s', + $server->node->scheme, + $server->node->fqdn, + $server->node->daemonListen, + $this->getKnownUuid() ), $response); } diff --git a/tests/Unit/Services/Databases/DeployServerDatabaseServiceTest.php b/tests/Unit/Services/Databases/DeployServerDatabaseServiceTest.php new file mode 100644 index 000000000..f8f2ff70c --- /dev/null +++ b/tests/Unit/Services/Databases/DeployServerDatabaseServiceTest.php @@ -0,0 +1,236 @@ +databaseHostRepository = m::mock(DatabaseHostRepositoryInterface::class); + $this->managementService = m::mock(DatabaseManagementService::class); + $this->repository = m::mock(DatabaseRepositoryInterface::class); + + // Set configs for testing instances. + config()->set('pterodactyl.client_features.databases.enabled', true); + config()->set('pterodactyl.client_features.databases.allow_random', true); + } + + /** + * Test handling of non-random hosts when a host is found. + * + * @dataProvider databaseLimitDataProvider + */ + public function testNonRandomFoundHost($limit, $count) + { + config()->set('pterodactyl.client_features.databases.allow_random', false); + + $server = factory(Server::class)->make(['database_limit' => $limit]); + $model = factory(Database::class)->make(); + + $this->repository->shouldReceive('findCountWhere') + ->once() + ->with([['server_id', '=', $server->id]]) + ->andReturn($count); + + $this->databaseHostRepository->shouldReceive('setColumns->findWhere') + ->once() + ->with([['node_id', '=', $server->node_id]]) + ->andReturn(collect([$model])); + + $this->managementService->shouldReceive('create') + ->once() + ->with($server->id, [ + 'database_host_id' => $model->id, + 'database' => 'testdb', + 'remote' => null, + ]) + ->andReturn($model); + + $response = $this->getService()->handle($server, ['database' => 'testdb']); + + $this->assertInstanceOf(Database::class, $response); + $this->assertSame($model, $response); + } + + /** + * Test that an exception is thrown if in non-random mode and no host is found. + * + * @expectedException \Pterodactyl\Exceptions\Service\Database\NoSuitableDatabaseHostException + */ + public function testNonRandomNoHost() + { + config()->set('pterodactyl.client_features.databases.allow_random', false); + + $server = factory(Server::class)->make(['database_limit' => 1]); + + $this->repository->shouldReceive('findCountWhere') + ->once() + ->with([['server_id', '=', $server->id]]) + ->andReturn(0); + + $this->databaseHostRepository->shouldReceive('setColumns->findWhere') + ->once() + ->with([['node_id', '=', $server->node_id]]) + ->andReturn(collect()); + + $this->getService()->handle($server, []); + } + + /** + * Test handling of random host selection. + */ + public function testRandomFoundHost() + { + $server = factory(Server::class)->make(['database_limit' => 1]); + $model = factory(Database::class)->make(); + + $this->repository->shouldReceive('findCountWhere') + ->once() + ->with([['server_id', '=', $server->id]]) + ->andReturn(0); + + $this->databaseHostRepository->shouldReceive('setColumns->findWhere') + ->once() + ->with([['node_id', '=', $server->node_id]]) + ->andReturn(collect()); + + $this->databaseHostRepository->shouldReceive('setColumns->all') + ->once() + ->andReturn(collect([$model])); + + $this->managementService->shouldReceive('create') + ->once() + ->with($server->id, [ + 'database_host_id' => $model->id, + 'database' => 'testdb', + 'remote' => null, + ]) + ->andReturn($model); + + $response = $this->getService()->handle($server, ['database' => 'testdb']); + + $this->assertInstanceOf(Database::class, $response); + $this->assertSame($model, $response); + } + + /** + * Test that an exception is thrown when no host is found and random is allowed. + * + * @expectedException \Pterodactyl\Exceptions\Service\Database\NoSuitableDatabaseHostException + */ + public function testRandomNoHost() + { + $server = factory(Server::class)->make(['database_limit' => 1]); + + $this->repository->shouldReceive('findCountWhere') + ->once() + ->with([['server_id', '=', $server->id]]) + ->andReturn(0); + + $this->databaseHostRepository->shouldReceive('setColumns->findWhere') + ->once() + ->with([['node_id', '=', $server->node_id]]) + ->andReturn(collect()); + + $this->databaseHostRepository->shouldReceive('setColumns->all') + ->once() + ->andReturn(collect()); + + $this->getService()->handle($server, []); + } + + /** + * Test that a server over the database limit throws an exception. + * + * @dataProvider databaseExceedingLimitDataProvider + * @expectedException \Pterodactyl\Exceptions\Service\Database\TooManyDatabasesException + */ + public function testServerOverDatabaseLimit($limit, $count) + { + $server = factory(Server::class)->make(['database_limit' => $limit]); + + $this->repository->shouldReceive('findCountWhere') + ->once() + ->with([['server_id', '=', $server->id]]) + ->andReturn($count); + + $this->getService()->handle($server, []); + } + + /** + * Test that an exception is thrown if the feature is not enabled. + * + * @expectedException \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException + */ + public function testFeatureNotEnabled() + { + config()->set('pterodactyl.client_features.databases.enabled', false); + + $this->getService()->handle(factory(Server::class)->make(), []); + } + + /** + * Provide limits and current database counts for testing. + * + * @return array + */ + public function databaseLimitDataProvider(): array + { + return [ + [null, 10], + [1, 0], + ]; + } + + /** + * Provide data for servers over their database limit. + * + * @return array + */ + public function databaseExceedingLimitDataProvider(): array + { + return [ + [2, 2], + [2, 3], + ]; + } + + /** + * Return an instance of the service with mocked dependencies for testing. + * + * @return \Pterodactyl\Services\Databases\DeployServerDatabaseService + */ + private function getService(): DeployServerDatabaseService + { + return new DeployServerDatabaseService($this->repository, $this->databaseHostRepository, $this->managementService); + } +}