Skip to content

Commit 9eb1461

Browse files
committed
Merge branch 'develop' into feature/service-changes
2 parents 5a0f58c + f627505 commit 9eb1461

File tree

20 files changed

+343
-68
lines changed

20 files changed

+343
-68
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@ This file is a running track of new features and fixes to each version of the pa
33

44
This project follows [Semantic Versioning](http://semver.org) guidelines.
55

6+
## v0.5.2 (Bodacious Boreopterus)
7+
### Fixed
8+
* Time axis on server graphs is corrected to show the minutes rather than the current month.
9+
* Node deletion now works correctly and deletes allocations as well.
10+
* Fixes a bug that would leave orphaned databases on the system if there was an error during creation.
11+
* Fixes an issue that could occur if a UUID contained `#e#` formatting within it when it comes to creating databases.
12+
* Fixed node status display to account for updated daemon security changes.
13+
* Fixes default language being selected as German (defaults to English now).
14+
* Fixes bug preventing the deletion of database servers.
15+
16+
### Changed
17+
* Using `node:<name>` when filtering servers now properly filters the servers by node name, rather than looking for the node ID.
18+
* Using `owner:<email>` when filtering servers now properly filters by the owner's email rather than ID.
19+
* Added some quick help buttons to the admin index page for getting support or checking the documentation.
20+
* Panel now displays `Pterodactyl Panel` as the company name if one is not set.
21+
22+
### Added
23+
* Added basic information about the daemon when viewing a node, including the host OS and version, CPU count, and the daemon version.
24+
* Added version checking for the daemon and panel that alerts admins when daemons or the panel is out of date.
25+
* Added multiplicator support to certain memory and disk fields that allow users to enter `10g` and have it converted to MB automatically.
26+
627
## v0.5.1 (Bodacious Boreopterus)
728
### Fixed
829
* Fixes a bug that allowed a user to bypass 2FA authentication if using the correct username and password for an account.

app/Console/Commands/ShowVersion.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
namespace Pterodactyl\Console\Commands;
2525

2626
use Illuminate\Console\Command;
27+
use Version;
2728

2829
class ShowVersion extends Command
2930
{
@@ -58,6 +59,6 @@ public function __construct()
5859
*/
5960
public function handle()
6061
{
61-
$this->info('You are running Pterodactyl Panel ' . config('app.version'));
62+
$this->info('You are running Pterodactyl Panel v' . Version::getCurrentPanel() . ' (' . ((Version::isLatestPanel()) ? 'Up to Date' : 'Latest: ' . Version::getDaemon()) . ')');
6263
}
6364
}

app/Facades/Version.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Facades;
25+
26+
use Illuminate\Support\Facades\Facade;
27+
28+
class Version extends Facade
29+
{
30+
31+
protected static function getFacadeAccessor()
32+
{
33+
return '\Pterodactyl\Services\VersionService';
34+
}
35+
}

app/Http/Controllers/Admin/NodesController.php

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,22 @@ public function postAllocations(Request $request, $id)
253253

254254
public function deleteNode(Request $request, $id)
255255
{
256-
$node = Models\Node::findOrFail($id);
257-
$servers = Models\Server::where('node', $id)->count();
258-
if ($servers > 0) {
259-
Alert::danger('You cannot delete a node with servers currently attached to it.')->flash();
260-
return redirect()->route('admin.nodes.view', [
261-
'id' => $id,
262-
'tab' => 'tab_delete'
263-
]);
256+
try {
257+
$repo = new NodeRepository;
258+
$repo->delete($id);
259+
Alert::success('Successfully deleted the requested node from the panel.')->flash();
260+
return redirect()->route('admin.nodes');
261+
} catch (DisplayException $e) {
262+
Alert::danger($e->getMessage())->flash();
263+
} catch (\Exception $e) {
264+
Log::error($e);
265+
Alert::danger('An unhandled exception occured while attempting to delete this node. Please try again.')->flash();
264266
}
265267

266-
$node->delete();
267-
Alert::success('Node successfully deleted.')->flash();
268-
return redirect()->route('admin.nodes');
269-
268+
return redirect()->route('admin.nodes.view', [
269+
'id' => $id,
270+
'tab' => 'tab_delete'
271+
]);
270272
}
271273

272274
}

app/Http/Controllers/Admin/ServersController.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,23 @@ public function getIndex(Request $request)
6868
$match = str_replace('"', '', $match);
6969
if (strpos($match, ':')) {
7070
list($field, $term) = explode(':', $match);
71-
$field = (strpos($field, '.')) ? $field : 'servers.' . $field;
71+
if ($field === 'node') {
72+
$field = 'nodes.name';
73+
} else if ($field === 'owner') {
74+
$field = 'users.email';
75+
} else if (!strpos($field, '.')) {
76+
$field = 'servers.' . $field;
77+
}
78+
7279
$query->orWhere($field, 'LIKE', '%' . $term . '%');
7380
} else {
7481
$query->where('servers.name', 'LIKE', '%' . $match . '%');
75-
$query->orWhere('servers.username', 'LIKE', '%' . $match . '%');
76-
$query->orWhere('users.email', 'LIKE', '%' . $match . '%');
77-
$query->orWhere('allocations.port', 'LIKE', '%' . $match . '%');
78-
$query->orWhere('allocations.ip', 'LIKE', '%' . $match . '%');
82+
$query->orWhere([
83+
['servers.username', 'LIKE', '%' . $match . '%'],
84+
['users.email', 'LIKE', '%' . $match . '%'],
85+
['allocations.port', 'LIKE', '%' . $match . '%'],
86+
['allocations.ip', 'LIKE', '%' . $match . '%'],
87+
]);
7988
}
8089
}
8190
}

app/Repositories/DatabaseRepository.php

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,12 @@ public function create($server, $options)
5656
}
5757

5858
DB::beginTransaction();
59-
6059
try {
6160
$db = new Models\Database;
6261
$db->fill([
6362
'server_id' => $server->id,
6463
'db_server' => $options['db_server'],
65-
'database' => $server->uuidShort . '_' . $options['database'],
64+
'database' => "s{$server->id}_{$options['database']}",
6665
'username' => $server->uuidShort . '_' . str_random(7),
6766
'remote' => $options['remote'],
6867
'password' => Crypt::encrypt(str_random(20))
@@ -90,16 +89,29 @@ public function create($server, $options)
9089

9190
$capsule->setAsGlobal();
9291

93-
Capsule::statement('CREATE DATABASE ' . $db->database);
94-
Capsule::statement('CREATE USER \'' . $db->username . '\'@\'' . $db->remote . '\' IDENTIFIED BY \'' . Crypt::decrypt($db->password) . '\'');
95-
Capsule::statement('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON ' . $db->database . '.* TO \'' . $db->username . '\'@\'' . $db->remote . '\'');
96-
Capsule::statement('FLUSH PRIVILEGES');
92+
} catch (\Exception $ex) {
93+
DB::rollBack();
94+
throw new DisplayException('There was an error while connecting to the Database Host Server. Please check the error logs.', $ex);
95+
}
9796

97+
try {
98+
Capsule::statement('CREATE DATABASE `' . $db->database . '`');
99+
Capsule::statement('CREATE USER `' . $db->username . '`@`' . $db->remote . '` IDENTIFIED BY \'' . Crypt::decrypt($db->password) . '\'');
100+
Capsule::statement('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `' . $db->database . '`.* TO `' . $db->username . '`@`' . $db->remote . '`');
101+
Capsule::statement('FLUSH PRIVILEGES');
98102
DB::commit();
99-
return true;
100103
} catch (\Exception $ex) {
101-
DB::rollback();
102-
throw $ex;
104+
try {
105+
Capsule::statement('DROP DATABASE `' . $db->database . '`');
106+
Capsule::statement('DROP USER `' . $db->username . '`@`' . $db->remote . '`');
107+
} catch (\Exception $exi) {
108+
// ignore it, if it fails its probably
109+
// because we failed to ever make the DB
110+
// or the user on the system.
111+
} finally {
112+
DB::rollBack();
113+
throw $ex;
114+
}
103115
}
104116
}
105117

@@ -138,7 +150,7 @@ public function modifyPassword($database, $password)
138150

139151
$capsule->setAsGlobal();
140152
Capsule::statement(sprintf(
141-
'SET PASSWORD FOR \'%s\'@\'%s\' = PASSWORD(\'%s\')',
153+
'SET PASSWORD FOR `%s`@`%s` = PASSWORD(\'%s\')',
142154
$db->username,
143155
$db->remote,
144156
$password
@@ -182,8 +194,8 @@ public function drop($database)
182194

183195
$capsule->setAsGlobal();
184196

185-
Capsule::statement('DROP USER \'' . $db->username . '\'@\'' . $db->remote . '\'');
186-
Capsule::statement('DROP DATABASE ' . $db->database);
197+
Capsule::statement('DROP USER `' . $db->username . '`@`' . $db->remote . '`');
198+
Capsule::statement('DROP DATABASE `' . $db->database . '`');
187199

188200
$db->delete();
189201

@@ -219,6 +231,11 @@ public function delete($server)
219231
*/
220232
public function add(array $data)
221233
{
234+
235+
if (isset($data['host'])) {
236+
$data['host'] = gethostbyname($data['host']);
237+
}
238+
222239
$validator = Validator::make($data, [
223240
'name' => 'required|string|max:255',
224241
'host' => 'required|ip|unique:database_servers,host',

app/Repositories/NodeRepository.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,30 @@ public function addAllocations($id, array $allocations)
229229

230230
public function delete($id)
231231
{
232-
// @TODO: add logic;
233-
return true;
232+
$node = Models\Node::findOrFail($id);
233+
if (Models\Server::where('node', $id)->count() > 0) {
234+
throw new DisplayException('You cannot delete a node with servers currently attached to it.');
235+
}
236+
237+
DB::beginTransaction();
238+
239+
try {
240+
// Unlink Database Servers
241+
Models\DatabaseServer::where('linked_node', $node->id)->update([
242+
'linked_node' => null,
243+
]);
244+
245+
// Delete Allocations
246+
Models\Allocation::where('node', $node->id)->delete();
247+
248+
// Delete Node
249+
$node->delete();
250+
251+
DB::commit();
252+
} catch (\Exception $ex) {
253+
DB::rollback();
254+
throw $ex;
255+
}
234256
}
235257

236258
}

app/Services/VersionService.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Services;
25+
26+
use Cache;
27+
use GuzzleHttp\Client;
28+
29+
class VersionService
30+
{
31+
32+
protected static $versions;
33+
34+
/**
35+
* Constructor
36+
*/
37+
public function __construct()
38+
{
39+
self::$versions = Cache::remember('versions', env('VERSION_CACHE_TIME', 60), function () {
40+
$client = new Client();
41+
42+
try {
43+
$response = $client->request('GET', env('VERSION_CHECK_URL', 'https://cdn.pterodactyl.io/releases/latest.json'));
44+
45+
if ($response->getStatusCode() === 200) {
46+
return json_decode($response->getBody());
47+
} else {
48+
throw new \Exception('Invalid response code.');
49+
}
50+
} catch (\Exception $ex) {
51+
// Failed request, just return errored version.
52+
return (object) [
53+
'panel' => 'error',
54+
'daemon' => 'error',
55+
];
56+
}
57+
});
58+
}
59+
60+
public static function getPanel()
61+
{
62+
return self::$versions->panel;
63+
}
64+
65+
public static function getDaemon()
66+
{
67+
return self::$versions->daemon;
68+
}
69+
70+
public function getCurrentPanel()
71+
{
72+
return config('app.version');
73+
}
74+
75+
public static function isLatestPanel()
76+
{
77+
if (config('app.version') === 'canary') {
78+
return true;
79+
}
80+
81+
return (version_compare(config('app.version'), self::$versions->panel) >= 0);
82+
}
83+
84+
public static function isLatestDaemon($daemon)
85+
{
86+
if ($daemon === '0.0.0-canary') {
87+
return true;
88+
}
89+
90+
return (version_compare($daemon, self::$versions->daemon) >= 0);
91+
}
92+
93+
}

config/app.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@
217217
'URL' => Illuminate\Support\Facades\URL::class,
218218
'Uuid' => Webpatser\Uuid\Uuid::class,
219219
'Validator' => Illuminate\Support\Facades\Validator::class,
220+
'Version' => Pterodactyl\Facades\Version::class,
220221
'View' => Illuminate\Support\Facades\View::class,
221222

222223
],

public/js/admin.min.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,24 @@ $(document).ready(function () {
4646
centerModal($(this));
4747
});
4848
$(window).on('resize', centerModal);
49+
50+
// Idea code for multiplicators submitted by @Taronyuu on Github
51+
// https://github.com/Pterodactyl/Panel/issues/154#issuecomment-257116078
52+
$('input[data-multiplicator="true"]').on('change', function () {
53+
var value = $(this).val();
54+
if (!/^\d+$/.test(value)) {
55+
var multiplicator = value.replace(/[0-9]/g, '').toLowerCase();
56+
value = value.replace(/\D/g, '');
57+
58+
if (multiplicator === 't') {
59+
value = value * (1024 * 1024);
60+
}
61+
62+
if (multiplicator === 'g') {
63+
value = value * 1024;
64+
}
65+
}
66+
67+
$(this).val(value);
68+
});
4969
});

0 commit comments

Comments
 (0)