Skip to content

Commit 20c1c74

Browse files
committed
Fix issues with validation in admin CP for server variables, closes pterodactyl#780
1 parent 0bb44a4 commit 20c1c74

File tree

6 files changed

+43
-89
lines changed

6 files changed

+43
-89
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
77
### Fixed
88
* `[beta.2]` — Fixes a bug that would cause an endless exception message stream in the console when attemping to setup environment settings in certain instances.
99
* `[beta.2]` — Fixes a bug causing the dropdown menu for a server's egg to display the wrong selected value.
10+
* `[beta.2]` — Fixes a bug that would throw a red page of death when submitting an invalid egg variable value for a server in the Admin CP.
1011

1112
## v0.7.0-beta.2 (Derelict Dermodactylus)
1213
### Fixed

app/Exceptions/DisplayValidationException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
namespace Pterodactyl\Exceptions;
1111

12-
class DisplayValidationException extends PterodactylException
12+
class DisplayValidationException extends DisplayException
1313
{
1414
}

app/Services/Servers/StartupModificationService.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ public function __construct(
7878
* @param \Pterodactyl\Models\Server $server
7979
* @param array $data
8080
*
81-
* @throws \Pterodactyl\Exceptions\DisplayException
81+
* @throws \Illuminate\Validation\ValidationException
8282
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
8383
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
84+
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
8485
*/
8586
public function handle(Server $server, array $data)
8687
{

app/Services/Servers/VariableValidatorService.php

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
use Pterodactyl\Models\User;
1313
use Illuminate\Support\Collection;
14+
use Illuminate\Validation\ValidationException;
1415
use Pterodactyl\Traits\Services\HasUserLevels;
15-
use Pterodactyl\Exceptions\DisplayValidationException;
1616
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
1717
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
1818
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
@@ -25,22 +25,22 @@ class VariableValidatorService
2525
/**
2626
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
2727
*/
28-
protected $optionVariableRepository;
28+
private $optionVariableRepository;
2929

3030
/**
3131
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
3232
*/
33-
protected $serverRepository;
33+
private $serverRepository;
3434

3535
/**
3636
* @var \Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface
3737
*/
38-
protected $serverVariableRepository;
38+
private $serverVariableRepository;
3939

4040
/**
4141
* @var \Illuminate\Contracts\Validation\Factory
4242
*/
43-
protected $validator;
43+
private $validator;
4444

4545
/**
4646
* VariableValidatorService constructor.
@@ -68,32 +68,32 @@ public function __construct(
6868
* @param int $egg
6969
* @param array $fields
7070
* @return \Illuminate\Support\Collection
71+
* @throws \Illuminate\Validation\ValidationException
7172
*/
7273
public function handle(int $egg, array $fields = []): Collection
7374
{
7475
$variables = $this->optionVariableRepository->findWhere([['egg_id', '=', $egg]]);
76+
$messages = $this->validator->make([], []);
7577

76-
return $variables->map(function ($item) use ($fields) {
78+
$response = $variables->map(function ($item) use ($fields, $messages) {
7779
// Skip doing anything if user is not an admin and
7880
// variable is not user viewable or editable.
7981
if (! $this->isUserLevel(User::USER_LEVEL_ADMIN) && (! $item->user_editable || ! $item->user_viewable)) {
8082
return false;
8183
}
8284

83-
$validator = $this->validator->make([
85+
$v = $this->validator->make([
8486
'variable_value' => array_get($fields, $item->env_variable),
8587
], [
8688
'variable_value' => $item->rules,
89+
], [], [
90+
'variable_value' => trans('validation.internal.variable_value', ['env' => $item->name]),
8791
]);
8892

89-
if ($validator->fails()) {
90-
throw new DisplayValidationException(json_encode(
91-
collect([
92-
'notice' => [
93-
trans('admin/server.exceptions.bad_variable', ['name' => $item->name]),
94-
],
95-
])->merge($validator->errors()->toArray())
96-
));
93+
if ($v->fails()) {
94+
foreach ($v->getMessageBag()->all() as $message) {
95+
$messages->getMessageBag()->add($item->env_variable, $message);
96+
}
9797
}
9898

9999
return (object) [
@@ -104,5 +104,11 @@ public function handle(int $egg, array $fields = []): Collection
104104
})->filter(function ($item) {
105105
return is_object($item);
106106
});
107+
108+
if (! empty($messages->getMessageBag()->all())) {
109+
throw new ValidationException($messages);
110+
}
111+
112+
return $response;
107113
}
108114
}

resources/lang/en/validation.php

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,6 @@
8585
'uploaded' => 'The :attribute failed to upload.',
8686
'url' => 'The :attribute format is invalid.',
8787

88-
/*
89-
|--------------------------------------------------------------------------
90-
| Custom Validation Language Lines
91-
|--------------------------------------------------------------------------
92-
|
93-
| Here you may specify custom validation messages for attributes using the
94-
| convention "attribute.rule" to name the lines. This makes it quick to
95-
| specify a specific custom language line for a given attribute rule.
96-
|
97-
*/
98-
99-
'custom' => [
100-
'attribute-name' => [
101-
'rule-name' => 'custom-message',
102-
],
103-
],
104-
10588
/*
10689
|--------------------------------------------------------------------------
10790
| Custom Validation Attributes
@@ -114,4 +97,9 @@
11497
*/
11598

11699
'attributes' => [],
100+
101+
// Internal validation logic for Pterodactyl
102+
'internal' => [
103+
'variable_value' => ':env variable',
104+
],
117105
];

tests/Unit/Services/Servers/VariableValidatorServiceTest.php

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
<?php
2-
/**
3-
* Pterodactyl - Panel
4-
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5-
*
6-
* This software is licensed under the terms of the MIT license.
7-
* https://opensource.org/licenses/MIT
8-
*/
92

103
namespace Tests\Unit\Services\Servers;
114

@@ -15,8 +8,7 @@
158
use Illuminate\Support\Collection;
169
use Pterodactyl\Models\EggVariable;
1710
use Illuminate\Contracts\Validation\Factory;
18-
use Pterodactyl\Exceptions\PterodactylException;
19-
use Pterodactyl\Exceptions\DisplayValidationException;
11+
use Illuminate\Validation\ValidationException;
2012
use Pterodactyl\Services\Servers\VariableValidatorService;
2113
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
2214
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
@@ -27,22 +19,17 @@ class VariableValidatorServiceTest extends TestCase
2719
/**
2820
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
2921
*/
30-
protected $optionVariableRepository;
22+
private $optionVariableRepository;
3123

3224
/**
3325
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
3426
*/
35-
protected $serverRepository;
27+
private $serverRepository;
3628

3729
/**
3830
* @var \Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface|\Mockery\Mock
3931
*/
40-
protected $serverVariableRepository;
41-
42-
/**
43-
* @var \Illuminate\Contracts\Validation\Factory|\Mockery\Mock
44-
*/
45-
protected $validator;
32+
private $serverVariableRepository;
4633

4734
/**
4835
* Setup tests.
@@ -54,7 +41,6 @@ public function setUp()
5441
$this->optionVariableRepository = m::mock(EggVariableRepositoryInterface::class);
5542
$this->serverRepository = m::mock(ServerRepositoryInterface::class);
5643
$this->serverVariableRepository = m::mock(ServerVariableRepositoryInterface::class);
57-
$this->validator = m::mock(Factory::class);
5844
}
5945

6046
/**
@@ -77,13 +63,6 @@ public function testValidatorShouldNotProcessVariablesSetAsNotUserEditableWhenAd
7763
$variables = $this->getVariableCollection();
7864
$this->optionVariableRepository->shouldReceive('findWhere')->with([['egg_id', '=', 1]])->andReturn($variables);
7965

80-
$this->validator->shouldReceive('make')->with([
81-
'variable_value' => 'Test_SomeValue_0',
82-
], [
83-
'variable_value' => $variables[0]->rules,
84-
])->once()->andReturnSelf();
85-
$this->validator->shouldReceive('fails')->withNoArgs()->once()->andReturn(false);
86-
8766
$response = $this->getService()->handle(1, [
8867
$variables[0]->env_variable => 'Test_SomeValue_0',
8968
$variables[1]->env_variable => 'Test_SomeValue_1',
@@ -112,15 +91,6 @@ public function testValidatorShouldProcessAllVariablesWhenAdminFlagIsSet()
11291
$variables = $this->getVariableCollection();
11392
$this->optionVariableRepository->shouldReceive('findWhere')->with([['egg_id', '=', 1]])->andReturn($variables);
11493

115-
foreach ($variables as $key => $variable) {
116-
$this->validator->shouldReceive('make')->with([
117-
'variable_value' => 'Test_SomeValue_' . $key,
118-
], [
119-
'variable_value' => $variables[$key]->rules,
120-
])->once()->andReturnSelf();
121-
$this->validator->shouldReceive('fails')->withNoArgs()->once()->andReturn(false);
122-
}
123-
12494
$service = $this->getService();
12595
$service->setUserLevel(User::USER_LEVEL_ADMIN);
12696
$response = $service->handle(1, [
@@ -152,28 +122,16 @@ public function testValidatorShouldThrowExceptionWhenAValidationErrorIsEncounter
152122
$variables = $this->getVariableCollection();
153123
$this->optionVariableRepository->shouldReceive('findWhere')->with([['egg_id', '=', 1]])->andReturn($variables);
154124

155-
$this->validator->shouldReceive('make')->with([
156-
'variable_value' => null,
157-
], [
158-
'variable_value' => $variables[0]->rules,
159-
])->once()->andReturnSelf();
160-
$this->validator->shouldReceive('fails')->withNoArgs()->once()->andReturn(true);
161-
162-
$this->validator->shouldReceive('errors')->withNoArgs()->once()->andReturnSelf();
163-
$this->validator->shouldReceive('toArray')->withNoArgs()->once()->andReturn([]);
164-
165125
try {
166126
$this->getService()->handle(1, [$variables[0]->env_variable => null]);
167-
} catch (PterodactylException $exception) {
168-
$this->assertInstanceOf(DisplayValidationException::class, $exception);
169-
170-
$decoded = json_decode($exception->getMessage());
171-
$this->assertEquals(0, json_last_error(), 'Assert that response is decodable JSON.');
172-
$this->assertObjectHasAttribute('notice', $decoded);
173-
$this->assertEquals(
174-
trans('admin/server.exceptions.bad_variable', ['name' => $variables[0]->name]),
175-
$decoded->notice[0]
176-
);
127+
} catch (ValidationException $exception) {
128+
$messages = $exception->validator->getMessageBag()->all();
129+
130+
$this->assertNotEmpty($messages);
131+
$this->assertSame(1, count($messages));
132+
$this->assertSame(trans('validation.required', [
133+
'attribute' => trans('validation.internal.variable_value', ['env' => $variables[0]->name]),
134+
]), $messages[0]);
177135
}
178136
}
179137

@@ -205,7 +163,7 @@ private function getService(): VariableValidatorService
205163
$this->optionVariableRepository,
206164
$this->serverRepository,
207165
$this->serverVariableRepository,
208-
$this->validator
166+
$this->app->make(Factory::class)
209167
);
210168
}
211169
}

0 commit comments

Comments
 (0)