Merge branch 'develop' into feature/service-changes
This commit is contained in:
commit
9eb14614c2
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -3,6 +3,27 @@ This file is a running track of new features and fixes to each version of the pa
|
||||||
|
|
||||||
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
|
## v0.5.2 (Bodacious Boreopterus)
|
||||||
|
### Fixed
|
||||||
|
* Time axis on server graphs is corrected to show the minutes rather than the current month.
|
||||||
|
* Node deletion now works correctly and deletes allocations as well.
|
||||||
|
* Fixes a bug that would leave orphaned databases on the system if there was an error during creation.
|
||||||
|
* Fixes an issue that could occur if a UUID contained `#e#` formatting within it when it comes to creating databases.
|
||||||
|
* Fixed node status display to account for updated daemon security changes.
|
||||||
|
* Fixes default language being selected as German (defaults to English now).
|
||||||
|
* Fixes bug preventing the deletion of database servers.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Using `node:<name>` when filtering servers now properly filters the servers by node name, rather than looking for the node ID.
|
||||||
|
* Using `owner:<email>` when filtering servers now properly filters by the owner's email rather than ID.
|
||||||
|
* Added some quick help buttons to the admin index page for getting support or checking the documentation.
|
||||||
|
* Panel now displays `Pterodactyl Panel` as the company name if one is not set.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Added basic information about the daemon when viewing a node, including the host OS and version, CPU count, and the daemon version.
|
||||||
|
* Added version checking for the daemon and panel that alerts admins when daemons or the panel is out of date.
|
||||||
|
* Added multiplicator support to certain memory and disk fields that allow users to enter `10g` and have it converted to MB automatically.
|
||||||
|
|
||||||
## v0.5.1 (Bodacious Boreopterus)
|
## v0.5.1 (Bodacious Boreopterus)
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fixes a bug that allowed a user to bypass 2FA authentication if using the correct username and password for an account.
|
* Fixes a bug that allowed a user to bypass 2FA authentication if using the correct username and password for an account.
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
namespace Pterodactyl\Console\Commands;
|
namespace Pterodactyl\Console\Commands;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Version;
|
||||||
|
|
||||||
class ShowVersion extends Command
|
class ShowVersion extends Command
|
||||||
{
|
{
|
||||||
|
@ -58,6 +59,6 @@ class ShowVersion extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->info('You are running Pterodactyl Panel ' . config('app.version'));
|
$this->info('You are running Pterodactyl Panel v' . Version::getCurrentPanel() . ' (' . ((Version::isLatestPanel()) ? 'Up to Date' : 'Latest: ' . Version::getDaemon()) . ')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pterodactyl - Panel
|
||||||
|
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Pterodactyl\Facades;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
class Version extends Facade
|
||||||
|
{
|
||||||
|
|
||||||
|
protected static function getFacadeAccessor()
|
||||||
|
{
|
||||||
|
return '\Pterodactyl\Services\VersionService';
|
||||||
|
}
|
||||||
|
}
|
|
@ -253,20 +253,22 @@ class NodesController extends Controller
|
||||||
|
|
||||||
public function deleteNode(Request $request, $id)
|
public function deleteNode(Request $request, $id)
|
||||||
{
|
{
|
||||||
$node = Models\Node::findOrFail($id);
|
try {
|
||||||
$servers = Models\Server::where('node', $id)->count();
|
$repo = new NodeRepository;
|
||||||
if ($servers > 0) {
|
$repo->delete($id);
|
||||||
Alert::danger('You cannot delete a node with servers currently attached to it.')->flash();
|
Alert::success('Successfully deleted the requested node from the panel.')->flash();
|
||||||
|
return redirect()->route('admin.nodes');
|
||||||
|
} catch (DisplayException $e) {
|
||||||
|
Alert::danger($e->getMessage())->flash();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error($e);
|
||||||
|
Alert::danger('An unhandled exception occured while attempting to delete this node. Please try again.')->flash();
|
||||||
|
}
|
||||||
|
|
||||||
return redirect()->route('admin.nodes.view', [
|
return redirect()->route('admin.nodes.view', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'tab' => 'tab_delete'
|
'tab' => 'tab_delete'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$node->delete();
|
|
||||||
Alert::success('Node successfully deleted.')->flash();
|
|
||||||
return redirect()->route('admin.nodes');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,14 +68,23 @@ class ServersController extends Controller
|
||||||
$match = str_replace('"', '', $match);
|
$match = str_replace('"', '', $match);
|
||||||
if (strpos($match, ':')) {
|
if (strpos($match, ':')) {
|
||||||
list($field, $term) = explode(':', $match);
|
list($field, $term) = explode(':', $match);
|
||||||
$field = (strpos($field, '.')) ? $field : 'servers.' . $field;
|
if ($field === 'node') {
|
||||||
|
$field = 'nodes.name';
|
||||||
|
} else if ($field === 'owner') {
|
||||||
|
$field = 'users.email';
|
||||||
|
} else if (!strpos($field, '.')) {
|
||||||
|
$field = 'servers.' . $field;
|
||||||
|
}
|
||||||
|
|
||||||
$query->orWhere($field, 'LIKE', '%' . $term . '%');
|
$query->orWhere($field, 'LIKE', '%' . $term . '%');
|
||||||
} else {
|
} else {
|
||||||
$query->where('servers.name', 'LIKE', '%' . $match . '%');
|
$query->where('servers.name', 'LIKE', '%' . $match . '%');
|
||||||
$query->orWhere('servers.username', 'LIKE', '%' . $match . '%');
|
$query->orWhere([
|
||||||
$query->orWhere('users.email', 'LIKE', '%' . $match . '%');
|
['servers.username', 'LIKE', '%' . $match . '%'],
|
||||||
$query->orWhere('allocations.port', 'LIKE', '%' . $match . '%');
|
['users.email', 'LIKE', '%' . $match . '%'],
|
||||||
$query->orWhere('allocations.ip', 'LIKE', '%' . $match . '%');
|
['allocations.port', 'LIKE', '%' . $match . '%'],
|
||||||
|
['allocations.ip', 'LIKE', '%' . $match . '%'],
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,13 +56,12 @@ class DatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db = new Models\Database;
|
$db = new Models\Database;
|
||||||
$db->fill([
|
$db->fill([
|
||||||
'server_id' => $server->id,
|
'server_id' => $server->id,
|
||||||
'db_server' => $options['db_server'],
|
'db_server' => $options['db_server'],
|
||||||
'database' => $server->uuidShort . '_' . $options['database'],
|
'database' => "s{$server->id}_{$options['database']}",
|
||||||
'username' => $server->uuidShort . '_' . str_random(7),
|
'username' => $server->uuidShort . '_' . str_random(7),
|
||||||
'remote' => $options['remote'],
|
'remote' => $options['remote'],
|
||||||
'password' => Crypt::encrypt(str_random(20))
|
'password' => Crypt::encrypt(str_random(20))
|
||||||
|
@ -90,18 +89,31 @@ class DatabaseRepository {
|
||||||
|
|
||||||
$capsule->setAsGlobal();
|
$capsule->setAsGlobal();
|
||||||
|
|
||||||
Capsule::statement('CREATE DATABASE ' . $db->database);
|
|
||||||
Capsule::statement('CREATE USER \'' . $db->username . '\'@\'' . $db->remote . '\' IDENTIFIED BY \'' . Crypt::decrypt($db->password) . '\'');
|
|
||||||
Capsule::statement('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON ' . $db->database . '.* TO \'' . $db->username . '\'@\'' . $db->remote . '\'');
|
|
||||||
Capsule::statement('FLUSH PRIVILEGES');
|
|
||||||
|
|
||||||
DB::commit();
|
|
||||||
return true;
|
|
||||||
} catch (\Exception $ex) {
|
} catch (\Exception $ex) {
|
||||||
DB::rollback();
|
DB::rollBack();
|
||||||
|
throw new DisplayException('There was an error while connecting to the Database Host Server. Please check the error logs.', $ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Capsule::statement('CREATE DATABASE `' . $db->database . '`');
|
||||||
|
Capsule::statement('CREATE USER `' . $db->username . '`@`' . $db->remote . '` IDENTIFIED BY \'' . Crypt::decrypt($db->password) . '\'');
|
||||||
|
Capsule::statement('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `' . $db->database . '`.* TO `' . $db->username . '`@`' . $db->remote . '`');
|
||||||
|
Capsule::statement('FLUSH PRIVILEGES');
|
||||||
|
DB::commit();
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
try {
|
||||||
|
Capsule::statement('DROP DATABASE `' . $db->database . '`');
|
||||||
|
Capsule::statement('DROP USER `' . $db->username . '`@`' . $db->remote . '`');
|
||||||
|
} catch (\Exception $exi) {
|
||||||
|
// ignore it, if it fails its probably
|
||||||
|
// because we failed to ever make the DB
|
||||||
|
// or the user on the system.
|
||||||
|
} finally {
|
||||||
|
DB::rollBack();
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the password for a given database.
|
* Updates the password for a given database.
|
||||||
|
@ -138,7 +150,7 @@ class DatabaseRepository {
|
||||||
|
|
||||||
$capsule->setAsGlobal();
|
$capsule->setAsGlobal();
|
||||||
Capsule::statement(sprintf(
|
Capsule::statement(sprintf(
|
||||||
'SET PASSWORD FOR \'%s\'@\'%s\' = PASSWORD(\'%s\')',
|
'SET PASSWORD FOR `%s`@`%s` = PASSWORD(\'%s\')',
|
||||||
$db->username,
|
$db->username,
|
||||||
$db->remote,
|
$db->remote,
|
||||||
$password
|
$password
|
||||||
|
@ -182,8 +194,8 @@ class DatabaseRepository {
|
||||||
|
|
||||||
$capsule->setAsGlobal();
|
$capsule->setAsGlobal();
|
||||||
|
|
||||||
Capsule::statement('DROP USER \'' . $db->username . '\'@\'' . $db->remote . '\'');
|
Capsule::statement('DROP USER `' . $db->username . '`@`' . $db->remote . '`');
|
||||||
Capsule::statement('DROP DATABASE ' . $db->database);
|
Capsule::statement('DROP DATABASE `' . $db->database . '`');
|
||||||
|
|
||||||
$db->delete();
|
$db->delete();
|
||||||
|
|
||||||
|
@ -219,6 +231,11 @@ class DatabaseRepository {
|
||||||
*/
|
*/
|
||||||
public function add(array $data)
|
public function add(array $data)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (isset($data['host'])) {
|
||||||
|
$data['host'] = gethostbyname($data['host']);
|
||||||
|
}
|
||||||
|
|
||||||
$validator = Validator::make($data, [
|
$validator = Validator::make($data, [
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'host' => 'required|ip|unique:database_servers,host',
|
'host' => 'required|ip|unique:database_servers,host',
|
||||||
|
|
|
@ -229,8 +229,30 @@ class NodeRepository {
|
||||||
|
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
// @TODO: add logic;
|
$node = Models\Node::findOrFail($id);
|
||||||
return true;
|
if (Models\Server::where('node', $id)->count() > 0) {
|
||||||
|
throw new DisplayException('You cannot delete a node with servers currently attached to it.');
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Unlink Database Servers
|
||||||
|
Models\DatabaseServer::where('linked_node', $node->id)->update([
|
||||||
|
'linked_node' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Delete Allocations
|
||||||
|
Models\Allocation::where('node', $node->id)->delete();
|
||||||
|
|
||||||
|
// Delete Node
|
||||||
|
$node->delete();
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
DB::rollback();
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pterodactyl - Panel
|
||||||
|
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Pterodactyl\Services;
|
||||||
|
|
||||||
|
use Cache;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
class VersionService
|
||||||
|
{
|
||||||
|
|
||||||
|
protected static $versions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
self::$versions = Cache::remember('versions', env('VERSION_CACHE_TIME', 60), function () {
|
||||||
|
$client = new Client();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $client->request('GET', env('VERSION_CHECK_URL', 'https://cdn.pterodactyl.io/releases/latest.json'));
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
return json_decode($response->getBody());
|
||||||
|
} else {
|
||||||
|
throw new \Exception('Invalid response code.');
|
||||||
|
}
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
// Failed request, just return errored version.
|
||||||
|
return (object) [
|
||||||
|
'panel' => 'error',
|
||||||
|
'daemon' => 'error',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getPanel()
|
||||||
|
{
|
||||||
|
return self::$versions->panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getDaemon()
|
||||||
|
{
|
||||||
|
return self::$versions->daemon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCurrentPanel()
|
||||||
|
{
|
||||||
|
return config('app.version');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isLatestPanel()
|
||||||
|
{
|
||||||
|
if (config('app.version') === 'canary') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (version_compare(config('app.version'), self::$versions->panel) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isLatestDaemon($daemon)
|
||||||
|
{
|
||||||
|
if ($daemon === '0.0.0-canary') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (version_compare($daemon, self::$versions->daemon) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -217,6 +217,7 @@ return [
|
||||||
'URL' => Illuminate\Support\Facades\URL::class,
|
'URL' => Illuminate\Support\Facades\URL::class,
|
||||||
'Uuid' => Webpatser\Uuid\Uuid::class,
|
'Uuid' => Webpatser\Uuid\Uuid::class,
|
||||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||||
|
'Version' => Pterodactyl\Facades\Version::class,
|
||||||
'View' => Illuminate\Support\Facades\View::class,
|
'View' => Illuminate\Support\Facades\View::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -46,4 +46,24 @@ $(document).ready(function () {
|
||||||
centerModal($(this));
|
centerModal($(this));
|
||||||
});
|
});
|
||||||
$(window).on('resize', centerModal);
|
$(window).on('resize', centerModal);
|
||||||
|
|
||||||
|
// Idea code for multiplicators submitted by @Taronyuu on Github
|
||||||
|
// https://github.com/Pterodactyl/Panel/issues/154#issuecomment-257116078
|
||||||
|
$('input[data-multiplicator="true"]').on('change', function () {
|
||||||
|
var value = $(this).val();
|
||||||
|
if (!/^\d+$/.test(value)) {
|
||||||
|
var multiplicator = value.replace(/[0-9]/g, '').toLowerCase();
|
||||||
|
value = value.replace(/\D/g, '');
|
||||||
|
|
||||||
|
if (multiplicator === 't') {
|
||||||
|
value = value * (1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiplicator === 'g') {
|
||||||
|
value = value * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).val(value);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -93,7 +93,7 @@
|
||||||
<td>{{ $db->username }}</td>
|
<td>{{ $db->username }}</td>
|
||||||
<td class="text-center">{{ $db->c_databases }}</td>
|
<td class="text-center">{{ $db->c_databases }}</td>
|
||||||
<td>@if(is_null($db->a_linkedNode))<em>unlinked</em>@else{{ $db->a_linkedNode }}@endif</td>
|
<td>@if(is_null($db->a_linkedNode))<em>unlinked</em>@else{{ $db->a_linkedNode }}@endif</td>
|
||||||
<td class="text-center"><a href="#" class="text-danger" data-action="delete" data-type="delete-dbserver" data-attr="{{ $db->id }}"><i class="fa fa-trash-o"></i></a></td>
|
<td class="text-center"><a href="#" class="text-danger" data-action="delete" data-type="delete-server" data-attr="{{ $db->id }}"><i class="fa fa-trash-o"></i></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -24,13 +24,31 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul class="breadcrumb">
|
<ul class="breadcrumb">
|
||||||
<li class="active">Admin Control</li>
|
<li class="active">Admin Control</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3 class="nopad">Pterodactyl Admin Control Panel</h3><hr />
|
<h3 class="nopad">Pterodactyl Admin Control Panel</h3><hr />
|
||||||
<p>Welcome to the most advanced, lightweight, and user-friendly open source game server control panel.</p>
|
@if (Version::isLatestPanel())
|
||||||
<p>You are running version <code>{{ config('app.version') }}</code>.</p>
|
<div class="alert alert-success">You are running Pterodactyl Panel version <code>{{ Version::getCurrentPanel() }}</code>. Your panel is up-to-date!</div>
|
||||||
|
@else
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
Your panel is <strong>not up-to-date!</strong> The latest version is <a href="https://github.com/Pterodactyl/Panel/releases/v{{ Version::getPanel() }}" target="_blank"><code>{{ Version::getPanel() }}</code></a> and you are currently running version <code>{{ Version::getCurrentPanel() }}</code>.
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="https://discord.gg/0gYt8oU8QOkDhKLS"><button class="btn btn-sm btn-warning" style="width:100%;"><i class="fa fa-fw fa-support"></i> Get Help <small>(via Discord)</small></button></a>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="https://docs.pterodactyl.io"><button class="btn btn-sm btn-default" style="width:100%;"><i class="fa fa-fw fa-link"></i> Documentation</button></a>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="https://github.com/Pterodactyl/Panel"><button class="btn btn-sm btn-default" style="width:100%;"><i class="fa fa-fw fa-support"></i> Github</button></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
|
@ -70,21 +70,27 @@
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#sidebar_links').find("a[href='/admin/nodes']").addClass('active');
|
$('#sidebar_links').find("a[href='/admin/nodes']").addClass('active');
|
||||||
pingNodes();
|
(function pingNodes() {
|
||||||
setInterval(pingNodes, 10000);
|
|
||||||
});
|
|
||||||
function pingNodes() {
|
|
||||||
$('td[data-action="ping"]').each(function(i, element) {
|
$('td[data-action="ping"]').each(function(i, element) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: $(element).data('location'),
|
url: $(element).data('location'),
|
||||||
|
headers: {
|
||||||
|
'X-Access-Token': '{{ $node->daemonSecret }}'
|
||||||
|
},
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
}).done(function (data) {
|
}).done(function (data) {
|
||||||
|
$(element).find('i').tooltip({
|
||||||
|
title: 'v' + data.version,
|
||||||
|
});
|
||||||
$(element).removeClass('text-muted').find('i').removeClass().addClass('fa fa-fw fa-heartbeat faa-pulse animated').css('color', '#50af51');
|
$(element).removeClass('text-muted').find('i').removeClass().addClass('fa fa-fw fa-heartbeat faa-pulse animated').css('color', '#50af51');
|
||||||
}).fail(function () {
|
}).fail(function () {
|
||||||
$(element).removeClass('text-muted').find('i').removeClass().addClass('fa fa-fw fa-heart-o').css('color', '#d9534f');
|
$(element).removeClass('text-muted').find('i').removeClass().addClass('fa fa-fw fa-heart-o').css('color', '#d9534f');
|
||||||
|
}).always(function () {
|
||||||
|
setTimeout(pingNodes, 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
})();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -92,14 +92,14 @@
|
||||||
<div class="form-group col-md-6 col-xs-6">
|
<div class="form-group col-md-6 col-xs-6">
|
||||||
<label for="memory" class="control-label">Total Memory</label>
|
<label for="memory" class="control-label">Total Memory</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="memory" class="form-control" value="{{ old('memory') }}"/>
|
<input type="text" name="memory" data-multiplicator="true" class="form-control" value="{{ old('memory') }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-6 col-xs-6">
|
<div class="form-group col-md-6 col-xs-6">
|
||||||
<label for="memory_overallocate" class="control-label">Overallocate</label>
|
<label for="memory_overallocate" class="control-label">Overallocate</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="memory_overallocate" class="form-control" value="{{ old('memory_overallocate', 0) }}"/>
|
<input type="text" name="memory_overallocate" data-multiplicator="true" class="form-control" value="{{ old('memory_overallocate', 0) }}"/>
|
||||||
<span class="input-group-addon">%</span>
|
<span class="input-group-addon">%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,6 +69,18 @@
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<table class="table table-striped" style="margin-bottom:0;">
|
<table class="table table-striped" style="margin-bottom:0;">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Daemon Version</td>
|
||||||
|
<td><code data-attr="info-version"><i class="fa fa-refresh fa-fw fa-spin"></i></code> (Latest: <code>{{ Version::getPanel() }}</code>)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>System Information</td>
|
||||||
|
<td data-attr="info-system"><i class="fa fa-refresh fa-fw fa-spin"></i></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Total CPU Cores</td>
|
||||||
|
<td data-attr="info-cpus"><i class="fa fa-refresh fa-fw fa-spin"></i></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total Servers</td>
|
<td>Total Servers</td>
|
||||||
<td>{{ count($servers) }}</td>
|
<td>{{ count($servers) }}</td>
|
||||||
|
@ -171,7 +183,7 @@
|
||||||
<div class="form-group col-md-3 col-xs-6">
|
<div class="form-group col-md-3 col-xs-6">
|
||||||
<label for="memory" class="control-label">Total Memory</label>
|
<label for="memory" class="control-label">Total Memory</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="memory" class="form-control" value="{{ old('memory', $node->memory) }}"/>
|
<input type="text" name="memory" class="form-control" data-multiplicator="true" value="{{ old('memory', $node->memory) }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -185,7 +197,7 @@
|
||||||
<div class="form-group col-md-3 col-xs-6">
|
<div class="form-group col-md-3 col-xs-6">
|
||||||
<label for="disk" class="control-label">Disk Space</label>
|
<label for="disk" class="control-label">Disk Space</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="disk" class="form-control" value="{{ old('disk', $node->disk) }}"/>
|
<input type="text" name="disk" class="form-control" data-multiplicator="true" value="{{ old('disk', $node->disk) }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -777,6 +789,24 @@ $(document).ready(function () {
|
||||||
element.parent().removeClass('has-error has-success');
|
element.parent().removeClass('has-error has-success');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(function getInformation() {
|
||||||
|
$.ajax({
|
||||||
|
method: 'GET',
|
||||||
|
url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}',
|
||||||
|
timeout: 5000,
|
||||||
|
headers: {
|
||||||
|
'X-Access-Token': '{{ $node->daemonSecret }}'
|
||||||
|
},
|
||||||
|
}).done(function (data) {
|
||||||
|
$('[data-attr="info-version"]').html(data.version);
|
||||||
|
$('[data-attr="info-system"]').html(data.system.type + '(' + data.system.arch + ') <code>' + data.system.release + '</code>');
|
||||||
|
$('[data-attr="info-cpus"]').html(data.system.cpus);
|
||||||
|
}).fail(function (jqXHR) {
|
||||||
|
|
||||||
|
}).always(function() {
|
||||||
|
setTimeout(getInformation, 10000);
|
||||||
|
});
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -118,14 +118,14 @@
|
||||||
<div class="form-group col-md-4 col-xs-4">
|
<div class="form-group col-md-4 col-xs-4">
|
||||||
<label for="memory" class="control-label">Memory</label>
|
<label for="memory" class="control-label">Memory</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="memory" class="form-control" value="{{ old('memory') }}"/>
|
<input type="text" name="memory" data-multiplicator="true" class="form-control" value="{{ old('memory') }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-4 col-xs-4">
|
<div class="form-group col-md-4 col-xs-4">
|
||||||
<label for="memory" class="control-label">Swap</label>
|
<label for="memory" class="control-label">Swap</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="swap" class="form-control" value="{{ old('swap', 0) }}"/>
|
<input type="text" name="swap" data-multiplicator="true" class="form-control" value="{{ old('swap', 0) }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
<div class="form-group col-md-4 col-xs-4">
|
<div class="form-group col-md-4 col-xs-4">
|
||||||
<label for="disk" class="control-label">Disk Space</label>
|
<label for="disk" class="control-label">Disk Space</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="disk" class="form-control" value="{{ old('disk') }}"/>
|
<input type="text" name="disk" data-multiplicator="true" class="form-control" value="{{ old('disk') }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -228,14 +228,14 @@
|
||||||
<div class="col-md-6 form-group {{ $errors->has('memory') ? 'has-error' : '' }}">
|
<div class="col-md-6 form-group {{ $errors->has('memory') ? 'has-error' : '' }}">
|
||||||
<label for="memory" class="control-label">Allocated Memory</label>
|
<label for="memory" class="control-label">Allocated Memory</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="memory" class="form-control" value="{{ old('memory', $server->memory) }}"/>
|
<input type="text" name="memory" data-multiplicator="true" class="form-control" value="{{ old('memory', $server->memory) }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 form-group {{ $errors->has('swap') ? 'has-error' : '' }}">
|
<div class="col-md-6 form-group {{ $errors->has('swap') ? 'has-error' : '' }}">
|
||||||
<label for="swap" class="control-label">Allocated Swap</label>
|
<label for="swap" class="control-label">Allocated Swap</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" name="swap" class="form-control" value="{{ old('swap', $server->swap) }}"/>
|
<input type="text" name="swap" data-multiplicator="true" class="form-control" value="{{ old('swap', $server->swap) }}"/>
|
||||||
<span class="input-group-addon">MB</span>
|
<span class="input-group-addon">MB</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted"><small>Setting this to <code>0</code> will disable swap space on this server.</small></p>
|
<p class="text-muted"><small>Setting this to <code>0</code> will disable swap space on this server.</small></p>
|
||||||
|
@ -373,7 +373,7 @@
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group col-md-6">
|
||||||
<label class="control-label">Database Name:</label>
|
<label class="control-label">Database Name:</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-addon">{{ $server->uuidShort }}_</div>
|
<div class="input-group-addon">s{{ $server->id }}_</div>
|
||||||
<input type="text" name="database" value="{{ old('database') }}" class="form-control">
|
<input type="text" name="database" value="{{ old('database') }}" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<div>
|
<div>
|
||||||
<select name="default_language" class="form-control">
|
<select name="default_language" class="form-control">
|
||||||
<option value="de" @if(Settings::get('default_language') === 'de')selected @endif>Deutsch</option>
|
<option value="de" @if(Settings::get('default_language') === 'de')selected @endif>Deutsch</option>
|
||||||
<option value="en" @if(Settings::get('default_language') === 'en')selected @endif>English</option>
|
<option value="en" @if(Settings::get('default_language', 'en') === 'en')selected @endif>English</option>
|
||||||
<option value="es" @if(Settings::get('default_language') === 'es')selected @endif>Español</option>
|
<option value="es" @if(Settings::get('default_language') === 'es')selected @endif>Español</option>
|
||||||
<option value="fr" @if(Settings::get('default_language') === 'fr')selected @endif>Français</option>
|
<option value="fr" @if(Settings::get('default_language') === 'fr')selected @endif>Français</option>
|
||||||
<option value="it" @if(Settings::get('default_language') === 'it')selected @endif>Italiano</option>
|
<option value="it" @if(Settings::get('default_language') === 'it')selected @endif>Italiano</option>
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="/">{{ Settings::get('company') }}</a>
|
<a class="navbar-brand" href="/">{{ Settings::get('company', 'Pterodactyl Panel') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||||
@section('navbar-links')
|
@section('navbar-links')
|
||||||
|
|
|
@ -164,7 +164,7 @@
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="/">{{ Settings::get('company') }}</a>
|
<a class="navbar-brand" href="/">{{ Settings::get('company', 'Pterodactyl Panel') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||||
@section('server-name')
|
@section('server-name')
|
||||||
|
|
Loading…
Reference in New Issue