Skip to content

Commit 2c054e7

Browse files
committed
Add initial support for viewing basic server details
Includes support for changing server name, owner, and daemon secret.
1 parent 41652d7 commit 2c054e7

File tree

6 files changed

+327
-4
lines changed

6 files changed

+327
-4
lines changed

app/Http/Controllers/Admin/ServersController.php

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Alert;
66
use Debugbar;
7+
use Log;
78

89
use Pterodactyl\Models;
910
use Pterodactyl\Repositories\ServerRepository;
@@ -49,7 +50,21 @@ public function getNew(Request $request)
4950

5051
public function getView(Request $request, $id)
5152
{
52-
//
53+
return view('admin.servers.view', [
54+
'server' => Models\Server::select(
55+
'servers.*',
56+
'nodes.name as a_nodeName',
57+
'users.email as a_ownerEmail',
58+
'locations.long as a_locationName',
59+
'services.name as a_serviceName',
60+
'service_options.name as a_servceOptionName'
61+
)->join('nodes', 'servers.node', '=', 'nodes.id')
62+
->join('users', 'servers.owner', '=', 'users.id')
63+
->join('locations', 'nodes.location', '=', 'locations.id')
64+
->join('services', 'servers.service', '=', 'services.id')
65+
->join('service_options', 'servers.option', '=', 'service_options.id')
66+
->first()
67+
]);
5368
}
5469

5570
public function postNewServer(Request $request)
@@ -170,4 +185,44 @@ public function postNewServerServiceVariables(Request $request)
170185

171186
}
172187

188+
public function postUpdateServerDetails(Request $request, $id)
189+
{
190+
191+
try {
192+
193+
$server = new ServerRepository;
194+
$server->updateDetails($id, [
195+
'owner' => $request->input('owner'),
196+
'name' => $request->input('name'),
197+
'reset_token' => ($request->input('reset_token', false) === 'on') ? true : false
198+
]);
199+
200+
Alert::success('Server details were successfully updated.')->flash();
201+
return redirect()->route('admin.servers.view', [
202+
'id' => $id,
203+
'tab' => 'tab_details'
204+
]);
205+
206+
} catch (\Exception $e) {
207+
208+
if ($e instanceof \Pterodactyl\Exceptions\DisplayValidationException) {
209+
return redirect()->route('admin.servers.view', [
210+
'id' => $id,
211+
'tab' => 'tab_details'
212+
])->withErrors(json_decode($e->getMessage()))->withInput();
213+
} else if ($e instanceof \Pterodactyl\Exceptions\DisplayException) {
214+
Alert::danger($e->getMessage())->flash();
215+
} else {
216+
Log::error($e);
217+
Alert::danger('An unhandled exception occured while attemping to add this server. Please try again.')->flash();
218+
}
219+
220+
return redirect()->route('admin.servers.view', [
221+
'id' => $id,
222+
'tab' => 'tab_details'
223+
])->withInput();
224+
225+
}
226+
}
227+
173228
}

app/Http/Routes/AdminRoutes.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function map(Router $router) {
3030
$router->get('/new', [ 'as' => 'admin.servers.new', 'uses' => 'Admin\ServersController@getNew' ]);
3131
$router->get('/view/{id}', [ 'as' => 'admin.servers.view', 'uses' => 'Admin\ServersController@getView' ]);
3232

33+
$router->post('/view/{id}/details', [ 'uses' => 'Admin\ServersController@postUpdateServerDetails' ]);
34+
3335
$router->post('/new', [ 'uses' => 'Admin\ServersController@postNewServer']);
3436
$router->post('/new/get-nodes', [ 'uses' => 'Admin\ServersController@postNewServerGetNodes' ]);
3537
$router->post('/new/get-ips', [ 'uses' => 'Admin\ServersController@postNewServerGetIps' ]);

app/Repositories/ServerRepository.php

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use DB;
66
use Debugbar;
77
use Validator;
8+
use Log;
89

910
use Pterodactyl\Models;
1011
use Pterodactyl\Services\UuidService;
@@ -41,7 +42,8 @@ protected function generateSFTPUsername($name)
4142

4243
/**
4344
* Adds a new server to the system.
44-
* @param array $data An array of data descriptors for creating the server. These should align to the columns in the database.
45+
* @param array $data An array of data descriptors for creating the server. These should align to the columns in the database.
46+
* @return integer
4547
*/
4648
public function create(array $data)
4749
{
@@ -209,4 +211,104 @@ public function create(array $data)
209211

210212
}
211213

214+
/**
215+
* [updateDetails description]
216+
* @param integer $id
217+
* @param array $data
218+
* @return boolean
219+
*/
220+
public function updateDetails($id, array $data)
221+
{
222+
223+
$uuid = new UuidService;
224+
$resetDaemonKey = false;
225+
226+
// Validate Fields
227+
$validator = Validator::make($data, [
228+
'owner' => 'email|exists:users,email',
229+
'name' => 'regex:([\w -]{4,35})'
230+
]);
231+
232+
// Run validator, throw catchable and displayable exception if it fails.
233+
// Exception includes a JSON result of failed validation rules.
234+
if ($validator->fails()) {
235+
throw new DisplayValidationException($validator->errors());
236+
}
237+
238+
DB::beginTransaction();
239+
$server = Models\Server::findOrFail($id);
240+
$owner = Models\User::findOrFail($server->owner);
241+
242+
// Update daemon secret if it was passed.
243+
if ((isset($data['reset_token']) && $data['reset_token'] === true) || (isset($data['owner']) && $data['owner'] !== $owner->email)) {
244+
$oldDaemonKey = $server->daemonSecret;
245+
$server->daemonSecret = $uuid->generate('servers', 'daemonSecret');
246+
$resetDaemonKey = true;
247+
}
248+
249+
// Update Server Owner if it was passed.
250+
if (isset($data['owner']) && $data['owner'] !== $owner->email) {
251+
$newOwner = Models\User::select('id')->where('email', $data['owner'])->first();
252+
$server->owner = $newOwner->id;
253+
}
254+
255+
// Update Server Name if it was passed.
256+
if (isset($data['name'])) {
257+
$server->name = $data['name'];
258+
}
259+
260+
// Save our changes
261+
$server->save();
262+
263+
// Do we need to update? If not, return successful.
264+
if (!$resetDaemonKey) {
265+
DB::commit();
266+
return true;
267+
}
268+
269+
// If we need to update do it here.
270+
try {
271+
272+
$node = Models\Node::getByID($server->node);
273+
$client = Models\Node::guzzleRequest($server->node);
274+
275+
$res = $client->request('PATCH', '/server', [
276+
'headers' => [
277+
'X-Access-Server' => $server->uuid,
278+
'X-Access-Token' => $node->daemonSecret
279+
],
280+
'exceptions' => false,
281+
'json' => [
282+
'keys' => [
283+
(string) $oldDaemonKey => [],
284+
(string) $server->daemonSecret => [
285+
's:get',
286+
's:power',
287+
's:console',
288+
's:command',
289+
's:files:get',
290+
's:files:read',
291+
's:files:post',
292+
's:files:delete',
293+
's:files:upload',
294+
's:set-password'
295+
]
296+
]
297+
]
298+
]);
299+
300+
if ($res->getStatusCode() === 204) {
301+
DB::commit();
302+
return true;
303+
} else {
304+
throw new DisplayException('Daemon returned a a non HTTP/204 error code. HTTP/' + $res->getStatusCode());
305+
}
306+
} catch (\Exception $ex) {
307+
DB::rollback();
308+
Log::error($ex);
309+
throw new DisplayException('An error occured while attempting to update this server\'s information.');
310+
}
311+
312+
}
313+
212314
}

public/css/pterodactyl.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,6 @@ pre{display:block;padding:12px 12px;margin:0;font-size:12px;color:#c7254e;backgr
7474
.close:hover {color:#000;opacity:0.5;}
7575
.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}
7676
form .text-muted {margin: 0 0 -5.5px}
77+
.tab-pane.active .panel.panel-default {border-top:0 !important}
78+
.tabs_with_panel > li.active > a {background-color: #f5f5f5 !important}
79+
.tabs_with_panel > li > a {background: transparent;}

resources/views/admin/servers/new.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts.admin')
22

33
@section('title')
4-
Server List
4+
Create New Server
55
@endsection
66

77
@section('content')
@@ -43,7 +43,7 @@
4343
<div class="form-group col-md-6">
4444
<label for="owner" class="control-label">Owner Email</label>
4545
<div>
46-
<input type="text" autocomplete="off" name="owner" class="form-control" value="{{ old('owner') }}" />
46+
<input type="text" autocomplete="off" name="owner" class="form-control" value="{{ old('owner', Input::get('email')) }}" />
4747
</div>
4848
</div>
4949
</div>
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
@extends('layouts.admin')
2+
3+
@section('title')
4+
Managing Server: {{ $server->name }} ({{ $server->uuidShort}})
5+
@endsection
6+
7+
@section('content')
8+
<div class="col-md-9">
9+
<ul class="breadcrumb">
10+
<li><a href="/admin">Admin Control</a></li>
11+
<li><a href="/admin/servers">Servers</a></li>
12+
<li class="active">{{ $server->name }} ({{ $server->uuidShort}})</li>
13+
</ul>
14+
@if (count($errors) > 0)
15+
<div class="alert alert-danger">
16+
<strong>{{ trans('strings.whoops') }}!</strong> {{ trans('base.validation_error') }}<br><br>
17+
<ul>
18+
@foreach ($errors->all() as $error)
19+
<li>{{ $error }}</li>
20+
@endforeach
21+
</ul>
22+
</div>
23+
@endif
24+
@foreach (Alert::getMessages() as $type => $messages)
25+
@foreach ($messages as $message)
26+
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
27+
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
28+
{!! $message !!}
29+
</div>
30+
@endforeach
31+
@endforeach
32+
<ul class="nav nav-tabs tabs_with_panel" id="config_tabs">
33+
<li class="active"><a href="#tab_about" data-toggle="tab">About</a></li>
34+
<li><a href="#tab_details" data-toggle="tab">Details</a></li>
35+
<li><a href="#tab_build" data-toggle="tab">Build Configuration</a></li>
36+
<li><a href="#tab_manage" data-toggle="tab">Manage</a></li>
37+
</ul>
38+
<div class="tab-content">
39+
<div class="tab-pane active" id="tab_about">
40+
<div class="panel panel-default">
41+
<div class="panel-heading"></div>
42+
<div class="panel-body">
43+
<table class="table table-striped" style="margin-bottom: 0;">
44+
<tbody>
45+
<tr>
46+
<td>UUID</td>
47+
<td>{{ $server->uuid }}</td>
48+
</tr>
49+
<tr>
50+
<td>Owner</td>
51+
<td>{{ $server->a_ownerEmail }}</td>
52+
</tr>
53+
<tr>
54+
<td>Location</td>
55+
<td>{{ $server->a_locationName }}</td>
56+
</tr>
57+
<tr>
58+
<td>Node</td>
59+
<td>{{ $server->a_nodeName }}</td>
60+
</tr>
61+
<tr>
62+
<td>Service</td>
63+
<td>{{ $server->a_serviceName }} :: {{ $server->a_servceOptionName }}</td>
64+
</tr>
65+
<tr>
66+
<td>Name</td>
67+
<td>{{ $server->name }}</td>
68+
</tr>
69+
<tr>
70+
<td>Memory</td>
71+
<td><code>{{ $server->memory }}MB</code> (Swap: {{ $server->swap }}MB) (OOM Killer: <strong>{{ ($server->oom_disabled === 0) ? 'enabled' : 'disabled' }}</strong>)</td>
72+
</tr>
73+
<tr>
74+
<td>Disk Space</td>
75+
<td><code>{{ $server->disk }}MB</code> (Enforced: <strong>no</strong>)</td>
76+
</tr>
77+
<tr>
78+
<td>Block IO Weight</td>
79+
<td><code>{{ $server->io }}</code></td>
80+
</tr>
81+
<tr>
82+
<td>CPU Limit</td>
83+
<td><code>{{ $server->cpu }}%</code></td>
84+
</tr>
85+
<tr>
86+
<td>Default Connection</td>
87+
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
88+
</tr>
89+
<tr>
90+
<td>Installed</td>
91+
<td>{{ ($server->installed === 1) ? 'Yes' : 'No' }}</td>
92+
</tr>
93+
</tbody>
94+
</table>
95+
</div>
96+
</div>
97+
</div>
98+
<div class="tab-pane" id="tab_details">
99+
<div class="panel panel-default">
100+
<div class="panel-heading"></div>
101+
<div class="panel-body">
102+
<form method="POST" action="/admin/servers/view/{{ $server->id }}/details">
103+
<div class="form-group {{ $errors->has('name') ? 'has-error' : '' }}">
104+
<label for="name" class="control-label">Server Name</label>
105+
<div>
106+
<input type="text" name="name" value="{{ old('name', $server->name) }}" class="form-control" />
107+
<p class="text-muted"><small>Character limits: <code>a-zA-Z0-9_-</code> and <code>[Space]</code> (max 35 characters).</small></p>
108+
</div>
109+
</div>
110+
<div class="form-group {{ $errors->has('owner') ? 'has-error' : '' }}">
111+
<label for="name" class="control-label">Server Owner</label>
112+
<div>
113+
<input type="text" name="owner" value="{{ old('owner', $server->a_ownerEmail) }}" class="form-control" />
114+
<p class="text-muted"><small>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.</small></p>
115+
</div>
116+
</div>
117+
<div class="form-group">
118+
<label for="name" class="control-label">Daemon Secret Token</label>
119+
<div>
120+
<input type="text" disabled value="{{ $server->daemonSecret }}" class="form-control" />
121+
<p class="text-muted"><small>This token should not be shared with anyone as it has full control over this server.</small></p>
122+
</div>
123+
</div>
124+
<div class="form-group">
125+
<div>
126+
<input type="checkbox" name="reset_token"/> Yes, Reset Daemon Token
127+
<p class="text-muted"><small>Resetting this token will cause any requests using the old token to fail.</small></p>
128+
</div>
129+
</div>
130+
<div class="form-group">
131+
{!! csrf_field() !!}
132+
<input type="submit" class="btn btn-sm btn-primary" value="Update Details" />
133+
</div>
134+
</form>
135+
</div>
136+
</div>
137+
</div>
138+
<div class="tab-pane" id="tab_build">
139+
<div class="panel panel-default">
140+
<div class="panel-heading"></div>
141+
<div class="panel-body">
142+
Build
143+
</div>
144+
</div>
145+
</div>
146+
<div class="tab-pane" id="tab_manage">
147+
<div class="panel panel-default">
148+
<div class="panel-heading"></div>
149+
<div class="panel-body">
150+
Manage
151+
</div>
152+
</div>
153+
</div>
154+
</div>
155+
</div>
156+
<script>
157+
$(document).ready(function () {
158+
$('#sidebar_links').find("a[href='/admin/servers']").addClass('active');
159+
});
160+
</script>
161+
@endsection

0 commit comments

Comments
 (0)