diff --git a/app/Http/Controllers/Admin/NodeAutoDeployController.php b/app/Http/Controllers/Admin/NodeAutoDeployController.php new file mode 100644 index 000000000..be6301c31 --- /dev/null +++ b/app/Http/Controllers/Admin/NodeAutoDeployController.php @@ -0,0 +1,88 @@ +keyCreationService = $keyCreationService; + $this->repository = $repository; + $this->encrypter = $encrypter; + } + + /** + * Generates a new API key for the logged in user with only permission to read + * nodes, and returns that as the deployment key for a node. + * + * @param \Illuminate\Http\Request $request + * @param \Pterodactyl\Models\Node $node + * @return \Illuminate\Http\JsonResponse + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + */ + public function __invoke(Request $request, Node $node) + { + /** @var \Pterodactyl\Models\ApiKey|null $key */ + $key = $this->repository->getApplicationKeys($request->user()) + ->filter(function (ApiKey $key) { + foreach ($key->getAttributes() as $permission => $value) { + if ($permission === 'r_nodes' && $value === 1) { + return true; + } + } + + return false; + }) + ->first(); + + // We couldn't find a key that exists for this user with only permission for + // reading nodes. Go ahead and create it now. + if (! $key) { + $key = $this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([ + 'user_id' => $request->user()->id, + 'memo' => 'Automatically generated node deployment key.', + 'allowed_ips' => [], + ], ['r_nodes' => 1]); + } + + return JsonResponse::create([ + 'node' => $node->id, + 'token' => $key->identifier . $this->encrypter->decrypt($key->token), + ]); + } +} diff --git a/app/Http/Controllers/Admin/NodesController.php b/app/Http/Controllers/Admin/NodesController.php index a7d710a10..d482c47ae 100644 --- a/app/Http/Controllers/Admin/NodesController.php +++ b/app/Http/Controllers/Admin/NodesController.php @@ -9,7 +9,6 @@ namespace Pterodactyl\Http\Controllers\Admin; -use Cake\Chronos\Chronos; use Illuminate\Http\Request; use Pterodactyl\Models\Node; use Illuminate\Http\Response; @@ -300,18 +299,4 @@ class NodesController extends Controller return redirect()->route('admin.nodes'); } - - /** - * Returns the configuration token to auto-deploy a node. - * - * @param \Pterodactyl\Models\Node $node - * @return \Illuminate\Http\JsonResponse - */ - public function setToken(Node $node) - { - $token = bin2hex(random_bytes(16)); - $this->cache->put('Node:Configuration:' . $token, $node->id, Chronos::now()->addMinutes(5)); - - return response()->json(['token' => $token]); - } } diff --git a/app/Http/Controllers/Api/Application/Nodes/NodeConfigurationController.php b/app/Http/Controllers/Api/Application/Nodes/NodeConfigurationController.php new file mode 100644 index 000000000..fc0c35f75 --- /dev/null +++ b/app/Http/Controllers/Api/Application/Nodes/NodeConfigurationController.php @@ -0,0 +1,25 @@ +getConfiguration()); + } +} diff --git a/resources/views/admin/nodes/view/configuration.blade.php b/resources/views/admin/nodes/view/configuration.blade.php index f1c7b0f34..778c6a057 100644 --- a/resources/views/admin/nodes/view/configuration.blade.php +++ b/resources/views/admin/nodes/view/configuration.blade.php @@ -71,8 +71,7 @@ swal({ type: 'success', title: 'Token created.', - text: 'Your token will expire in 5 minutes.

' + - '

To auto-configure your node run the following command:

npm run configure -- --panel-url {{ config('app.url') }} --token ' + data.token + '

', + text: '

To auto-configure your node run the following command:

cd /srv/wings && ./wings configure --panel-url {{ config('app.url') }} --token ' + data.token + ' --node ' + data.node + '{{ config('app.debug') ? ' --allow-insecure' : '' }}

', html: true }) }).fail(function () { diff --git a/routes/admin.php b/routes/admin.php index e9e8ec490..7a1c9fa75 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -151,7 +151,7 @@ Route::group(['prefix' => 'nodes'], function () { Route::get('/view/{node}/allocation', 'Nodes\NodeViewController@allocations')->name('admin.nodes.view.allocation'); Route::get('/view/{node}/servers', 'Nodes\NodeViewController@servers')->name('admin.nodes.view.servers'); Route::get('/view/{node}/system-information', 'Nodes\SystemInformationController'); - Route::get('/view/{node}/settings/token', 'NodesController@setToken')->name('admin.nodes.view.configuration.token'); + Route::get('/view/{node}/settings/token', 'NodeAutoDeployController')->name('admin.nodes.view.configuration.token'); Route::post('/new', 'NodesController@store'); Route::post('/view/{node}/allocation', 'NodesController@createAllocation'); diff --git a/routes/api-application.php b/routes/api-application.php index fe7181667..e32461717 100644 --- a/routes/api-application.php +++ b/routes/api-application.php @@ -1,5 +1,7 @@ '/users'], function () { Route::get('/', 'Users\UserController@index')->name('api.application.users'); Route::get('/{user}', 'Users\UserController@view')->name('api.application.users.view'); @@ -30,6 +33,7 @@ Route::group(['prefix' => '/users'], function () { Route::group(['prefix' => '/nodes'], function () { Route::get('/', 'Nodes\NodeController@index')->name('api.application.nodes'); Route::get('/{node}', 'Nodes\NodeController@view')->name('api.application.nodes.view'); + Route::get('/{node}/configuration', 'Nodes\NodeConfigurationController'); Route::post('/', 'Nodes\NodeController@store'); Route::patch('/{node}', 'Nodes\NodeController@update'); @@ -38,9 +42,7 @@ Route::group(['prefix' => '/nodes'], function () { Route::group(['prefix' => '/{node}/allocations'], function () { Route::get('/', 'Nodes\AllocationController@index')->name('api.application.allocations'); - Route::post('/', 'Nodes\AllocationController@store'); - Route::delete('/{allocation}', 'Nodes\AllocationController@delete')->name('api.application.allocations.view'); }); });