diff --git a/app/Http/Controllers/Admin/PackController.php b/app/Http/Controllers/Admin/PackController.php index 1ef60b8c8..675ccc738 100644 --- a/app/Http/Controllers/Admin/PackController.php +++ b/app/Http/Controllers/Admin/PackController.php @@ -80,6 +80,12 @@ class PackController extends Controller ]); } + /** + * Handle create pack request and route user to location. + * + * @param Request $request + * @return \Illuminate\View\View + */ public function create(Request $request) { $repo = new PackRepository; @@ -108,43 +114,102 @@ class PackController extends Controller return redirect()->route('admin.packs.new')->withInput(); } + /** + * Display pack view template to user. + * + * @param Request $request + * @param int $id + * @return \Illuminate\View\View + */ + public function view(Request $request, $id) + { + return view('admin.packs.view', [ + 'pack' => Pack::with('servers.node', 'servers.user')->findOrFail($id), + 'services' => Service::with('options')->get(), + ]); + } - // public function export(Request $request, $id, $files = false) - // { - // $pack = Models\Pack::findOrFail($id); - // $json = [ - // 'name' => $pack->name, - // 'version' => $pack->version, - // 'description' => $pack->dscription, - // 'selectable' => (bool) $pack->selectable, - // 'visible' => (bool) $pack->visible, - // ]; + /** + * Handle updating or deleting pack information. + * + * @param Request $request + * @param int $id + * @return \Illuminate\Response\RedirectResponse + */ + public function update(Request $request, $id) + { + $repo = new PackRepository; - // $filename = tempnam(sys_get_temp_dir(), 'pterodactyl_'); - // if ((bool) $files) { - // $zip = new \ZipArchive; - // if (! $zip->open($filename, \ZipArchive::CREATE)) { - // abort(503, 'Unable to open file for writing.'); - // } + try { + if ($request->input('action') !== 'delete') { + $pack = $repo->update($id, $request->intersect([ + 'name', 'description', 'version', + 'option_id', 'selectable', 'visible', 'locked' + ])); + Alert::success('Pack successfully updated.')->flash(); + } else { + $repo->delete($id); + Alert::success('Pack was successfully deleted from the system.')->flash(); - // $files = Storage::files('packs/' . $pack->uuid); - // foreach ($files as $file) { - // $zip->addFile(storage_path('app/' . $file), basename(storage_path('app/' . $file))); - // } + return redirect()->route('admin.packs'); + } + } catch(DisplayValidationException $ex) { + return redirect()->route('admin.packs.view', $id)->withErrors(json_decode($ex->getMessage())); + } catch (DisplayException $ex) { + Alert::danger($ex->getMessage())->flash(); + } catch (\Exception $ex) { + Log::error($ex); + Alert::danger('An error occured while attempting to edit this service pack. This error has been logged.')->flash(); + } - // $zip->addFromString('import.json', json_encode($json, JSON_PRETTY_PRINT)); - // $zip->close(); + return redirect()->route('admin.packs.view', $id); + } - // return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true); - // } else { - // $fp = fopen($filename, 'a+'); - // fwrite($fp, json_encode($json, JSON_PRETTY_PRINT)); - // fclose($fp); + /** + * Creates an archive of the pack and downloads it to the browser. + * + * @param Request $request + * @param int $id + * @param bool $files + * @return \Illuminate\Response\BinaryFileResponse + */ + public function export(Request $request, $id, $files = false) + { + $pack = Pack::findOrFail($id); + $json = [ + 'name' => $pack->name, + 'version' => $pack->version, + 'description' => $pack->description, + 'selectable' => $pack->selectable, + 'visible' => $pack->visible, + 'locked' => $pack->locked, + ]; - // return response()->download($filename, 'pack-' . $pack->name . '.json', [ - // 'Content-Type' => 'application/json', - // ])->deleteFileAfterSend(true); - // } - // } + $filename = tempnam(sys_get_temp_dir(), 'pterodactyl_'); + if ($files === 'with-files') { + $zip = new \ZipArchive; + if (! $zip->open($filename, \ZipArchive::CREATE)) { + abort(503, 'Unable to open file for writing.'); + } + + $files = Storage::files('packs/' . $pack->uuid); + foreach ($files as $file) { + $zip->addFile(storage_path('app/' . $file), basename(storage_path('app/' . $file))); + } + + $zip->addFromString('import.json', json_encode($json, JSON_PRETTY_PRINT)); + $zip->close(); + + return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true); + } else { + $fp = fopen($filename, 'a+'); + fwrite($fp, json_encode($json, JSON_PRETTY_PRINT)); + fclose($fp); + + return response()->download($filename, 'pack-' . $pack->name . '.json', [ + 'Content-Type' => 'application/json', + ])->deleteFileAfterSend(true); + } + } } diff --git a/app/Http/Controllers/Remote/RemoteController.php b/app/Http/Controllers/Remote/RemoteController.php index 2e8b782a1..93dd672e1 100644 --- a/app/Http/Controllers/Remote/RemoteController.php +++ b/app/Http/Controllers/Remote/RemoteController.php @@ -98,10 +98,6 @@ class RemoteController extends Controller ], 403); } - // Passes Validation, Setup Notifications - $notify = new NotificationService($server); - $notify->pass($request->input('notification')); - return response('', 201); } diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php index f714f632d..f8cbc17fa 100644 --- a/app/Http/Routes/AdminRoutes.php +++ b/app/Http/Routes/AdminRoutes.php @@ -474,6 +474,13 @@ class AdminRoutes 'as' => 'admin.packs.view', 'uses' => 'Admin\PackController@view', ]); + + $router->post('/view/{id}', 'Admin\PackController@update'); + + $router->post('/view/{id}/export/{files?}', [ + 'as' => 'admin.packs.view.export', + 'uses' => 'Admin\PackController@export', + ]); }); } } diff --git a/app/Models/Pack.php b/app/Models/Pack.php index 5675fb25a..0a6310660 100644 --- a/app/Models/Pack.php +++ b/app/Models/Pack.php @@ -24,6 +24,8 @@ namespace Pterodactyl\Models; +use File; +use Storage; use Illuminate\Database\Eloquent\Model; use Nicolaslopezj\Searchable\SearchableTrait; @@ -78,6 +80,29 @@ class Pack extends Model ], ]; + /** + * Returns all of the archived files for a given pack. + * + * @param bool $collection + * @return \Illuminate\Support\Collection|object + */ + public function files($collection = false) + { + $files = collect(Storage::files('packs/' . $this->uuid)); + + $files = $files->map(function ($item) { + $path = storage_path('app/' . $item); + + return (object) [ + 'name' => basename($item), + 'hash' => sha1_file($path), + 'size' => File::humanReadableSize($path), + ]; + }); + + return ($collection) ? $files : (object) $files->all(); + } + /** * Gets option associated with a service pack. * diff --git a/app/Services/NotificationService.php b/app/Providers/MacroServiceProvider.php similarity index 58% rename from app/Services/NotificationService.php rename to app/Providers/MacroServiceProvider.php index 7912cf65d..ad23aaf74 100644 --- a/app/Services/NotificationService.php +++ b/app/Providers/MacroServiceProvider.php @@ -22,41 +22,31 @@ * SOFTWARE. */ -namespace Pterodactyl\Services; +namespace Pterodactyl\Providers; -use Pterodactyl\Models\Server; -use Pterodactyl\Notifications\Daemon; +use File; +use Illuminate\Support\ServiceProvider; -class NotificationService +class MacroServiceProvider extends ServiceProvider { - protected $server; - - protected $user; - /** - * Daemon will pass an event name, this matches that event name with the notification to send. - * @var array + * Bootstrap the application services. + * + * @return void */ - protected $types = [ - // 'crashed' => 'CrashNotification', - // 'started' => 'StartNotification', - // 'stopped' => 'StopNotification', - // 'rebuild' => 'RebuildNotification' - ]; - - public function __construct(Server $server) + public function boot() { - $this->server = $server; - } + File::macro('humanReadableSize', function ($path, $precision = 2) { + $size = File::size($path); + static $units = ['B', 'kB', 'MB', 'GB', 'TB']; - public function pass(array $notification) - { - if (! $notification->type) { - return; - } + $i = 0; + while (($size / 1024) > 0.9) { + $size = $size / 1024; + $i++; + } - if (class_exists($this->types[$notification->type]::class)) { - $user->notify(new $this->types[$notification->type]($notification->payload)); - } + return round($size, ($i < 2) ? 0 : $precision) . ' ' . $units[$i]; + }); } } diff --git a/app/Repositories/PackRepository.php b/app/Repositories/PackRepository.php index 3fc6b2571..fdc5fbd5d 100644 --- a/app/Repositories/PackRepository.php +++ b/app/Repositories/PackRepository.php @@ -177,12 +177,14 @@ class PackRepository * @param array $data * @return \Pterodactyl\Models\Pack * + * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\DisplayValidationException */ public function update($id, array $data) { $validator = Validator::make($data, [ 'name' => 'sometimes|required|string', + 'option_id' => 'sometimes|required|exists:service_options,id', 'version' => 'sometimes|required|string', 'description' => 'sometimes|string', 'selectable' => 'sometimes|required|boolean', @@ -194,14 +196,20 @@ class PackRepository throw new DisplayValidationException(json_encode($validator->errors())); } - $pack = Pack::findOrFail($id); + $pack = Pack::withCount('servers')->findOrFail($id); + + if ($pack->servers_count > 0 && (isset($data['option_id']) && (int) $data['option_id'] !== $pack->option_id)) { + throw new DisplayException('You cannot modify the associated option if servers are attached to a pack.'); + } + $pack->fill([ 'name' => isset($data['name']) ? $data['name'] : $pack->name, + 'option_id' => isset($data['option_id']) ? $data['option_id'] : $pack->option_id, 'version' => isset($data['version']) ? $data['version'] : $pack->version, 'description' => (empty($data['description'])) ? null : $data['description'], - 'selectable' => isset($data['selectable']) ? $data['selectable'] : $data->selectable, - 'visible' => isset($data['visible']) ? $data['visible'] : $data->visible, - 'locked' => isset($data['locked']) ? $data['locked'] : $data->locked, + 'selectable' => isset($data['selectable']), + 'visible' => isset($data['visible']), + 'locked' => isset($data['locked']), ])->save(); return $pack; diff --git a/app/Services/FileService.php b/app/Services/FileService.php new file mode 100644 index 000000000..e69de29bb diff --git a/config/app.php b/config/app.php index 622098a9b..4721bb3d2 100644 --- a/config/app.php +++ b/config/app.php @@ -150,6 +150,7 @@ return [ Pterodactyl\Providers\AuthServiceProvider::class, Pterodactyl\Providers\EventServiceProvider::class, Pterodactyl\Providers\RouteServiceProvider::class, + Pterodactyl\Providers\MacroServiceProvider::class, Pterodactyl\Providers\PhraseAppTranslationProvider::class, /* diff --git a/resources/themes/pterodactyl/admin/packs/view.blade.php b/resources/themes/pterodactyl/admin/packs/view.blade.php new file mode 100644 index 000000000..03b331bee --- /dev/null +++ b/resources/themes/pterodactyl/admin/packs/view.blade.php @@ -0,0 +1,192 @@ +{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.admin') + +@section('title') + Packs → View → {{ $pack->name }} +@endsection + +@section('content-header') +

{{ $pack->name }}{{ str_limit($pack->description, 60) }}

+ +@endsection + +@section('content') +
+
+
+
+
+

Pack Details

+
+
+
+ + +

A short but descriptive name of what this pack is. For example, Counter Strike: Source if it is a Counter Strike package.

+
+
+ + +
+
+ + +

The version of this package, or the version of the files contained within the package.

+
+
+
+
+
+
+
+

Pack Configuration

+
+
+
+ + +

The option that this pack is assocaited with. Only servers that are assigned this option will be able to access this pack. This assigned option cannot be changed if servers are attached to this pack.

+
+
+
+ selectable ?: 'checked' }}/> + +
+

Check this box if user should be able to select this pack to install on their servers.

+
+
+
+ visible ?: 'checked' }}/> + +
+

Check this box if this pack is visible in the dropdown menu. If this pack is assigned to a server it will be visible regardless of this setting.

+
+
+
+ locked ?: 'checked' }}/> + +
+

Check this box if servers assigned this pack should not be able to switch to a different pack.

+
+
+ +
+
+
+
+
+
+
+
+

Stored Files

+
+
+ + + + + + + @foreach($pack->files() as $file) + + + + + + @endforeach +
NameSHA1 HashFile Size
{{ $file->name }}{{ $file->hash }}{{ $file->size }}
+
+ +
+
+
+
+
+
+
+

Servers Using This Pack

+
+
+ + + + + + + + @foreach($pack->servers as $server) + + + + + + + @endforeach +
IDServer NameNodeOwner
{{ $server->uuidShort }}{{ $server->name }}{{ $server->node->name }}{{ $server->user->email }}
+
+
+
+
+
+
+
+ {!! csrf_field() !!} + +
+
+ {!! csrf_field() !!} + +
+
+
+@endsection + +@section('footer-scripts') + @parent + +@endsection diff --git a/resources/views/admin/services/packs/edit.blade.php b/resources/views/admin/services/packs/edit.blade.php deleted file mode 100644 index cc6470b3b..000000000 --- a/resources/views/admin/services/packs/edit.blade.php +++ /dev/null @@ -1,160 +0,0 @@ -{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} - -{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} -{{-- of this software and associated documentation files (the "Software"), to deal --}} -{{-- in the Software without restriction, including without limitation the rights --}} -{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} -{{-- copies of the Software, and to permit persons to whom the Software is --}} -{{-- furnished to do so, subject to the following conditions: --}} - -{{-- The above copyright notice and this permission notice shall be included in all --}} -{{-- copies or substantial portions of the Software. --}} - -{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} -{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} -{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} -{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} -{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} -{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} -{{-- SOFTWARE. --}} -@extends('layouts.admin') - -@section('title') - Add New Service Pack -@endsection - -@section('content') -
- -

Manage Service Pack


-
-
-
- -
- -

The name of the pack which will be seen in dropdown menus and to users.

-
-
-
- -
- -

The version of the program included in this pack.

-
-
-
- -
- -

Provide a description of the pack which will be shown to users.

-
-
-
-
-
- - -
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
Package Archive
-
-
-
- @if(count($files) > 1) -
Warning! Service packs should only contain a single pack archive in .tar.gz format. We've detected more than one file for this pack.
- @endif - - - - - - - - - - - @foreach($files as &$file) - - - - - - - @endforeach - -
FilenameFile SizeSHA1 HashLast Modified
{{ basename($file) }}{{ Storage::size($file) }} Bytes{{ sha1_file(storage_path('app/' . $file)) }}{{ Carbon::createFromTimestamp(Storage::lastModified($file))->toDateTimeString() }}
-

If you wish to modify or upload a new file it should be uploaded to {{ storage_path('app/packs/' . $pack->uuid) }} as archive.tar.gz.

-
-
-
-
-
-
-
-
-
- {!! csrf_field() !!} - - - - -
-
- -
-{!! Theme::js('js/vendor/ace/ace.js') !!} -{!! Theme::js('js/vendor/ace/ext-modelist.js') !!} - -@endsection diff --git a/resources/views/admin/services/packs/index.blade.php b/resources/views/admin/services/packs/index.blade.php deleted file mode 100644 index 6456ca317..000000000 --- a/resources/views/admin/services/packs/index.blade.php +++ /dev/null @@ -1,47 +0,0 @@ -{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} - -{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} -{{-- of this software and associated documentation files (the "Software"), to deal --}} -{{-- in the Software without restriction, including without limitation the rights --}} -{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} -{{-- copies of the Software, and to permit persons to whom the Software is --}} -{{-- furnished to do so, subject to the following conditions: --}} - -{{-- The above copyright notice and this permission notice shall be included in all --}} -{{-- copies or substantial portions of the Software. --}} - -{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} -{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} -{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} -{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} -{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} -{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} -{{-- SOFTWARE. --}} -@extends('layouts.admin') - -@section('title') - Service Packs -@endsection - -@section('content') -
- -

Service Packs


-
- @foreach ($services as $service) - - @endforeach -
-
- -@endsection diff --git a/resources/views/admin/services/packs/new.blade.php b/resources/views/admin/services/packs/new.blade.php deleted file mode 100644 index d5b0440da..000000000 --- a/resources/views/admin/services/packs/new.blade.php +++ /dev/null @@ -1,135 +0,0 @@ -{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} - -{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} -{{-- of this software and associated documentation files (the "Software"), to deal --}} -{{-- in the Software without restriction, including without limitation the rights --}} -{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} -{{-- copies of the Software, and to permit persons to whom the Software is --}} -{{-- furnished to do so, subject to the following conditions: --}} - -{{-- The above copyright notice and this permission notice shall be included in all --}} -{{-- copies or substantial portions of the Software. --}} - -{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} -{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} -{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} -{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} -{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} -{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} -{{-- SOFTWARE. --}} -@extends('layouts.admin') - -@section('title') - Add New Service Pack -@endsection - -@section('content') -
- -

New Service Pack


-
-
-
- -
- -

The name of the pack which will be seen in dropdown menus and to users.

-
-
-
- -
- -

The version of the program included in this pack.

-
-
-
- -
- -

Provide a description of the pack which will be shown to users.

-
-
-
-
-
- - -
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
File Upload
-
-
-
- - -

This package file must be a .tar.gz archive of files to use for either building or running this pack.

If your file is larger than 20MB we recommend uploading it using SFTP. Once you have added this pack to the system, a path will be provided where you should upload the file. - This server is currently configured with the following limits: upload_max_filesize={{ ini_get('upload_max_filesize') }} and post_max_size={{ ini_get('post_max_size') }}. If your file is larger than either of those values this request will fail.

-
-
-
-
-
-
-
-
-
- {!! csrf_field() !!} - -
-
- -
-{!! Theme::js('js/vendor/ace/ace.js') !!} -{!! Theme::js('js/vendor/ace/ext-modelist.js') !!} - -@endsection diff --git a/resources/views/admin/services/packs/upload.blade.php b/resources/views/admin/services/packs/upload.blade.php deleted file mode 100644 index cb5e548d8..000000000 --- a/resources/views/admin/services/packs/upload.blade.php +++ /dev/null @@ -1,45 +0,0 @@ -