forked from Alex/Pterodactyl-Panel
New models for node and location admin pages.
This commit is contained in:
parent
96d3aa767f
commit
09d23deed6
@ -45,8 +45,8 @@ class LocationsController extends Controller
|
||||
return view('admin.locations.index', [
|
||||
'locations' => Models\Location::select(
|
||||
'locations.*',
|
||||
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location = locations.id) as a_nodeCount'),
|
||||
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.location = locations.id)) as a_serverCount')
|
||||
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location_id = locations.id) as a_nodeCount'),
|
||||
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.location_id = locations.id)) as a_serverCount')
|
||||
)->paginate(20),
|
||||
]);
|
||||
}
|
||||
@ -55,8 +55,8 @@ class LocationsController extends Controller
|
||||
{
|
||||
$model = Models\Location::select(
|
||||
'locations.id',
|
||||
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location = locations.id) as a_nodeCount'),
|
||||
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.location = locations.id)) as a_serverCount')
|
||||
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location_id = locations.id) as a_nodeCount'),
|
||||
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.location_id = locations.id)) as a_serverCount')
|
||||
)->where('id', $id)->first();
|
||||
|
||||
if (! $model) {
|
||||
@ -80,12 +80,12 @@ class LocationsController extends Controller
|
||||
{
|
||||
try {
|
||||
$location = new LocationRepository;
|
||||
$location->edit($id, $request->all());
|
||||
$location->edit($id, $request->only(['long', 'short']));
|
||||
|
||||
return response('', 204);
|
||||
} catch (DisplayValidationException $ex) {
|
||||
return response()->json([
|
||||
'error' => 'There was a validation error while processing this request. Location descriptions must be between 1 and 255 characters, and the location code must be between 1 and 10 characters with no spaces or special characters.',
|
||||
'error' => 'There was a validation error while processing this request. Location descriptions must be between 1 and 255 characters, and the location code must be between 1 and 20 characters with no spaces or special characters.',
|
||||
], 422);
|
||||
} catch (\Exception $ex) {
|
||||
// This gets caught and processed into JSON anyways.
|
||||
@ -97,9 +97,7 @@ class LocationsController extends Controller
|
||||
{
|
||||
try {
|
||||
$location = new LocationRepository;
|
||||
$id = $location->create($request->except([
|
||||
'_token',
|
||||
]));
|
||||
$id = $location->create($request->only(['long', 'short']));
|
||||
Alert::success('New location successfully added.')->flash();
|
||||
|
||||
return redirect()->route('admin.locations');
|
||||
|
@ -48,17 +48,15 @@ class NodesController extends Controller
|
||||
|
||||
public function getScript(Request $request, $id)
|
||||
{
|
||||
return response()->view('admin.nodes.remote.deploy', ['node' => Models\Node::findOrFail($id)])->header('Content-Type', 'text/plain');
|
||||
return response()->view('admin.nodes.remote.deploy', [
|
||||
'node' => Models\Node::findOrFail($id),
|
||||
])->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
public function getIndex(Request $request)
|
||||
{
|
||||
return view('admin.nodes.index', [
|
||||
'nodes' => Models\Node::select(
|
||||
'nodes.*',
|
||||
'locations.long as a_locationName',
|
||||
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node_id = nodes.id) as a_serverCount')
|
||||
)->join('locations', 'nodes.location', '=', 'locations.id')->paginate(20),
|
||||
'nodes' => Models\Node::with('location')->withCount('servers')->paginate(20),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -78,15 +76,25 @@ class NodesController extends Controller
|
||||
public function postNew(Request $request)
|
||||
{
|
||||
try {
|
||||
$node = new NodeRepository;
|
||||
$new = $node->create($request->except([
|
||||
'_token',
|
||||
$repo = new NodeRepository;
|
||||
$node = $repo->create($request->only([
|
||||
'name',
|
||||
'location',
|
||||
'public',
|
||||
'fqdn',
|
||||
'scheme',
|
||||
'memory',
|
||||
'memory_overallocate',
|
||||
'disk',
|
||||
'disk_overallocate',
|
||||
'daemonBase',
|
||||
'daemonSFTP',
|
||||
'daemonListen',
|
||||
]));
|
||||
Alert::success('Successfully created new node. <strong>Before you can add any servers you need to first assign some IP addresses and ports.</strong>')->flash();
|
||||
Alert::info('<strong>To simplify the node setup you can generate a token on the configuration tab.</strong>')->flash();
|
||||
Alert::success('Successfully created new node that can be configured automatically on your remote machine by visiting the configuration tab. <strong>Before you can add any servers you need to first assign some IP addresses and ports.</strong>')->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view', [
|
||||
'id' => $new,
|
||||
'id' => $node->id,
|
||||
'tab' => 'tab_allocation',
|
||||
]);
|
||||
} catch (DisplayValidationException $e) {
|
||||
@ -103,26 +111,18 @@ class NodesController extends Controller
|
||||
|
||||
public function getView(Request $request, $id)
|
||||
{
|
||||
$node = Models\Node::findOrFail($id);
|
||||
$node = Models\Node::with(
|
||||
'servers.user',
|
||||
'servers.service',
|
||||
'servers.allocations',
|
||||
'location'
|
||||
)->findOrFail($id);
|
||||
$node->setRelation('allocations', $node->allocations()->paginate(40));
|
||||
|
||||
return view('admin.nodes.view', [
|
||||
'node' => $node,
|
||||
'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail', 'services.name as a_serviceName')
|
||||
->join('users', 'users.id', '=', 'servers.owner_id')
|
||||
->join('services', 'services.id', '=', 'servers.service_id')
|
||||
->where('node_id', $id)->paginate(10, ['*'], 'servers'),
|
||||
'stats' => Models\Server::select(DB::raw('SUM(memory) as memory, SUM(disk) as disk'))->where('node_id', $node->id)->first(),
|
||||
'locations' => Models\Location::all(),
|
||||
'allocations' => Models\Allocation::select('allocations.*', 'servers.name as assigned_to_name')
|
||||
->where('allocations.node', $node->id)
|
||||
->leftJoin('servers', 'servers.id', '=', 'allocations.assigned_to')
|
||||
->orderBy('allocations.ip', 'asc')
|
||||
->orderBy('allocations.port', 'asc')
|
||||
->paginate(20, ['*'], 'allocations'),
|
||||
'allocation_ips' => Models\Allocation::select('id', 'ip')
|
||||
->where('node', $node->id)
|
||||
->groupBy('ip')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -130,8 +130,21 @@ class NodesController extends Controller
|
||||
{
|
||||
try {
|
||||
$node = new NodeRepository;
|
||||
$node->update($id, $request->except([
|
||||
'_token',
|
||||
$node->update($id, $request->only([
|
||||
'name',
|
||||
'location',
|
||||
'public',
|
||||
'fqdn',
|
||||
'scheme',
|
||||
'memory',
|
||||
'memory_overallocate',
|
||||
'disk',
|
||||
'disk_overallocate',
|
||||
'upload_size',
|
||||
'daemonBase',
|
||||
'daemonSFTP',
|
||||
'daemonListen',
|
||||
'reset_secret',
|
||||
]));
|
||||
Alert::success('Successfully update this node\'s information. If you changed any daemon settings you will need to restart it now.')->flash();
|
||||
|
||||
|
@ -48,8 +48,8 @@ class Allocation extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'node' => 'integer',
|
||||
'node_id' => 'integer',
|
||||
'port' => 'integer',
|
||||
'assigned_to' => 'integer',
|
||||
'server_id' => 'integer',
|
||||
];
|
||||
}
|
||||
|
@ -226,4 +226,24 @@ class Node extends Model
|
||||
{
|
||||
return $this->hasOne(Location::class, 'id', 'location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the servers associated with a node.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function servers()
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the allocations associated with a node.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function allocations()
|
||||
{
|
||||
return $this->hasMany(Allocation::class);
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ class Server extends Model
|
||||
'services.name as a_serviceName',
|
||||
'service_options.name as a_serviceOptionName'
|
||||
)->join('nodes', 'servers.node_id', '=', 'nodes.id')
|
||||
->join('locations', 'nodes.location', '=', 'locations.id')
|
||||
->join('locations', 'nodes.location_id', '=', 'locations.id')
|
||||
->join('services', 'servers.service_id', '=', 'services.id')
|
||||
->join('service_options', 'servers.option_id', '=', 'service_options.id')
|
||||
->join('allocations', 'servers.allocation_id', '=', 'allocations.id');
|
||||
@ -218,6 +218,16 @@ class Server extends Model
|
||||
return Javascript::put($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user who owns the server.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->hasOne(User::class, 'id', 'owner_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all allocations associated with this server.
|
||||
*
|
||||
@ -225,7 +235,7 @@ class Server extends Model
|
||||
*/
|
||||
public function allocations()
|
||||
{
|
||||
return $this->hasMany(Allocation::class, 'assigned_to');
|
||||
return $this->hasMany(Allocation::class, 'server_id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ class LocationRepository
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'short' => 'required|regex:/^[a-z0-9_.-]{1,10}$/i|unique:locations,short',
|
||||
'short' => 'required|regex:/^[\w.-]{1,20}$/i|unique:locations,short',
|
||||
'long' => 'required|string|min:1|max:255',
|
||||
]);
|
||||
|
||||
@ -73,9 +73,11 @@ class LocationRepository
|
||||
*/
|
||||
public function edit($id, array $data)
|
||||
{
|
||||
$location = Models\Location::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'short' => 'regex:/^[a-z0-9_.-]{1,10}$/i',
|
||||
'long' => 'string|min:1|max:255',
|
||||
'short' => 'required|regex:/^[\w.-]{1,20}$/i|unique:locations,short,' . $location->id,
|
||||
'long' => 'required|string|min:1|max:255',
|
||||
]);
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
@ -84,15 +86,7 @@ class LocationRepository
|
||||
throw new DisplayValidationException($validator->errors());
|
||||
}
|
||||
|
||||
$location = Models\Location::findOrFail($id);
|
||||
|
||||
if (isset($data['short'])) {
|
||||
$location->short = $data['short'];
|
||||
}
|
||||
|
||||
if (isset($data['long'])) {
|
||||
$location->long = $data['long'];
|
||||
}
|
||||
$location->fill($data);
|
||||
|
||||
return $location->save();
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class NodeRepository
|
||||
|
||||
// Verify the FQDN if using SSL
|
||||
if (filter_var($data['fqdn'], FILTER_VALIDATE_IP) && $data['scheme'] === 'https') {
|
||||
throw new DisplayException('A fully qualified domain name is required to use secure comunication on this node.');
|
||||
throw new DisplayException('A fully qualified domain name is required to use a secure comunication method on this node.');
|
||||
}
|
||||
|
||||
// Verify FQDN is resolvable, or if not using SSL that the IP is valid.
|
||||
@ -86,7 +86,7 @@ class NodeRepository
|
||||
$node->fill($data);
|
||||
$node->save();
|
||||
|
||||
return $node->id;
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function update($id, array $data)
|
||||
@ -152,18 +152,12 @@ class NodeRepository
|
||||
$oldDaemonKey = $node->daemonSecret;
|
||||
$node->update($data);
|
||||
try {
|
||||
$client = Models\Node::guzzleRequest($node->id);
|
||||
$client->request('PATCH', '/config', [
|
||||
'headers' => [
|
||||
'X-Access-Token' => $oldDaemonKey,
|
||||
],
|
||||
$node->guzzleClient(['X-Access-Token' => $oldDaemonKey])->request('PATCH', '/config', [
|
||||
'json' => [
|
||||
'web' => [
|
||||
'listen' => $node->daemonListen,
|
||||
'ssl' => [
|
||||
'enabled' => ($node->scheme === 'https'),
|
||||
'certificate' => '/etc/letsencrypt/live/' . $node->fqdn . '/fullchain.pem',
|
||||
'key' => '/etc/letsencrypt/live/' . $node->fqdn . '/privkey.pem',
|
||||
],
|
||||
],
|
||||
'sftp' => [
|
||||
|
48
database/migrations/2017_02_03_155554_RenameColumns.php
Normal file
48
database/migrations/2017_02_03_155554_RenameColumns.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameColumns extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('allocations', function (Blueprint $table) {
|
||||
$table->dropForeign('allocations_node_foreign');
|
||||
$table->dropForeign('allocations_assigned_to_foreign');
|
||||
$table->dropIndex('allocations_node_foreign');
|
||||
$table->dropIndex('allocations_assigned_to_foreign');
|
||||
|
||||
$table->renameColumn('node', 'node_id');
|
||||
$table->renameColumn('assigned_to', 'server_id');
|
||||
$table->foreign('node_id')->references('id')->on('nodes');
|
||||
$table->foreign('server_id')->references('id')->on('servers');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('allocations', function (Blueprint $table) {
|
||||
$table->dropForeign('allocations_node_id_foreign');
|
||||
$table->dropForeign('allocations_server_id_foreign');
|
||||
$table->dropIndex('allocations_node_id_foreign');
|
||||
$table->dropIndex('allocations_server_id_foreign');
|
||||
|
||||
$table->renameColumn('node_id', 'node');
|
||||
$table->renameColumn('server_id', 'assigned_to');
|
||||
$table->foreign('node')->references('id')->on('nodes');
|
||||
$table->foreign('assigned_to')->references('id')->on('servers');
|
||||
});
|
||||
}
|
||||
}
|
@ -53,10 +53,10 @@
|
||||
<tr>
|
||||
<td class="text-center text-muted left-icon" data-action="ping" data-secret="{{ $node->daemonSecret }}" data-location="{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}"><i class="fa fa-fw fa-refresh fa-spin"></i></td>
|
||||
<td><a href="/admin/nodes/view/{{ $node->id }}">{{ $node->name }}</td>
|
||||
<td>{{ $node->a_locationName }}</td>
|
||||
<td>{{ $node->location->short }}</td>
|
||||
<td class="hidden-xs">{{ $node->memory }} MB</td>
|
||||
<td class="hidden-xs">{{ $node->disk }} MB</td>
|
||||
<td class="text-center hidden-xs">{{ $node->a_serverCount }}</td>
|
||||
<td class="text-center hidden-xs">{{ $node->servers_count }}</td>
|
||||
<td class="text-center" style="color:{{ ($node->scheme === 'https') ? '#50af51' : '#d9534f' }}"><i class="fa fa-{{ ($node->scheme === 'https') ? 'lock' : 'unlock' }}"></i></td>
|
||||
<td class="text-center hidden-xs"><i class="fa fa-{{ ($node->public === 1) ? 'eye' : 'eye-slash' }}"></i></td>
|
||||
</tr>
|
||||
|
@ -60,7 +60,7 @@
|
||||
<li><a href="#tab_configuration" data-toggle="tab">Configuration</a></li>
|
||||
<li><a href="#tab_allocation" data-toggle="tab">Allocation</a></li>
|
||||
<li><a href="#tab_servers" data-toggle="tab">Servers</a></li>
|
||||
@if(count($servers) === 0)<li><a href="#tab_delete" data-toggle="tab">Delete</a></li>@endif
|
||||
@if(count($node->servers) === 0)<li><a href="#tab_delete" data-toggle="tab">Delete</a></li>@endif
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tab_about">
|
||||
@ -83,7 +83,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total Servers</td>
|
||||
<td>{{ count($servers) }}</td>
|
||||
<td>{{ count($node->servers) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Memory Allocated</td>
|
||||
@ -309,7 +309,7 @@
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
@foreach($allocation_ips as $allocation)
|
||||
@foreach($node->allocations->unique('ip')->values()->all() as $allocation)
|
||||
<li data-action="alloc_dropdown_val" data-value="{{ $allocation->ip }}"><a href="#">{{ $allocation->ip }}</a></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@ -355,7 +355,7 @@
|
||||
<td></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($allocations as $allocation)
|
||||
@foreach($node->allocations as $allocation)
|
||||
<tr>
|
||||
<td class="col-sm-3 align-middle">{{ $allocation->ip }}</td>
|
||||
<td class="col-sm-3 align-middle">
|
||||
@ -376,7 +376,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="col-md-12 text-center">
|
||||
{{ $allocations->appends(['tab' => 'tab_allocation'])->links() }}
|
||||
{{ $node->allocations->appends(['tab' => 'tab_allocation'])->render() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -402,11 +402,11 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($servers as $server)
|
||||
@foreach($node->servers as $server)
|
||||
<tr data-server="{{ $server->uuid }}">
|
||||
<td><a href="/admin/servers/view/{{ $server->id }}">{{ $server->name }}</a></td>
|
||||
<td><a href="/admin/users/view/{{ $server->owner_id }}"><code>{{ $server->a_ownerEmail }}</a></a></td>
|
||||
<td>{{ $server->a_serviceName }}</td>
|
||||
<td><a href="/admin/users/view/{{ $server->owner_id }}"><code>{{ $server->user->email }}</a></a></td>
|
||||
<td>{{ $server->service->name }}</td>
|
||||
<td class="text-center"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
||||
<td class="text-center">{{ $server->disk }} MB</td>
|
||||
<td class="text-center"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
|
||||
@ -415,13 +415,10 @@
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">{!! $servers->appends(['tab' => 'tab_servers'])->render() !!}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if(count($servers) === 0)
|
||||
@if(count($node->servers) === 0)
|
||||
<div class="tab-pane" id="tab_delete">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"></div>
|
||||
@ -459,7 +456,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<select class="form-control" name="ip">
|
||||
@foreach($allocation_ips as $allocation)
|
||||
@foreach($node->allocations->unique('ip')->values()->all() as $allocation)
|
||||
<option value="{{ $allocation->ip }}">{{ $allocation->ip }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
Loading…
Reference in New Issue
Block a user