Skip to content

Commit fb21bf9

Browse files
committed
Begin implementation of server admin view
Currently completed tabs: About, Details, Build Configuration
1 parent bbf9fd1 commit fb21bf9

File tree

6 files changed

+464
-147
lines changed

6 files changed

+464
-147
lines changed

app/Http/Controllers/Admin/ServersController.php

Lines changed: 7 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -149,71 +149,13 @@ public function postNewServerGetNodes(Request $request)
149149
})->values();
150150
}
151151

152-
/**
153-
* Returns a JSON tree of all avaliable IPs and Ports on a given node.
154-
*
155-
* @param \Illuminate\Http\Request $request
156-
* @return \Illuminate\Contracts\View\View
157-
*/
158-
public function postNewServerGetIps(Request $request)
159-
{
160-
return Models\Allocation::select('id', 'ip')->where('node_id', $request->input('node'))->whereNull('server_id')->get()->unique('ip')->values()->all();
161-
}
162-
163-
/**
164-
* Returns a JSON tree of all avaliable options for a given service.
165-
*
166-
* @param \Illuminate\Http\Request $request
167-
* @return \Illuminate\Contracts\View\View
168-
*/
169-
public function postNewServerServiceOption(Request $request)
170-
{
171-
if (! $request->input('service')) {
172-
return response()->json([
173-
'error' => 'Missing service in request.',
174-
], 500);
175-
}
176-
177-
$service = Models\Service::select('executable', 'startup')->where('id', $request->input('service'))->first();
178-
179-
return response()->json(Models\ServiceOption::select('id', 'name', 'docker_image')->where('service_id', $request->input('service'))->orderBy('name', 'asc')->get());
180-
}
181-
182-
/**
183-
* Returns a JSON tree of all avaliable variables for a given service option.
184-
*
185-
* @param \Illuminate\Http\Request $request
186-
* @return \Illuminate\Contracts\View\View
187-
*/
188-
public function postNewServerOptionDetails(Request $request)
189-
{
190-
if (! $request->input('option')) {
191-
return response()->json([
192-
'error' => 'Missing option in request.',
193-
], 500);
194-
}
195-
196-
$option = Models\ServiceOption::with('variables')->with(['packs' => function ($query) {
197-
$query->where('selectable', true);
198-
}])->findOrFail($request->input('option'));
199-
200-
return response()->json([
201-
'packs' => $option->packs,
202-
'variables' => $option->variables,
203-
'exec' => $option->display_executable,
204-
'startup' => $option->display_startup,
205-
]);
206-
}
207-
208152
public function postUpdateServerDetails(Request $request, $id)
209153
{
210154
try {
211155
$server = new ServerRepository;
212-
$server->updateDetails($id, [
213-
'owner' => $request->input('owner'),
214-
'name' => $request->input('name'),
215-
'reset_token' => ($request->input('reset_token', false) === 'on') ? true : false,
216-
]);
156+
$server->updateDetails($id, $request->intersect([
157+
'owner_id', 'name', 'reset_token'
158+
]));
217159

218160
Alert::success('Server details were successfully updated.')->flash();
219161
} catch (DisplayValidationException $ex) {
@@ -238,7 +180,7 @@ public function postUpdateContainerDetails(Request $request, $id)
238180
{
239181
try {
240182
$server = new ServerRepository;
241-
$server->updateContainer($id, ['image' => $request->input('docker_image')]);
183+
$server->updateContainer($id, $request->intersect('docker_image'));
242184
Alert::success('Successfully updated this server\'s docker image.')->flash();
243185
} catch (DisplayValidationException $ex) {
244186
return redirect()->route('admin.servers.view', [
@@ -283,9 +225,9 @@ public function postUpdateServerUpdateBuild(Request $request, $id)
283225
{
284226
try {
285227
$server = new ServerRepository;
286-
$server->changeBuild($id, $request->only([
287-
'default', 'add_additional',
288-
'remove_additional', 'memory',
228+
$server->changeBuild($id, $request->intersect([
229+
'allocation_id', 'add_allocations',
230+
'remove_allocations', 'memory',
289231
'swap', 'io', 'cpu',
290232
]));
291233
Alert::success('Server details were successfully updated.')->flash();

app/Http/Routes/AdminRoutes.php

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,6 @@ public function map(Router $router)
140140
'uses' => 'Admin\ServersController@postNewServerGetNodes',
141141
]);
142142

143-
$router->post('/new/get-ips', [
144-
'as' => 'admin.servers.new.get-ips',
145-
'uses' => 'Admin\ServersController@postNewServerGetIps',
146-
]);
147-
148-
$router->post('/new/service-options', [
149-
'as' => 'admin.servers.new.service-options',
150-
'uses' => 'Admin\ServersController@postNewServerServiceOption',
151-
]);
152-
153-
$router->post('/new/option-details', [
154-
'as' => 'admin.servers.new.option-details',
155-
'uses' => 'Admin\ServersController@postNewServerOptionDetails',
156-
]);
157-
// End Assorted Page Helpers
158-
159143
// View Specific Server
160144
$router->get('/view/{id}', [
161145
'as' => 'admin.servers.view',
@@ -170,6 +154,7 @@ public function map(Router $router)
170154

171155
// Change Server Details
172156
$router->post('/view/{id}/details', [
157+
'as' => 'admin.servers.view.details',
173158
'uses' => 'Admin\ServersController@postUpdateServerDetails',
174159
]);
175160

app/Repositories/ServerRepository.php

Lines changed: 39 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,9 @@ public function updateDetails($id, array $data)
352352

353353
// Validate Fields
354354
$validator = Validator::make($data, [
355-
'owner' => 'email|exists:users,email',
356-
'name' => 'regex:([\w .-]{1,200})',
355+
'owner_id' => 'sometimes|required|numeric|exists:users,id',
356+
'name' => 'sometimes|required|regex:([\w .-]{1,200})',
357+
'reset_token' => 'sometimes|required|accepted'
357358
]);
358359

359360
// Run validator, throw catchable and displayable exception if it fails.
@@ -368,16 +369,15 @@ public function updateDetails($id, array $data)
368369
$server = Models\Server::with('user')->findOrFail($id);
369370

370371
// Update daemon secret if it was passed.
371-
if ((isset($data['reset_token']) && $data['reset_token'] === true) || (isset($data['owner']) && $data['owner'] !== $server->user->email)) {
372+
if (isset($data['reset_token']) || (isset($data['owner_id']) && $data['owner_id'] !== $server->user->id)) {
372373
$oldDaemonKey = $server->daemonSecret;
373374
$server->daemonSecret = $uuid->generate('servers', 'daemonSecret');
374375
$resetDaemonKey = true;
375376
}
376377

377378
// Update Server Owner if it was passed.
378-
if (isset($data['owner']) && $data['owner'] !== $server->user->email) {
379-
$newOwner = Models\User::select('id')->where('email', $data['owner'])->first();
380-
$server->owner_id = $newOwner->id;
379+
if (isset($data['owner_id']) && $data['owner_id'] !== $server->user->id) {
380+
$server->owner_id = $data['owner_id'];
381381
}
382382

383383
// Update Server Name if it was passed.
@@ -431,7 +431,7 @@ public function updateDetails($id, array $data)
431431
public function updateContainer($id, array $data)
432432
{
433433
$validator = Validator::make($data, [
434-
'image' => 'required|string',
434+
'docker_image' => 'required|string',
435435
]);
436436

437437
// Run validator, throw catchable and displayable exception if it fails.
@@ -444,7 +444,7 @@ public function updateContainer($id, array $data)
444444
try {
445445
$server = Models\Server::findOrFail($id);
446446

447-
$server->image = $data['image'];
447+
$server->image = $data['docker_image'];
448448
$server->save();
449449

450450
$server->node->guzzleClient([
@@ -479,17 +479,14 @@ public function updateContainer($id, array $data)
479479
public function changeBuild($id, array $data)
480480
{
481481
$validator = Validator::make($data, [
482-
'default' => [
483-
'string',
484-
'regex:/^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5])):(\d{1,5})$/',
485-
],
486-
'add_additional' => 'nullable|array',
487-
'remove_additional' => 'nullable|array',
488-
'memory' => 'integer|min:0',
489-
'swap' => 'integer|min:-1',
490-
'io' => 'integer|min:10|max:1000',
491-
'cpu' => 'integer|min:0',
492-
'disk' => 'integer|min:0',
482+
'allocation_id' => 'sometimes|required|exists:allocations,id',
483+
'add_allocations' => 'sometimes|required|array',
484+
'remove_allocations' => 'sometimes|required|array',
485+
'memory' => 'sometimes|required|integer|min:0',
486+
'swap' => 'sometimes|required|integer|min:-1',
487+
'io' => 'sometimes|required|integer|min:10|max:1000',
488+
'cpu' => 'sometimes|required|integer|min:0',
489+
'disk' => 'sometimes|required|integer|min:0',
493490
]);
494491

495492
// Run validator, throw catchable and displayable exception if it fails.
@@ -503,43 +500,33 @@ public function changeBuild($id, array $data)
503500
try {
504501
$server = Models\Server::with('allocation', 'allocations')->findOrFail($id);
505502
$newBuild = [];
503+
$newAllocations = [];
506504

507-
if (isset($data['default'])) {
508-
list($ip, $port) = explode(':', $data['default']);
509-
if ($ip !== $server->allocation->ip || (int) $port !== $server->allocation->port) {
510-
$selection = $server->allocations->where('ip', $ip)->where('port', $port)->first();
505+
if (isset($data['allocation_id'])) {
506+
if ((int) $data['allocation_id'] !== $server->allocation_id) {
507+
$selection = $server->allocations->where('id', $data['allocation_id'])->first();
511508
if (! $selection) {
512-
throw new DisplayException('The requested default connection (' . $ip . ':' . $port . ') is not allocated to this server.');
509+
throw new DisplayException('The requested default connection is not allocated to this server.');
513510
}
514511

515512
$server->allocation_id = $selection->id;
516-
$newBuild['default'] = [
517-
'ip' => $ip,
518-
'port' => (int) $port,
519-
];
513+
$newBuild['default'] = ['ip' => $selection->ip, 'port' => $selection->port];
520514

521-
// Re-Run to keep updated for rest of function
522515
$server->load('allocation');
523516
}
524517
}
525518

526519
$newPorts = false;
527520
// Remove Assignments
528-
if (isset($data['remove_additional'])) {
529-
foreach ($data['remove_additional'] as $id => $combo) {
530-
list($ip, $port) = explode(':', $combo);
531-
// Invalid, not worth killing the whole thing, we'll just skip over it.
532-
if (! filter_var($ip, FILTER_VALIDATE_IP) || ! preg_match('/^(\d{1,5})$/', $port)) {
533-
break;
534-
}
535-
521+
if (isset($data['remove_allocations'])) {
522+
foreach ($data['remove_allocations'] as $allocation) {
536523
// Can't remove the assigned IP/Port combo
537-
if ($ip === $server->allocation->ip && (int) $port === (int) $server->allocation->port) {
538-
break;
524+
if ((int) $allocation === $server->allocation_id) {
525+
continue;
539526
}
540527

541528
$newPorts = true;
542-
$server->allocations->where('ip', $ip)->where('port', $port)->update([
529+
Models\Allocation::where('id', $allocation)->where('server_id', $server->id)->update([
543530
'server_id' => null,
544531
]);
545532
}
@@ -548,40 +535,26 @@ public function changeBuild($id, array $data)
548535
}
549536

550537
// Add Assignments
551-
if (isset($data['add_additional'])) {
552-
foreach ($data['add_additional'] as $id => $combo) {
553-
list($ip, $port) = explode(':', $combo);
554-
// Invalid, not worth killing the whole thing, we'll just skip over it.
555-
if (! filter_var($ip, FILTER_VALIDATE_IP) || ! preg_match('/^(\d{1,5})$/', $port)) {
556-
break;
557-
}
558-
559-
// Don't allow double port assignments
560-
if ($server->allocations->where('port', $port)->count() !== 0) {
561-
break;
538+
if (isset($data['add_allocations'])) {
539+
foreach ($data['add_allocations'] as $allocation) {
540+
$model = Models\Allocation::where('id', $allocation)->whereNull('server_id')->first();
541+
if (! $model) {
542+
continue;
562543
}
563544

564545
$newPorts = true;
565-
Models\Allocation::where('ip', $ip)->where('port', $port)->whereNull('server_id')->update([
546+
$model->update([
566547
'server_id' => $server->id,
567548
]);
568549
}
569550

570551
$server->load('allocations');
571552
}
572553

573-
// Loop All Assignments
574-
$additionalAssignments = [];
575-
foreach ($server->allocations as &$assignment) {
576-
if (array_key_exists((string) $assignment->ip, $additionalAssignments)) {
577-
array_push($additionalAssignments[(string) $assignment->ip], (int) $assignment->port);
578-
} else {
579-
$additionalAssignments[(string) $assignment->ip] = [(int) $assignment->port];
580-
}
581-
}
582-
583-
if ($newPorts === true) {
584-
$newBuild['ports|overwrite'] = $additionalAssignments;
554+
if ($newPorts) {
555+
$newBuild['ports|overwrite'] = $server->allocations->groupBy('ip')->map(function ($item) {
556+
return $item->pluck('port');
557+
})->toArray();
585558
}
586559

587560
// @TODO: verify that server can be set to this much memory without
@@ -617,6 +590,7 @@ public function changeBuild($id, array $data)
617590
// This won't be committed unless the HTTP request succeedes anyways
618591
$server->save();
619592

593+
dd($newBuild);
620594
if (! empty($newBuild)) {
621595
$server->node->guzzleClient([
622596
'X-Access-Server' => $server->uuid,
@@ -630,7 +604,7 @@ public function changeBuild($id, array $data)
630604

631605
DB::commit();
632606

633-
return true;
607+
return $server;
634608
} catch (TransferException $ex) {
635609
DB::rollBack();
636610
throw new DisplayException('An error occured while attempting to update the configuration.', $ex);

public/themes/pterodactyl/css/pterodactyl.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,29 @@ span[aria-labelledby="select2-pUserId-container"] {
198198
color: #777 !important;
199199
background: transparent !important;
200200
}
201+
202+
.tab-pane .box-footer {
203+
margin: 0 -10px -10px;
204+
}
205+
206+
.select2-container{ width: 100% !important; }
207+
208+
.nav-tabs-custom > .nav-tabs > li:hover {
209+
border-top-color:#3c8dbc;
210+
}
211+
212+
.nav-tabs-custom > .nav-tabs > li.active.tab-danger, .nav-tabs-custom > .nav-tabs > li.tab-danger:hover {
213+
border-top-color: #c23321;
214+
}
215+
216+
.nav-tabs-custom > .nav-tabs > li.active.tab-success, .nav-tabs-custom > .nav-tabs > li.tab-success:hover {
217+
border-top-color: #00733e;
218+
}
219+
220+
.nav-tabs-custom > .nav-tabs > li.active.tab-info, .nav-tabs-custom > .nav-tabs > li.tab-info:hover {
221+
border-top-color: #0097bc;
222+
}
223+
224+
.nav-tabs-custom > .nav-tabs > li.active.tab-warning, .nav-tabs-custom > .nav-tabs > li.tab-warning:hover {
225+
border-top-color: #c87f0a;
226+
}

0 commit comments

Comments
 (0)