From 2c054e7edc166d428d19cf0fa4830295e62fd633 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 2 Jan 2016 18:04:18 -0500 Subject: [PATCH] Add initial support for viewing basic server details Includes support for changing server name, owner, and daemon secret. --- .../Controllers/Admin/ServersController.php | 57 ++++++- app/Http/Routes/AdminRoutes.php | 2 + app/Repositories/ServerRepository.php | 104 ++++++++++- public/css/pterodactyl.css | 3 + resources/views/admin/servers/new.blade.php | 4 +- resources/views/admin/servers/view.blade.php | 161 ++++++++++++++++++ 6 files changed, 327 insertions(+), 4 deletions(-) create mode 100644 resources/views/admin/servers/view.blade.php diff --git a/app/Http/Controllers/Admin/ServersController.php b/app/Http/Controllers/Admin/ServersController.php index 57227b6d7..3831e9a0f 100644 --- a/app/Http/Controllers/Admin/ServersController.php +++ b/app/Http/Controllers/Admin/ServersController.php @@ -4,6 +4,7 @@ namespace Pterodactyl\Http\Controllers\Admin; use Alert; use Debugbar; +use Log; use Pterodactyl\Models; use Pterodactyl\Repositories\ServerRepository; @@ -49,7 +50,21 @@ class ServersController extends Controller public function getView(Request $request, $id) { - // + return view('admin.servers.view', [ + 'server' => Models\Server::select( + 'servers.*', + 'nodes.name as a_nodeName', + 'users.email as a_ownerEmail', + 'locations.long as a_locationName', + 'services.name as a_serviceName', + 'service_options.name as a_servceOptionName' + )->join('nodes', 'servers.node', '=', 'nodes.id') + ->join('users', 'servers.owner', '=', 'users.id') + ->join('locations', 'nodes.location', '=', 'locations.id') + ->join('services', 'servers.service', '=', 'services.id') + ->join('service_options', 'servers.option', '=', 'service_options.id') + ->first() + ]); } public function postNewServer(Request $request) @@ -170,4 +185,44 @@ class ServersController extends Controller } + public function postUpdateServerDetails(Request $request, $id) + { + + try { + + $server = new ServerRepository; + $server->updateDetails($id, [ + 'owner' => $request->input('owner'), + 'name' => $request->input('name'), + 'reset_token' => ($request->input('reset_token', false) === 'on') ? true : false + ]); + + Alert::success('Server details were successfully updated.')->flash(); + return redirect()->route('admin.servers.view', [ + 'id' => $id, + 'tab' => 'tab_details' + ]); + + } catch (\Exception $e) { + + if ($e instanceof \Pterodactyl\Exceptions\DisplayValidationException) { + return redirect()->route('admin.servers.view', [ + 'id' => $id, + 'tab' => 'tab_details' + ])->withErrors(json_decode($e->getMessage()))->withInput(); + } else if ($e instanceof \Pterodactyl\Exceptions\DisplayException) { + Alert::danger($e->getMessage())->flash(); + } else { + Log::error($e); + Alert::danger('An unhandled exception occured while attemping to add this server. Please try again.')->flash(); + } + + return redirect()->route('admin.servers.view', [ + 'id' => $id, + 'tab' => 'tab_details' + ])->withInput(); + + } + } + } diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php index 18ceff19f..709bf3993 100644 --- a/app/Http/Routes/AdminRoutes.php +++ b/app/Http/Routes/AdminRoutes.php @@ -30,6 +30,8 @@ class AdminRoutes { $router->get('/new', [ 'as' => 'admin.servers.new', 'uses' => 'Admin\ServersController@getNew' ]); $router->get('/view/{id}', [ 'as' => 'admin.servers.view', 'uses' => 'Admin\ServersController@getView' ]); + $router->post('/view/{id}/details', [ 'uses' => 'Admin\ServersController@postUpdateServerDetails' ]); + $router->post('/new', [ 'uses' => 'Admin\ServersController@postNewServer']); $router->post('/new/get-nodes', [ 'uses' => 'Admin\ServersController@postNewServerGetNodes' ]); $router->post('/new/get-ips', [ 'uses' => 'Admin\ServersController@postNewServerGetIps' ]); diff --git a/app/Repositories/ServerRepository.php b/app/Repositories/ServerRepository.php index d383917a9..170bc97c6 100644 --- a/app/Repositories/ServerRepository.php +++ b/app/Repositories/ServerRepository.php @@ -5,6 +5,7 @@ namespace Pterodactyl\Repositories; use DB; use Debugbar; use Validator; +use Log; use Pterodactyl\Models; use Pterodactyl\Services\UuidService; @@ -41,7 +42,8 @@ class ServerRepository /** * Adds a new server to the system. - * @param array $data An array of data descriptors for creating the server. These should align to the columns in the database. + * @param array $data An array of data descriptors for creating the server. These should align to the columns in the database. + * @return integer */ public function create(array $data) { @@ -209,4 +211,104 @@ class ServerRepository } + /** + * [updateDetails description] + * @param integer $id + * @param array $data + * @return boolean + */ + public function updateDetails($id, array $data) + { + + $uuid = new UuidService; + $resetDaemonKey = false; + + // Validate Fields + $validator = Validator::make($data, [ + 'owner' => 'email|exists:users,email', + 'name' => 'regex:([\w -]{4,35})' + ]); + + // Run validator, throw catchable and displayable exception if it fails. + // Exception includes a JSON result of failed validation rules. + if ($validator->fails()) { + throw new DisplayValidationException($validator->errors()); + } + + DB::beginTransaction(); + $server = Models\Server::findOrFail($id); + $owner = Models\User::findOrFail($server->owner); + + // Update daemon secret if it was passed. + if ((isset($data['reset_token']) && $data['reset_token'] === true) || (isset($data['owner']) && $data['owner'] !== $owner->email)) { + $oldDaemonKey = $server->daemonSecret; + $server->daemonSecret = $uuid->generate('servers', 'daemonSecret'); + $resetDaemonKey = true; + } + + // Update Server Owner if it was passed. + if (isset($data['owner']) && $data['owner'] !== $owner->email) { + $newOwner = Models\User::select('id')->where('email', $data['owner'])->first(); + $server->owner = $newOwner->id; + } + + // Update Server Name if it was passed. + if (isset($data['name'])) { + $server->name = $data['name']; + } + + // Save our changes + $server->save(); + + // Do we need to update? If not, return successful. + if (!$resetDaemonKey) { + DB::commit(); + return true; + } + + // If we need to update do it here. + try { + + $node = Models\Node::getByID($server->node); + $client = Models\Node::guzzleRequest($server->node); + + $res = $client->request('PATCH', '/server', [ + 'headers' => [ + 'X-Access-Server' => $server->uuid, + 'X-Access-Token' => $node->daemonSecret + ], + 'exceptions' => false, + 'json' => [ + 'keys' => [ + (string) $oldDaemonKey => [], + (string) $server->daemonSecret => [ + 's:get', + 's:power', + 's:console', + 's:command', + 's:files:get', + 's:files:read', + 's:files:post', + 's:files:delete', + 's:files:upload', + 's:set-password' + ] + ] + ] + ]); + + if ($res->getStatusCode() === 204) { + DB::commit(); + return true; + } else { + throw new DisplayException('Daemon returned a a non HTTP/204 error code. HTTP/' + $res->getStatusCode()); + } + } catch (\Exception $ex) { + DB::rollback(); + Log::error($ex); + throw new DisplayException('An error occured while attempting to update this server\'s information.'); + } + + } + } diff --git a/public/css/pterodactyl.css b/public/css/pterodactyl.css index b28497705..b5d42870d 100755 --- a/public/css/pterodactyl.css +++ b/public/css/pterodactyl.css @@ -74,3 +74,6 @@ pre{display:block;padding:12px 12px;margin:0;font-size:12px;color:#c7254e;backgr .close:hover {color:#000;opacity:0.5;} .filename {outline: none;width:450px;background: transparent;margin-left:-5px;padding:0;border: 0px;font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight: 250;line-height: 1.1;font-size: 19px;color: #aaa} form .text-muted {margin: 0 0 -5.5px} +.tab-pane.active .panel.panel-default {border-top:0 !important} +.tabs_with_panel > li.active > a {background-color: #f5f5f5 !important} +.tabs_with_panel > li > a {background: transparent;} diff --git a/resources/views/admin/servers/new.blade.php b/resources/views/admin/servers/new.blade.php index 0865f17ac..ae8a55156 100644 --- a/resources/views/admin/servers/new.blade.php +++ b/resources/views/admin/servers/new.blade.php @@ -1,7 +1,7 @@ @extends('layouts.admin') @section('title') - Server List + Create New Server @endsection @section('content') @@ -43,7 +43,7 @@
- +
diff --git a/resources/views/admin/servers/view.blade.php b/resources/views/admin/servers/view.blade.php new file mode 100644 index 000000000..982526d91 --- /dev/null +++ b/resources/views/admin/servers/view.blade.php @@ -0,0 +1,161 @@ +@extends('layouts.admin') + +@section('title') + Managing Server: {{ $server->name }} ({{ $server->uuidShort}}) +@endsection + +@section('content') +
+ + @if (count($errors) > 0) +
+ {{ trans('strings.whoops') }}! {{ trans('base.validation_error') }}

+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + @foreach (Alert::getMessages() as $type => $messages) + @foreach ($messages as $message) + + @endforeach + @endforeach + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UUID{{ $server->uuid }}
Owner{{ $server->a_ownerEmail }}
Location{{ $server->a_locationName }}
Node{{ $server->a_nodeName }}
Service{{ $server->a_serviceName }} :: {{ $server->a_servceOptionName }}
Name{{ $server->name }}
Memory{{ $server->memory }}MB (Swap: {{ $server->swap }}MB) (OOM Killer: {{ ($server->oom_disabled === 0) ? 'enabled' : 'disabled' }})
Disk Space{{ $server->disk }}MB (Enforced: no)
Block IO Weight{{ $server->io }}
CPU Limit{{ $server->cpu }}%
Default Connection{{ $server->ip }}:{{ $server->port }}
Installed{{ ($server->installed === 1) ? 'Yes' : 'No' }}
+
+
+
+
+
+
+
+
+
+ +
+ +

Character limits: a-zA-Z0-9_- and [Space] (max 35 characters).

+
+
+
+ +
+ +

You can change the owner of this server by changing this field to an email matching another use on this system. If you do this a new daemon security token will be generated automatically.

+
+
+
+ +
+ +

This token should not be shared with anyone as it has full control over this server.

+
+
+
+
+ Yes, Reset Daemon Token +

Resetting this token will cause any requests using the old token to fail.

+
+
+
+ {!! csrf_field() !!} + +
+
+
+
+
+
+
+
+
+ Build +
+
+
+
+
+
+
+ Manage +
+
+
+
+
+ +@endsection