' . $secret . '
')->flash();
+ $secret = $repo->create($request->only([
+ 'memo', 'allowed_ips',
+ 'adminPermissions', 'permissions',
+ ]));
+ Alert::success('An API Key-Pair has successfully been generated. The API secret for this public key is shown below and will not be shown again.' . $secret . '
')->flash();
return redirect()->route('account.api');
} catch (DisplayValidationException $ex) {
diff --git a/app/Http/Controllers/Base/IndexController.php b/app/Http/Controllers/Base/IndexController.php
index 160bc67e6..6b0bd273e 100644
--- a/app/Http/Controllers/Base/IndexController.php
+++ b/app/Http/Controllers/Base/IndexController.php
@@ -26,7 +26,6 @@
namespace Pterodactyl\Http\Controllers\Base;
use Illuminate\Http\Request;
-use Pterodactyl\Models\Server;
use Pterodactyl\Http\Controllers\Controller;
class IndexController extends Controller
@@ -48,7 +47,7 @@ class IndexController extends Controller
public function getIndex(Request $request)
{
return view('base.index', [
- 'servers' => Server::getUserServers(10),
+ 'servers' => $request->user()->serverAccessCollection(10)->load('node', 'allocation'),
]);
}
diff --git a/app/Http/Controllers/Base/SecurityController.php b/app/Http/Controllers/Base/SecurityController.php
index cf8bf2dc1..23b6f0d68 100644
--- a/app/Http/Controllers/Base/SecurityController.php
+++ b/app/Http/Controllers/Base/SecurityController.php
@@ -118,8 +118,7 @@ class SecurityController extends Controller
public function revoke(Request $request, $id)
{
- $session = Session::where('id', $id)->where('user_id', $request->user()->id)->firstOrFail();
- $session->delete();
+ Session::where('user_id', $request->user()->id)->findOrFail($id)->delete();
return redirect()->route('account.security');
}
diff --git a/app/Http/Controllers/Remote/RemoteController.php b/app/Http/Controllers/Remote/RemoteController.php
index b0aa0983e..95ff6ab3e 100644
--- a/app/Http/Controllers/Remote/RemoteController.php
+++ b/app/Http/Controllers/Remote/RemoteController.php
@@ -28,7 +28,6 @@ use Carbon\Carbon;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
-use Pterodactyl\Services\NotificationService;
class RemoteController extends Controller
{
@@ -42,7 +41,7 @@ class RemoteController extends Controller
public function postDownload(Request $request)
{
- $download = Models\Download::where('token', $request->input('token', '00'))->first();
+ $download = Models\Download::where('token', $request->input('token'))->first();
if (! $download) {
return response()->json([
'error' => 'An invalid request token was recieved with this request.',
@@ -59,18 +58,17 @@ class RemoteController extends Controller
public function postInstall(Request $request)
{
- $server = Models\Server::where('uuid', $request->input('server'))->first();
+ $server = Models\Server::where('uuid', $request->input('server'))->with('node')->first();
if (! $server) {
return response()->json([
'error' => 'No server by that ID was found on the system.',
], 422);
}
- $node = Models\Node::findOrFail($server->node);
$hmac = $request->input('signed');
$status = $request->input('installed');
- if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
+ if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $server->node->daemonSecret, true)) {
return response()->json([
'error' => 'Signed HMAC was invalid.',
], 403);
@@ -86,17 +84,15 @@ class RemoteController extends Controller
public function event(Request $request)
{
- $server = Models\Server::where('uuid', $request->input('server'))->first();
+ $server = Models\Server::where('uuid', $request->input('server'))->with('node')->first();
if (! $server) {
return response()->json([
'error' => 'No server by that ID was found on the system.',
], 422);
}
- $node = Models\Node::findOrFail($server->node);
-
$hmac = $request->input('signed');
- if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
+ if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $server->node->daemonSecret, true)) {
return response()->json([
'error' => 'Signed HMAC was invalid.',
], 403);
@@ -130,7 +126,6 @@ class RemoteController extends Controller
$token->delete();
// Manually as getConfigurationAsJson() returns it in correct format already
- return response($node->getConfigurationAsJson(), 200)
- ->header('Content-Type', 'application/json');
+ return response()->json($node->getConfigurationAsJson(), 200);
}
}
diff --git a/app/Http/Controllers/Server/AjaxController.php b/app/Http/Controllers/Server/AjaxController.php
index da4d058ac..9493bc0f0 100644
--- a/app/Http/Controllers/Server/AjaxController.php
+++ b/app/Http/Controllers/Server/AjaxController.php
@@ -67,18 +67,14 @@ class AjaxController extends Controller
*/
public function getStatus(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
if (! $server) {
return response()->json([], 404);
}
- $client = Models\Node::guzzleRequest($server->node);
-
try {
- $res = $client->request('GET', '/server', [
- 'headers' => Models\Server::getGuzzleHeaders($uuid),
- ]);
+ $res = $server->guzzleClient()->request('GET', '/server');
if ($res->getStatusCode() === 200) {
return response()->json(json_decode($res->getBody()));
}
@@ -98,10 +94,10 @@ class AjaxController extends Controller
*/
public function postDirectoryList(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
- $this->directory = '/' . trim(urldecode($request->input('directory', '/')), '/');
+ $server = Models\Server::byUuid($uuid);
$this->authorize('list-files', $server);
+ $this->directory = '/' . trim(urldecode($request->input('directory', '/')), '/');
$prevDir = [
'header' => ($this->directory !== '/') ? $this->directory : '',
];
@@ -149,7 +145,7 @@ class AjaxController extends Controller
*/
public function postSaveFile(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('save-files', $server);
$controller = new Repositories\Daemon\FileRepository($uuid);
@@ -175,17 +171,17 @@ class AjaxController extends Controller
*/
public function postSetPrimary(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('allocations');
$this->authorize('set-connection', $server);
- if ((int) $request->input('allocation') === $server->allocation) {
+ if ((int) $request->input('allocation') === $server->allocation_id) {
return response()->json([
'error' => 'You are already using this as your default connection.',
], 409);
}
try {
- $allocation = Models\Allocation::where('id', $request->input('allocation'))->where('assigned_to', $server->id)->first();
+ $allocation = $server->allocations->where('id', $request->input('allocation'))->where('assigned_to', $server->id)->first();
if (! $allocation) {
return response()->json([
'error' => 'No allocation matching your request was found in the system.',
@@ -217,10 +213,10 @@ class AjaxController extends Controller
public function postResetDatabasePassword(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
- $database = Models\Database::where('id', $request->input('database'))->where('server_id', $server->id)->firstOrFail();
-
+ $server = Models\Server::byUuid($uuid);
$this->authorize('reset-db-password', $server);
+
+ $database = Models\Database::where('id', $request->input('database'))->where('server_id', $server->id)->firstOrFail();
try {
$repo = new Repositories\DatabaseRepository;
$password = str_random(16);
diff --git a/app/Http/Controllers/Server/ServerController.php b/app/Http/Controllers/Server/ServerController.php
index 593049ca1..2e09c8672 100644
--- a/app/Http/Controllers/Server/ServerController.php
+++ b/app/Http/Controllers/Server/ServerController.php
@@ -28,7 +28,6 @@ use DB;
use Log;
use Uuid;
use Alert;
-use Javascript;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
@@ -55,14 +54,11 @@ class ServerController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
- public function getIndex(Request $request)
+ public function getIndex(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($request->route()->server);
- $node = Models\Node::find($server->node);
+ $server = Models\Server::byUuid($uuid);
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
+ $server->js([
'meta' => [
'saveFile' => route('server.files.save', $server->uuidShort),
'csrfToken' => csrf_token(),
@@ -71,7 +67,7 @@ class ServerController extends Controller
return view('server.index', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
]);
}
@@ -83,14 +79,10 @@ class ServerController extends Controller
*/
public function getFiles(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('list-files', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only('uuid', 'uuidShort', 'daemonSecret'),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
+ $server->js([
'meta' => [
'directoryList' => route('server.files.directory-list', $server->uuidShort),
'csrftoken' => csrf_token(),
@@ -108,7 +100,7 @@ class ServerController extends Controller
return view('server.files.index', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
]);
}
@@ -120,18 +112,14 @@ class ServerController extends Controller
*/
public function getAddFile(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('add-files', $server);
- $node = Models\Node::find($server->node);
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.files.add', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
'directory' => (in_array($request->get('dir'), [null, '/', ''])) ? '' : trim($request->get('dir'), '/') . '/',
]);
}
@@ -146,9 +134,8 @@ class ServerController extends Controller
*/
public function getEditFile(Request $request, $uuid, $file)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('edit-files', $server);
- $node = Models\Node::find($server->node);
$fileInfo = (object) pathinfo($file);
$controller = new FileRepository($uuid);
@@ -166,15 +153,13 @@ class ServerController extends Controller
return redirect()->route('server.files.index', $uuid);
}
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
+ $server->js([
'stat' => $fileContent['stat'],
]);
return view('server.files.edit', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
'file' => $file,
'stat' => $fileContent['stat'],
'contents' => $fileContent['file']->content,
@@ -192,9 +177,7 @@ class ServerController extends Controller
*/
public function getDownloadFile(Request $request, $uuid, $file)
{
- $server = Models\Server::getByUUID($uuid);
- $node = Models\Node::find($server->node);
-
+ $server = Models\Server::byUuid($uuid);
$this->authorize('download-files', $server);
$download = new Models\Download;
@@ -205,69 +188,65 @@ class ServerController extends Controller
$download->save();
- return redirect($node->scheme . '://' . $node->fqdn . ':' . $node->daemonListen . '/server/file/download/' . $download->token);
+ return redirect($server->node->scheme . '://' . $server->node->fqdn . ':' . $server->node->daemonListen . '/server/file/download/' . $download->token);
}
public function getAllocation(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('view-allocation', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.settings.allocation', [
- 'server' => $server,
- 'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
- 'node' => $node,
+ 'server' => $server->load(['allocations' => function ($query) {
+ $query->orderBy('ip', 'asc');
+ $query->orderBy('port', 'asc');
+ }]),
+ 'node' => $server->node,
]);
}
public function getStartup(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
+ $server->load(['allocations' => function ($query) use ($server) {
+ $query->where('id', $server->allocation_id);
+ }]);
$this->authorize('view-startup', $server);
- $node = Models\Node::find($server->node);
- $allocation = Models\Allocation::findOrFail($server->allocation);
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
-
- $variables = Models\ServiceVariables::select(
+ $variables = Models\ServiceVariable::select(
'service_variables.*',
DB::raw('COALESCE(server_variables.variable_value, service_variables.default_value) as a_serverValue')
)->leftJoin('server_variables', 'server_variables.variable_id', '=', 'service_variables.id')
- ->where('service_variables.option_id', $server->option)
+ ->where('service_variables.option_id', $server->option_id)
->where('server_variables.server_id', $server->id)
->get();
$service = Models\Service::select(
DB::raw('IFNULL(service_options.executable, services.executable) as executable')
- )->leftJoin('service_options', 'service_options.parent_service', '=', 'services.id')
- ->where('service_options.id', $server->option)
- ->where('services.id', $server->service)
+ )->leftJoin('service_options', 'service_options.service_id', '=', 'services.id')
+ ->where('service_options.id', $server->option_id)
+ ->where('services.id', $server->service_id)
->first();
- $serverVariables = [
+ $allocation = $server->allocations->pop();
+ $ServerVariable = [
'{{SERVER_MEMORY}}' => $server->memory,
'{{SERVER_IP}}' => $allocation->ip,
'{{SERVER_PORT}}' => $allocation->port,
];
- $processed = str_replace(array_keys($serverVariables), array_values($serverVariables), $server->startup);
+ $processed = str_replace(array_keys($ServerVariable), array_values($ServerVariable), $server->startup);
foreach ($variables as &$variable) {
- $replace = ($variable->user_viewable === 1) ? $variable->a_serverValue : '**';
+ $replace = ($variable->user_viewable === 1) ? $variable->a_serverValue : '[hidden]';
$processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed);
}
+ $server->js();
+
return view('server.settings.startup', [
'server' => $server,
- 'node' => Models\Node::find($server->node),
+ 'node' => $server->node,
'variables' => $variables->where('user_viewable', 1),
'service' => $service,
'processedStartup' => $processed,
@@ -276,18 +255,13 @@ class ServerController extends Controller
public function getDatabases(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('view-databases', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.settings.databases', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
->where('server_id', $server->id)
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
@@ -297,24 +271,19 @@ class ServerController extends Controller
public function getSFTP(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('view-sftp', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.settings.sftp', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
]);
}
public function postSettingsSFTP(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('reset-sftp', $server);
try {
@@ -335,7 +304,7 @@ class ServerController extends Controller
public function postSettingsStartup(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('edit-startup', $server);
try {
diff --git a/app/Http/Controllers/Server/SubuserController.php b/app/Http/Controllers/Server/SubuserController.php
index a8761c717..a3ae8e3ba 100644
--- a/app/Http/Controllers/Server/SubuserController.php
+++ b/app/Http/Controllers/Server/SubuserController.php
@@ -24,11 +24,9 @@
namespace Pterodactyl\Http\Controllers\Server;
-use DB;
use Log;
use Auth;
use Alert;
-use Javascript;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
@@ -50,73 +48,47 @@ class SubuserController extends Controller
public function getIndex(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('subusers.user');
$this->authorize('list-subusers', $server);
- $node = Models\Node::find($server->node);
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.users.index', [
'server' => $server,
- 'node' => $node,
- 'subusers' => Models\Subuser::select('subusers.*', 'users.email', 'users.username', 'users.use_totp')
- ->join('users', 'users.id', '=', 'subusers.user_id')
- ->where('server_id', $server->id)
- ->get(),
+ 'node' => $server->node,
+ 'subusers' => $server->subusers,
]);
}
public function getView(Request $request, $uuid, $id)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('node');
$this->authorize('view-subuser', $server);
- $node = Models\Node::find($server->node);
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $subuser = Models\Subuser::with('permissions', 'user')
+ ->where('server_id', $server->id)->findOrFail($id);
- $subuser = Models\Subuser::select('subusers.*', 'users.email as a_userEmail')
- ->join('users', 'users.id', '=', 'subusers.user_id')
- ->where(DB::raw('md5(subusers.id)'), $id)->where('subusers.server_id', $server->id)
- ->first();
-
- if (! $subuser) {
- abort(404);
- }
-
- $permissions = [];
- $modelPermissions = Models\Permission::select('permission')
- ->where('user_id', $subuser->user_id)->where('server_id', $server->id)
- ->get();
-
- foreach ($modelPermissions as &$perm) {
- $permissions[$perm->permission] = true;
- }
+ $server->js();
return view('server.users.view', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
'subuser' => $subuser,
- 'permissions' => $permissions,
+ 'permissions' => $subuser->permissions->mapWithKeys(function ($item, $key) {
+ return [$item->permission => true];
+ }),
]);
}
public function postView(Request $request, $uuid, $id)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('edit-subuser', $server);
- $subuser = Models\Subuser::where(DB::raw('md5(id)'), $id)->where('server_id', $server->id)->first();
+ $subuser = Models\Subuser::where('server_id', $server->id)->findOrFail($id);
try {
- if (! $subuser) {
- throw new DisplayException('Unable to locate a subuser by that ID.');
- } elseif ($subuser->user_id === Auth::user()->id) {
+ if ($subuser->user_id === Auth::user()->id) {
throw new DisplayException('You are not authorized to edit you own account.');
}
@@ -148,36 +120,31 @@ class SubuserController extends Controller
public function getNew(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('create-subuser', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.users.new', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
]);
}
public function postNew(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('create-subuser', $server);
try {
$repo = new SubuserRepository;
- $id = $repo->create($server->id, $request->except([
- '_token',
+ $subuser = $repo->create($server->id, $request->only([
+ 'permissions', 'email',
]));
Alert::success('Successfully created new subuser.')->flash();
return redirect()->route('server.subusers.view', [
'uuid' => $uuid,
- 'id' => md5($id),
+ 'id' => $subuser->id,
]);
} catch (DisplayValidationException $ex) {
return redirect()->route('server.subusers.new', $uuid)->withErrors(json_decode($ex->getMessage()))->withInput();
@@ -193,14 +160,11 @@ class SubuserController extends Controller
public function deleteSubuser(Request $request, $uuid, $id)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('delete-subuser', $server);
try {
- $subuser = Models\Subuser::select('id')->where(DB::raw('md5(id)'), $id)->where('server_id', $server->id)->first();
- if (! $subuser) {
- throw new DisplayException('No subuser by that ID was found on the system.');
- }
+ $subuser = Models\Subuser::where('server_id', $server->id)->findOrFail($id);
$repo = new SubuserRepository;
$repo->delete($subuser->id);
diff --git a/app/Http/Controllers/Server/TaskController.php b/app/Http/Controllers/Server/TaskController.php
index 8c49ad6bc..643e70a45 100644
--- a/app/Http/Controllers/Server/TaskController.php
+++ b/app/Http/Controllers/Server/TaskController.php
@@ -26,7 +26,6 @@ namespace Pterodactyl\Http\Controllers\Server;
use Log;
use Alert;
-use Javascript;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Repositories;
@@ -43,19 +42,14 @@ class TaskController extends Controller
public function getIndex(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('tasks');
$this->authorize('list-tasks', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.tasks.index', [
'server' => $server,
- 'node' => $node,
- 'tasks' => Models\Task::where('server', $server->id)->get(),
+ 'node' => $server->node,
+ 'tasks' => $server->tasks,
'actions' => [
'command' => trans('server.tasks.actions.command'),
'power' => trans('server.tasks.actions.power'),
@@ -65,24 +59,19 @@ class TaskController extends Controller
public function getNew(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('create-task', $server);
- $node = Models\Node::find($server->node);
-
- Javascript::put([
- 'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
- 'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
- ]);
+ $server->js();
return view('server.tasks.new', [
'server' => $server,
- 'node' => $node,
+ 'node' => $server->node,
]);
}
public function postNew(Request $request, $uuid)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid);
$this->authorize('create-task', $server);
try {
@@ -106,12 +95,11 @@ class TaskController extends Controller
public function deleteTask(Request $request, $uuid, $id)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('tasks');
$this->authorize('delete-task', $server);
- $task = Models\Task::findOrFail($id);
-
- if (! $task || $server->id !== $task->server) {
+ $task = $server->tasks->where('id', $id)->first();
+ if (! $task) {
return response()->json([
'error' => 'No task by that ID was found associated with this server.',
], 404);
@@ -133,12 +121,11 @@ class TaskController extends Controller
public function toggleTask(Request $request, $uuid, $id)
{
- $server = Models\Server::getByUUID($uuid);
+ $server = Models\Server::byUuid($uuid)->load('tasks');
$this->authorize('toggle-task', $server);
- $task = Models\Task::findOrFail($id);
-
- if (! $task || $server->id !== $task->server) {
+ $task = $server->tasks->where('id', $id)->first();
+ if (! $task) {
return response()->json([
'error' => 'No task by that ID was found associated with this server.',
], 404);
diff --git a/app/Http/Middleware/APISecretToken.php b/app/Http/Middleware/APISecretToken.php
index a1c203c9d..25bf891ba 100755
--- a/app/Http/Middleware/APISecretToken.php
+++ b/app/Http/Middleware/APISecretToken.php
@@ -121,7 +121,7 @@ class APISecretToken extends Authorization
// Log the Route Access
APILogService::log($request, null, true);
- return Auth::loginUsingId($key->user);
+ return Auth::loginUsingId($key->user_id);
}
protected function _generateHMAC($body, $key)
diff --git a/app/Http/Middleware/CheckServer.php b/app/Http/Middleware/CheckServer.php
index cd83bd9d1..dba9395ac 100644
--- a/app/Http/Middleware/CheckServer.php
+++ b/app/Http/Middleware/CheckServer.php
@@ -26,6 +26,7 @@ namespace Pterodactyl\Http\Middleware;
use Auth;
use Closure;
+use Illuminate\Http\Request;
use Pterodactyl\Models\Server;
class CheckServer
@@ -37,22 +38,22 @@ class CheckServer
* @param \Closure $next
* @return mixed
*/
- public function handle($request, Closure $next)
+ public function handle(Request $request, Closure $next)
{
if (! Auth::user()) {
return redirect()->guest('auth/login');
}
- $server = Server::getByUUID($request->route()->server);
+ $server = Server::byUuid($request->route()->server);
if (! $server) {
return response()->view('errors.404', [], 404);
}
- if ($server->suspended === 1) {
+ if ($server->suspended) {
return response()->view('errors.suspended', [], 403);
}
- if ($server->installed !== 1) {
+ if (! $server->installed) {
return response()->view('errors.installing', [], 403);
}
diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php
index e3a81cb66..127055daa 100644
--- a/app/Http/Routes/AdminRoutes.php
+++ b/app/Http/Routes/AdminRoutes.php
@@ -144,7 +144,7 @@ class AdminRoutes
]);
$router->post('/new/service-options', [
- 'uses' => 'Admin\ServersController@postNewServerServiceOptions',
+ 'uses' => 'Admin\ServersController@postNewServerServiceOption',
]);
$router->post('/new/option-details', [
diff --git a/app/Models/APIKey.php b/app/Models/APIKey.php
index 4b94b6782..68e481712 100644
--- a/app/Models/APIKey.php
+++ b/app/Models/APIKey.php
@@ -48,4 +48,14 @@ class APIKey extends Model
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
+
+ /**
+ * Gets the permissions associated with a key.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function permissions()
+ {
+ return $this->hasMany(APIPermission::class, 'key_id');
+ }
}
diff --git a/app/Models/Allocation.php b/app/Models/Allocation.php
index 10308ebdd..aad98ac63 100644
--- a/app/Models/Allocation.php
+++ b/app/Models/Allocation.php
@@ -48,8 +48,30 @@ class Allocation extends Model
* @var array
*/
protected $casts = [
- 'node' => 'integer',
+ 'node_id' => 'integer',
'port' => 'integer',
- 'assigned_to' => 'integer',
+ 'server_id' => 'integer',
];
+
+ /**
+ * Accessor to automatically provide the IP alias if defined.
+ *
+ * @param null|string $value
+ * @return string
+ */
+ public function getAliasAttribute($value)
+ {
+ return (is_null($this->ip_alias)) ? $this->ip : $this->ip_alias;
+ }
+
+ /**
+ * Accessor to quickly determine if this allocation has an alias.
+ *
+ * @param null|string $value
+ * @return bool
+ */
+ public function getHasAliasAttribute($value)
+ {
+ return ! is_null($this->ip_alias);
+ }
}
diff --git a/app/Models/Database.php b/app/Models/Database.php
index 99e768c29..b5e9d39ad 100644
--- a/app/Models/Database.php
+++ b/app/Models/Database.php
@@ -55,7 +55,27 @@ class Database extends Model
* @var array
*/
protected $casts = [
- 'server' => 'integer',
+ 'server_id' => 'integer',
'db_server' => 'integer',
];
+
+ /**
+ * Gets the host database server associated with a database.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function host()
+ {
+ return $this->belongsTo(DatabaseServer::class, 'db_server');
+ }
+
+ /**
+ * Gets the server associated with a database.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function server()
+ {
+ return $this->belongsTo(Server::class);
+ }
}
diff --git a/app/Models/DatabaseServer.php b/app/Models/DatabaseServer.php
index 74fd88694..1ebb7546f 100644
--- a/app/Models/DatabaseServer.php
+++ b/app/Models/DatabaseServer.php
@@ -59,4 +59,24 @@ class DatabaseServer extends Model
'server_id' => 'integer',
'db_server' => 'integer',
];
+
+ /**
+ * Gets the node associated with a database host.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function node()
+ {
+ return $this->belongsTo(Node::class, 'linked_node');
+ }
+
+ /**
+ * Gets the databases assocaited with this host.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function databases()
+ {
+ return $this->hasMany(Database::class, 'db_server');
+ }
}
diff --git a/app/Models/Location.php b/app/Models/Location.php
index 5c8feb9fa..f9ceec767 100644
--- a/app/Models/Location.php
+++ b/app/Models/Location.php
@@ -41,4 +41,24 @@ class Location extends Model
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
+
+ /**
+ * Gets the nodes in a specificed location.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function nodes()
+ {
+ return $this->hasMany(Node::class);
+ }
+
+ /**
+ * Gets the servers within a given location.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
+ */
+ public function servers()
+ {
+ return $this->hasManyThrough(Server::class, Node::class);
+ }
}
diff --git a/app/Models/Node.php b/app/Models/Node.php
index a5cbce464..78e0828f7 100644
--- a/app/Models/Node.php
+++ b/app/Models/Node.php
@@ -53,7 +53,7 @@ class Node extends Model
*/
protected $casts = [
'public' => 'integer',
- 'location' => 'integer',
+ 'location_id' => 'integer',
'memory' => 'integer',
'disk' => 'integer',
'daemonListen' => 'integer',
@@ -61,11 +61,18 @@ class Node extends Model
];
/**
- * Fields that are not mass assignable.
+ * Fields that are mass assignable.
*
* @var array
*/
- protected $guarded = ['id', 'created_at', 'updated_at'];
+ protected $fillable = [
+ 'public', 'name', 'location_id',
+ 'fqdn', 'scheme', 'memory',
+ 'memory_overallocate', 'disk',
+ 'disk_overallocate', 'upload_size',
+ 'daemonSecret', 'daemonBase',
+ 'daemonSFTP', 'daemonListen',
+ ];
/**
* @var array
@@ -96,11 +103,28 @@ class Node extends Model
return self::$nodes[$id];
}
+ /**
+ * Return an instance of the Guzzle client for this specific node.
+ *
+ * @param array $headers
+ * @return \GuzzleHttp\Client
+ */
+ public function guzzleClient($headers = [])
+ {
+ return new Client([
+ 'base_uri' => sprintf('%s://%s:%s/', $this->scheme, $this->fqdn, $this->daemonListen),
+ 'timeout' => env('GUZZLE_TIMEOUT', 5.0),
+ 'connect_timeout' => env('GUZZLE_CONNECT_TIMEOUT', 3.0),
+ 'headers' => $headers,
+ ]);
+ }
+
/**
* Returns a Guzzle Client for the node in question.
*
* @param int $node
* @return \GuzzleHttp\Client
+ * @deprecated
*/
public static function guzzleRequest($node)
{
@@ -177,4 +201,34 @@ class Node extends Model
return json_encode($config, $json_options);
}
+
+ /**
+ * Gets the location associated with a node.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function location()
+ {
+ return $this->belongsTo(Location::class);
+ }
+
+ /**
+ * 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);
+ }
}
diff --git a/app/Models/Permission.php b/app/Models/Permission.php
index 008473f3c..7dfd55f3f 100644
--- a/app/Models/Permission.php
+++ b/app/Models/Permission.php
@@ -28,6 +28,13 @@ use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
+ /**
+ * Should timestamps be used on this model.
+ *
+ * @var bool
+ */
+ public $timestamps = false;
+
/**
* The table associated with the model.
*
@@ -42,22 +49,35 @@ class Permission extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
- /**
- * Cast values to correct type.
- *
- * @var array
- */
- protected $casts = [
- 'user_id' => 'integer',
- 'server_id' => 'integer',
- ];
+ /**
+ * Cast values to correct type.
+ *
+ * @var array
+ */
+ protected $casts = [
+ 'subuser_id' => 'integer',
+ ];
+ /**
+ * Find permission by permission node.
+ *
+ * @param \Illuminate\Database\Query\Builder $query
+ * @param string $permission
+ * @return \Illuminate\Database\Query\Builder
+ */
public function scopePermission($query, $permission)
{
return $query->where('permission', $permission);
}
- public function scopeServer($query, $server)
+ /**
+ * Filter permission by server.
+ *
+ * @param \Illuminate\Database\Query\Builder $query
+ * @param \Pterodactyl\Models\Server $server
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeServer($query, Server $server)
{
return $query->where('server_id', $server->id);
}
diff --git a/app/Models/Server.php b/app/Models/Server.php
index a9f9bd087..5dd5bb357 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -25,6 +25,7 @@
namespace Pterodactyl\Models;
use Auth;
+use Javascript;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -67,18 +68,19 @@ class Server extends Model
* @var array
*/
protected $casts = [
- 'node' => 'integer',
+ 'node_id' => 'integer',
'suspended' => 'integer',
- 'owner' => 'integer',
+ 'owner_id' => 'integer',
'memory' => 'integer',
'swap' => 'integer',
'disk' => 'integer',
'io' => 'integer',
'cpu' => 'integer',
'oom_disabled' => 'integer',
- 'port' => 'integer',
- 'service' => 'integer',
- 'option' => 'integer',
+ 'allocation_id' => 'integer',
+ 'service_id' => 'integer',
+ 'option_id' => 'integer',
+ 'pack_id' => 'integer',
'installed' => 'integer',
];
@@ -101,62 +103,6 @@ class Server extends Model
self::$user = Auth::user();
}
- /**
- * Determine if we need to change the server's daemonSecret value to
- * match that of the user if they are a subuser.
- *
- * @param Illuminate\Database\Eloquent\Model\Server $server
- * @return string
- */
- public static function getUserDaemonSecret(Server $server)
- {
- if (self::$user->id === $server->owner || self::$user->root_admin === 1) {
- return $server->daemonSecret;
- }
-
- $subuser = Subuser::where('server_id', $server->id)->where('user_id', self::$user->id)->first();
-
- if (is_null($subuser)) {
- return null;
- }
-
- return $subuser->daemonSecret;
- }
-
- /**
- * Returns array of all servers owned by the logged in user.
- * Returns all users servers if user is a root admin.
- *
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public static function getUserServers($paginate = null)
- {
- $query = self::select(
- 'servers.*',
- 'nodes.name as nodeName',
- 'locations.short as a_locationShort',
- 'allocations.ip',
- 'allocations.ip_alias',
- 'allocations.port',
- 'services.name as a_serviceName',
- 'service_options.name as a_serviceOptionName'
- )->join('nodes', 'servers.node', '=', 'nodes.id')
- ->join('locations', 'nodes.location', '=', 'locations.id')
- ->join('services', 'servers.service', '=', 'services.id')
- ->join('service_options', 'servers.option', '=', 'service_options.id')
- ->join('allocations', 'servers.allocation', '=', 'allocations.id');
-
- if (self::$user->root_admin !== 1) {
- $query->whereIn('servers.id', Subuser::accessServers());
- }
-
- if (is_numeric($paginate)) {
- return $query->paginate($paginate);
- }
-
- return $query->get();
- }
-
/**
* Returns a single server specified by UUID.
* DO NOT USE THIS TO MODIFY SERVER DETAILS OR SAVE THOSE DETAILS.
@@ -165,30 +111,23 @@ class Server extends Model
* @param string $uuid The Short-UUID of the server to return an object about.
* @return \Illuminate\Database\Eloquent\Collection
*/
- public static function getByUUID($uuid)
+ public static function byUuid($uuid)
{
- if (array_key_exists($uuid, self::$serverUUIDInstance)) {
- return self::$serverUUIDInstance[$uuid];
- }
+ $query = self::with('service', 'node')->where(function ($q) use ($uuid) {
+ $q->where('uuidShort', $uuid)->orWhere('uuid', $uuid);
+ });
- $query = self::select('servers.*', 'services.file as a_serviceFile')
- ->join('services', 'services.id', '=', 'servers.service')
- ->where('uuidShort', $uuid)
- ->orWhere('uuid', $uuid);
-
- if (self::$user->root_admin !== 1) {
- $query->whereIn('servers.id', Subuser::accessServers());
+ if (! Auth::user()->isRootAdmin()) {
+ $query->whereIn('id', Auth::user()->serverAccessArray());
}
$result = $query->first();
if (! is_null($result)) {
- $result->daemonSecret = self::getUserDaemonSecret($result);
+ $result->daemonSecret = Auth::user()->daemonToken($result);
}
- self::$serverUUIDInstance[$uuid] = $result;
-
- return self::$serverUUIDInstance[$uuid];
+ return $result;
}
/**
@@ -197,16 +136,84 @@ class Server extends Model
* @param string $uuid
* @return array
*/
- public static function getGuzzleHeaders($uuid)
+ public function guzzleHeaders()
{
- if (array_key_exists($uuid, self::$serverUUIDInstance)) {
- return [
- 'X-Access-Server' => self::$serverUUIDInstance[$uuid]->uuid,
- 'X-Access-Token' => self::$serverUUIDInstance[$uuid]->daemonSecret,
- ];
+ return [
+ 'X-Access-Server' => $this->uuid,
+ 'X-Access-Token' => Auth::user()->daemonToken($this),
+ ];
+ }
+
+ /**
+ * Return an instance of the Guzzle client for this specific server using defined access token.
+ *
+ * @return \GuzzleHttp\Client
+ */
+ public function guzzleClient()
+ {
+ return $this->node->guzzleClient($this->guzzleHeaders());
+ }
+
+ /**
+ * Returns javascript object to be embedded on server view pages with relevant information.
+ *
+ * @return \Laracasts\Utilities\JavaScript\JavaScriptFacade
+ */
+ public function js($additional = null, $overwrite = null)
+ {
+ $response = [
+ 'server' => collect($this->makeVisible('daemonSecret'))->only([
+ 'uuid',
+ 'uuidShort',
+ 'daemonSecret',
+ 'username',
+ ]),
+ 'node' => collect($this->node)->only([
+ 'fqdn',
+ 'scheme',
+ 'daemonListen',
+ ]),
+ ];
+
+ if (is_array($additional)) {
+ $response = array_merge($response, $additional);
}
- return [];
+ if (is_array($overwrite)) {
+ $response = $overwrite;
+ }
+
+ return Javascript::put($response);
+ }
+
+ /**
+ * Gets the user who owns the server.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function user()
+ {
+ return $this->belongsTo(User::class, 'owner_id');
+ }
+
+ /**
+ * Gets the subusers associated with a server.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function subusers()
+ {
+ return $this->hasMany(Subuser::class);
+ }
+
+ /**
+ * Gets the default allocation for a server.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasOne
+ */
+ public function allocation()
+ {
+ return $this->hasOne(Allocation::class, 'id', 'allocation_id');
}
/**
@@ -216,7 +223,7 @@ class Server extends Model
*/
public function allocations()
{
- return $this->hasMany(Allocation::class, 'assigned_to');
+ return $this->hasMany(Allocation::class, 'server_id');
}
/**
@@ -226,27 +233,27 @@ class Server extends Model
*/
public function pack()
{
- return $this->hasOne(ServicePack::class, 'id', 'pack');
+ return $this->hasOne(ServicePack::class, 'id', 'pack_id');
}
/**
* Gets information for the service associated with this server.
*
- * @return \Illuminate\Database\Eloquent\Relations\HasOne
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function service()
{
- return $this->hasOne(Service::class, 'id', 'service');
+ return $this->belongsTo(Service::class);
}
/**
* Gets information for the service option associated with this server.
*
- * @return \Illuminate\Database\Eloquent\Relations\HasOne
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function option()
{
- return $this->hasOne(ServiceOptions::class, 'id', 'option');
+ return $this->belongsTo(ServiceOption::class);
}
/**
@@ -256,6 +263,37 @@ class Server extends Model
*/
public function variables()
{
- return $this->hasMany(ServerVariables::class);
+ return $this->hasMany(ServerVariable::class);
+ }
+
+ /**
+ * Gets information for the node associated with this server.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function node()
+ {
+ return $this->belongsTo(Node::class);
+ }
+
+ /**
+ * Gets information for the tasks associated with this server.
+ *
+ * @TODO adjust server column in tasks to be server_id
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function tasks()
+ {
+ return $this->hasMany(Task::class, 'server', 'id');
+ }
+
+ /**
+ * Gets all databases associated with a server.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function databases()
+ {
+ return $this->hasMany(Database::class);
}
}
diff --git a/app/Models/ServerVariables.php b/app/Models/ServerVariable.php
similarity index 84%
rename from app/Models/ServerVariables.php
rename to app/Models/ServerVariable.php
index c6c6970bc..e92c5caf2 100644
--- a/app/Models/ServerVariables.php
+++ b/app/Models/ServerVariable.php
@@ -26,7 +26,7 @@ namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
-class ServerVariables extends Model
+class ServerVariable extends Model
{
/**
* The table associated with the model.
@@ -51,4 +51,14 @@ class ServerVariables extends Model
'server_id' => 'integer',
'variable_id' => 'integer',
];
+
+ /**
+ * Returns information about a given variables parent.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function variable()
+ {
+ return $this->belongsTo(ServiceVariable::class, 'variable_id');
+ }
}
diff --git a/app/Models/Service.php b/app/Models/Service.php
index 8c0f27790..39e74e5b8 100644
--- a/app/Models/Service.php
+++ b/app/Models/Service.php
@@ -40,5 +40,38 @@ class Service extends Model
*
* @var array
*/
- protected $guarded = ['id', 'created_at', 'updated_at'];
+ protected $fillable = ['id', 'created_at', 'updated_at'];
+
+ /**
+ * Gets all service options associated with this service.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function options()
+ {
+ return $this->hasMany(ServiceOption::class);
+ }
+
+ /**
+ * Returns all of the packs associated with a service, regardless of the service option.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
+ */
+ public function packs()
+ {
+ return $this->hasManyThrough(
+ 'Pterodactyl\Models\ServicePack', 'Pterodactyl\Models\ServiceOption',
+ 'service_id', 'option_id'
+ );
+ }
+
+ /**
+ * Gets all servers associated with this service.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function servers()
+ {
+ return $this->hasMany(Server::class);
+ }
}
diff --git a/app/Models/ServiceOptions.php b/app/Models/ServiceOption.php
similarity index 58%
rename from app/Models/ServiceOptions.php
rename to app/Models/ServiceOption.php
index 9b4a3a7ae..adf646d88 100644
--- a/app/Models/ServiceOptions.php
+++ b/app/Models/ServiceOption.php
@@ -26,7 +26,7 @@ namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
-class ServiceOptions extends Model
+class ServiceOption extends Model
{
/**
* The table associated with the model.
@@ -48,9 +48,51 @@ class ServiceOptions extends Model
* @var array
*/
protected $casts = [
- 'parent_service' => 'integer',
+ 'service_id' => 'integer',
];
+ /**
+ * Returns the display executable for the option and will use the parent
+ * service one if the option does not have one defined.
+ *
+ * @return string
+ */
+ public function getDisplayExecutableAttribute($value)
+ {
+ return (is_null($this->executable)) ? $this->service->executable : $this->executable;
+ }
+
+ /**
+ * Returns the display startup string for the option and will use the parent
+ * service one if the option does not have one defined.
+ *
+ * @return string
+ */
+ public function getDisplayStartupAttribute($value)
+ {
+ return (is_null($this->startup)) ? $this->service->startup : $this->startup;
+ }
+
+ /**
+ * Gets service associated with a service option.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function service()
+ {
+ return $this->belongsTo(Service::class);
+ }
+
+ /**
+ * Gets all servers associated with this service option.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function servers()
+ {
+ return $this->hasMany(Server::class, 'option_id');
+ }
+
/**
* Gets all variables associated with this service.
*
@@ -58,7 +100,7 @@ class ServiceOptions extends Model
*/
public function variables()
{
- return $this->hasMany(ServiceVariables::class, 'option_id');
+ return $this->hasMany(ServiceVariable::class, 'option_id');
}
/**
@@ -68,6 +110,6 @@ class ServiceOptions extends Model
*/
public function packs()
{
- return $this->hasMany(ServicePack::class, 'option');
+ return $this->hasMany(ServicePack::class, 'option_id');
}
}
diff --git a/app/Models/ServicePack.php b/app/Models/ServicePack.php
index cefcc0a32..e82f72411 100644
--- a/app/Models/ServicePack.php
+++ b/app/Models/ServicePack.php
@@ -56,4 +56,14 @@ class ServicePack extends Model
'selectable' => 'boolean',
'visible' => 'boolean',
];
+
+ /**
+ * Gets option associated with a service pack.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function option()
+ {
+ return $this->belongsTo(ServiceOption::class);
+ }
}
diff --git a/app/Models/ServiceVariables.php b/app/Models/ServiceVariable.php
similarity index 92%
rename from app/Models/ServiceVariables.php
rename to app/Models/ServiceVariable.php
index 5082d714e..aedfc6351 100644
--- a/app/Models/ServiceVariables.php
+++ b/app/Models/ServiceVariable.php
@@ -26,7 +26,7 @@ namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
-class ServiceVariables extends Model
+class ServiceVariable extends Model
{
/**
* The table associated with the model.
@@ -53,4 +53,9 @@ class ServiceVariables extends Model
'user_editable' => 'integer',
'required' => 'integer',
];
+
+ public function serverVariable()
+ {
+ return $this->hasMany(ServerVariable::class, 'variable_id');
+ }
}
diff --git a/app/Models/Subuser.php b/app/Models/Subuser.php
index 8d4a5b133..15fc5cbea 100644
--- a/app/Models/Subuser.php
+++ b/app/Models/Subuser.php
@@ -24,7 +24,6 @@
namespace Pterodactyl\Models;
-use Auth;
use Illuminate\Database\Eloquent\Model;
class Subuser extends Model
@@ -50,38 +49,43 @@ class Subuser extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
- /**
- * Cast values to correct type.
- *
- * @var array
- */
- protected $casts = [
- 'user_id' => 'integer',
- 'server_id' => 'integer',
- ];
+ /**
+ * Cast values to correct type.
+ *
+ * @var array
+ */
+ protected $casts = [
+ 'user_id' => 'integer',
+ 'server_id' => 'integer',
+ ];
/**
- * @var mixed
+ * Gets the server associated with a subuser.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
- protected static $user;
-
- /**
- * Constructor.
- */
- public function __construct()
+ public function server()
{
- self::$user = Auth::user();
+ return $this->belongsTo(Server::class);
}
/**
- * Returns an array of each server ID that the user has access to.
+ * Gets the user associated with a subuser.
*
- * @return array
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
- public static function accessServers()
+ public function user()
{
- $union = self::select('server_id')->where('user_id', self::$user->id);
+ return $this->belongsTo(User::class);
+ }
- return Server::select('id')->where('owner', self::$user->id)->union($union)->pluck('id');
+ /**
+ * Gets the permissions associated with a subuser.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function permissions()
+ {
+ return $this->hasMany(Permission::class);
}
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 80d9192fa..abcddf227 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -87,16 +87,6 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
*/
protected $hidden = ['password', 'remember_token', 'totp_secret'];
- /**
- * Determines if a user has permissions.
- *
- * @return bool
- */
- public function permissions()
- {
- return $this->hasMany(Permission::class);
- }
-
/**
* Enables or disables TOTP on an account if the token is valid.
*
@@ -156,4 +146,73 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
{
return $this->root_admin === 1;
}
+
+ /**
+ * Returns the user's daemon secret for a given server.
+ * @param Server $server \Pterodactyl\Models\Server
+ * @return null|string
+ */
+ public function daemonToken(Server $server)
+ {
+ if ($this->id === $server->owner_id || $this->isRootAdmin()) {
+ return $server->daemonSecret;
+ }
+
+ $subuser = Subuser::where('server_id', $server->id)->where('user_id', $this->id)->first();
+
+ if (is_null($subuser)) {
+ return null;
+ }
+
+ return $subuser->daemonSecret;
+ }
+
+ /**
+ * Returns an array of all servers a user is able to access.
+ * Note: does not account for user admin status.
+ *
+ * @return array
+ */
+ public function serverAccessArray()
+ {
+ $union = Subuser::select('server_id')->where('user_id', $this->id);
+
+ return Server::select('id')->where('owner_id', $this->id)->union($union)->pluck('id')->all();
+ }
+
+ /**
+ * Returns an array of all servers a user is able to access.
+ * Note: does not account for user admin status.
+ *
+ * @return Collection
+ */
+ public function serverAccessCollection($paginate = null)
+ {
+ $query = Server::with('service', 'node');
+ if (! $this->isRootAdmin()) {
+ $query->whereIn('id', $this->serverAccessArray());
+ }
+
+ return (is_numeric($paginate)) ? $query->paginate($paginate) : $query->get();
+ }
+
+ /**
+ * Returns all permissions that a user has.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
+ */
+ public function permissions()
+ {
+ return $this->hasManyThrough(Permission::class, Subuser::class);
+ }
+
+ /**
+ * Returns all servers that a user owns.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function servers()
+ {
+ return $this->hasMany(Server::class, 'owner_id');
+ }
}
diff --git a/app/Observers/ServerObserver.php b/app/Observers/ServerObserver.php
index 6506f03f2..e4b00e000 100644
--- a/app/Observers/ServerObserver.php
+++ b/app/Observers/ServerObserver.php
@@ -26,7 +26,6 @@ namespace Pterodactyl\Observers;
use Carbon;
use Pterodactyl\Events;
-use Pterodactyl\Models;
use Pterodactyl\Models\Server;
use Pterodactyl\Jobs\DeleteServer;
use Pterodactyl\Jobs\SuspendServer;
@@ -59,20 +58,14 @@ class ServerObserver
event(new Events\Server\Created($server));
// Queue Notification Email
- $user = Models\User::findOrFail($server->owner);
- $node = Models\Node::select('name')->where('id', $server->node)->first();
- $service = Models\Service::select('services.name', 'service_options.name as optionName')
- ->join('service_options', 'service_options.parent_service', '=', 'services.id')
- ->where('services.id', $server->service)
- ->where('service_options.id', $server->option)
- ->first();
+ $server->load('user', 'node', 'service.option');
- $user->notify((new ServerCreated([
+ $server->user->notify((new ServerCreated([
'name' => $server->name,
'memory' => $server->memory,
- 'node' => $node->name,
- 'service' => $service->name,
- 'option' => $service->optionName,
+ 'node' => $server->node->name,
+ 'service' => $server->service->name,
+ 'option' => $server->service->option->name,
'uuidShort' => $server->uuidShort,
])));
}
diff --git a/app/Policies/ServerPolicy.php b/app/Policies/ServerPolicy.php
index f297fe829..d67f3aced 100644
--- a/app/Policies/ServerPolicy.php
+++ b/app/Policies/ServerPolicy.php
@@ -39,6 +39,23 @@ class ServerPolicy
//
}
+ /**
+ * Checks if the user has the given permission on/for the server.
+ *
+ * @param \Pterodactyl\Models\User $user
+ * @param \Pterodactyl\Models\Server $server
+ * @param $permission
+ * @return bool
+ */
+ private function checkPermission(User $user, Server $server, $permission)
+ {
+ if ($this->isOwner($user, $server)) {
+ return true;
+ }
+
+ return $user->permissions()->server($server)->permission($permission)->exists();
+ }
+
/**
* Determine if current user is the owner of a server.
*
@@ -48,7 +65,7 @@ class ServerPolicy
*/
protected function isOwner(User $user, Server $server)
{
- return $server->owner === $user->id;
+ return $server->owner_id === $user->id;
}
/**
@@ -521,21 +538,4 @@ class ServerPolicy
{
return $this->checkPermission($user, $server, 'set-allocation');
}
-
- /**
- * Checks if the user has the given permission on/for the server.
- *
- * @param \Pterodactyl\Models\User $user
- * @param \Pterodactyl\Models\Server $server
- * @param $permission
- * @return bool
- */
- private function checkPermission(User $user, Server $server, $permission)
- {
- if ($this->isOwner($user, $server)) {
- return true;
- }
-
- return $user->permissions()->server($server)->permission($permission)->exists();
- }
}
diff --git a/app/Repositories/APIRepository.php b/app/Repositories/APIRepository.php
index 7ce94f34b..71fbb88b5 100644
--- a/app/Repositories/APIRepository.php
+++ b/app/Repositories/APIRepository.php
@@ -62,8 +62,8 @@ class APIRepository
// Node Management Routes
'nodes.list',
+ 'nodes.view',
'nodes.create',
- 'nodes.list',
'nodes.allocations',
'nodes.delete',
@@ -102,7 +102,7 @@ class APIRepository
{
$this->user = is_null($user) ? Auth::user() : $user;
if (is_null($this->user)) {
- throw new \Exception('Cannot access API Repository without passing a user to __construct().');
+ throw new \Exception('Cannot access API Repository without passing a user to constructor.');
}
}
@@ -149,7 +149,7 @@ class APIRepository
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
$key = new Models\APIKey;
$key->fill([
- 'user' => $this->user->id,
+ 'user_id' => $this->user->id,
'public' => str_random(16),
'secret' => Crypt::encrypt($secretKey),
'allowed_ips' => empty($this->allowed) ? null : json_encode($this->allowed),
@@ -178,7 +178,7 @@ class APIRepository
}
}
- if ($this->user->root_admin === 1 && isset($data['adminPermissions'])) {
+ if ($this->user->isRootAdmin() && isset($data['adminPermissions'])) {
foreach ($data['adminPermissions'] as $permNode) {
if (! strpos($permNode, ':')) {
continue;
diff --git a/app/Repositories/Daemon/FileRepository.php b/app/Repositories/Daemon/FileRepository.php
index d1319cf91..5fc2245fb 100644
--- a/app/Repositories/Daemon/FileRepository.php
+++ b/app/Repositories/Daemon/FileRepository.php
@@ -26,7 +26,6 @@ namespace Pterodactyl\Repositories\Daemon;
use Exception;
use GuzzleHttp\Client;
-use Pterodactyl\Models\Node;
use Pterodactyl\Models\Server;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\HelperRepository;
@@ -40,28 +39,6 @@ class FileRepository
*/
protected $server;
- /**
- * The Eloquent Model for the node corresponding with the requested server.
- *
- * @var \Illuminate\Database\Eloquent\Model
- */
- protected $node;
-
- /**
- * The Guzzle Client associated with the requested server and node.
- *
- * @var \GuzzleHttp\Client
- */
- protected $client;
-
- /**
- * The Guzzle Client headers associated with the requested server and node.
- * (non-administrative headers).
- *
- * @var array
- */
- protected $headers;
-
/**
* Constructor.
*
@@ -69,10 +46,7 @@ class FileRepository
*/
public function __construct($uuid)
{
- $this->server = Server::getByUUID($uuid);
- $this->node = Node::getByID($this->server->node);
- $this->client = Node::guzzleRequest($this->server->node);
- $this->headers = Server::getGuzzleHeaders($uuid);
+ $this->server = Server::byUuid($uuid);
}
/**
@@ -88,12 +62,9 @@ class FileRepository
}
$file = (object) pathinfo($file);
-
$file->dirname = (in_array($file->dirname, ['.', './', '/'])) ? null : trim($file->dirname, '/') . '/';
- $res = $this->client->request('GET', '/server/file/stat/' . rawurlencode($file->dirname . $file->basename), [
- 'headers' => $this->headers,
- ]);
+ $res = $this->server->guzzleClient()->request('GET', '/server/file/stat/' . rawurlencode($file->dirname . $file->basename));
$stat = json_decode($res->getBody());
if ($res->getStatusCode() !== 200 || ! isset($stat->size)) {
@@ -108,9 +79,7 @@ class FileRepository
throw new DisplayException('That file is too large to open in the browser, consider using a SFTP client.');
}
- $res = $this->client->request('GET', '/server/file/f/' . rawurlencode($file->dirname . $file->basename), [
- 'headers' => $this->headers,
- ]);
+ $res = $this->server->guzzleClient()->request('GET', '/server/file/f/' . rawurlencode($file->dirname . $file->basename));
$json = json_decode($res->getBody());
if ($res->getStatusCode() !== 200 || ! isset($json->content)) {
@@ -137,11 +106,9 @@ class FileRepository
}
$file = (object) pathinfo($file);
-
$file->dirname = (in_array($file->dirname, ['.', './', '/'])) ? null : trim($file->dirname, '/') . '/';
- $res = $this->client->request('POST', '/server/file/save', [
- 'headers' => $this->headers,
+ $res = $this->server->guzzleClient()->request('POST', '/server/file/save', [
'json' => [
'path' => rawurlencode($file->dirname . $file->basename),
'content' => $content,
@@ -167,9 +134,7 @@ class FileRepository
throw new Exception('A valid directory must be specified in order to list its contents.');
}
- $res = $this->client->request('GET', '/server/directory/' . rawurlencode($directory), [
- 'headers' => $this->headers,
- ]);
+ $res = $this->server->guzzleClient()->request('GET', '/server/directory/' . rawurlencode($directory));
$json = json_decode($res->getBody());
if ($res->getStatusCode() !== 200) {
@@ -180,7 +145,7 @@ class FileRepository
$files = [];
$folders = [];
foreach ($json as &$value) {
- if ($value->directory === true) {
+ if ($value->directory) {
// @TODO Handle Symlinks
$folders[] = [
'entry' => $value->name,
@@ -189,7 +154,7 @@ class FileRepository
'date' => strtotime($value->modified),
'mime' => $value->mime,
];
- } elseif ($value->file === true) {
+ } elseif ($value->file) {
$files[] = [
'entry' => $value->name,
'directory' => trim($directory, '/'),
diff --git a/app/Repositories/DatabaseRepository.php b/app/Repositories/DatabaseRepository.php
index 1abf8e155..c605a32de 100644
--- a/app/Repositories/DatabaseRepository.php
+++ b/app/Repositories/DatabaseRepository.php
@@ -114,28 +114,27 @@ class DatabaseRepository
/**
* Updates the password for a given database.
- * @param int $database The ID of the database to modify.
+ * @param int $id The ID of the database to modify.
* @param string $password The new password to use for the database.
* @return bool
*/
- public function modifyPassword($database, $password)
+ public function modifyPassword($id, $password)
{
- $db = Models\Database::findOrFail($database);
- $dbr = Models\DatabaseServer::findOrFail($db->db_server);
+ $database = Models\Database::with('host')->findOrFail($id);
DB::beginTransaction();
try {
- $db->password = Crypt::encrypt($password);
- $db->save();
+ $database->password = Crypt::encrypt($password);
+ $database->save();
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
- 'host' => $dbr->host,
- 'port' => $dbr->port,
+ 'host' => $database->host->host,
+ 'port' => $database->host->port,
'database' => 'mysql',
- 'username' => $dbr->username,
- 'password' => Crypt::decrypt($dbr->password),
+ 'username' => $database->host->username,
+ 'password' => Crypt::decrypt($database->host->password),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
@@ -147,8 +146,8 @@ class DatabaseRepository
$capsule->setAsGlobal();
Capsule::statement(sprintf(
'SET PASSWORD FOR `%s`@`%s` = PASSWORD(\'%s\')',
- $db->username,
- $db->remote,
+ $database->username,
+ $database->remote,
$password
));
@@ -161,13 +160,12 @@ class DatabaseRepository
/**
* Drops a database from the associated MySQL Server.
- * @param int $database The ID of the database to drop.
+ * @param int $id The ID of the database to drop.
* @return bool
*/
- public function drop($database)
+ public function drop($id)
{
- $db = Models\Database::findOrFail($database);
- $dbr = Models\DatabaseServer::findOrFail($db->db_server);
+ $database = Models\Database::with('host')->findOrFail($id);
DB::beginTransaction();
@@ -175,11 +173,11 @@ class DatabaseRepository
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
- 'host' => $dbr->host,
- 'port' => $dbr->port,
+ 'host' => $database->host->host,
+ 'port' => $database->host->port,
'database' => 'mysql',
- 'username' => $dbr->username,
- 'password' => Crypt::decrypt($dbr->password),
+ 'username' => $database->host->username,
+ 'password' => Crypt::decrypt($database->host->password),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
@@ -190,10 +188,10 @@ class DatabaseRepository
$capsule->setAsGlobal();
- Capsule::statement('DROP USER `' . $db->username . '`@`' . $db->remote . '`');
- Capsule::statement('DROP DATABASE `' . $db->database . '`');
+ Capsule::statement('DROP USER `' . $database->username . '`@`' . $database->remote . '`');
+ Capsule::statement('DROP DATABASE `' . $database->database . '`');
- $db->delete();
+ $database->delete();
DB::commit();
@@ -206,19 +204,19 @@ class DatabaseRepository
/**
* Deletes a database server from the system if it is empty.
+ *
* @param int $server The ID of the Database Server.
* @return
*/
public function delete($server)
{
- $dbh = Models\DatabaseServer::findOrFail($server);
- $databases = Models\Database::where('db_server', $dbh->id)->count();
+ $host = Models\DatabaseServer::withCount('databases')->findOrFail($server);
- if ($databases > 0) {
+ if ($host->databases_count > 0) {
throw new DisplayException('You cannot delete a database server that has active databases attached to it.');
}
- return $dbh->delete();
+ return $host->delete();
}
/**
@@ -268,8 +266,7 @@ class DatabaseRepository
// Allows us to check that we can connect to things.
Capsule::select('SELECT 1 FROM dual');
- $dbh = new Models\DatabaseServer;
- $dbh->fill([
+ Models\DatabaseServer::create([
'name' => $data['name'],
'host' => $data['host'],
'port' => $data['port'],
@@ -278,7 +275,6 @@ class DatabaseRepository
'max_databases' => null,
'linked_node' => (! empty($data['linked_node']) && $data['linked_node'] > 0) ? $data['linked_node'] : null,
]);
- $dbh->save();
DB::commit();
} catch (\Exception $ex) {
diff --git a/app/Repositories/LocationRepository.php b/app/Repositories/LocationRepository.php
index 79196ff35..1b6f50613 100644
--- a/app/Repositories/LocationRepository.php
+++ b/app/Repositories/LocationRepository.php
@@ -37,14 +37,15 @@ class LocationRepository
/**
* Creates a new location on the system.
+ *
* @param array $data
- * @throws Pterodactyl\Exceptions\DisplayValidationException
- * @return int
+ * @throws \Pterodactyl\Exceptions\DisplayValidationException
+ * @return \Pterodactyl\Models\Location
*/
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',
]);
@@ -54,14 +55,12 @@ class LocationRepository
throw new DisplayValidationException($validator->errors());
}
- $location = new Models\Location;
- $location->fill([
+ $location = Models\Location::create([
'long' => $data['long'],
'short' => $data['short'],
]);
- $location->save();
- return $location->id;
+ return $location;
}
/**
@@ -73,9 +72,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 +85,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();
}
diff --git a/app/Repositories/NodeRepository.php b/app/Repositories/NodeRepository.php
index d55446196..1af316b23 100644
--- a/app/Repositories/NodeRepository.php
+++ b/app/Repositories/NodeRepository.php
@@ -44,7 +44,7 @@ class NodeRepository
// Validate Fields
$validator = Validator::make($data, [
'name' => 'required|regex:/^([\w .-]{1,100})$/',
- 'location' => 'required|numeric|min:1|exists:locations,id',
+ 'location_id' => 'required|numeric|min:1|exists:locations,id',
'public' => 'required|numeric|between:0,1',
'fqdn' => 'required|string|unique:nodes,fqdn',
'scheme' => 'required|regex:/^(http(s)?)$/',
@@ -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.
@@ -81,12 +81,7 @@ class NodeRepository
$uuid = new UuidService;
$data['daemonSecret'] = (string) $uuid->generate('nodes', 'daemonSecret');
- // Store the Data
- $node = new Models\Node;
- $node->fill($data);
- $node->save();
-
- return $node->id;
+ return Models\Node::create($data);
}
public function update($id, array $data)
@@ -96,7 +91,7 @@ class NodeRepository
// Validate Fields
$validator = $validator = Validator::make($data, [
'name' => 'regex:/^([\w .-]{1,100})$/',
- 'location' => 'numeric|min:1|exists:locations,id',
+ 'location_id' => 'numeric|min:1|exists:locations,id',
'public' => 'numeric|between:0,1',
'fqdn' => 'string|unique:nodes,fqdn,' . $id,
'scheme' => 'regex:/^(http(s)?)$/',
@@ -152,18 +147,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' => [
@@ -221,13 +210,13 @@ class NodeRepository
foreach ($portBlock as $assignPort) {
$alloc = Models\Allocation::firstOrNew([
- 'node' => $node->id,
+ 'node_id' => $node->id,
'ip' => $ip,
'port' => $assignPort,
]);
if (! $alloc->exists) {
$alloc->fill([
- 'node' => $node->id,
+ 'node_id' => $node->id,
'ip' => $ip,
'port' => $assignPort,
'ip_alias' => $setAlias,
@@ -238,13 +227,13 @@ class NodeRepository
}
} else {
$alloc = Models\Allocation::firstOrNew([
- 'node' => $node->id,
+ 'node_id' => $node->id,
'ip' => $ip,
'port' => $port,
]);
if (! $alloc->exists) {
$alloc->fill([
- 'node' => $node->id,
+ 'node_id' => $node->id,
'ip' => $ip,
'port' => $port,
'ip_alias' => $setAlias,
@@ -266,8 +255,8 @@ class NodeRepository
public function delete($id)
{
- $node = Models\Node::findOrFail($id);
- if (Models\Server::where('node', $id)->count() > 0) {
+ $node = Models\Node::withCount('servers')->findOrFail($id);
+ if ($node->servers_count > 0) {
throw new DisplayException('You cannot delete a node with servers currently attached to it.');
}
@@ -280,7 +269,7 @@ class NodeRepository
]);
// Delete Allocations
- Models\Allocation::where('node', $node->id)->delete();
+ Models\Allocation::where('node_id', $node->id)->delete();
// Delete configure tokens
Models\NodeConfigurationToken::where('node', $node->id)->delete();
diff --git a/app/Repositories/ServerRepository.php b/app/Repositories/ServerRepository.php
index beb5d94a6..a72512d3e 100644
--- a/app/Repositories/ServerRepository.php
+++ b/app/Repositories/ServerRepository.php
@@ -30,6 +30,7 @@ use Crypt;
use Validator;
use Pterodactyl\Models;
use Pterodactyl\Services\UuidService;
+use GuzzleHttp\Exception\TransferException;
use Pterodactyl\Services\DeploymentService;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
@@ -89,17 +90,17 @@ class ServerRepository
'io' => 'required|numeric|min:10|max:1000',
'cpu' => 'required|numeric|min:0',
'disk' => 'required|numeric|min:0',
- 'service' => 'required|numeric|min:1|exists:services,id',
- 'option' => 'required|numeric|min:1|exists:service_options,id',
- 'location' => 'required|numeric|min:1|exists:locations,id',
- 'pack' => 'sometimes|nullable|numeric|min:0',
+ 'service_id' => 'required|numeric|min:1|exists:services,id',
+ 'option_id' => 'required|numeric|min:1|exists:service_options,id',
+ 'location_id' => 'required|numeric|min:1|exists:locations,id',
+ 'pack_id' => 'sometimes|nullable|numeric|min:0',
'startup' => 'string',
'custom_image_name' => 'required_if:use_custom_image,on',
'auto_deploy' => 'sometimes|boolean',
'custom_id' => 'sometimes|required|numeric|unique:servers,id',
]);
- $validator->sometimes('node', 'bail|required|numeric|min:1|exists:nodes,id', function ($input) {
+ $validator->sometimes('node_id', 'bail|required|numeric|min:1|exists:nodes,id', function ($input) {
return ! ($input->auto_deploy);
});
@@ -111,7 +112,7 @@ class ServerRepository
return ! $input->auto_deploy && ! $input->allocation;
});
- $validator->sometimes('allocation', 'numeric|exists:allocations,id', function ($input) {
+ $validator->sometimes('allocation_id', 'numeric|exists:allocations,id', function ($input) {
return ! ($input->auto_deploy || ($input->port && $input->ip));
});
@@ -121,12 +122,7 @@ class ServerRepository
throw new DisplayValidationException($validator->errors());
}
- if (is_int($data['owner'])) {
- $user = Models\User::select('id', 'email')->where('id', $data['owner'])->first();
- } else {
- $user = Models\User::select('id', 'email')->where('email', $data['owner'])->first();
- }
-
+ $user = Models\User::select('id', 'email')->where((is_int($data['owner'])) ? 'id' : 'email', $data['owner'])->first();
if (! $user) {
throw new DisplayException('The user id or email passed to the function was not found on the system.');
}
@@ -135,19 +131,19 @@ class ServerRepository
if (isset($data['auto_deploy']) && in_array($data['auto_deploy'], [true, 1, '1'])) {
// This is an auto-deployment situation
// Ignore any other passed node data
- unset($data['node'], $data['ip'], $data['port'], $data['allocation']);
+ unset($data['node_id'], $data['ip'], $data['port'], $data['allocation_id']);
$autoDeployed = true;
- $node = DeploymentService::smartRandomNode($data['memory'], $data['disk'], $data['location']);
+ $node = DeploymentService::smartRandomNode($data['memory'], $data['disk'], $data['location_id']);
$allocation = DeploymentService::randomAllocation($node->id);
} else {
- $node = Models\Node::getByID($data['node']);
+ $node = Models\Node::findOrFail($data['node_id']);
}
// Verify IP & Port are a.) free and b.) assigned to the node.
// We know the node exists because of 'exists:nodes,id' in the validation
if (! $autoDeployed) {
- if (! isset($data['allocation'])) {
+ if (! isset($data['allocation_id'])) {
$allocation = Models\Allocation::where('ip', $data['ip'])->where('port', $data['port'])->where('node', $data['node'])->whereNull('assigned_to')->first();
} else {
$allocation = Models\Allocation::where('id', $data['allocation'])->where('node', $data['node'])->whereNull('assigned_to')->first();
@@ -163,28 +159,28 @@ class ServerRepository
// We know the service and option exists because of the validation.
// We need to verify that the option exists for the service, and then check for
// any required variable fields. (fields are labeled env_{{DL_VERSION}}
in the URL to automatically insert the assigned version into the URL. If you do not enter a URL Spigot will build directly in the container (this will fail on low memory containers).',
@@ -183,7 +183,7 @@ class MinecraftServiceTableSeeder extends Seeder
private function addSpongeVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['sponge']->id,
'name' => 'Sponge Version',
'description' => 'The version of SpongeVanilla to download and use.',
@@ -195,7 +195,7 @@ class MinecraftServiceTableSeeder extends Seeder
'regex' => '/^([a-zA-Z0-9.\-_]+)$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['sponge']->id,
'name' => 'Server Jar File',
'description' => 'The name of the Jarfile to use when running SpongeVanilla.',
@@ -210,7 +210,7 @@ class MinecraftServiceTableSeeder extends Seeder
private function addBungeecordVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['bungeecord']->id,
'name' => 'Bungeecord Version',
'description' => 'The version of Bungeecord to download and use.',
@@ -222,7 +222,7 @@ class MinecraftServiceTableSeeder extends Seeder
'regex' => '/^(latest|[\d]{1,6})$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['bungeecord']->id,
'name' => 'Bungeecord Jar File',
'description' => 'The name of the Jarfile to use when running Bungeecord.',
diff --git a/database/seeds/SourceServiceTableSeeder.php b/database/seeds/SourceServiceTableSeeder.php
index 838814db8..f6b93e090 100644
--- a/database/seeds/SourceServiceTableSeeder.php
+++ b/database/seeds/SourceServiceTableSeeder.php
@@ -66,7 +66,7 @@ class SourceServiceTableSeeder extends Seeder
private function addCoreOptions()
{
- $this->option['insurgency'] = Models\ServiceOptions::create([
+ $this->option['insurgency'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Insurgency',
'description' => 'Take to the streets for intense close quarters combat, where a team\'s survival depends upon securing crucial strongholds and destroying enemy supply in this multiplayer and cooperative Source Engine based experience.',
@@ -76,7 +76,7 @@ class SourceServiceTableSeeder extends Seeder
'startup' => '-game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} -strictportbind -norestart',
]);
- $this->option['tf2'] = Models\ServiceOptions::create([
+ $this->option['tf2'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Team Fortress 2',
'description' => 'Team Fortress 2 is a team-based first-person shooter multiplayer video game developed and published by Valve Corporation. It is the sequel to the 1996 mod Team Fortress for Quake and its 1999 remake.',
@@ -86,7 +86,7 @@ class SourceServiceTableSeeder extends Seeder
'startup' => '-game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} -strictportbind -norestart',
]);
- $this->option['ark'] = Models\ServiceOptions::create([
+ $this->option['ark'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Ark: Survival Evolved',
'description' => 'As a man or woman stranded, naked, freezing, and starving on the unforgiving shores of a mysterious island called ARK, use your skill and cunning to kill or tame and ride the plethora of leviathan dinosaurs and other primeval creatures roaming the land. Hunt, harvest resources, craft items, grow crops, research technologies, and build shelters to withstand the elements and store valuables, all while teaming up with (or preying upon) hundreds of other players to survive, dominate... and escape! — Gamepedia: ARK',
@@ -96,7 +96,7 @@ class SourceServiceTableSeeder extends Seeder
'startup' => 'TheIsland?listen?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?MaxPlayers={{SERVER_MAX_PLAYERS}}',
]);
- $this->option['custom'] = Models\ServiceOptions::create([
+ $this->option['custom'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Custom Source Engine Game',
'description' => 'This option allows modifying the startup arguments and other details to run a custo SRCDS based game on the panel.',
@@ -117,7 +117,7 @@ class SourceServiceTableSeeder extends Seeder
private function addInsurgencyVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['insurgency']->id,
'name' => 'Game ID',
'description' => 'The ID corresponding to the game to download and run using SRCDS.',
@@ -129,7 +129,7 @@ class SourceServiceTableSeeder extends Seeder
'regex' => '/^(17705)$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['insurgency']->id,
'name' => 'Game Name',
'description' => 'The name corresponding to the game to download and run using SRCDS.',
@@ -141,7 +141,7 @@ class SourceServiceTableSeeder extends Seeder
'regex' => '/^(insurgency)$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['insurgency']->id,
'name' => 'Default Map',
'description' => 'The default map to use when starting the server.',
@@ -156,7 +156,7 @@ class SourceServiceTableSeeder extends Seeder
private function addTF2Variables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['tf2']->id,
'name' => 'Game ID',
'description' => 'The ID corresponding to the game to download and run using SRCDS.',
@@ -168,7 +168,7 @@ class SourceServiceTableSeeder extends Seeder
'regex' => '/^(232250)$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['tf2']->id,
'name' => 'Game Name',
'description' => 'The name corresponding to the game to download and run using SRCDS.',
@@ -180,7 +180,7 @@ class SourceServiceTableSeeder extends Seeder
'regex' => '/^(tf)$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['tf2']->id,
'name' => 'Default Map',
'description' => 'The default map to use when starting the server.',
@@ -234,7 +234,7 @@ class SourceServiceTableSeeder extends Seeder
private function addCustomVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['custom']->id,
'name' => 'Game ID',
'description' => 'The ID corresponding to the game to download and run using SRCDS.',
@@ -246,7 +246,7 @@ class SourceServiceTableSeeder extends Seeder
'regex' => '/^(\d){1,6}$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['custom']->id,
'name' => 'Game Name',
'description' => 'The name corresponding to the game to download and run using SRCDS.',
diff --git a/database/seeds/TerrariaServiceTableSeeder.php b/database/seeds/TerrariaServiceTableSeeder.php
index bd3089ea2..41ed23924 100644
--- a/database/seeds/TerrariaServiceTableSeeder.php
+++ b/database/seeds/TerrariaServiceTableSeeder.php
@@ -66,7 +66,7 @@ class TerrariaServiceTableSeeder extends Seeder
private function addCoreOptions()
{
- $this->option['tshock'] = Models\ServiceOptions::create([
+ $this->option['tshock'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Terraria Server (TShock)',
'description' => 'TShock is a server modification for Terraria, written in C#, and based upon the Terraria Server API. It uses JSON for configuration management, and offers several features not present in the Terraria Server normally.',
@@ -79,7 +79,7 @@ class TerrariaServiceTableSeeder extends Seeder
private function addVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['tshock']->id,
'name' => 'TShock Version',
'description' => 'Which version of TShock to install and use.',
@@ -91,7 +91,7 @@ class TerrariaServiceTableSeeder extends Seeder
'regex' => '/^([0-9_\.-]{5,10})$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['tshock']->id,
'name' => 'Maximum Slots',
'description' => 'Total number of slots to allow on the server.',
diff --git a/database/seeds/VoiceServiceTableSeeder.php b/database/seeds/VoiceServiceTableSeeder.php
index 1fca3a475..563683214 100644
--- a/database/seeds/VoiceServiceTableSeeder.php
+++ b/database/seeds/VoiceServiceTableSeeder.php
@@ -66,7 +66,7 @@ class VoiceServiceTableSeeder extends Seeder
private function addCoreOptions()
{
- $this->option['mumble'] = Models\ServiceOptions::create([
+ $this->option['mumble'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Mumble Server',
'description' => 'Mumble is an open source, low-latency, high quality voice chat software primarily intended for use while gaming.',
@@ -76,7 +76,7 @@ class VoiceServiceTableSeeder extends Seeder
'startup' => '-fg',
]);
- $this->option['ts3'] = Models\ServiceOptions::create([
+ $this->option['ts3'] = Models\ServiceOption::create([
'parent_service' => $this->service->id,
'name' => 'Teamspeak3 Server',
'description' => 'VoIP software designed with security in mind, featuring crystal clear voice quality, endless customization options, and scalabilty up to thousands of simultaneous users.',
@@ -89,7 +89,7 @@ class VoiceServiceTableSeeder extends Seeder
private function addVariables()
{
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['mumble']->id,
'name' => 'Maximum Users',
'description' => 'Maximum concurrent users on the mumble server.',
@@ -101,7 +101,7 @@ class VoiceServiceTableSeeder extends Seeder
'regex' => '/^(\d){1,6}$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['mumble']->id,
'name' => 'Server Version',
'description' => 'Version of Mumble Server to download and use.',
@@ -113,7 +113,7 @@ class VoiceServiceTableSeeder extends Seeder
'regex' => '/^([0-9_\.-]{5,8})$/',
]);
- Models\ServiceVariables::create([
+ Models\ServiceVariable::create([
'option_id' => $this->option['ts3']->id,
'name' => 'Server Version',
'description' => 'The version of Teamspeak 3 to use when running the server.',
diff --git a/public/js/laroute.js b/public/js/laroute.js
index f9a87a665..4bc8ff78c 100644
--- a/public/js/laroute.js
+++ b/public/js/laroute.js
@@ -6,7 +6,7 @@
absolute: false,
rootUrl: 'http://pterodactyl.app',
- routes : [{"host":null,"methods":["GET","HEAD"],"uri":"admin","name":"admin.index","action":"Pterodactyl\Http\Controllers\Admin\BaseController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings","name":"admin.settings","action":"Pterodactyl\Http\Controllers\Admin\BaseController@getSettings"},{"host":null,"methods":["POST"],"uri":"admin\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\BaseController@postSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users","name":"admin.users","action":"Pterodactyl\Http\Controllers\Admin\UserController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/accounts.json","name":"admin.users.json","action":"Pterodactyl\Http\Controllers\Admin\UserController@getJson"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/view\/{id}","name":"admin.users.view","action":"Pterodactyl\Http\Controllers\Admin\UserController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@updateUser"},{"host":null,"methods":["DELETE"],"uri":"admin\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@deleteUser"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/new","name":"admin.users.new","action":"Pterodactyl\Http\Controllers\Admin\UserController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers","name":"admin.servers","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/new","name":"admin.servers.new","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/get-nodes","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerGetNodes"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/get-ips","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerGetIps"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/service-options","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerServiceOptions"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/option-details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerOptionDetails"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{id}","name":"admin.servers.view","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/database","name":"admin.servers.database","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postDatabase"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerDetails"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/container","name":"admin.servers.post.container","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateContainerDetails"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/startup","name":"admin.servers.post.startup","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerStartup"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/rebuild","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerToggleBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/build","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerUpdateBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/suspend","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postSuspendServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/unsuspend","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUnsuspendServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/installed","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postToggleInstall"},{"host":null,"methods":["DELETE"],"uri":"admin\/servers\/view\/{id}\/{force?}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@deleteServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/queuedDeletion","name":"admin.servers.post.queuedDeletion","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postQueuedDeletionHandler"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes","name":"admin.nodes","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/new","name":"admin.nodes.new","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}","name":"admin.nodes.view","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@postView"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{id}\/deallocate\/single\/{allocation}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@deallocateSingle"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/deallocate\/block","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@deallocateBlock"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/alias","name":"admin.nodes.alias","action":"Pterodactyl\Http\Controllers\Admin\NodesController@setAlias"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}\/allocations.json","name":"admin.nodes.view.allocations","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getAllocationsJson"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/allocations","name":"admin.nodes.post.allocations","action":"Pterodactyl\Http\Controllers\Admin\NodesController@postAllocations"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}\/deploy","name":"admin.nodes.deply","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getScript"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{id}","name":"admin.nodes.delete","action":"Pterodactyl\Http\Controllers\Admin\NodesController@deleteNode"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/{id}\/configurationtoken","name":"admin.nodes.configuration-token","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getConfigurationToken"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations","name":"admin.locations","action":"Pterodactyl\Http\Controllers\Admin\LocationsController@getIndex"},{"host":null,"methods":["DELETE"],"uri":"admin\/locations\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@deleteLocation"},{"host":null,"methods":["PATCH"],"uri":"admin\/locations\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@patchLocation"},{"host":null,"methods":["POST"],"uri":"admin\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@postLocation"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases","name":"admin.databases","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases\/new","name":"admin.databases.new","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/databases\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@postNew"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/delete\/{id}","name":"admin.databases.delete","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@deleteDatabase"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/delete-server\/{id}","name":"admin.databases.delete-server","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@deleteServer"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services","name":"admin.services","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/new","name":"admin.services.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/services\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{id}","name":"admin.services.service","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getService"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postService"},{"host":null,"methods":["DELETE"],"uri":"admin\/services\/service\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteService"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{id}\/configuration","name":"admin.services.service.config","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getConfiguration"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{id}\/configuration","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/new","name":"admin.services.option.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@newOption"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNewOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}","name":"admin.services.option","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getOption"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postOption"},{"host":null,"methods":["DELETE"],"uri":"admin\/services\/service\/{service}\/option\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/new","name":"admin.services.option.variable.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getNewVariable"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNewVariable"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/{variable}","name":"admin.services.option.variable","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postOptionVariable"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/{variable}\/delete","name":"admin.services.option.variable.delete","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteVariable"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/new\/{option?}","name":"admin.services.packs.new","action":"Pterodactyl\Http\Controllers\Admin\PackController@new"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/upload\/{option?}","name":"admin.services.packs.uploadForm","action":"Pterodactyl\Http\Controllers\Admin\PackController@uploadForm"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/upload","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@postUpload"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs","name":"admin.services.packs","action":"Pterodactyl\Http\Controllers\Admin\PackController@listAll"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/for\/option\/{option}","name":"admin.services.packs.option","action":"Pterodactyl\Http\Controllers\Admin\PackController@listByOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/for\/service\/{service}","name":"admin.services.packs.service","action":"Pterodactyl\Http\Controllers\Admin\PackController@listByService"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/edit\/{pack}","name":"admin.services.packs.edit","action":"Pterodactyl\Http\Controllers\Admin\PackController@edit"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/edit\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/edit\/{pack}\/export\/{archive?}","name":"admin.services.packs.export","action":"Pterodactyl\Http\Controllers\Admin\PackController@export"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login","name":"auth.login","action":"Pterodactyl\Http\Controllers\Auth\LoginController@showLoginForm"},{"host":null,"methods":["POST"],"uri":"auth\/login","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@login"},{"host":null,"methods":["POST"],"uri":"auth\/login\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@checkTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password","name":"auth.password","action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm"},{"host":null,"methods":["POST"],"uri":"auth\/password","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password\/reset\/{token}","name":"auth.reset","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@showResetForm"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset","name":"auth.reset.post","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@reset"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/logout","name":"auth.logout","action":"Pterodactyl\Http\Controllers\Auth\LoginController@logout"},{"host":null,"methods":["GET","HEAD"],"uri":"\/","name":"index","action":"Pterodactyl\Http\Controllers\Base\IndexController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"index","name":null,"action":"Closure"},{"host":null,"methods":["GET","HEAD"],"uri":"password-gen\/{length}","name":"password-gen","action":"Pterodactyl\Http\Controllers\Base\IndexController@getPassword"},{"host":null,"methods":["GET","HEAD"],"uri":"account","name":"account","action":"Pterodactyl\Http\Controllers\Base\AccountController@index"},{"host":null,"methods":["POST"],"uri":"account\/password","name":"account.password","action":"Pterodactyl\Http\Controllers\Base\AccountController@password"},{"host":null,"methods":["POST"],"uri":"account\/email","name":"account.email","action":"Pterodactyl\Http\Controllers\Base\AccountController@email"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api","name":"account.api","action":"Pterodactyl\Http\Controllers\Base\APIController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api\/new","name":"account.api.new","action":"Pterodactyl\Http\Controllers\Base\APIController@create"},{"host":null,"methods":["POST"],"uri":"account\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Base\APIController@save"},{"host":null,"methods":["DELETE"],"uri":"account\/api\/revoke\/{key}","name":null,"action":"Pterodactyl\Http\Controllers\Base\APIController@revoke"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security","name":"account.security","action":"Pterodactyl\Http\Controllers\Base\SecurityController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security\/revoke\/{id}","name":"account.security.revoke","action":"Pterodactyl\Http\Controllers\Base\SecurityController@revoke"},{"host":null,"methods":["PUT"],"uri":"account\/security\/totp","name":"account.security.totp","action":"Pterodactyl\Http\Controllers\Base\SecurityController@generateTotp"},{"host":null,"methods":["POST"],"uri":"account\/security\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Base\SecurityController@setTotp"},{"host":null,"methods":["DELETE"],"uri":"account\/security\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Base\SecurityController@disableTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/services","name":"daemon.services","action":"Pterodactyl\Http\Controllers\Daemon\ServiceController@list"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/services\/pull\/{service}\/{file}","name":"remote.install","action":"Pterodactyl\Http\Controllers\Daemon\ServiceController@pull"},{"host":null,"methods":["GET","HEAD"],"uri":"language\/{lang}","name":"langauge.set","action":"Pterodactyl\Http\Controllers\Base\LanguageController@setLanguage"},{"host":null,"methods":["POST"],"uri":"remote\/download","name":"remote.download","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@postDownload"},{"host":null,"methods":["POST"],"uri":"remote\/install","name":"remote.install","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@postInstall"},{"host":null,"methods":["POST"],"uri":"remote\/event","name":"remote.event","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@event"},{"host":null,"methods":["GET","HEAD"],"uri":"remote\/configuration\/{token}","name":"remote.configuration","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@getConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}","name":"server.index","action":"Pterodactyl\Http\Controllers\Server\ServerController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings","name":"server.settings","action":"Pterodactyl\Http\Controllers\Server\ServerController@getSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/databases","name":"server.settings.databases","action":"Pterodactyl\Http\Controllers\Server\ServerController@getDatabases"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/sftp","name":"server.settings.sftp","action":"Pterodactyl\Http\Controllers\Server\ServerController@getSFTP"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/settings\/sftp","name":null,"action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsSFTP"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/startup","name":"server.settings.startup","action":"Pterodactyl\Http\Controllers\Server\ServerController@getStartup"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/settings\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsStartup"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/allocation","name":"server.settings.allocation","action":"Pterodactyl\Http\Controllers\Server\ServerController@getAllocation"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files","name":"server.files.index","action":"Pterodactyl\Http\Controllers\Server\ServerController@getFiles"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/edit\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\ServerController@getEditFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/download\/{file}","name":"server.files.download","action":"Pterodactyl\Http\Controllers\Server\ServerController@getDownloadFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/add","name":"server.files.add","action":"Pterodactyl\Http\Controllers\Server\ServerController@getAddFile"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/directory-list","name":"server.files.directory-list","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postDirectoryList"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/save","name":"server.files.save","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postSaveFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users","name":"server.subusers","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/new","name":"server.subusers.new","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getNew"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/view\/{id}","name":"server.subusers.view","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getView"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@postView"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/users\/delete\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@deleteSubuser"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks","name":"server.tasks","action":"Pterodactyl\Http\Controllers\Server\TaskController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks\/view\/{id}","name":"server.tasks.view","action":"Pterodactyl\Http\Controllers\Server\TaskController@getView"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks\/new","name":"server.tasks.new","action":"Pterodactyl\Http\Controllers\Server\TaskController@getNew"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/tasks\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\TaskController@postNew"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/tasks\/delete\/{id}","name":"server.tasks.delete","action":"Pterodactyl\Http\Controllers\Server\TaskController@deleteTask"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/tasks\/toggle\/{id}","name":"server.tasks.toggle","action":"Pterodactyl\Http\Controllers\Server\TaskController@toggleTask"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/ajax\/status","name":"server.ajax.status","action":"Pterodactyl\Http\Controllers\Server\AjaxController@getStatus"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/ajax\/set-primary","name":null,"action":"Pterodactyl\Http\Controllers\Server\AjaxController@postSetPrimary"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/ajax\/settings\/reset-database-password","name":"server.ajax.reset-database-password","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postResetDatabasePassword"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/open","name":"debugbar.openhandler","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@handle"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/clockwork\/{id}","name":"debugbar.clockwork","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@clockwork"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/stylesheets","name":"debugbar.assets.css","action":"Barryvdh\Debugbar\Controllers\AssetController@css"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/javascript","name":"debugbar.assets.js","action":"Barryvdh\Debugbar\Controllers\AssetController@js"}],
+ routes : [{"host":null,"methods":["GET","HEAD"],"uri":"admin","name":"admin.index","action":"Pterodactyl\Http\Controllers\Admin\BaseController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/settings","name":"admin.settings","action":"Pterodactyl\Http\Controllers\Admin\BaseController@getSettings"},{"host":null,"methods":["POST"],"uri":"admin\/settings","name":null,"action":"Pterodactyl\Http\Controllers\Admin\BaseController@postSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users","name":"admin.users","action":"Pterodactyl\Http\Controllers\Admin\UserController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/accounts.json","name":"admin.users.json","action":"Pterodactyl\Http\Controllers\Admin\UserController@getJson"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/view\/{id}","name":"admin.users.view","action":"Pterodactyl\Http\Controllers\Admin\UserController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@updateUser"},{"host":null,"methods":["DELETE"],"uri":"admin\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@deleteUser"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/users\/new","name":"admin.users.new","action":"Pterodactyl\Http\Controllers\Admin\UserController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\UserController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers","name":"admin.servers","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/new","name":"admin.servers.new","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/get-nodes","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerGetNodes"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/get-ips","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerGetIps"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/service-options","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerServiceOption"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/new\/option-details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postNewServerOptionDetails"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/servers\/view\/{id}","name":"admin.servers.view","action":"Pterodactyl\Http\Controllers\Admin\ServersController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/database","name":"admin.servers.database","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postDatabase"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/details","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerDetails"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/container","name":"admin.servers.post.container","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateContainerDetails"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/startup","name":"admin.servers.post.startup","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerStartup"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/rebuild","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerToggleBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/build","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUpdateServerUpdateBuild"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/suspend","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postSuspendServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/unsuspend","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postUnsuspendServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/installed","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@postToggleInstall"},{"host":null,"methods":["DELETE"],"uri":"admin\/servers\/view\/{id}\/{force?}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServersController@deleteServer"},{"host":null,"methods":["POST"],"uri":"admin\/servers\/view\/{id}\/queuedDeletion","name":"admin.servers.post.queuedDeletion","action":"Pterodactyl\Http\Controllers\Admin\ServersController@postQueuedDeletionHandler"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes","name":"admin.nodes","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/new","name":"admin.nodes.new","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}","name":"admin.nodes.view","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getView"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@postView"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{id}\/deallocate\/single\/{allocation}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@deallocateSingle"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/deallocate\/block","name":null,"action":"Pterodactyl\Http\Controllers\Admin\NodesController@deallocateBlock"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/alias","name":"admin.nodes.alias","action":"Pterodactyl\Http\Controllers\Admin\NodesController@setAlias"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}\/allocations.json","name":"admin.nodes.view.allocations","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getAllocationsJson"},{"host":null,"methods":["POST"],"uri":"admin\/nodes\/view\/{id}\/allocations","name":"admin.nodes.post.allocations","action":"Pterodactyl\Http\Controllers\Admin\NodesController@postAllocations"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/view\/{id}\/deploy","name":"admin.nodes.deply","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getScript"},{"host":null,"methods":["DELETE"],"uri":"admin\/nodes\/view\/{id}","name":"admin.nodes.delete","action":"Pterodactyl\Http\Controllers\Admin\NodesController@deleteNode"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/nodes\/{id}\/configurationtoken","name":"admin.nodes.configuration-token","action":"Pterodactyl\Http\Controllers\Admin\NodesController@getConfigurationToken"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/locations","name":"admin.locations","action":"Pterodactyl\Http\Controllers\Admin\LocationsController@getIndex"},{"host":null,"methods":["DELETE"],"uri":"admin\/locations\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@deleteLocation"},{"host":null,"methods":["PATCH"],"uri":"admin\/locations\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@patchLocation"},{"host":null,"methods":["POST"],"uri":"admin\/locations","name":null,"action":"Pterodactyl\Http\Controllers\Admin\LocationsController@postLocation"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases","name":"admin.databases","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/databases\/new","name":"admin.databases.new","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/databases\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@postNew"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/delete\/{id}","name":"admin.databases.delete","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@deleteDatabase"},{"host":null,"methods":["DELETE"],"uri":"admin\/databases\/delete-server\/{id}","name":"admin.databases.delete-server","action":"Pterodactyl\Http\Controllers\Admin\DatabaseController@deleteServer"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services","name":"admin.services","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/new","name":"admin.services.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getNew"},{"host":null,"methods":["POST"],"uri":"admin\/services\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{id}","name":"admin.services.service","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getService"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postService"},{"host":null,"methods":["DELETE"],"uri":"admin\/services\/service\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteService"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{id}\/configuration","name":"admin.services.service.config","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getConfiguration"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{id}\/configuration","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/new","name":"admin.services.option.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@newOption"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNewOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}","name":"admin.services.option","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getOption"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postOption"},{"host":null,"methods":["DELETE"],"uri":"admin\/services\/service\/{service}\/option\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/new","name":"admin.services.option.variable.new","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@getNewVariable"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postNewVariable"},{"host":null,"methods":["POST"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/{variable}","name":"admin.services.option.variable","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@postOptionVariable"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/service\/{service}\/option\/{option}\/variable\/{variable}\/delete","name":"admin.services.option.variable.delete","action":"Pterodactyl\Http\Controllers\Admin\ServiceController@deleteVariable"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/new\/{option?}","name":"admin.services.packs.new","action":"Pterodactyl\Http\Controllers\Admin\PackController@new"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/new","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@create"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/upload\/{option?}","name":"admin.services.packs.uploadForm","action":"Pterodactyl\Http\Controllers\Admin\PackController@uploadForm"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/upload","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@postUpload"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs","name":"admin.services.packs","action":"Pterodactyl\Http\Controllers\Admin\PackController@listAll"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/for\/option\/{option}","name":"admin.services.packs.option","action":"Pterodactyl\Http\Controllers\Admin\PackController@listByOption"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/for\/service\/{service}","name":"admin.services.packs.service","action":"Pterodactyl\Http\Controllers\Admin\PackController@listByService"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/edit\/{pack}","name":"admin.services.packs.edit","action":"Pterodactyl\Http\Controllers\Admin\PackController@edit"},{"host":null,"methods":["POST"],"uri":"admin\/services\/packs\/edit\/{pack}","name":null,"action":"Pterodactyl\Http\Controllers\Admin\PackController@update"},{"host":null,"methods":["GET","HEAD"],"uri":"admin\/services\/packs\/edit\/{pack}\/export\/{archive?}","name":"admin.services.packs.export","action":"Pterodactyl\Http\Controllers\Admin\PackController@export"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/login","name":"auth.login","action":"Pterodactyl\Http\Controllers\Auth\LoginController@showLoginForm"},{"host":null,"methods":["POST"],"uri":"auth\/login","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@login"},{"host":null,"methods":["POST"],"uri":"auth\/login\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Auth\LoginController@checkTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password","name":"auth.password","action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm"},{"host":null,"methods":["POST"],"uri":"auth\/password","name":null,"action":"Pterodactyl\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/password\/reset\/{token}","name":"auth.reset","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@showResetForm"},{"host":null,"methods":["POST"],"uri":"auth\/password\/reset","name":"auth.reset.post","action":"Pterodactyl\Http\Controllers\Auth\ResetPasswordController@reset"},{"host":null,"methods":["GET","HEAD"],"uri":"auth\/logout","name":"auth.logout","action":"Pterodactyl\Http\Controllers\Auth\LoginController@logout"},{"host":null,"methods":["GET","HEAD"],"uri":"\/","name":"index","action":"Pterodactyl\Http\Controllers\Base\IndexController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"index","name":null,"action":"Closure"},{"host":null,"methods":["GET","HEAD"],"uri":"password-gen\/{length}","name":"password-gen","action":"Pterodactyl\Http\Controllers\Base\IndexController@getPassword"},{"host":null,"methods":["GET","HEAD"],"uri":"account","name":"account","action":"Pterodactyl\Http\Controllers\Base\AccountController@index"},{"host":null,"methods":["POST"],"uri":"account\/password","name":"account.password","action":"Pterodactyl\Http\Controllers\Base\AccountController@password"},{"host":null,"methods":["POST"],"uri":"account\/email","name":"account.email","action":"Pterodactyl\Http\Controllers\Base\AccountController@email"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api","name":"account.api","action":"Pterodactyl\Http\Controllers\Base\APIController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/api\/new","name":"account.api.new","action":"Pterodactyl\Http\Controllers\Base\APIController@create"},{"host":null,"methods":["POST"],"uri":"account\/api\/new","name":null,"action":"Pterodactyl\Http\Controllers\Base\APIController@save"},{"host":null,"methods":["DELETE"],"uri":"account\/api\/revoke\/{key}","name":null,"action":"Pterodactyl\Http\Controllers\Base\APIController@revoke"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security","name":"account.security","action":"Pterodactyl\Http\Controllers\Base\SecurityController@index"},{"host":null,"methods":["GET","HEAD"],"uri":"account\/security\/revoke\/{id}","name":"account.security.revoke","action":"Pterodactyl\Http\Controllers\Base\SecurityController@revoke"},{"host":null,"methods":["PUT"],"uri":"account\/security\/totp","name":"account.security.totp","action":"Pterodactyl\Http\Controllers\Base\SecurityController@generateTotp"},{"host":null,"methods":["POST"],"uri":"account\/security\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Base\SecurityController@setTotp"},{"host":null,"methods":["DELETE"],"uri":"account\/security\/totp","name":null,"action":"Pterodactyl\Http\Controllers\Base\SecurityController@disableTotp"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/services","name":"daemon.services","action":"Pterodactyl\Http\Controllers\Daemon\ServiceController@list"},{"host":null,"methods":["GET","HEAD"],"uri":"daemon\/services\/pull\/{service}\/{file}","name":"remote.install","action":"Pterodactyl\Http\Controllers\Daemon\ServiceController@pull"},{"host":null,"methods":["GET","HEAD"],"uri":"language\/{lang}","name":"langauge.set","action":"Pterodactyl\Http\Controllers\Base\LanguageController@setLanguage"},{"host":null,"methods":["POST"],"uri":"remote\/download","name":"remote.download","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@postDownload"},{"host":null,"methods":["POST"],"uri":"remote\/install","name":"remote.install","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@postInstall"},{"host":null,"methods":["POST"],"uri":"remote\/event","name":"remote.event","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@event"},{"host":null,"methods":["GET","HEAD"],"uri":"remote\/configuration\/{token}","name":"remote.configuration","action":"Pterodactyl\Http\Controllers\Remote\RemoteController@getConfiguration"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}","name":"server.index","action":"Pterodactyl\Http\Controllers\Server\ServerController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings","name":"server.settings","action":"Pterodactyl\Http\Controllers\Server\ServerController@getSettings"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/databases","name":"server.settings.databases","action":"Pterodactyl\Http\Controllers\Server\ServerController@getDatabases"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/sftp","name":"server.settings.sftp","action":"Pterodactyl\Http\Controllers\Server\ServerController@getSFTP"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/settings\/sftp","name":null,"action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsSFTP"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/startup","name":"server.settings.startup","action":"Pterodactyl\Http\Controllers\Server\ServerController@getStartup"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/settings\/startup","name":null,"action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsStartup"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/settings\/allocation","name":"server.settings.allocation","action":"Pterodactyl\Http\Controllers\Server\ServerController@getAllocation"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files","name":"server.files.index","action":"Pterodactyl\Http\Controllers\Server\ServerController@getFiles"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/edit\/{file}","name":"server.files.edit","action":"Pterodactyl\Http\Controllers\Server\ServerController@getEditFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/download\/{file}","name":"server.files.download","action":"Pterodactyl\Http\Controllers\Server\ServerController@getDownloadFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/files\/add","name":"server.files.add","action":"Pterodactyl\Http\Controllers\Server\ServerController@getAddFile"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/directory-list","name":"server.files.directory-list","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postDirectoryList"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/files\/save","name":"server.files.save","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postSaveFile"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users","name":"server.subusers","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/new","name":"server.subusers.new","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getNew"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@postNew"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/users\/view\/{id}","name":"server.subusers.view","action":"Pterodactyl\Http\Controllers\Server\SubuserController@getView"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/users\/view\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@postView"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/users\/delete\/{id}","name":null,"action":"Pterodactyl\Http\Controllers\Server\SubuserController@deleteSubuser"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks","name":"server.tasks","action":"Pterodactyl\Http\Controllers\Server\TaskController@getIndex"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks\/view\/{id}","name":"server.tasks.view","action":"Pterodactyl\Http\Controllers\Server\TaskController@getView"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/tasks\/new","name":"server.tasks.new","action":"Pterodactyl\Http\Controllers\Server\TaskController@getNew"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/tasks\/new","name":null,"action":"Pterodactyl\Http\Controllers\Server\TaskController@postNew"},{"host":null,"methods":["DELETE"],"uri":"server\/{server}\/tasks\/delete\/{id}","name":"server.tasks.delete","action":"Pterodactyl\Http\Controllers\Server\TaskController@deleteTask"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/tasks\/toggle\/{id}","name":"server.tasks.toggle","action":"Pterodactyl\Http\Controllers\Server\TaskController@toggleTask"},{"host":null,"methods":["GET","HEAD"],"uri":"server\/{server}\/ajax\/status","name":"server.ajax.status","action":"Pterodactyl\Http\Controllers\Server\AjaxController@getStatus"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/ajax\/set-primary","name":null,"action":"Pterodactyl\Http\Controllers\Server\AjaxController@postSetPrimary"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/ajax\/settings\/reset-database-password","name":"server.ajax.reset-database-password","action":"Pterodactyl\Http\Controllers\Server\AjaxController@postResetDatabasePassword"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/open","name":"debugbar.openhandler","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@handle"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/clockwork\/{id}","name":"debugbar.clockwork","action":"Barryvdh\Debugbar\Controllers\OpenHandlerController@clockwork"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/stylesheets","name":"debugbar.assets.css","action":"Barryvdh\Debugbar\Controllers\AssetController@css"},{"host":null,"methods":["GET","HEAD"],"uri":"_debugbar\/assets\/javascript","name":"debugbar.assets.js","action":"Barryvdh\Debugbar\Controllers\AssetController@js"}],
prefix: '',
route : function (name, parameters, route) {
diff --git a/public/js/vendor/ace/mode-vbscript.js b/public/js/vendor/ace/mode-vbscript.js
index 1de7b7c48..da888780f 100755
--- a/public/js/vendor/ace/mode-vbscript.js
+++ b/public/js/vendor/ace/mode-vbscript.js
@@ -1 +1 @@
-define("ace/mode/vbscript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e=this.createKeywordMapper({"keyword.control.asp":"If|Then|Else|ElseIf|End|While|Wend|For|To|Each|Case|Select|Return|Continue|Do|Until|Loop|Next|With|Exit|Function|Property|Type|Enum|Sub|IIf","storage.type.asp":"Dim|Call|Class|Const|Dim|Redim|Set|Let|Get|New|Randomize|Option|Explicit","storage.modifier.asp":"Private|Public|Default","keyword.operator.asp":"Mod|And|Not|Or|Xor|as","constant.language.asp":"Empty|False|Nothing|Null|True","support.class.asp":"Application|ObjectContext|Request|Response|Server|Session","support.class.collection.asp":"Contents|StaticObjects|ClientCertificate|Cookies|Form|QueryString|ServerVariables","support.constant.asp":"TotalBytes|Buffer|CacheControl|Charset|ContentType|Expires|ExpiresAbsolute|IsClientConnected|PICS|Status|ScriptTimeout|CodePage|LCID|SessionID|Timeout","support.function.asp":"Lock|Unlock|SetAbort|SetComplete|BinaryRead|AddHeader|AppendToLog|BinaryWrite|Clear|Flush|Redirect|Write|CreateObject|HTMLEncode|MapPath|URLEncode|Abandon|Convert|Regex","support.function.event.asp":"Application_OnEnd|Application_OnStart|OnTransactionAbort|OnTransactionCommit|Session_OnEnd|Session_OnStart","support.function.vb.asp":"Array|Add|Asc|Atn|CBool|CByte|CCur|CDate|CDbl|Chr|CInt|CLng|Conversions|Cos|CreateObject|CSng|CStr|Date|DateAdd|DateDiff|DatePart|DateSerial|DateValue|Day|Derived|Math|Escape|Eval|Exists|Exp|Filter|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent|GetLocale|GetObject|GetRef|Hex|Hour|InputBox|InStr|InStrRev|Int|Fix|IsArray|IsDate|IsEmpty|IsNull|IsNumeric|IsObject|Item|Items|Join|Keys|LBound|LCase|Left|Len|LoadPicture|Log|LTrim|RTrim|Trim|Maths|Mid|Minute|Month|MonthName|MsgBox|Now|Oct|Remove|RemoveAll|Replace|RGB|Right|Rnd|Round|ScriptEngine|ScriptEngineBuildVersion|ScriptEngineMajorVersion|ScriptEngineMinorVersion|Second|SetLocale|Sgn|Sin|Space|Split|Sqr|StrComp|String|StrReverse|Tan|Time|Timer|TimeSerial|TimeValue|TypeName|UBound|UCase|Unescape|VarType|Weekday|WeekdayName|Year","support.type.vb.asp":"vbtrue|vbfalse|vbcr|vbcrlf|vbformfeed|vblf|vbnewline|vbnullchar|vbnullstring|int32|vbtab|vbverticaltab|vbbinarycompare|vbtextcomparevbsunday|vbmonday|vbtuesday|vbwednesday|vbthursday|vbfriday|vbsaturday|vbusesystemdayofweek|vbfirstjan1|vbfirstfourdays|vbfirstfullweek|vbgeneraldate|vblongdate|vbshortdate|vblongtime|vbshorttime|vbobjecterror|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant|vbDataObject|vbDecimal|vbByte|vbArray"},"identifier",!0);this.$rules={start:[{token:["meta.ending-space"],regex:"$"},{token:[null],regex:"^(?=\\t)",next:"state_3"},{token:[null],regex:"^(?= )",next:"state_4"},{token:["text","storage.type.function.asp","text","entity.name.function.asp","text","punctuation.definition.parameters.asp","variable.parameter.function.asp","punctuation.definition.parameters.asp"],regex:"^(\\s*)(Function|Sub)(\\s+)([a-zA-Z_]\\w*)(\\s*)(\\()([^)]*)(\\))"},{token:"punctuation.definition.comment.asp",regex:"'|REM(?=\\s|$)",next:"comment",caseInsensitive:!0},{token:"storage.type.asp",regex:"On Error Resume Next|On Error GoTo",caseInsensitive:!0},{token:"punctuation.definition.string.begin.asp",regex:'"',next:"string"},{token:["punctuation.definition.variable.asp"],regex:"(\\$)[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b\\s*"},{token:"constant.numeric.asp",regex:"-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)(?:L|l|UL|ul|u|U|F|f)?\\b"},{regex:"\\w+",token:e},{token:["entity.name.function.asp"],regex:"(?:(\\b[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b)(?=\\(\\)?))"},{token:["keyword.operator.asp"],regex:"\\-|\\+|\\*\\/|\\>|\\<|\\=|\\&"}],state_3:[{token:["meta.odd-tab.tabs","meta.even-tab.tabs"],regex:"(\\t)(\\t)?"},{token:"meta.leading-space",regex:"(?=[^\\t])",next:"start"},{token:"meta.leading-space",regex:".",next:"state_3"}],state_4:[{token:["meta.odd-tab.spaces","meta.even-tab.spaces"],regex:"( )( )?"},{token:"meta.leading-space",regex:"(?=[^ ])",next:"start"},{defaultToken:"meta.leading-space"}],comment:[{token:"comment.line.apostrophe.asp",regex:"$|(?=(?:%>))",next:"start"},{defaultToken:"comment.line.apostrophe.asp"}],string:[{token:"constant.character.escape.apostrophe.asp",regex:'""'},{token:"string.quoted.double.asp",regex:'"',next:"start"},{defaultToken:"string.quoted.double.asp"}]}};r.inherits(s,i),t.VBScriptHighlightRules=s}),define("ace/mode/vbscript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/vbscript_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./vbscript_highlight_rules").VBScriptHighlightRules,o=function(){this.HighlightRules=s};r.inherits(o,i),function(){this.lineCommentStart=["'","REM"],this.$id="ace/mode/vbscript"}.call(o.prototype),t.Mode=o})
\ No newline at end of file
+define("ace/mode/vbscript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e=this.createKeywordMapper({"keyword.control.asp":"If|Then|Else|ElseIf|End|While|Wend|For|To|Each|Case|Select|Return|Continue|Do|Until|Loop|Next|With|Exit|Function|Property|Type|Enum|Sub|IIf","storage.type.asp":"Dim|Call|Class|Const|Dim|Redim|Set|Let|Get|New|Randomize|Option|Explicit","storage.modifier.asp":"Private|Public|Default","keyword.operator.asp":"Mod|And|Not|Or|Xor|as","constant.language.asp":"Empty|False|Nothing|Null|True","support.class.asp":"Application|ObjectContext|Request|Response|Server|Session","support.class.collection.asp":"Contents|StaticObjects|ClientCertificate|Cookies|Form|QueryString|ServerVariable","support.constant.asp":"TotalBytes|Buffer|CacheControl|Charset|ContentType|Expires|ExpiresAbsolute|IsClientConnected|PICS|Status|ScriptTimeout|CodePage|LCID|SessionID|Timeout","support.function.asp":"Lock|Unlock|SetAbort|SetComplete|BinaryRead|AddHeader|AppendToLog|BinaryWrite|Clear|Flush|Redirect|Write|CreateObject|HTMLEncode|MapPath|URLEncode|Abandon|Convert|Regex","support.function.event.asp":"Application_OnEnd|Application_OnStart|OnTransactionAbort|OnTransactionCommit|Session_OnEnd|Session_OnStart","support.function.vb.asp":"Array|Add|Asc|Atn|CBool|CByte|CCur|CDate|CDbl|Chr|CInt|CLng|Conversions|Cos|CreateObject|CSng|CStr|Date|DateAdd|DateDiff|DatePart|DateSerial|DateValue|Day|Derived|Math|Escape|Eval|Exists|Exp|Filter|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent|GetLocale|GetObject|GetRef|Hex|Hour|InputBox|InStr|InStrRev|Int|Fix|IsArray|IsDate|IsEmpty|IsNull|IsNumeric|IsObject|Item|Items|Join|Keys|LBound|LCase|Left|Len|LoadPicture|Log|LTrim|RTrim|Trim|Maths|Mid|Minute|Month|MonthName|MsgBox|Now|Oct|Remove|RemoveAll|Replace|RGB|Right|Rnd|Round|ScriptEngine|ScriptEngineBuildVersion|ScriptEngineMajorVersion|ScriptEngineMinorVersion|Second|SetLocale|Sgn|Sin|Space|Split|Sqr|StrComp|String|StrReverse|Tan|Time|Timer|TimeSerial|TimeValue|TypeName|UBound|UCase|Unescape|VarType|Weekday|WeekdayName|Year","support.type.vb.asp":"vbtrue|vbfalse|vbcr|vbcrlf|vbformfeed|vblf|vbnewline|vbnullchar|vbnullstring|int32|vbtab|vbverticaltab|vbbinarycompare|vbtextcomparevbsunday|vbmonday|vbtuesday|vbwednesday|vbthursday|vbfriday|vbsaturday|vbusesystemdayofweek|vbfirstjan1|vbfirstfourdays|vbfirstfullweek|vbgeneraldate|vblongdate|vbshortdate|vblongtime|vbshorttime|vbobjecterror|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant|vbDataObject|vbDecimal|vbByte|vbArray"},"identifier",!0);this.$rules={start:[{token:["meta.ending-space"],regex:"$"},{token:[null],regex:"^(?=\\t)",next:"state_3"},{token:[null],regex:"^(?= )",next:"state_4"},{token:["text","storage.type.function.asp","text","entity.name.function.asp","text","punctuation.definition.parameters.asp","variable.parameter.function.asp","punctuation.definition.parameters.asp"],regex:"^(\\s*)(Function|Sub)(\\s+)([a-zA-Z_]\\w*)(\\s*)(\\()([^)]*)(\\))"},{token:"punctuation.definition.comment.asp",regex:"'|REM(?=\\s|$)",next:"comment",caseInsensitive:!0},{token:"storage.type.asp",regex:"On Error Resume Next|On Error GoTo",caseInsensitive:!0},{token:"punctuation.definition.string.begin.asp",regex:'"',next:"string"},{token:["punctuation.definition.variable.asp"],regex:"(\\$)[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b\\s*"},{token:"constant.numeric.asp",regex:"-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)(?:L|l|UL|ul|u|U|F|f)?\\b"},{regex:"\\w+",token:e},{token:["entity.name.function.asp"],regex:"(?:(\\b[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*?\\b)(?=\\(\\)?))"},{token:["keyword.operator.asp"],regex:"\\-|\\+|\\*\\/|\\>|\\<|\\=|\\&"}],state_3:[{token:["meta.odd-tab.tabs","meta.even-tab.tabs"],regex:"(\\t)(\\t)?"},{token:"meta.leading-space",regex:"(?=[^\\t])",next:"start"},{token:"meta.leading-space",regex:".",next:"state_3"}],state_4:[{token:["meta.odd-tab.spaces","meta.even-tab.spaces"],regex:"( )( )?"},{token:"meta.leading-space",regex:"(?=[^ ])",next:"start"},{defaultToken:"meta.leading-space"}],comment:[{token:"comment.line.apostrophe.asp",regex:"$|(?=(?:%>))",next:"start"},{defaultToken:"comment.line.apostrophe.asp"}],string:[{token:"constant.character.escape.apostrophe.asp",regex:'""'},{token:"string.quoted.double.asp",regex:'"',next:"start"},{defaultToken:"string.quoted.double.asp"}]}};r.inherits(s,i),t.VBScriptHighlightRules=s}),define("ace/mode/vbscript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/vbscript_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./vbscript_highlight_rules").VBScriptHighlightRules,o=function(){this.HighlightRules=s};r.inherits(o,i),function(){this.lineCommentStart=["'","REM"],this.$id="ace/mode/vbscript"}.call(o.prototype),t.Mode=o})
\ No newline at end of file
diff --git a/resources/themes/pterodactyl/base/index.blade.php b/resources/themes/pterodactyl/base/index.blade.php
index c6066c25a..71efda93f 100644
--- a/resources/themes/pterodactyl/base/index.blade.php
+++ b/resources/themes/pterodactyl/base/index.blade.php
@@ -62,8 +62,8 @@
{{ $server->uuidShort }}
@if(!is_null($server->ip_alias)){{ $server->ip_alias }}@else{{ $server->ip }}@endif:{{ $server->port }}
{{ $server->allocation->alias }}:{{ $server->allocation->port }}
{{ $allocation->ip }}
@@ -63,7 +63,7 @@
{{ $allocation->port }}
{{ $user->email }}
{{ $subuser->user->email }}
{{ $db->a_host }}:{{ $db->a_port }}
{{ $host->host }}:{{ $host->port }}
{{ $db->host }}:{{ $db->port }}
{{ $database->host }}:{{ $database->port }}
A linked node implies that this Database Server is running on that node and it will be auto-selected when adding a database to servers on that node.
diff --git a/resources/views/admin/locations/index.blade.php b/resources/views/admin/locations/index.blade.php index 9aaf49faa..2fbd4b05a 100644 --- a/resources/views/admin/locations/index.blade.php +++ b/resources/views/admin/locations/index.blade.php @@ -46,8 +46,8 @@{{ $location->short }}
{{ $server->a_ownerEmail }}
{{ $server->user->email }}