Skip to content

Commit 6e4cfe8

Browse files
committed
Ensure that a Node's daemon secret can be properly reset
1 parent 4d8760f commit 6e4cfe8

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

app/Http/Controllers/Admin/NodesController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public function viewServers($node)
263263
*/
264264
public function updateSettings(NodeFormRequest $request, Node $node)
265265
{
266-
$this->updateService->handle($node, $request->normalize());
266+
$this->updateService->handle($node, $request->normalize(), $request->input('reset_secret') === 'on');
267267
$this->alert->success(trans('admin/node.notices.node_updated'))->flash();
268268

269269
return redirect()->route('admin.nodes.view.settings', $node->id)->withInput();
@@ -289,7 +289,7 @@ public function allocationRemoveSingle(int $node, Allocation $allocation): Respo
289289
* Removes multiple individual allocations from a node.
290290
*
291291
* @param \Illuminate\Http\Request $request
292-
* @param int $node
292+
* @param int $node
293293
* @return \Illuminate\Http\Response
294294
*
295295
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException

app/Http/Controllers/Api/Application/Nodes/NodeController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public function store(StoreNodeRequest $request): JsonResponse
125125
public function update(UpdateNodeRequest $request): array
126126
{
127127
$node = $this->updateService->handle(
128-
$request->getModel(Node::class), $request->validated()
128+
$request->getModel(Node::class), $request->validated(), $request->input('reset_secret') === true
129129
);
130130

131131
return $this->fractal->item($node)

app/Services/Nodes/NodeUpdateService.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,41 @@ public function __construct(
5050
*
5151
* @param \Pterodactyl\Models\Node $node
5252
* @param array $data
53+
* @param bool $resetToken
54+
*
5355
* @return \Pterodactyl\Models\Node
5456
*
55-
* @throws \Pterodactyl\Exceptions\DisplayException
5657
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
5758
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
59+
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
60+
* @throws \Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException
5861
*/
59-
public function handle(Node $node, array $data)
62+
public function handle(Node $node, array $data, bool $resetToken = false)
6063
{
61-
if (! is_null(array_get($data, 'reset_secret'))) {
64+
if ($resetToken) {
6265
$data['daemonSecret'] = str_random(Node::DAEMON_SECRET_LENGTH);
63-
unset($data['reset_secret']);
6466
}
6567

6668
$this->connection->beginTransaction();
69+
70+
/** @var \Pterodactyl\Models\Node $updatedModel */
6771
$updatedModel = $this->repository->update($node->id, $data);
6872

6973
try {
70-
$this->configRepository->setNode($updatedModel)->update();
74+
if ($resetToken) {
75+
// We need to clone the new model and set it's authentication token to be the
76+
// old one so we can connect. Then we will pass the new token through as an
77+
// override on the call.
78+
$cloned = $updatedModel->replicate(['daemonSecret']);
79+
$cloned->setAttribute('daemonSecret', $node->getAttribute('daemonSecret'));
80+
81+
$this->configRepository->setNode($cloned)->update([
82+
'keys' => [$data['daemonSecret']],
83+
]);
84+
} else {
85+
$this->configRepository->setNode($updatedModel)->update();
86+
}
87+
7188
$this->connection->commit();
7289
} catch (RequestException $exception) {
7390
// Failed to connect to the Daemon. Let's go ahead and save the configuration

tests/Unit/Services/Nodes/NodeUpdateServiceTest.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,34 @@ public function setUp()
5151
public function testNodeIsUpdatedAndDaemonSecretIsReset()
5252
{
5353
$model = factory(Node::class)->make();
54+
$updatedModel = factory(Node::class)->make([
55+
'name' => 'New Name',
56+
'daemonSecret' => 'abcd1234',
57+
]);
5458

5559
$this->getFunctionMock('\\Pterodactyl\\Services\\Nodes', 'str_random')
56-
->expects($this->once())->willReturn('random_string');
60+
->expects($this->once())->willReturn($updatedModel->daemonSecret);
5761

5862
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
5963
$this->repository->shouldReceive('update')->with($model->id, [
60-
'name' => 'NewName',
61-
'daemonSecret' => 'random_string',
64+
'name' => $updatedModel->name,
65+
'daemonSecret' => $updatedModel->daemonSecret,
6266
])->andReturn($model);
6367

64-
$this->configRepository->shouldReceive('setNode')->with($model)->once()->andReturnSelf()
65-
->shouldReceive('update')->withNoArgs()->once()->andReturn(new Response);
68+
$cloned = $updatedModel->replicate(['daemonSecret']);
69+
$cloned->daemonSecret = $model->daemonSecret;
70+
71+
$this->configRepository->shouldReceive('setNode')->with(m::on(function ($model) use ($updatedModel) {
72+
return $model->daemonSecret !== $updatedModel->daemonSecret;
73+
}))->once()->andReturnSelf();
74+
75+
$this->configRepository->shouldReceive('update')->with([
76+
'keys' => ['abcd1234'],
77+
])->once()->andReturn(new Response);
78+
6679
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
6780

68-
$response = $this->getService()->handle($model, ['name' => 'NewName', 'reset_secret' => true]);
81+
$response = $this->getService()->handle($model, ['name' => $updatedModel->name], true);
6982
$this->assertInstanceOf(Node::class, $response);
7083
}
7184

0 commit comments

Comments
 (0)