Added validation to variable validation rules to validate that the validation rules are valid
closes #988
This commit is contained in:
parent
7a04a9f169
commit
b96c2d16ee
9 changed files with 246 additions and 32 deletions
|
@ -9,6 +9,7 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Added a new client API endpoint for gathering the utilization stats for servers including disk, cpu, and memory. `GET /api/client/servers/<id>/utilization`
|
* Added a new client API endpoint for gathering the utilization stats for servers including disk, cpu, and memory. `GET /api/client/servers/<id>/utilization`
|
||||||
|
* Added validation to variable validation rules to validate that the validation rules are valid because we heard you like validating your validation.
|
||||||
|
|
||||||
## v0.7.6 (Derelict Dermodactylus)
|
## v0.7.6 (Derelict Dermodactylus)
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Exceptions\Service\Egg\Variable;
|
||||||
|
|
||||||
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
|
|
||||||
|
class BadValidationRuleException extends DisplayException
|
||||||
|
{
|
||||||
|
}
|
|
@ -3,24 +3,46 @@
|
||||||
namespace Pterodactyl\Services\Eggs\Variables;
|
namespace Pterodactyl\Services\Eggs\Variables;
|
||||||
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
use Pterodactyl\Models\EggVariable;
|
||||||
|
use Illuminate\Contracts\Validation\Factory;
|
||||||
|
use Pterodactyl\Traits\Services\ValidatesValidationRules;
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
||||||
|
|
||||||
class VariableCreationService
|
class VariableCreationService
|
||||||
{
|
{
|
||||||
|
use ValidatesValidationRules;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
|
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Validation\Factory
|
||||||
|
*/
|
||||||
|
private $validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VariableCreationService constructor.
|
* VariableCreationService constructor.
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface $repository
|
* @param \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface $repository
|
||||||
|
* @param \Illuminate\Contracts\Validation\Factory $validator
|
||||||
*/
|
*/
|
||||||
public function __construct(EggVariableRepositoryInterface $repository)
|
public function __construct(EggVariableRepositoryInterface $repository, Factory $validator)
|
||||||
{
|
{
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
|
$this->validator = $validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the validation factory instance to be used by rule validation
|
||||||
|
* checking in the trait.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Validation\Factory
|
||||||
|
*/
|
||||||
|
protected function getValidator(): Factory
|
||||||
|
{
|
||||||
|
return $this->validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +53,7 @@ class VariableCreationService
|
||||||
* @return \Pterodactyl\Models\EggVariable
|
* @return \Pterodactyl\Models\EggVariable
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||||
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
||||||
*/
|
*/
|
||||||
public function handle(int $egg, array $data): EggVariable
|
public function handle(int $egg, array $data): EggVariable
|
||||||
|
@ -42,6 +65,10 @@ class VariableCreationService
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! empty($data['rules'] ?? '')) {
|
||||||
|
$this->validateRules($data['rules']);
|
||||||
|
}
|
||||||
|
|
||||||
$options = array_get($data, 'options') ?? [];
|
$options = array_get($data, 'options') ?? [];
|
||||||
|
|
||||||
return $this->repository->create([
|
return $this->repository->create([
|
||||||
|
|
|
@ -3,25 +3,47 @@
|
||||||
namespace Pterodactyl\Services\Eggs\Variables;
|
namespace Pterodactyl\Services\Eggs\Variables;
|
||||||
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
use Pterodactyl\Models\EggVariable;
|
||||||
|
use Illuminate\Contracts\Validation\Factory;
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
|
use Pterodactyl\Traits\Services\ValidatesValidationRules;
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
||||||
|
|
||||||
class VariableUpdateService
|
class VariableUpdateService
|
||||||
{
|
{
|
||||||
|
use ValidatesValidationRules;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
|
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Contracts\Validation\Factory
|
||||||
|
*/
|
||||||
|
private $validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VariableUpdateService constructor.
|
* VariableUpdateService constructor.
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface $repository
|
* @param \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface $repository
|
||||||
|
* @param \Illuminate\Contracts\Validation\Factory $validator
|
||||||
*/
|
*/
|
||||||
public function __construct(EggVariableRepositoryInterface $repository)
|
public function __construct(EggVariableRepositoryInterface $repository, Factory $validator)
|
||||||
{
|
{
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
|
$this->validator = $validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the validation factory instance to be used by rule validation
|
||||||
|
* checking in the trait.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Validation\Factory
|
||||||
|
*/
|
||||||
|
protected function getValidator(): Factory
|
||||||
|
{
|
||||||
|
return $this->validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,6 +80,10 @@ class VariableUpdateService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! empty($data['rules'] ?? '')) {
|
||||||
|
$this->validateRules($data['rules']);
|
||||||
|
}
|
||||||
|
|
||||||
$options = array_get($data, 'options') ?? [];
|
$options = array_get($data, 'options') ?? [];
|
||||||
|
|
||||||
return $this->repository->withoutFreshModel()->update($variable->id, [
|
return $this->repository->withoutFreshModel()->update($variable->id, [
|
||||||
|
|
40
app/Traits/Services/ValidatesValidationRules.php
Normal file
40
app/Traits/Services/ValidatesValidationRules.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Traits\Services;
|
||||||
|
|
||||||
|
use BadMethodCallException;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Contracts\Validation\Factory;
|
||||||
|
use Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException;
|
||||||
|
|
||||||
|
trait ValidatesValidationRules
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Contracts\Validation\Factory
|
||||||
|
*/
|
||||||
|
abstract protected function getValidator(): Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the rules being provided are valid for Laravel and can
|
||||||
|
* be resolved.
|
||||||
|
*
|
||||||
|
* @param array|string $rules
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||||
|
*/
|
||||||
|
public function validateRules($rules)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->getValidator()->make(['__TEST' => 'test'], ['__TEST' => $rules])->fails();
|
||||||
|
} catch (BadMethodCallException $exception) {
|
||||||
|
$matches = [];
|
||||||
|
if (preg_match('/Method \[(.+)\] does not exist\./', $exception->getMessage(), $matches)) {
|
||||||
|
throw new BadValidationRuleException(trans('exceptions.nest.variables.bad_validation_rule', [
|
||||||
|
'rule' => Str::snake(str_replace('validate', '', array_get($matches, 1, 'unknownRule'))),
|
||||||
|
]), $exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ return [
|
||||||
'variables' => [
|
'variables' => [
|
||||||
'env_not_unique' => 'The environment variable :name must be unique to this Egg.',
|
'env_not_unique' => 'The environment variable :name must be unique to this Egg.',
|
||||||
'reserved_name' => 'The environment variable :name is protected and cannot be assigned to a variable.',
|
'reserved_name' => 'The environment variable :name is protected and cannot be assigned to a variable.',
|
||||||
|
'bad_validation_rule' => 'The validation rule ":rule" is not a valid rule for this application.',
|
||||||
],
|
],
|
||||||
'importer' => [
|
'importer' => [
|
||||||
'json_error' => 'There was an error while attempting to parse the JSON file: :error.',
|
'json_error' => 'There was an error while attempting to parse the JSON file: :error.',
|
||||||
|
|
|
@ -105,20 +105,20 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label">Name <span class="field-required"></span></label>
|
<label class="control-label">Name <span class="field-required"></span></label>
|
||||||
<input type="text" name="name" class="form-control" />
|
<input type="text" name="name" class="form-control" value="{{ old('name') }}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label">Description</label>
|
<label class="control-label">Description</label>
|
||||||
<textarea name="description" class="form-control" rows="3"></textarea>
|
<textarea name="description" class="form-control" rows="3">{{ old('description') }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label class="control-label">Environment Variable <span class="field-required"></span></label>
|
<label class="control-label">Environment Variable <span class="field-required"></span></label>
|
||||||
<input type="text" name="env_variable" class="form-control" />
|
<input type="text" name="env_variable" class="form-control" value="{{ old('env_variable') }}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label class="control-label">Default Value</label>
|
<label class="control-label">Default Value</label>
|
||||||
<input type="text" name="default_value" class="form-control" />
|
<input type="text" name="default_value" class="form-control" value="{{ old('default_value') }}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<p class="text-muted small">This variable can be accessed in the statup command by entering <code>@{{environment variable value}}</code>.</p>
|
<p class="text-muted small">This variable can be accessed in the statup command by entering <code>@{{environment variable value}}</code>.</p>
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label">Input Rules <span class="field-required"></span></label>
|
<label class="control-label">Input Rules <span class="field-required"></span></label>
|
||||||
<input type="text" name="rules" class="form-control" value="required|string|max:20" placeholder="required|string|max:20" />
|
<input type="text" name="rules" class="form-control" value="{{ old('rules', 'required|string|max:20') }}" placeholder="required|string|max:20" />
|
||||||
<p class="text-muted small">These rules are defined using standard Laravel Framework validation rules.</p>
|
<p class="text-muted small">These rules are defined using standard Laravel Framework validation rules.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,9 @@ namespace Tests\Unit\Services\Eggs\Variables;
|
||||||
|
|
||||||
use Mockery as m;
|
use Mockery as m;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
use BadMethodCallException;
|
||||||
use Pterodactyl\Models\EggVariable;
|
use Pterodactyl\Models\EggVariable;
|
||||||
|
use Illuminate\Contracts\Validation\Factory;
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
||||||
|
|
||||||
|
@ -13,12 +15,12 @@ class VariableCreationServiceTest extends TestCase
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Services\Eggs\Variables\VariableCreationService
|
* @var \Illuminate\Contracts\Validation\Factory|\Mockery\Mock
|
||||||
*/
|
*/
|
||||||
protected $service;
|
private $validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup tests.
|
* Setup tests.
|
||||||
|
@ -28,8 +30,7 @@ class VariableCreationServiceTest extends TestCase
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
||||||
|
$this->validator = m::mock(Factory::class);
|
||||||
$this->service = new VariableCreationService($this->repository);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +47,7 @@ class VariableCreationServiceTest extends TestCase
|
||||||
'env_variable' => 'TEST_VAR_123',
|
'env_variable' => 'TEST_VAR_123',
|
||||||
]))->once()->andReturn(new EggVariable);
|
]))->once()->andReturn(new EggVariable);
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->service->handle(1, $data));
|
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,7 +63,7 @@ class VariableCreationServiceTest extends TestCase
|
||||||
'env_variable' => 'TEST_VAR_123',
|
'env_variable' => 'TEST_VAR_123',
|
||||||
]))->once()->andReturn(new EggVariable);
|
]))->once()->andReturn(new EggVariable);
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->service->handle(1, $data));
|
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,18 +82,20 @@ class VariableCreationServiceTest extends TestCase
|
||||||
'user_editable' => false,
|
'user_editable' => false,
|
||||||
]))->once()->andReturn(new EggVariable);
|
]))->once()->andReturn(new EggVariable);
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->service->handle(1, $data));
|
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that all of the reserved variables defined in the model trigger an exception.
|
* Test that all of the reserved variables defined in the model trigger an exception.
|
||||||
*
|
*
|
||||||
|
* @param string $variable
|
||||||
|
*
|
||||||
* @dataProvider reservedNamesProvider
|
* @dataProvider reservedNamesProvider
|
||||||
* @expectedException \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
* @expectedException \Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException
|
||||||
*/
|
*/
|
||||||
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
||||||
{
|
{
|
||||||
$this->service->handle(1, ['env_variable' => $variable]);
|
$this->getService()->handle(1, ['env_variable' => $variable]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +109,49 @@ class VariableCreationServiceTest extends TestCase
|
||||||
'egg_id' => 1,
|
'egg_id' => 1,
|
||||||
]))->once()->andReturn(new EggVariable);
|
]))->once()->andReturn(new EggVariable);
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->service->handle(1, $data));
|
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that validation errors due to invalid rules are caught and handled properly.
|
||||||
|
*
|
||||||
|
* @expectedException \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||||
|
* @expectedExceptionMessage The validation rule "hodor_door" is not a valid rule for this application.
|
||||||
|
*/
|
||||||
|
public function testInvalidValidationRulesResultInException()
|
||||||
|
{
|
||||||
|
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string|hodorDoor'];
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('make')->once()
|
||||||
|
->with(['__TEST' => 'test'], ['__TEST' => 'string|hodorDoor'])
|
||||||
|
->andReturnSelf();
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('fails')->once()
|
||||||
|
->withNoArgs()
|
||||||
|
->andThrow(new BadMethodCallException('Method [validateHodorDoor] does not exist.'));
|
||||||
|
|
||||||
|
$this->getService()->handle(1, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that an exception not stemming from a bad rule is not caught.
|
||||||
|
*
|
||||||
|
* @expectedException \BadMethodCallException
|
||||||
|
* @expectedExceptionMessage Received something, but no expectations were specified.
|
||||||
|
*/
|
||||||
|
public function testExceptionNotCausedByBadRuleIsNotCaught()
|
||||||
|
{
|
||||||
|
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string'];
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('make')->once()
|
||||||
|
->with(['__TEST' => 'test'], ['__TEST' => 'string'])
|
||||||
|
->andReturnSelf();
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('fails')->once()
|
||||||
|
->withNoArgs()
|
||||||
|
->andThrow(new BadMethodCallException('Received something, but no expectations were specified.'));
|
||||||
|
|
||||||
|
$this->getService()->handle(1, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,4 +169,14 @@ class VariableCreationServiceTest extends TestCase
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of the service with mocked dependencies for testing.
|
||||||
|
*
|
||||||
|
* @return \Pterodactyl\Services\Eggs\Variables\VariableCreationService
|
||||||
|
*/
|
||||||
|
private function getService(): VariableCreationService
|
||||||
|
{
|
||||||
|
return new VariableCreationService($this->repository, $this->validator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ namespace Tests\Unit\Services\Eggs\Variables;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Mockery as m;
|
use Mockery as m;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
use BadMethodCallException;
|
||||||
use Pterodactyl\Models\EggVariable;
|
use Pterodactyl\Models\EggVariable;
|
||||||
|
use Illuminate\Contracts\Validation\Factory;
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
use Pterodactyl\Exceptions\DisplayException;
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
||||||
|
@ -15,17 +17,17 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Models\EggVariable|\Mockery\Mock
|
* @var \Pterodactyl\Models\EggVariable|\Mockery\Mock
|
||||||
*/
|
*/
|
||||||
protected $model;
|
private $model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
||||||
*/
|
*/
|
||||||
protected $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Services\Eggs\Variables\VariableUpdateService
|
* @var \Illuminate\Contracts\Validation\Factory|\Mockery\Mock
|
||||||
*/
|
*/
|
||||||
protected $service;
|
private $validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup tests.
|
* Setup tests.
|
||||||
|
@ -36,8 +38,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
|
|
||||||
$this->model = factory(EggVariable::class)->make();
|
$this->model = factory(EggVariable::class)->make();
|
||||||
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
||||||
|
$this->validator = m::mock(Factory::class);
|
||||||
$this->service = new VariableUpdateService($this->repository);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +52,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
'user_editable' => false,
|
'user_editable' => false,
|
||||||
]))->once()->andReturn(true);
|
]))->once()->andReturn(true);
|
||||||
|
|
||||||
$this->assertTrue($this->service->handle($this->model, []));
|
$this->assertTrue($this->getService()->handle($this->model, []));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +68,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
'default_value' => '',
|
'default_value' => '',
|
||||||
]))->once()->andReturn(true);
|
]))->once()->andReturn(true);
|
||||||
|
|
||||||
$this->assertTrue($this->service->handle($this->model, ['default_value' => null]));
|
$this->assertTrue($this->getService()->handle($this->model, ['default_value' => null]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,7 +90,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
'env_variable' => 'TEST_VAR_123',
|
'env_variable' => 'TEST_VAR_123',
|
||||||
]))->once()->andReturn(true);
|
]))->once()->andReturn(true);
|
||||||
|
|
||||||
$this->assertTrue($this->service->handle($this->model, ['env_variable' => 'TEST_VAR_123']));
|
$this->assertTrue($this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +108,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
'description' => '',
|
'description' => '',
|
||||||
]))->once()->andReturn(true);
|
]))->once()->andReturn(true);
|
||||||
|
|
||||||
$this->assertTrue($this->service->handle($this->model, ['options' => null, 'description' => null]));
|
$this->assertTrue($this->getService()->handle($this->model, ['options' => null, 'description' => null]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,7 +130,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
'env_variable' => 'TEST_VAR_123',
|
'env_variable' => 'TEST_VAR_123',
|
||||||
]))->once()->andReturn(true);
|
]))->once()->andReturn(true);
|
||||||
|
|
||||||
$this->assertTrue($this->service->handle($this->model, ['user_viewable' => 123456, 'env_variable' => 'TEST_VAR_123']));
|
$this->assertTrue($this->getService()->handle($this->model, ['user_viewable' => 123456, 'env_variable' => 'TEST_VAR_123']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,7 +146,7 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
])->once()->andReturn(1);
|
])->once()->andReturn(1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->service->handle($this->model, ['env_variable' => 'TEST_VAR_123']);
|
$this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123']);
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
$this->assertInstanceOf(DisplayException::class, $exception);
|
$this->assertInstanceOf(DisplayException::class, $exception);
|
||||||
$this->assertEquals(trans('exceptions.service.variables.env_not_unique', [
|
$this->assertEquals(trans('exceptions.service.variables.env_not_unique', [
|
||||||
|
@ -162,7 +163,51 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
||||||
{
|
{
|
||||||
$this->service->handle($this->model, ['env_variable' => $variable]);
|
$this->getService()->handle($this->model, ['env_variable' => $variable]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that validation errors due to invalid rules are caught and handled properly.
|
||||||
|
*
|
||||||
|
* @expectedException \Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException
|
||||||
|
* @expectedExceptionMessage The validation rule "hodor_door" is not a valid rule for this application.
|
||||||
|
*/
|
||||||
|
public function testInvalidValidationRulesResultInException()
|
||||||
|
{
|
||||||
|
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string|hodorDoor'];
|
||||||
|
|
||||||
|
$this->repository->shouldReceive('setColumns->findCountWhere')->once()->andReturn(0);
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('make')->once()
|
||||||
|
->with(['__TEST' => 'test'], ['__TEST' => 'string|hodorDoor'])
|
||||||
|
->andReturnSelf();
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('fails')->once()
|
||||||
|
->withNoArgs()
|
||||||
|
->andThrow(new BadMethodCallException('Method [validateHodorDoor] does not exist.'));
|
||||||
|
|
||||||
|
$this->getService()->handle($this->model, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that an exception not stemming from a bad rule is not caught.
|
||||||
|
*
|
||||||
|
* @expectedException \BadMethodCallException
|
||||||
|
* @expectedExceptionMessage Received something, but no expectations were specified.
|
||||||
|
*/
|
||||||
|
public function testExceptionNotCausedByBadRuleIsNotCaught()
|
||||||
|
{
|
||||||
|
$data = ['rules' => 'string'];
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('make')->once()
|
||||||
|
->with(['__TEST' => 'test'], ['__TEST' => 'string'])
|
||||||
|
->andReturnSelf();
|
||||||
|
|
||||||
|
$this->validator->shouldReceive('fails')->once()
|
||||||
|
->withNoArgs()
|
||||||
|
->andThrow(new BadMethodCallException('Received something, but no expectations were specified.'));
|
||||||
|
|
||||||
|
$this->getService()->handle($this->model, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,4 +225,14 @@ class VariableUpdateServiceTest extends TestCase
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of the service with mocked dependencies for testing.
|
||||||
|
*
|
||||||
|
* @return \Pterodactyl\Services\Eggs\Variables\VariableUpdateService
|
||||||
|
*/
|
||||||
|
private function getService(): VariableUpdateService
|
||||||
|
{
|
||||||
|
return new VariableUpdateService($this->repository, $this->validator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue