From 7618f306bdbebbbf9c7143437b520b49ed9adbc9 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 2 Nov 2020 20:20:36 -0800 Subject: [PATCH] Support functionality for per-egg features --- app/Models/Egg.php | 33 +++++++++++++++++++ app/Services/Eggs/EggUpdateService.php | 8 ++--- .../Eggs/Sharing/EggExporterService.php | 1 + .../Eggs/Sharing/EggImporterService.php | 1 + .../Eggs/Sharing/EggUpdateImporterService.php | 1 + ..._02_201014_add_features_column_to_eggs.php | 32 ++++++++++++++++++ .../Services/Eggs/EggUpdateServiceTest.php | 14 -------- 7 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2020_11_02_201014_add_features_column_to_eggs.php diff --git a/app/Models/Egg.php b/app/Models/Egg.php index 4aa33beff..dd133380a 100644 --- a/app/Models/Egg.php +++ b/app/Models/Egg.php @@ -9,6 +9,7 @@ namespace Pterodactyl\Models; * @property string $author * @property string $name * @property string|null $description + * @property array|null $features * @property string $docker_image * @property string|null $config_files * @property string|null $config_startup @@ -31,6 +32,7 @@ namespace Pterodactyl\Models; * @property string|null $inherit_config_startup * @property string|null $inherit_config_logs * @property string|null $inherit_config_stop + * @property array|null $inherit_features * * @property \Pterodactyl\Models\Nest $nest * @property \Illuminate\Database\Eloquent\Collection|\Pterodactyl\Models\Server[] $servers @@ -46,6 +48,18 @@ class Egg extends Model */ const RESOURCE_NAME = 'egg'; + /** + * Different features that can be enabled on any given egg. These are used internally + * to determine which types of frontend functionality should be shown to the user. Eggs + * will automatically inherit features from a parent egg if they are already configured + * to copy configuration values from said egg. + * + * To skip copying the features, an empty array value should be passed in ("[]") rather + * than leaving it null. + */ + const FEATURE_EULA_POPUP = 'eula'; + const FEATURE_FASTDL = 'fastdl'; + /** * The table associated with the model. * @@ -61,6 +75,7 @@ class Egg extends Model protected $fillable = [ 'name', 'description', + 'features', 'docker_image', 'config_files', 'config_startup', @@ -85,6 +100,7 @@ class Egg extends Model 'config_from' => 'integer', 'script_is_privileged' => 'boolean', 'copy_script_from' => 'integer', + 'features' => 'array', ]; /** @@ -95,6 +111,7 @@ class Egg extends Model 'uuid' => 'required|string|size:36', 'name' => 'required|string|max:191', 'description' => 'string|nullable', + 'features' => 'json|nullable', 'author' => 'required|string|email', 'docker_image' => 'required|string|max:191', 'startup' => 'required|nullable|string', @@ -109,6 +126,7 @@ class Egg extends Model * @var array */ protected $attributes = [ + 'features' => null, 'config_stop' => null, 'config_startup' => null, 'config_logs' => null, @@ -216,6 +234,21 @@ class Egg extends Model return $this->configFrom->config_stop; } + /** + * Returns the features available to this egg from the parent configuration if there are + * no features defined for this egg specifically and there is a parent egg configured. + * + * @return array|null + */ + public function getInheritFeaturesAttribute() + { + if (! is_null($this->features) || is_null($this->config_from)) { + return $this->features; + } + + return $this->configFrom->features; + } + /** * Gets nest associated with an egg. * diff --git a/app/Services/Eggs/EggUpdateService.php b/app/Services/Eggs/EggUpdateService.php index aa4ec39b6..dc0bffc1f 100644 --- a/app/Services/Eggs/EggUpdateService.php +++ b/app/Services/Eggs/EggUpdateService.php @@ -33,19 +33,15 @@ class EggUpdateService /** * Update a service option. * - * @param int|\Pterodactyl\Models\Egg $egg + * @param \Pterodactyl\Models\Egg $egg * @param array $data * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\Egg\NoParentConfigurationFoundException */ - public function handle($egg, array $data) + public function handle(Egg $egg, array $data) { - if (! $egg instanceof Egg) { - $egg = $this->repository->find($egg); - } - if (! is_null(array_get($data, 'config_from'))) { $results = $this->repository->findCountWhere([ ['nest_id', '=', $egg->nest_id], diff --git a/app/Services/Eggs/Sharing/EggExporterService.php b/app/Services/Eggs/Sharing/EggExporterService.php index 1602fc919..2d32060ac 100644 --- a/app/Services/Eggs/Sharing/EggExporterService.php +++ b/app/Services/Eggs/Sharing/EggExporterService.php @@ -43,6 +43,7 @@ class EggExporterService 'name' => $egg->name, 'author' => $egg->author, 'description' => $egg->description, + 'features' => $egg->features, 'image' => $egg->docker_image, 'startup' => $egg->startup, 'config' => [ diff --git a/app/Services/Eggs/Sharing/EggImporterService.php b/app/Services/Eggs/Sharing/EggImporterService.php index 96c4c72eb..786cf7a50 100644 --- a/app/Services/Eggs/Sharing/EggImporterService.php +++ b/app/Services/Eggs/Sharing/EggImporterService.php @@ -101,6 +101,7 @@ class EggImporterService 'author' => object_get($parsed, 'author'), 'name' => object_get($parsed, 'name'), 'description' => object_get($parsed, 'description'), + 'features' => object_get($parsed, 'features'), 'docker_image' => object_get($parsed, 'image'), 'config_files' => object_get($parsed, 'config.files'), 'config_startup' => object_get($parsed, 'config.startup'), diff --git a/app/Services/Eggs/Sharing/EggUpdateImporterService.php b/app/Services/Eggs/Sharing/EggUpdateImporterService.php index 91b8d2b2e..3a3913a58 100644 --- a/app/Services/Eggs/Sharing/EggUpdateImporterService.php +++ b/app/Services/Eggs/Sharing/EggUpdateImporterService.php @@ -86,6 +86,7 @@ class EggUpdateImporterService 'author' => object_get($parsed, 'author'), 'name' => object_get($parsed, 'name'), 'description' => object_get($parsed, 'description'), + 'features' => object_get($parsed, 'features'), 'docker_image' => object_get($parsed, 'image'), 'config_files' => object_get($parsed, 'config.files'), 'config_startup' => object_get($parsed, 'config.startup'), diff --git a/database/migrations/2020_11_02_201014_add_features_column_to_eggs.php b/database/migrations/2020_11_02_201014_add_features_column_to_eggs.php new file mode 100644 index 000000000..1da0cca4f --- /dev/null +++ b/database/migrations/2020_11_02_201014_add_features_column_to_eggs.php @@ -0,0 +1,32 @@ +json('features')->after('description')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('eggs', function (Blueprint $table) { + $table->dropColumn('features'); + }); + } +} diff --git a/tests/Unit/Services/Eggs/EggUpdateServiceTest.php b/tests/Unit/Services/Eggs/EggUpdateServiceTest.php index 0ffe4f373..22104995e 100644 --- a/tests/Unit/Services/Eggs/EggUpdateServiceTest.php +++ b/tests/Unit/Services/Eggs/EggUpdateServiceTest.php @@ -88,18 +88,4 @@ class EggUpdateServiceTest extends TestCase $this->assertEquals(trans('exceptions.nest.egg.must_be_child'), $exception->getMessage()); } } - - /** - * Test that an integer linking to a model can be passed in place of the Egg model. - */ - public function testIntegerCanBePassedInPlaceOfModel() - { - $this->repository->shouldReceive('find')->with($this->model->id)->once()->andReturn($this->model); - $this->repository->shouldReceive('withoutFreshModel->update') - ->with($this->model->id, ['test_field' => 'field_value'])->once()->andReturnNull(); - - $this->service->handle($this->model->id, ['test_field' => 'field_value']); - - $this->assertTrue(true); - } }