Add mounts page to server admin view

This commit is contained in:
Matthew Penner 2020-05-21 13:19:59 -06:00
parent 34f718a8b1
commit fa902cc074
9 changed files with 151 additions and 17 deletions

View file

@ -8,9 +8,9 @@ use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Mounts\MountUpdateService; use Pterodactyl\Services\Mounts\MountUpdateService;
use Pterodactyl\Http\Requests\Admin\MountFormRequest;
use Pterodactyl\Services\Mounts\MountCreationService; use Pterodactyl\Services\Mounts\MountCreationService;
use Pterodactyl\Services\Mounts\MountDeletionService; use Pterodactyl\Services\Mounts\MountDeletionService;
use Pterodactyl\Http\Requests\Admin\MountFormRequest;
use Pterodactyl\Repositories\Eloquent\MountRepository; use Pterodactyl\Repositories\Eloquent\MountRepository;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
@ -22,6 +22,11 @@ class MountController extends Controller
*/ */
protected $alert; protected $alert;
/**
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
*/
protected $mountRepository;
/** /**
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface * @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
*/ */

View file

@ -9,6 +9,7 @@ use Pterodactyl\Models\Server;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\Eloquent\MountRepository;
use Pterodactyl\Repositories\Eloquent\NestRepository; use Pterodactyl\Repositories\Eloquent\NestRepository;
use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Eloquent\NodeRepository;
use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Repositories\Eloquent\ServerRepository;
@ -35,6 +36,11 @@ class ServerViewController extends Controller
*/ */
private $repository; private $repository;
/**
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
*/
protected $mountRepository;
/** /**
* @var \Pterodactyl\Repositories\Eloquent\NestRepository * @var \Pterodactyl\Repositories\Eloquent\NestRepository
*/ */
@ -53,27 +59,30 @@ class ServerViewController extends Controller
/** /**
* ServerViewController constructor. * ServerViewController constructor.
* *
* @param \Illuminate\Contracts\View\Factory $view
* @param \Pterodactyl\Repositories\Eloquent\DatabaseHostRepository $databaseHostRepository * @param \Pterodactyl\Repositories\Eloquent\DatabaseHostRepository $databaseHostRepository
* @param \Pterodactyl\Repositories\Eloquent\NestRepository $nestRepository
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository * @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
* @param \Pterodactyl\Repositories\Eloquent\MountRepository $mountRepository
* @param \Pterodactyl\Repositories\Eloquent\NestRepository $nestRepository
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository * @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository * @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
* @param \Illuminate\Contracts\View\Factory $view
*/ */
public function __construct( public function __construct(
Factory $view,
DatabaseHostRepository $databaseHostRepository, DatabaseHostRepository $databaseHostRepository,
NestRepository $nestRepository,
LocationRepository $locationRepository, LocationRepository $locationRepository,
MountRepository $mountRepository,
NestRepository $nestRepository,
NodeRepository $nodeRepository, NodeRepository $nodeRepository,
ServerRepository $repository, ServerRepository $repository
Factory $view
) { ) {
$this->view = $view; $this->view = $view;
$this->databaseHostRepository = $databaseHostRepository; $this->databaseHostRepository = $databaseHostRepository;
$this->repository = $repository; $this->locationRepository = $locationRepository;
$this->mountRepository = $mountRepository;
$this->nestRepository = $nestRepository; $this->nestRepository = $nestRepository;
$this->nodeRepository = $nodeRepository; $this->nodeRepository = $nodeRepository;
$this->locationRepository = $locationRepository; $this->repository = $repository;
} }
/** /**
@ -160,6 +169,21 @@ class ServerViewController extends Controller
]); ]);
} }
/**
* Returns all of the mounts that exist for the server.
*
* @param \Illuminate\Http\Request $request
* @param \Pterodactyl\Models\Server $server
* @return \Illuminate\Contracts\View\View
*/
public function mounts(Request $request, Server $server)
{
return $this->view->make('admin.servers.view.mounts', [
'mounts' => $this->mountRepository->getMountListForServer($server),
'server' => $server,
]);
}
/** /**
* Returns the base server management page, or an exception if the server * Returns the base server management page, or an exception if the server
* is in a state that cannot be recovered from. * is in a state that cannot be recovered from.
@ -169,7 +193,6 @@ class ServerViewController extends Controller
* @return \Illuminate\Contracts\View\View * @return \Illuminate\Contracts\View\View
* *
* @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function manage(Request $request, Server $server) public function manage(Request $request, Server $server)
{ {

View file

@ -16,6 +16,7 @@ use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Servers\SuspensionService; use Pterodactyl\Services\Servers\SuspensionService;
use Pterodactyl\Repositories\Eloquent\MountRepository;
use Pterodactyl\Services\Servers\ServerDeletionService; use Pterodactyl\Services\Servers\ServerDeletionService;
use Pterodactyl\Services\Servers\ReinstallServerService; use Pterodactyl\Services\Servers\ReinstallServerService;
use Pterodactyl\Services\Servers\BuildModificationService; use Pterodactyl\Services\Servers\BuildModificationService;
@ -83,6 +84,11 @@ class ServersController extends Controller
*/ */
protected $detailsModificationService; protected $detailsModificationService;
/**
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
*/
protected $mountRepository;
/** /**
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface * @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
*/ */
@ -123,6 +129,7 @@ class ServersController extends Controller
* @param \Pterodactyl\Services\Servers\DetailsModificationService $detailsModificationService * @param \Pterodactyl\Services\Servers\DetailsModificationService $detailsModificationService
* @param \Pterodactyl\Services\Servers\ReinstallServerService $reinstallService * @param \Pterodactyl\Services\Servers\ReinstallServerService $reinstallService
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository * @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
* @param \Pterodactyl\Repositories\Eloquent\MountRepository $mountRepository
* @param \Pterodactyl\Contracts\Repository\NestRepositoryInterface $nestRepository * @param \Pterodactyl\Contracts\Repository\NestRepositoryInterface $nestRepository
* @param \Pterodactyl\Services\Servers\StartupModificationService $startupModificationService * @param \Pterodactyl\Services\Servers\StartupModificationService $startupModificationService
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService * @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
@ -140,6 +147,7 @@ class ServersController extends Controller
DetailsModificationService $detailsModificationService, DetailsModificationService $detailsModificationService,
ReinstallServerService $reinstallService, ReinstallServerService $reinstallService,
ServerRepositoryInterface $repository, ServerRepositoryInterface $repository,
MountRepository $mountRepository,
NestRepositoryInterface $nestRepository, NestRepositoryInterface $nestRepository,
StartupModificationService $startupModificationService, StartupModificationService $startupModificationService,
SuspensionService $suspensionService SuspensionService $suspensionService
@ -157,6 +165,7 @@ class ServersController extends Controller
$this->nestRepository = $nestRepository; $this->nestRepository = $nestRepository;
$this->reinstallService = $reinstallService; $this->reinstallService = $reinstallService;
$this->repository = $repository; $this->repository = $repository;
$this->mountRepository = $mountRepository;
$this->startupModificationService = $startupModificationService; $this->startupModificationService = $startupModificationService;
$this->suspensionService = $suspensionService; $this->suspensionService = $suspensionService;
} }
@ -168,7 +177,6 @@ class ServersController extends Controller
* @param \Pterodactyl\Models\Server $server * @param \Pterodactyl\Models\Server $server
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
* *
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */

View file

@ -4,6 +4,7 @@ namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Mount; use Pterodactyl\Models\Mount;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Pterodactyl\Models\Server;
use Pterodactyl\Repositories\Concerns\Searchable; use Pterodactyl\Repositories\Concerns\Searchable;
use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\ModelNotFoundException;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException; use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
@ -48,4 +49,22 @@ class MountRepository extends EloquentRepository
throw new RecordNotFoundException; throw new RecordNotFoundException;
} }
} }
/**
* Return mounts available to a server. (ignoring if they are or are not mounted)
*
* @param Server $server
* @return \Illuminate\Support\Collection
*/
public function getMountListForServer(Server $server): Collection
{
return $this->getBuilder()
->whereHas('eggs', function ($q) use ($server) {
$q->where('id', '=', $server->egg_id);
})
->whereHas('nodes', function ($q) use ($server) {
$q->where('id', '=', $server->node_id);
})
->get($this->getColumns());
}
} }

View file

@ -29,6 +29,11 @@
<form action="{{ route('admin.mounts.view', $mount->id) }}" method="POST"> <form action="{{ route('admin.mounts.view', $mount->id) }}" method="POST">
<div class="box-body"> <div class="box-body">
<div class="form-group">
<label for="PUniqueID" class="form-label">Unique ID</label>
<input type="text" id="PUniqueID" class="form-control" value="{{ $mount->uuid }}" disabled />
</div>
<div class="form-group"> <div class="form-group">
<label for="pName" class="form-label">Name</label> <label for="pName" class="form-label">Name</label>
<input type="text" id="pName" name="name" class="form-control" value="{{ $mount->name }}" /> <input type="text" id="pName" name="name" class="form-control" value="{{ $mount->name }}" />
@ -117,8 +122,8 @@
@foreach ($mount->eggs as $egg) @foreach ($mount->eggs as $egg)
<tr> <tr>
<td><code>{{ $egg->id }}</code></td> <td class="col-sm-2 middle"><code>{{ $egg->id }}</code></td>
<td><a href="{{ route('admin.nests.egg.view', $egg->id) }}">{{ $egg->name }}</a></td> <td class="middle"><a href="{{ route('admin.nests.egg.view', $egg->id) }}">{{ $egg->name }}</a></td>
<td class="col-sm-1 middle"> <td class="col-sm-1 middle">
<button data-action="detach-egg" data-id="{{ $egg->id }}" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i></button> <button data-action="detach-egg" data-id="{{ $egg->id }}" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i></button>
</td> </td>
@ -148,9 +153,9 @@
@foreach ($mount->nodes as $node) @foreach ($mount->nodes as $node)
<tr> <tr>
<td><code>{{ $node->id }}</code></td> <td class="col-sm-2 middle"><code>{{ $node->id }}</code></td>
<td><a href="{{ route('admin.nodes.view', $node->id) }}">{{ $node->name }}</a></td> <td class="middle"><a href="{{ route('admin.nodes.view', $node->id) }}">{{ $node->name }}</a></td>
<td><code>{{ $node->fqdn }}</code></td> <td class="middle"><code>{{ $node->fqdn }}</code></td>
<td class="col-sm-1 middle"> <td class="col-sm-1 middle">
<button data-action="detach-node" data-id="{{ $node->id }}" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i></button> <button data-action="detach-node" data-id="{{ $node->id }}" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i></button>
</td> </td>
@ -254,7 +259,7 @@
@section('footer-scripts') @section('footer-scripts')
@parent @parent
<script type="application/javascript"> <script>
$(document).ready(function() { $(document).ready(function() {
$('#pEggs').select2({ $('#pEggs').select2({
placeholder: 'Select eggs..', placeholder: 'Select eggs..',

View file

@ -21,6 +21,9 @@
<li class="{{ $router->currentRouteNamed('admin.servers.view.database') ? 'active' : '' }}"> <li class="{{ $router->currentRouteNamed('admin.servers.view.database') ? 'active' : '' }}">
<a href="{{ route('admin.servers.view.database', $server->id) }}">Database</a> <a href="{{ route('admin.servers.view.database', $server->id) }}">Database</a>
</li> </li>
<li class="{{ $router->currentRouteNamed('admin.servers.view.mounts') ? 'active' : '' }}">
<a href="{{ route('admin.servers.view.mounts', $server->id) }}">Mounts</a>
</li>
@endif @endif
<li class="{{ $router->currentRouteNamed('admin.servers.view.manage') ? 'active' : '' }}"> <li class="{{ $router->currentRouteNamed('admin.servers.view.manage') ? 'active' : '' }}">
<a href="{{ route('admin.servers.view.manage', $server->id) }}">Manage</a> <a href="{{ route('admin.servers.view.manage', $server->id) }}">Manage</a>

View file

@ -37,7 +37,7 @@
<th>Username</th> <th>Username</th>
<th>Connections From</th> <th>Connections From</th>
<th>Host</th> <th>Host</th>
<th>Max Conenctions</th> <th>Max Connections</th>
<th></th> <th></th>
</tr> </tr>
@foreach($server->databases as $database) @foreach($server->databases as $database)

View file

@ -0,0 +1,70 @@
@extends('layouts.admin')
@section('title')
Server {{ $server->name }}: Mounts
@endsection
@section('content-header')
<h1>{{ $server->name }}<small>Manage server mounts.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.servers') }}">Servers</a></li>
<li><a href="{{ route('admin.servers.view', $server->id) }}">{{ $server->name }}</a></li>
<li class="active">Mounts</li>
</ol>
@endsection
@section('content')
@include('admin.servers.partials.navigation')
<div class="row">
<div class="col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Available Mounts</h3>
</div>
<div class="box-body table-responsible no-padding">
<table class="table table-hover">
<tr>
<th>ID</th>
<th>Name</th>
<th>Source</th>
<th>Target</th>
<th>Status</th>
<th></th>
</tr>
@foreach ($mounts as $mount)
<tr>
<td class="col-sm-1 middle"><code>{{ $mount->id }}</code></td>
<td class="middle"><a href="{{ route('admin.mounts.view', $mount->id) }}">{{ $mount->name }}</a></td>
<td class="middle"><code>{{ $mount->source }}</code></td>
<td class="col-sm-2 middle"><code>{{ $mount->target }}</code></td>
<td class="col-sm-2 middle">
@if ($mount->id == 2)
<span class="label label-primary">Unmounted</span>
@else
<span class="label label-success">Mounted</span>
@endif
</td>
<td class="col-sm-1 middle">
@if ($mount->id == 2)
<button data-action="mount" data-id="{{ $mount->id }}" class="btn btn-xs btn-success"><i class="fa fa-plus"></i></button>
@else
<button data-action="unmount" data-id="{{ $mount->id }}" class="btn btn-xs btn-danger"><i class="fa fa-times"></i></button>
@endif
</td>
</tr>
@endforeach
</table>
</div>
</div>
</div>
</div>
@endsection
@section('footer-scripts')
@parent
@endsection

View file

@ -113,6 +113,7 @@ Route::group(['prefix' => 'servers'], function () {
Route::get('/view/{server}/build', 'Servers\ServerViewController@build')->name('admin.servers.view.build'); Route::get('/view/{server}/build', 'Servers\ServerViewController@build')->name('admin.servers.view.build');
Route::get('/view/{server}/startup', 'Servers\ServerViewController@startup')->name('admin.servers.view.startup'); Route::get('/view/{server}/startup', 'Servers\ServerViewController@startup')->name('admin.servers.view.startup');
Route::get('/view/{server}/database', 'Servers\ServerViewController@database')->name('admin.servers.view.database'); Route::get('/view/{server}/database', 'Servers\ServerViewController@database')->name('admin.servers.view.database');
Route::get('/view/{server}/mounts', 'Servers\ServerViewController@mounts')->name('admin.servers.view.mounts');
}); });
Route::get('/view/{server}/manage', 'Servers\ServerViewController@manage')->name('admin.servers.view.manage'); Route::get('/view/{server}/manage', 'Servers\ServerViewController@manage')->name('admin.servers.view.manage');