Skip to content

Commit 1c47b2e

Browse files
committed
Finish pack management in Admin CP
1 parent 4730309 commit 1c47b2e

File tree

13 files changed

+359
-462
lines changed

13 files changed

+359
-462
lines changed

app/Http/Controllers/Admin/PackController.php

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ public function newTemplate(Request $request)
8080
]);
8181
}
8282

83+
/**
84+
* Handle create pack request and route user to location.
85+
*
86+
* @param Request $request
87+
* @return \Illuminate\View\View
88+
*/
8389
public function create(Request $request)
8490
{
8591
$repo = new PackRepository;
@@ -108,43 +114,102 @@ public function create(Request $request)
108114
return redirect()->route('admin.packs.new')->withInput();
109115
}
110116

117+
/**
118+
* Display pack view template to user.
119+
*
120+
* @param Request $request
121+
* @param int $id
122+
* @return \Illuminate\View\View
123+
*/
124+
public function view(Request $request, $id)
125+
{
126+
return view('admin.packs.view', [
127+
'pack' => Pack::with('servers.node', 'servers.user')->findOrFail($id),
128+
'services' => Service::with('options')->get(),
129+
]);
130+
}
131+
132+
/**
133+
* Handle updating or deleting pack information.
134+
*
135+
* @param Request $request
136+
* @param int $id
137+
* @return \Illuminate\Response\RedirectResponse
138+
*/
139+
public function update(Request $request, $id)
140+
{
141+
$repo = new PackRepository;
142+
143+
try {
144+
if ($request->input('action') !== 'delete') {
145+
$pack = $repo->update($id, $request->intersect([
146+
'name', 'description', 'version',
147+
'option_id', 'selectable', 'visible', 'locked'
148+
]));
149+
Alert::success('Pack successfully updated.')->flash();
150+
} else {
151+
$repo->delete($id);
152+
Alert::success('Pack was successfully deleted from the system.')->flash();
153+
154+
return redirect()->route('admin.packs');
155+
}
156+
} catch(DisplayValidationException $ex) {
157+
return redirect()->route('admin.packs.view', $id)->withErrors(json_decode($ex->getMessage()));
158+
} catch (DisplayException $ex) {
159+
Alert::danger($ex->getMessage())->flash();
160+
} catch (\Exception $ex) {
161+
Log::error($ex);
162+
Alert::danger('An error occured while attempting to edit this service pack. This error has been logged.')->flash();
163+
}
164+
165+
return redirect()->route('admin.packs.view', $id);
166+
}
167+
168+
/**
169+
* Creates an archive of the pack and downloads it to the browser.
170+
*
171+
* @param Request $request
172+
* @param int $id
173+
* @param bool $files
174+
* @return \Illuminate\Response\BinaryFileResponse
175+
*/
176+
public function export(Request $request, $id, $files = false)
177+
{
178+
$pack = Pack::findOrFail($id);
179+
$json = [
180+
'name' => $pack->name,
181+
'version' => $pack->version,
182+
'description' => $pack->description,
183+
'selectable' => $pack->selectable,
184+
'visible' => $pack->visible,
185+
'locked' => $pack->locked,
186+
];
187+
188+
$filename = tempnam(sys_get_temp_dir(), 'pterodactyl_');
189+
if ($files === 'with-files') {
190+
$zip = new \ZipArchive;
191+
if (! $zip->open($filename, \ZipArchive::CREATE)) {
192+
abort(503, 'Unable to open file for writing.');
193+
}
111194

112-
// public function export(Request $request, $id, $files = false)
113-
// {
114-
// $pack = Models\Pack::findOrFail($id);
115-
// $json = [
116-
// 'name' => $pack->name,
117-
// 'version' => $pack->version,
118-
// 'description' => $pack->dscription,
119-
// 'selectable' => (bool) $pack->selectable,
120-
// 'visible' => (bool) $pack->visible,
121-
// ];
122-
123-
// $filename = tempnam(sys_get_temp_dir(), 'pterodactyl_');
124-
// if ((bool) $files) {
125-
// $zip = new \ZipArchive;
126-
// if (! $zip->open($filename, \ZipArchive::CREATE)) {
127-
// abort(503, 'Unable to open file for writing.');
128-
// }
129-
130-
// $files = Storage::files('packs/' . $pack->uuid);
131-
// foreach ($files as $file) {
132-
// $zip->addFile(storage_path('app/' . $file), basename(storage_path('app/' . $file)));
133-
// }
134-
135-
// $zip->addFromString('import.json', json_encode($json, JSON_PRETTY_PRINT));
136-
// $zip->close();
137-
138-
// return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true);
139-
// } else {
140-
// $fp = fopen($filename, 'a+');
141-
// fwrite($fp, json_encode($json, JSON_PRETTY_PRINT));
142-
// fclose($fp);
143-
144-
// return response()->download($filename, 'pack-' . $pack->name . '.json', [
145-
// 'Content-Type' => 'application/json',
146-
// ])->deleteFileAfterSend(true);
147-
// }
148-
// }
195+
$files = Storage::files('packs/' . $pack->uuid);
196+
foreach ($files as $file) {
197+
$zip->addFile(storage_path('app/' . $file), basename(storage_path('app/' . $file)));
198+
}
199+
200+
$zip->addFromString('import.json', json_encode($json, JSON_PRETTY_PRINT));
201+
$zip->close();
202+
203+
return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true);
204+
} else {
205+
$fp = fopen($filename, 'a+');
206+
fwrite($fp, json_encode($json, JSON_PRETTY_PRINT));
207+
fclose($fp);
208+
209+
return response()->download($filename, 'pack-' . $pack->name . '.json', [
210+
'Content-Type' => 'application/json',
211+
])->deleteFileAfterSend(true);
212+
}
213+
}
149214

150215
}

app/Http/Controllers/Remote/RemoteController.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ public function event(Request $request)
9898
], 403);
9999
}
100100

101-
// Passes Validation, Setup Notifications
102-
$notify = new NotificationService($server);
103-
$notify->pass($request->input('notification'));
104-
105101
return response('', 201);
106102
}
107103

app/Http/Routes/AdminRoutes.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,13 @@ public function map(Router $router)
474474
'as' => 'admin.packs.view',
475475
'uses' => 'Admin\PackController@view',
476476
]);
477+
478+
$router->post('/view/{id}', 'Admin\PackController@update');
479+
480+
$router->post('/view/{id}/export/{files?}', [
481+
'as' => 'admin.packs.view.export',
482+
'uses' => 'Admin\PackController@export',
483+
]);
477484
});
478485
}
479486
}

app/Models/Pack.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
namespace Pterodactyl\Models;
2626

27+
use File;
28+
use Storage;
2729
use Illuminate\Database\Eloquent\Model;
2830
use Nicolaslopezj\Searchable\SearchableTrait;
2931

@@ -78,6 +80,29 @@ class Pack extends Model
7880
],
7981
];
8082

83+
/**
84+
* Returns all of the archived files for a given pack.
85+
*
86+
* @param bool $collection
87+
* @return \Illuminate\Support\Collection|object
88+
*/
89+
public function files($collection = false)
90+
{
91+
$files = collect(Storage::files('packs/' . $this->uuid));
92+
93+
$files = $files->map(function ($item) {
94+
$path = storage_path('app/' . $item);
95+
96+
return (object) [
97+
'name' => basename($item),
98+
'hash' => sha1_file($path),
99+
'size' => File::humanReadableSize($path),
100+
];
101+
});
102+
103+
return ($collection) ? $files : (object) $files->all();
104+
}
105+
81106
/**
82107
* Gets option associated with a service pack.
83108
*
Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,31 @@
2222
* SOFTWARE.
2323
*/
2424

25-
namespace Pterodactyl\Services;
25+
namespace Pterodactyl\Providers;
2626

27-
use Pterodactyl\Models\Server;
28-
use Pterodactyl\Notifications\Daemon;
27+
use File;
28+
use Illuminate\Support\ServiceProvider;
2929

30-
class NotificationService
30+
class MacroServiceProvider extends ServiceProvider
3131
{
32-
protected $server;
33-
34-
protected $user;
35-
3632
/**
37-
* Daemon will pass an event name, this matches that event name with the notification to send.
38-
* @var array
33+
* Bootstrap the application services.
34+
*
35+
* @return void
3936
*/
40-
protected $types = [
41-
// 'crashed' => 'CrashNotification',
42-
// 'started' => 'StartNotification',
43-
// 'stopped' => 'StopNotification',
44-
// 'rebuild' => 'RebuildNotification'
45-
];
46-
47-
public function __construct(Server $server)
37+
public function boot()
4838
{
49-
$this->server = $server;
50-
}
51-
52-
public function pass(array $notification)
53-
{
54-
if (! $notification->type) {
55-
return;
56-
}
57-
58-
if (class_exists($this->types[$notification->type]::class)) {
59-
$user->notify(new $this->types[$notification->type]($notification->payload));
60-
}
39+
File::macro('humanReadableSize', function ($path, $precision = 2) {
40+
$size = File::size($path);
41+
static $units = ['B', 'kB', 'MB', 'GB', 'TB'];
42+
43+
$i = 0;
44+
while (($size / 1024) > 0.9) {
45+
$size = $size / 1024;
46+
$i++;
47+
}
48+
49+
return round($size, ($i < 2) ? 0 : $precision) . ' ' . $units[$i];
50+
});
6151
}
6252
}

app/Repositories/PackRepository.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,14 @@ public function createWithTemplate(array $data)
177177
* @param array $data
178178
* @return \Pterodactyl\Models\Pack
179179
*
180+
* @throws \Pterodactyl\Exceptions\DisplayException
180181
* @throws \Pterodactyl\Exceptions\DisplayValidationException
181182
*/
182183
public function update($id, array $data)
183184
{
184185
$validator = Validator::make($data, [
185186
'name' => 'sometimes|required|string',
187+
'option_id' => 'sometimes|required|exists:service_options,id',
186188
'version' => 'sometimes|required|string',
187189
'description' => 'sometimes|string',
188190
'selectable' => 'sometimes|required|boolean',
@@ -194,14 +196,20 @@ public function update($id, array $data)
194196
throw new DisplayValidationException(json_encode($validator->errors()));
195197
}
196198

197-
$pack = Pack::findOrFail($id);
199+
$pack = Pack::withCount('servers')->findOrFail($id);
200+
201+
if ($pack->servers_count > 0 && (isset($data['option_id']) && (int) $data['option_id'] !== $pack->option_id)) {
202+
throw new DisplayException('You cannot modify the associated option if servers are attached to a pack.');
203+
}
204+
198205
$pack->fill([
199206
'name' => isset($data['name']) ? $data['name'] : $pack->name,
207+
'option_id' => isset($data['option_id']) ? $data['option_id'] : $pack->option_id,
200208
'version' => isset($data['version']) ? $data['version'] : $pack->version,
201209
'description' => (empty($data['description'])) ? null : $data['description'],
202-
'selectable' => isset($data['selectable']) ? $data['selectable'] : $data->selectable,
203-
'visible' => isset($data['visible']) ? $data['visible'] : $data->visible,
204-
'locked' => isset($data['locked']) ? $data['locked'] : $data->locked,
210+
'selectable' => isset($data['selectable']),
211+
'visible' => isset($data['visible']),
212+
'locked' => isset($data['locked']),
205213
])->save();
206214

207215
return $pack;

app/Services/FileService.php

Whitespace-only changes.

config/app.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
Pterodactyl\Providers\AuthServiceProvider::class,
151151
Pterodactyl\Providers\EventServiceProvider::class,
152152
Pterodactyl\Providers\RouteServiceProvider::class,
153+
Pterodactyl\Providers\MacroServiceProvider::class,
153154
Pterodactyl\Providers\PhraseAppTranslationProvider::class,
154155

155156
/*

0 commit comments

Comments
 (0)