Skip to content

Commit e01d749

Browse files
committed
Add ability to update an Egg by re-uploading a file.
1 parent e2cb789 commit e01d749

File tree

17 files changed

+449
-23
lines changed

17 files changed

+449
-23
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Pterodactyl\Exceptions\Service\Egg;
4+
5+
use Pterodactyl\Exceptions\DisplayException;
6+
7+
class BadJsonFormatException extends DisplayException
8+
{
9+
}

app/Exceptions/Service/Pack/InvalidFileUploadException.php renamed to app/Exceptions/Service/InvalidFileUploadException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* https://opensource.org/licenses/MIT
88
*/
99

10-
namespace Pterodactyl\Exceptions\Service\Pack;
10+
namespace Pterodactyl\Exceptions\Service;
1111

1212
use Pterodactyl\Exceptions\DisplayException;
1313

app/Http/Controllers/Admin/Nests/EggShareController.php

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Pterodactyl\Services\Eggs\Sharing\EggExporterService;
1818
use Pterodactyl\Services\Eggs\Sharing\EggImporterService;
1919
use Pterodactyl\Http\Requests\Admin\Egg\EggImportFormRequest;
20+
use Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService;
2021

2122
class EggShareController extends Controller
2223
{
@@ -35,21 +36,29 @@ class EggShareController extends Controller
3536
*/
3637
protected $importerService;
3738

39+
/**
40+
* @var \Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService
41+
*/
42+
protected $updateImporterService;
43+
3844
/**
3945
* OptionShareController constructor.
4046
*
41-
* @param \Prologue\Alerts\AlertsMessageBag $alert
42-
* @param \Pterodactyl\Services\Eggs\Sharing\EggExporterService $exporterService
43-
* @param \Pterodactyl\Services\Eggs\Sharing\EggImporterService $importerService
47+
* @param \Prologue\Alerts\AlertsMessageBag $alert
48+
* @param \Pterodactyl\Services\Eggs\Sharing\EggExporterService $exporterService
49+
* @param \Pterodactyl\Services\Eggs\Sharing\EggImporterService $importerService
50+
* @param \Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService $updateImporterService
4451
*/
4552
public function __construct(
4653
AlertsMessageBag $alert,
4754
EggExporterService $exporterService,
48-
EggImporterService $importerService
55+
EggImporterService $importerService,
56+
EggUpdateImporterService $updateImporterService
4957
) {
5058
$this->alert = $alert;
5159
$this->exporterService = $exporterService;
5260
$this->importerService = $importerService;
61+
$this->updateImporterService = $updateImporterService;
5362
}
5463

5564
/**
@@ -76,7 +85,8 @@ public function export(Egg $egg): Response
7685
*
7786
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
7887
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
79-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
88+
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
89+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
8090
*/
8191
public function import(EggImportFormRequest $request): RedirectResponse
8292
{
@@ -85,4 +95,24 @@ public function import(EggImportFormRequest $request): RedirectResponse
8595

8696
return redirect()->route('admin.nests.egg.view', ['egg' => $egg->id]);
8797
}
98+
99+
/**
100+
* Update an existing Egg using a new imported file.
101+
*
102+
* @param \Pterodactyl\Http\Requests\Admin\Egg\EggImportFormRequest $request
103+
* @param int $egg
104+
* @return \Illuminate\Http\RedirectResponse
105+
*
106+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
107+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
108+
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
109+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
110+
*/
111+
public function update(EggImportFormRequest $request, int $egg): RedirectResponse
112+
{
113+
$this->updateImporterService->handle($egg, $request->file('import_file'));
114+
$this->alert->success(trans('admin/nests.eggs.notices.updated_via_import'))->flash();
115+
116+
return redirect()->route('admin.nests.egg.view', ['egg' => $egg]);
117+
}
88118
}

app/Http/Controllers/Admin/PackController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public function newTemplate()
156156
*
157157
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
158158
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
159-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
159+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
160160
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException
161161
* @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException
162162
* @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException

app/Http/Requests/Admin/Egg/EggImportFormRequest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ class EggImportFormRequest extends AdminFormRequest
1818
*/
1919
public function rules()
2020
{
21-
return [
21+
$rules = [
2222
'import_file' => 'bail|required|file|max:1000|mimetypes:application/json,text/plain',
23-
'import_to_nest' => 'bail|required|integer|exists:nests,id',
2423
];
24+
25+
if ($this->method() !== 'PUT') {
26+
$rules['import_to_nest'] = 'bail|required|integer|exists:nests,id';
27+
}
28+
29+
return $rules;
2530
}
2631
}

app/Services/Eggs/Sharing/EggImporterService.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
use Illuminate\Database\ConnectionInterface;
1616
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
1717
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
18-
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
18+
use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException;
19+
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
1920
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
2021

2122
class EggImporterService
@@ -69,7 +70,8 @@ public function __construct(
6970
*
7071
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
7172
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
72-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
73+
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
74+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
7375
*/
7476
public function handle(UploadedFile $file, int $nest): Egg
7577
{
@@ -78,6 +80,11 @@ public function handle(UploadedFile $file, int $nest): Egg
7880
}
7981

8082
$parsed = json_decode($file->openFile()->fread($file->getSize()));
83+
if (json_last_error() !== 0) {
84+
throw new BadJsonFormatException(trans('exceptions.nest.importer.json_error', [
85+
'error' => json_last_error_msg(),
86+
]));
87+
}
8188

8289
if (object_get($parsed, 'meta.version') !== 'PTDL_v1') {
8390
throw new InvalidFileUploadException(trans('exceptions.nest.importer.invalid_json_provided'));
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
namespace Pterodactyl\Services\Eggs\Sharing;
4+
5+
use Illuminate\Http\UploadedFile;
6+
use Illuminate\Database\ConnectionInterface;
7+
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
8+
use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException;
9+
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
10+
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
11+
12+
class EggUpdateImporterService
13+
{
14+
/**
15+
* @var \Illuminate\Database\ConnectionInterface
16+
*/
17+
protected $connection;
18+
19+
/**
20+
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface
21+
*/
22+
protected $repository;
23+
24+
/**
25+
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
26+
*/
27+
protected $variableRepository;
28+
29+
/**
30+
* EggUpdateImporterService constructor.
31+
*
32+
* @param \Illuminate\Database\ConnectionInterface $connection
33+
* @param \Pterodactyl\Contracts\Repository\EggRepositoryInterface $repository
34+
* @param \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface $variableRepository
35+
*/
36+
public function __construct(
37+
ConnectionInterface $connection,
38+
EggRepositoryInterface $repository,
39+
EggVariableRepositoryInterface $variableRepository
40+
) {
41+
$this->connection = $connection;
42+
$this->repository = $repository;
43+
$this->variableRepository = $variableRepository;
44+
}
45+
46+
/**
47+
* Update an existing Egg using an uploaded JSON file.
48+
*
49+
* @param int $egg
50+
* @param \Illuminate\Http\UploadedFile $file
51+
*
52+
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
53+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
54+
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
55+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
56+
*/
57+
public function handle(int $egg, UploadedFile $file)
58+
{
59+
if (! $file->isValid() || ! $file->isFile()) {
60+
throw new InvalidFileUploadException(trans('exceptions.nest.importer.file_error'));
61+
}
62+
63+
$parsed = json_decode($file->openFile()->fread($file->getSize()));
64+
if (json_last_error() !== 0) {
65+
throw new BadJsonFormatException(trans('exceptions.nest.importer.json_error', [
66+
'error' => json_last_error_msg(),
67+
]));
68+
}
69+
70+
if (object_get($parsed, 'meta.version') !== 'PTDL_v1') {
71+
throw new InvalidFileUploadException(trans('exceptions.nest.importer.invalid_json_provided'));
72+
}
73+
74+
$this->connection->beginTransaction();
75+
$this->repository->update($egg, [
76+
'author' => object_get($parsed, 'author'),
77+
'name' => object_get($parsed, 'name'),
78+
'description' => object_get($parsed, 'description'),
79+
'docker_image' => object_get($parsed, 'image'),
80+
'config_files' => object_get($parsed, 'config.files'),
81+
'config_startup' => object_get($parsed, 'config.startup'),
82+
'config_logs' => object_get($parsed, 'config.logs'),
83+
'config_stop' => object_get($parsed, 'config.stop'),
84+
'startup' => object_get($parsed, 'startup'),
85+
'script_install' => object_get($parsed, 'scripts.installation.script'),
86+
'script_entry' => object_get($parsed, 'scripts.installation.entrypoint'),
87+
'script_container' => object_get($parsed, 'scripts.installation.container'),
88+
], true, true);
89+
90+
// Update Existing Variables
91+
collect($parsed->variables)->each(function ($variable) use ($egg) {
92+
$this->variableRepository->withoutFresh()->updateOrCreate([
93+
'egg_id' => $egg,
94+
'env_variable' => $variable->env_variable,
95+
], collect($variable)->except(['egg_id', 'env_variable'])->toArray());
96+
});
97+
98+
$imported = collect($parsed->variables)->pluck('env_variable')->toArray();
99+
$existing = $this->variableRepository->withColumns(['id', 'env_variable'])->findWhere([['egg_id', '=', $egg]]);
100+
101+
// Delete variables not present in the import.
102+
collect($existing)->each(function ($variable) use ($egg, $imported) {
103+
if (! in_array($variable->env_variable, $imported)) {
104+
$this->variableRepository->deleteWhere([
105+
['egg_id', '=', $egg],
106+
['env_variable', '=', $variable->env_variable],
107+
]);
108+
}
109+
});
110+
111+
$this->connection->commit();
112+
}
113+
}

app/Services/Packs/PackCreationService.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
use Illuminate\Http\UploadedFile;
1414
use Illuminate\Database\ConnectionInterface;
1515
use Pterodactyl\Contracts\Repository\PackRepositoryInterface;
16+
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
1617
use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory;
17-
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
1818
use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException;
1919

2020
class PackCreationService
@@ -65,7 +65,7 @@ public function __construct(
6565
*
6666
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
6767
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
68-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
68+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
6969
*/
7070
public function handle(array $data, UploadedFile $file = null)
7171
{

app/Services/Packs/TemplateUploadService.php

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

1212
use ZipArchive;
1313
use Illuminate\Http\UploadedFile;
14+
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
1415
use Pterodactyl\Exceptions\Service\Pack\ZipExtractionException;
15-
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
1616
use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException;
1717
use Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException;
1818
use Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException;
@@ -58,7 +58,7 @@ public function __construct(
5858
*
5959
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
6060
* @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException
61-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
61+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
6262
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
6363
* @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException
6464
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException
@@ -94,7 +94,7 @@ public function handle($egg, UploadedFile $file)
9494
*
9595
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
9696
* @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException
97-
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
97+
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
9898
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
9999
* @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException
100100
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException

resources/lang/en/admin/nests.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
'eggs' => [
1717
'notices' => [
1818
'imported' => 'Successfully imported this Egg and its associated variables.',
19+
'updated_via_import' => 'This Egg has been updated using the file provided.',
1920
'deleted' => 'Successfully deleted the requested egg from the Panel.',
2021
'updated' => 'Egg configuration has been updated successfully.',
2122
'script_updated' => 'Egg install script has been updated and will run whenever servers are installed.',

0 commit comments

Comments
 (0)