From e01d7497f56f8486d1296b7949374e061f9bb5ed Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 8 Oct 2017 23:50:52 -0500 Subject: [PATCH] Add ability to update an Egg by re-uploading a file. --- .../Service/Egg/BadJsonFormatException.php | 9 + .../{Pack => }/InvalidFileUploadException.php | 2 +- .../Admin/Nests/EggShareController.php | 40 +++- app/Http/Controllers/Admin/PackController.php | 2 +- .../Admin/Egg/EggImportFormRequest.php | 9 +- .../Eggs/Sharing/EggImporterService.php | 11 +- .../Eggs/Sharing/EggUpdateImporterService.php | 113 ++++++++++ app/Services/Packs/PackCreationService.php | 4 +- app/Services/Packs/TemplateUploadService.php | 6 +- resources/lang/en/admin/nests.php | 1 + resources/lang/en/exceptions.php | 1 + .../pterodactyl/admin/eggs/view.blade.php | 31 ++- routes/admin.php | 2 + .../Eggs/Sharing/EggImporterServiceTest.php | 25 ++- .../Sharing/EggUpdateImporterServiceTest.php | 212 ++++++++++++++++++ .../Packs/PackCreationServiceTest.php | 2 +- .../Packs/TemplateUploadServiceTest.php | 2 +- 17 files changed, 449 insertions(+), 23 deletions(-) create mode 100644 app/Exceptions/Service/Egg/BadJsonFormatException.php rename app/Exceptions/Service/{Pack => }/InvalidFileUploadException.php (87%) create mode 100644 app/Services/Eggs/Sharing/EggUpdateImporterService.php create mode 100644 tests/Unit/Services/Eggs/Sharing/EggUpdateImporterServiceTest.php diff --git a/app/Exceptions/Service/Egg/BadJsonFormatException.php b/app/Exceptions/Service/Egg/BadJsonFormatException.php new file mode 100644 index 000000000..0246f031c --- /dev/null +++ b/app/Exceptions/Service/Egg/BadJsonFormatException.php @@ -0,0 +1,9 @@ +alert = $alert; $this->exporterService = $exporterService; $this->importerService = $importerService; + $this->updateImporterService = $updateImporterService; } /** @@ -76,7 +85,8 @@ class EggShareController extends Controller * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException */ public function import(EggImportFormRequest $request): RedirectResponse { @@ -85,4 +95,24 @@ class EggShareController extends Controller return redirect()->route('admin.nests.egg.view', ['egg' => $egg->id]); } + + /** + * Update an existing Egg using a new imported file. + * + * @param \Pterodactyl\Http\Requests\Admin\Egg\EggImportFormRequest $request + * @param int $egg + * @return \Illuminate\Http\RedirectResponse + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException + */ + public function update(EggImportFormRequest $request, int $egg): RedirectResponse + { + $this->updateImporterService->handle($egg, $request->file('import_file')); + $this->alert->success(trans('admin/nests.eggs.notices.updated_via_import'))->flash(); + + return redirect()->route('admin.nests.egg.view', ['egg' => $egg]); + } } diff --git a/app/Http/Controllers/Admin/PackController.php b/app/Http/Controllers/Admin/PackController.php index 742f1ed0a..ae6c86fda 100644 --- a/app/Http/Controllers/Admin/PackController.php +++ b/app/Http/Controllers/Admin/PackController.php @@ -156,7 +156,7 @@ class PackController extends Controller * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException * @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException * @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException diff --git a/app/Http/Requests/Admin/Egg/EggImportFormRequest.php b/app/Http/Requests/Admin/Egg/EggImportFormRequest.php index 776c291e2..b6adb768e 100644 --- a/app/Http/Requests/Admin/Egg/EggImportFormRequest.php +++ b/app/Http/Requests/Admin/Egg/EggImportFormRequest.php @@ -18,9 +18,14 @@ class EggImportFormRequest extends AdminFormRequest */ public function rules() { - return [ + $rules = [ 'import_file' => 'bail|required|file|max:1000|mimetypes:application/json,text/plain', - 'import_to_nest' => 'bail|required|integer|exists:nests,id', ]; + + if ($this->method() !== 'PUT') { + $rules['import_to_nest'] = 'bail|required|integer|exists:nests,id'; + } + + return $rules; } } diff --git a/app/Services/Eggs/Sharing/EggImporterService.php b/app/Services/Eggs/Sharing/EggImporterService.php index 3155eefe8..7143bbc6e 100644 --- a/app/Services/Eggs/Sharing/EggImporterService.php +++ b/app/Services/Eggs/Sharing/EggImporterService.php @@ -15,7 +15,8 @@ use Illuminate\Http\UploadedFile; use Illuminate\Database\ConnectionInterface; use Pterodactyl\Contracts\Repository\EggRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; +use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface; class EggImporterService @@ -69,7 +70,8 @@ class EggImporterService * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException */ public function handle(UploadedFile $file, int $nest): Egg { @@ -78,6 +80,11 @@ class EggImporterService } $parsed = json_decode($file->openFile()->fread($file->getSize())); + if (json_last_error() !== 0) { + throw new BadJsonFormatException(trans('exceptions.nest.importer.json_error', [ + 'error' => json_last_error_msg(), + ])); + } if (object_get($parsed, 'meta.version') !== 'PTDL_v1') { throw new InvalidFileUploadException(trans('exceptions.nest.importer.invalid_json_provided')); diff --git a/app/Services/Eggs/Sharing/EggUpdateImporterService.php b/app/Services/Eggs/Sharing/EggUpdateImporterService.php new file mode 100644 index 000000000..41bc29f06 --- /dev/null +++ b/app/Services/Eggs/Sharing/EggUpdateImporterService.php @@ -0,0 +1,113 @@ +connection = $connection; + $this->repository = $repository; + $this->variableRepository = $variableRepository; + } + + /** + * Update an existing Egg using an uploaded JSON file. + * + * @param int $egg + * @param \Illuminate\Http\UploadedFile $file + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + * @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException + */ + public function handle(int $egg, UploadedFile $file) + { + if (! $file->isValid() || ! $file->isFile()) { + throw new InvalidFileUploadException(trans('exceptions.nest.importer.file_error')); + } + + $parsed = json_decode($file->openFile()->fread($file->getSize())); + if (json_last_error() !== 0) { + throw new BadJsonFormatException(trans('exceptions.nest.importer.json_error', [ + 'error' => json_last_error_msg(), + ])); + } + + if (object_get($parsed, 'meta.version') !== 'PTDL_v1') { + throw new InvalidFileUploadException(trans('exceptions.nest.importer.invalid_json_provided')); + } + + $this->connection->beginTransaction(); + $this->repository->update($egg, [ + 'author' => object_get($parsed, 'author'), + 'name' => object_get($parsed, 'name'), + 'description' => object_get($parsed, 'description'), + 'docker_image' => object_get($parsed, 'image'), + 'config_files' => object_get($parsed, 'config.files'), + 'config_startup' => object_get($parsed, 'config.startup'), + 'config_logs' => object_get($parsed, 'config.logs'), + 'config_stop' => object_get($parsed, 'config.stop'), + 'startup' => object_get($parsed, 'startup'), + 'script_install' => object_get($parsed, 'scripts.installation.script'), + 'script_entry' => object_get($parsed, 'scripts.installation.entrypoint'), + 'script_container' => object_get($parsed, 'scripts.installation.container'), + ], true, true); + + // Update Existing Variables + collect($parsed->variables)->each(function ($variable) use ($egg) { + $this->variableRepository->withoutFresh()->updateOrCreate([ + 'egg_id' => $egg, + 'env_variable' => $variable->env_variable, + ], collect($variable)->except(['egg_id', 'env_variable'])->toArray()); + }); + + $imported = collect($parsed->variables)->pluck('env_variable')->toArray(); + $existing = $this->variableRepository->withColumns(['id', 'env_variable'])->findWhere([['egg_id', '=', $egg]]); + + // Delete variables not present in the import. + collect($existing)->each(function ($variable) use ($egg, $imported) { + if (! in_array($variable->env_variable, $imported)) { + $this->variableRepository->deleteWhere([ + ['egg_id', '=', $egg], + ['env_variable', '=', $variable->env_variable], + ]); + } + }); + + $this->connection->commit(); + } +} diff --git a/app/Services/Packs/PackCreationService.php b/app/Services/Packs/PackCreationService.php index ff40f072a..80b452d88 100644 --- a/app/Services/Packs/PackCreationService.php +++ b/app/Services/Packs/PackCreationService.php @@ -13,8 +13,8 @@ use Ramsey\Uuid\Uuid; use Illuminate\Http\UploadedFile; use Illuminate\Database\ConnectionInterface; use Pterodactyl\Contracts\Repository\PackRepositoryInterface; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException; class PackCreationService @@ -65,7 +65,7 @@ class PackCreationService * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException */ public function handle(array $data, UploadedFile $file = null) { diff --git a/app/Services/Packs/TemplateUploadService.php b/app/Services/Packs/TemplateUploadService.php index 045bfec48..6495edd68 100644 --- a/app/Services/Packs/TemplateUploadService.php +++ b/app/Services/Packs/TemplateUploadService.php @@ -11,8 +11,8 @@ namespace Pterodactyl\Services\Packs; use ZipArchive; use Illuminate\Http\UploadedFile; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\ZipExtractionException; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException; use Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException; use Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException; @@ -58,7 +58,7 @@ class TemplateUploadService * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException * @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException @@ -94,7 +94,7 @@ class TemplateUploadService * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException - * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException + * @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException * @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException * @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException diff --git a/resources/lang/en/admin/nests.php b/resources/lang/en/admin/nests.php index b78af4903..19e6b5a1e 100644 --- a/resources/lang/en/admin/nests.php +++ b/resources/lang/en/admin/nests.php @@ -16,6 +16,7 @@ return [ 'eggs' => [ 'notices' => [ 'imported' => 'Successfully imported this Egg and its associated variables.', + 'updated_via_import' => 'This Egg has been updated using the file provided.', 'deleted' => 'Successfully deleted the requested egg from the Panel.', 'updated' => 'Egg configuration has been updated successfully.', 'script_updated' => 'Egg install script has been updated and will run whenever servers are installed.', diff --git a/resources/lang/en/exceptions.php b/resources/lang/en/exceptions.php index c700b62ff..e5bee177d 100644 --- a/resources/lang/en/exceptions.php +++ b/resources/lang/en/exceptions.php @@ -31,6 +31,7 @@ return [ 'reserved_name' => 'The environment variable :name is protected and cannot be assigned to a variable.', ], 'importer' => [ + 'json_error' => 'There was an error while attempting to parse the JSON file: :error.', 'file_error' => 'The JSON file provided was not valid.', 'invalid_json_provided' => 'The JSON file provided is not in a format that can be recognized.', ], diff --git a/resources/themes/pterodactyl/admin/eggs/view.blade.php b/resources/themes/pterodactyl/admin/eggs/view.blade.php index 215273005..e5b615c6f 100644 --- a/resources/themes/pterodactyl/admin/eggs/view.blade.php +++ b/resources/themes/pterodactyl/admin/eggs/view.blade.php @@ -30,14 +30,39 @@ +
+
+ Notice: Editing an Egg or any of the Process Management fields requires that each Daemon be rebooted in order to apply the changes. +
+
-
+
-
- Notice: Editing an Egg or any of the Process Management fields requires that each Daemon be rebooted in order to apply the changes. +
+
+
+
+
+ +
+ +

If you would like to replace settings for this Egg by uploading a new JSON file, simply select it here and press "Update Egg". This will not change any existing startup strings or Docker images for existing servers.

+
+
+
+
+ {!! csrf_field() !!} + +
+
+
+
+ +
+
diff --git a/routes/admin.php b/routes/admin.php index 8952f3217..da1451cb9 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -163,6 +163,8 @@ Route::group(['prefix' => 'nests'], function () { Route::post('/egg/new', 'Nests\EggController@store'); Route::post('/egg/{egg}/variables', 'Nests\EggVariableController@store'); + Route::put('/egg/{egg}', 'Nests\EggShareController@update'); + Route::patch('/view/{nest}', 'Nests\NestController@update'); Route::patch('/egg/{egg}', 'Nests\EggController@update'); Route::patch('/egg/{egg}/scripts', 'Nests\EggScriptController@update'); diff --git a/tests/Unit/Services/Eggs/Sharing/EggImporterServiceTest.php b/tests/Unit/Services/Eggs/Sharing/EggImporterServiceTest.php index 870482e68..db6618784 100644 --- a/tests/Unit/Services/Eggs/Sharing/EggImporterServiceTest.php +++ b/tests/Unit/Services/Eggs/Sharing/EggImporterServiceTest.php @@ -21,7 +21,8 @@ use Pterodactyl\Exceptions\PterodactylException; use Pterodactyl\Services\Eggs\Sharing\EggImporterService; use Pterodactyl\Contracts\Repository\EggRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; +use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface; class EggImporterServiceTest extends TestCase @@ -90,7 +91,7 @@ class EggImporterServiceTest extends TestCase $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([ 'meta' => ['version' => 'PTDL_v1'], 'name' => $egg->name, - 'tag' => $egg->tag, + 'author' => $egg->author, 'variables' => [ $variable = factory(EggVariable::class)->make(), ], @@ -165,4 +166,24 @@ class EggImporterServiceTest extends TestCase $this->assertEquals(trans('exceptions.nest.importer.invalid_json_provided'), $exception->getMessage()); } } + + /** + * Test that an exception is thrown if bad JSON is provided. + */ + public function testExceptionIsThrownIfBadJsonIsProvided() + { + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100); + $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn('}'); + + try { + $this->service->handle($this->file, 1234); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(BadJsonFormatException::class, $exception); + $this->assertEquals(trans('exceptions.nest.importer.json_error', [ + 'error' => json_last_error_msg(), + ]), $exception->getMessage()); + } + } } diff --git a/tests/Unit/Services/Eggs/Sharing/EggUpdateImporterServiceTest.php b/tests/Unit/Services/Eggs/Sharing/EggUpdateImporterServiceTest.php new file mode 100644 index 000000000..b376b80b6 --- /dev/null +++ b/tests/Unit/Services/Eggs/Sharing/EggUpdateImporterServiceTest.php @@ -0,0 +1,212 @@ +connection = m::mock(ConnectionInterface::class); + $this->file = m::mock(UploadedFile::class); + $this->repository = m::mock(EggRepositoryInterface::class); + $this->variableRepository = m::mock(EggVariableRepositoryInterface::class); + + $this->service = new EggUpdateImporterService($this->connection, $this->repository, $this->variableRepository); + } + + /** + * Test that an egg update is handled correctly using an uploaded file. + */ + public function testEggIsUpdated() + { + $egg = factory(Egg::class)->make(); + $variable = factory(EggVariable::class)->make(); + + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100); + $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([ + 'meta' => ['version' => 'PTDL_v1'], + 'name' => $egg->name, + 'author' => 'newauthor@example.com', + 'variables' => [$variable->toArray()], + ])); + + $this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); + $this->repository->shouldReceive('update')->with($egg->id, m::subset([ + 'author' => 'newauthor@example.com', + 'name' => $egg->name, + ]), true, true)->once()->andReturn($egg); + + $this->variableRepository->shouldReceive('withoutFresh->updateOrCreate')->with([ + 'egg_id' => $egg->id, + 'env_variable' => $variable->env_variable, + ], collect($variable)->except(['egg_id', 'env_variable'])->toArray())->once()->andReturnNull(); + + $this->variableRepository->shouldReceive('withColumns')->with(['id', 'env_variable'])->once()->andReturnSelf() + ->shouldReceive('findWhere')->with([['egg_id', '=', $egg->id]])->once()->andReturn([$variable]); + + $this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); + + $this->service->handle($egg->id, $this->file); + $this->assertTrue(true); + } + + /** + * Test that an imported file with less variables than currently existing deletes + * the un-needed variables from the database. + */ + public function testVariablesMissingFromImportAreDeleted() + { + $egg = factory(Egg::class)->make(); + $variable1 = factory(EggVariable::class)->make(); + $variable2 = factory(EggVariable::class)->make(); + + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100); + $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([ + 'meta' => ['version' => 'PTDL_v1'], + 'name' => $egg->name, + 'author' => 'newauthor@example.com', + 'variables' => [$variable1->toArray()], + ])); + + $this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); + $this->repository->shouldReceive('update')->with($egg->id, m::subset([ + 'author' => 'newauthor@example.com', + 'name' => $egg->name, + ]), true, true)->once()->andReturn($egg); + + $this->variableRepository->shouldReceive('withoutFresh->updateOrCreate')->with([ + 'egg_id' => $egg->id, + 'env_variable' => $variable1->env_variable, + ], collect($variable1)->except(['egg_id', 'env_variable'])->toArray())->once()->andReturnNull(); + + $this->variableRepository->shouldReceive('withColumns')->with(['id', 'env_variable'])->once()->andReturnSelf() + ->shouldReceive('findWhere')->with([['egg_id', '=', $egg->id]])->once()->andReturn([$variable1, $variable2]); + + $this->variableRepository->shouldReceive('deleteWhere')->with([ + ['egg_id', '=', $egg->id], + ['env_variable', '=', $variable2->env_variable], + ])->once()->andReturnNull(); + + $this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); + + $this->service->handle($egg->id, $this->file); + $this->assertTrue(true); + } + + /** + * Test that an exception is thrown if the file is invalid. + */ + public function testExceptionIsThrownIfFileIsInvalid() + { + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(false); + try { + $this->service->handle(1234, $this->file); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(InvalidFileUploadException::class, $exception); + $this->assertEquals(trans('exceptions.nest.importer.file_error'), $exception->getMessage()); + } + } + + /** + * Test that an exception is thrown if the file is not a file. + */ + public function testExceptionIsThrownIfFileIsNotAFile() + { + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(false); + + try { + $this->service->handle(1234, $this->file); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(InvalidFileUploadException::class, $exception); + $this->assertEquals(trans('exceptions.nest.importer.file_error'), $exception->getMessage()); + } + } + + /** + * Test that an exception is thrown if the JSON metadata is invalid. + */ + public function testExceptionIsThrownIfJsonMetaDataIsInvalid() + { + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100); + $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([ + 'meta' => ['version' => 'hodor'], + ])); + + try { + $this->service->handle(1234, $this->file); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(InvalidFileUploadException::class, $exception); + $this->assertEquals(trans('exceptions.nest.importer.invalid_json_provided'), $exception->getMessage()); + } + } + + /** + * Test that an exception is thrown if bad JSON is provided. + */ + public function testExceptionIsThrownIfBadJsonIsProvided() + { + $this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true); + $this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100); + $this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn('}'); + + try { + $this->service->handle(1234, $this->file); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(BadJsonFormatException::class, $exception); + $this->assertEquals(trans('exceptions.nest.importer.json_error', [ + 'error' => json_last_error_msg(), + ]), $exception->getMessage()); + } + } +} diff --git a/tests/Unit/Services/Packs/PackCreationServiceTest.php b/tests/Unit/Services/Packs/PackCreationServiceTest.php index 972ee7a45..d0baddf30 100644 --- a/tests/Unit/Services/Packs/PackCreationServiceTest.php +++ b/tests/Unit/Services/Packs/PackCreationServiceTest.php @@ -19,7 +19,7 @@ use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Database\ConnectionInterface; use Pterodactyl\Services\Packs\PackCreationService; use Pterodactyl\Contracts\Repository\PackRepositoryInterface; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException; class PackCreationServiceTest extends TestCase diff --git a/tests/Unit/Services/Packs/TemplateUploadServiceTest.php b/tests/Unit/Services/Packs/TemplateUploadServiceTest.php index 4082fdd59..c1df4c207 100644 --- a/tests/Unit/Services/Packs/TemplateUploadServiceTest.php +++ b/tests/Unit/Services/Packs/TemplateUploadServiceTest.php @@ -16,8 +16,8 @@ use Pterodactyl\Models\Pack; use Illuminate\Http\UploadedFile; use Pterodactyl\Services\Packs\PackCreationService; use Pterodactyl\Services\Packs\TemplateUploadService; +use Pterodactyl\Exceptions\Service\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\ZipExtractionException; -use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException; use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException; use Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException; use Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException;