From 2fc852c6a47ad53ad35c48d24b533758a5a0c7f4 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 15 Jan 2017 14:09:57 -0500 Subject: [PATCH] Push 'Account' and 'Security' pages as well as 'My Servers' --- .../Controllers/Base/SecurityController.php | 6 +- app/Http/Routes/BaseRoutes.php | 3 + app/Http/Routes/ServerRoutes.php | 1 + composer.json | 3 +- config/app.php | 1 + config/laroute.php | 58 ++++ public/js/laroute.js | 186 +++++++++++++ public/themes/pterodactyl/css/pterodactyl.css | 9 + .../pterodactyl/js/frontend/2fa-modal.js | 76 ++++++ .../pterodactyl/js/frontend/serverlist.js | 75 ++++++ .../adminlte/colors/skin-blue-light.min.css | 1 + .../vendor/adminlte/colors/skin-blue.min.css | 1 + .../slimscroll/jquery.slimscroll.min.js | 16 ++ resources/lang/en/base.php | 33 +++ resources/lang/en/strings.php | 19 ++ .../themes/pterodactyl/base/account.blade.php | 98 +++++++ .../themes/pterodactyl/base/index.blade.php | 89 ++++++ .../pterodactyl/base/security.blade.php | 143 ++++++++++ .../pterodactyl/layouts/master.blade.php | 253 ++++++++++++++++++ 19 files changed, 1068 insertions(+), 3 deletions(-) create mode 100644 config/laroute.php create mode 100644 public/js/laroute.js create mode 100644 public/themes/pterodactyl/js/frontend/2fa-modal.js create mode 100644 public/themes/pterodactyl/js/frontend/serverlist.js create mode 100755 public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css create mode 100755 public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css create mode 100755 public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js create mode 100644 resources/lang/en/base.php create mode 100644 resources/themes/pterodactyl/base/account.blade.php create mode 100644 resources/themes/pterodactyl/base/security.blade.php create mode 100644 resources/themes/pterodactyl/layouts/master.blade.php diff --git a/app/Http/Controllers/Base/SecurityController.php b/app/Http/Controllers/Base/SecurityController.php index 1feaa0df3..510d91330 100644 --- a/app/Http/Controllers/Base/SecurityController.php +++ b/app/Http/Controllers/Base/SecurityController.php @@ -79,7 +79,9 @@ class SecurityController extends Controller public function setTotp(Request $request) { if (! $request->has('token')) { - return response(null, 500); + return response()->json([ + 'error' => 'Request is missing token parameter.' + ], 500); } $user = $request->user(); @@ -101,7 +103,7 @@ class SecurityController extends Controller if (! $request->has('token')) { Alert::danger('Missing required `token` field in request.')->flash(); - return redirect()->route('account.totp'); + return redirect()->route('account.security'); } $user = $request->user(); diff --git a/app/Http/Routes/BaseRoutes.php b/app/Http/Routes/BaseRoutes.php index 2cf012e0f..811fb45b7 100644 --- a/app/Http/Routes/BaseRoutes.php +++ b/app/Http/Routes/BaseRoutes.php @@ -64,9 +64,11 @@ class BaseRoutes 'uses' => 'Base\AccountController@index', ]); $router->post('/password', [ + 'as' => 'account.password', 'uses' => 'Base\AccountController@password', ]); $router->post('/email', [ + 'as' => 'account.email', 'uses' => 'Base\AccountController@email', ]); }); @@ -113,6 +115,7 @@ class BaseRoutes 'uses' => 'Base\SecurityController@revoke', ]); $router->put('/totp', [ + 'as' => 'account.security.totp', 'uses' => 'Base\SecurityController@generateTotp', ]); $router->post('/totp', [ diff --git a/app/Http/Routes/ServerRoutes.php b/app/Http/Routes/ServerRoutes.php index 061652761..bef077328 100644 --- a/app/Http/Routes/ServerRoutes.php +++ b/app/Http/Routes/ServerRoutes.php @@ -153,6 +153,7 @@ class ServerRoutes $router->group(['prefix' => 'ajax'], function ($server) use ($router) { // Returns Server Status $router->get('status', [ + 'as' => 'server.ajax.status', 'uses' => 'Server\AjaxController@getStatus', ]); diff --git a/composer.json b/composer.json index 585c51728..6556f5fb9 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "dingo/api": "1.0.0-beta6", "aws/aws-sdk-php": "3.19.20", "predis/predis": "1.1.1", - "laracasts/utilities": "2.1.0" + "laracasts/utilities": "2.1.0", + "lord/laroute": "^2.3" }, "require-dev": { "fzaninotto/faker": "~1.4", diff --git a/config/app.php b/config/app.php index 8fbce1528..bb517f5f7 100644 --- a/config/app.php +++ b/config/app.php @@ -159,6 +159,7 @@ return [ Prologue\Alerts\AlertsServiceProvider::class, Krucas\Settings\Providers\SettingsServiceProvider::class, Laracasts\Utilities\JavaScript\JavaScriptServiceProvider::class, + Lord\Laroute\LarouteServiceProvider::class, ], diff --git a/config/laroute.php b/config/laroute.php new file mode 100644 index 000000000..7b332c40a --- /dev/null +++ b/config/laroute.php @@ -0,0 +1,58 @@ + 'public/js', + + /* + * The destination filename for the javascript file. + */ + 'filename' => 'laroute', + + /* + * The namespace for the helper functions. By default this will bind them to + * `window.laroute`. + */ + 'namespace' => 'Router', + + /* + * Generate absolute URLs + * + * Set the Application URL in config/app.php + */ + 'absolute' => false, + + /* + * The Filter Method + * + * 'all' => All routes except "'laroute' => false" + * 'only' => Only "'laroute' => true" routes + * 'force' => All routes, ignored "laroute" route parameter + */ + 'filter' => 'all', + + /* + * Controller Namespace + * + * Set here your controller namespace (see RouteServiceProvider -> $namespace) for cleaner action calls + * e.g. 'App\Http\Controllers' + */ + 'action_namespace' => '', + + /* + * The path to the template `laroute.js` file. This is the file that contains + * the ported helper Laravel url/route functions and the route data to go + * with them. + */ + 'template' => 'vendor/lord/laroute/src/templates/laroute.js', + + /* + * Appends a prefix to URLs. By default the prefix is an empty string. + * + */ + 'prefix' => '', + +]; diff --git a/public/js/laroute.js b/public/js/laroute.js new file mode 100644 index 000000000..d8913f682 --- /dev/null +++ b/public/js/laroute.js @@ -0,0 +1,186 @@ +(function () { + + var laroute = (function () { + + var routes = { + + 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":["POST"],"uri":"server\/{server}\/settings\/sftp","name":"server.settings.sftp","action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsSFTP"},{"host":null,"methods":["POST"],"uri":"server\/{server}\/settings\/startup","name":"server.settings.startup","action":"Pterodactyl\Http\Controllers\Server\ServerController@postSettingsStartup"},{"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) { + route = route || this.getByName(name); + + if ( ! route ) { + return undefined; + } + + return this.toRoute(route, parameters); + }, + + url: function (url, parameters) { + parameters = parameters || []; + + var uri = url + '/' + parameters.join('/'); + + return this.getCorrectUrl(uri); + }, + + toRoute : function (route, parameters) { + var uri = this.replaceNamedParameters(route.uri, parameters); + var qs = this.getRouteQueryString(parameters); + + return this.getCorrectUrl(uri + qs); + }, + + replaceNamedParameters : function (uri, parameters) { + uri = uri.replace(/\{(.*?)\??\}/g, function(match, key) { + if (parameters.hasOwnProperty(key)) { + var value = parameters[key]; + delete parameters[key]; + return value; + } else { + return match; + } + }); + + // Strip out any optional parameters that were not given + uri = uri.replace(/\/\{.*?\?\}/g, ''); + + return uri; + }, + + getRouteQueryString : function (parameters) { + var qs = []; + for (var key in parameters) { + if (parameters.hasOwnProperty(key)) { + qs.push(key + '=' + parameters[key]); + } + } + + if (qs.length < 1) { + return ''; + } + + return '?' + qs.join('&'); + }, + + getByName : function (name) { + for (var key in this.routes) { + if (this.routes.hasOwnProperty(key) && this.routes[key].name === name) { + return this.routes[key]; + } + } + }, + + getByAction : function(action) { + for (var key in this.routes) { + if (this.routes.hasOwnProperty(key) && this.routes[key].action === action) { + return this.routes[key]; + } + } + }, + + getCorrectUrl: function (uri) { + var url = this.prefix + '/' + uri.replace(/^\/?/, ''); + + if(!this.absolute) + return url; + + return this.rootUrl.replace('/\/?$/', '') + url; + } + }; + + var getLinkAttributes = function(attributes) { + if ( ! attributes) { + return ''; + } + + var attrs = []; + for (var key in attributes) { + if (attributes.hasOwnProperty(key)) { + attrs.push(key + '="' + attributes[key] + '"'); + } + } + + return attrs.join(' '); + }; + + var getHtmlLink = function (url, title, attributes) { + title = title || url; + attributes = getLinkAttributes(attributes); + + return '' + title + ''; + }; + + return { + // Generate a url for a given controller action. + // Router.action('HomeController@getIndex', [params = {}]) + action : function (name, parameters) { + parameters = parameters || {}; + + return routes.route(name, parameters, routes.getByAction(name)); + }, + + // Generate a url for a given named route. + // Router.route('routeName', [params = {}]) + route : function (route, parameters) { + parameters = parameters || {}; + + return routes.route(route, parameters); + }, + + // Generate a fully qualified URL to the given path. + // Router.route('url', [params = {}]) + url : function (route, parameters) { + parameters = parameters || {}; + + return routes.url(route, parameters); + }, + + // Generate a html link to the given url. + // Router.link_to('foo/bar', [title = url], [attributes = {}]) + link_to : function (url, title, attributes) { + url = this.url(url); + + return getHtmlLink(url, title, attributes); + }, + + // Generate a html link to the given route. + // Router.link_to_route('route.name', [title=url], [parameters = {}], [attributes = {}]) + link_to_route : function (route, title, parameters, attributes) { + var url = this.route(route, parameters); + + return getHtmlLink(url, title, attributes); + }, + + // Generate a html link to the given controller action. + // Router.link_to_action('HomeController@getIndex', [title=url], [parameters = {}], [attributes = {}]) + link_to_action : function(action, title, parameters, attributes) { + var url = this.action(action, parameters); + + return getHtmlLink(url, title, attributes); + } + + }; + + }).call(this); + + /** + * Expose the class either via AMD, CommonJS or the global object + */ + if (typeof define === 'function' && define.amd) { + define(function () { + return laroute; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = laroute; + } + else { + window.Router = laroute; + } + +}).call(this); + diff --git a/public/themes/pterodactyl/css/pterodactyl.css b/public/themes/pterodactyl/css/pterodactyl.css index fd02c82c2..c3c27b00e 100644 --- a/public/themes/pterodactyl/css/pterodactyl.css +++ b/public/themes/pterodactyl/css/pterodactyl.css @@ -36,3 +36,12 @@ .btn-clear { background: transparent; } + +.user-panel > .info { + position: relative; + left: 0; +} + +code { + font-size: 85%; +} diff --git a/public/themes/pterodactyl/js/frontend/2fa-modal.js b/public/themes/pterodactyl/js/frontend/2fa-modal.js new file mode 100644 index 000000000..492cb1607 --- /dev/null +++ b/public/themes/pterodactyl/js/frontend/2fa-modal.js @@ -0,0 +1,76 @@ +// Copyright (c) 2015 - 2016 Dane Everitt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +$(document).ready(function () { + $('#close_reload').click(function () { + location.reload(); + }); + $('#do_2fa').submit(function (event) { + event.preventDefault(); + + $.ajax({ + type: 'PUT', + url: Router.route('account.security.totp'), + headers: { + 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'), + } + }).done(function (data) { + var image = new Image(); + image.src = data.qrImage; + $(image).load(function () { + $('#hide_img_load').slideUp(function () { + $('#qr_image_insert').attr('src', image.src).slideDown(); + }); + }); + $('#2fa_secret_insert').html(data.secret); + $('#open2fa').modal('show'); + }).fail(function (jqXHR) { + alert('An error occured while attempting to load the 2FA setup modal. Please try again.'); + console.error(jqXHR); + }); + + }); + $('#2fa_token_verify').submit(function (event) { + event.preventDefault(); + $('#submit_action').html(' Submit').addClass('disabled'); + + $.ajax({ + type: 'POST', + url: Router.route('account.security.totp'), + headers: { + 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'), + }, + data: { + token: $('#2fa_token').val() + } + }).done(function (data) { + $('#notice_box_2fa').hide(); + if (data === 'true') { + $('#notice_box_2fa').html('
2-Factor Authentication has been enabled on your account. Press \'Close\' below to reload the page.
').slideDown(); + } else { + $('#notice_box_2fa').html('
The token provided was invalid.
').slideDown(); + } + }).fail(function (jqXHR) { + $('#notice_box_2fa').html('
There was an error while attempting to enable 2-Factor Authentication on this account.
').slideDown(); + console.error(jqXHR); + }).always(function () { + $('#submit_action').html('Submit').removeClass('disabled'); + }); + }); +}); diff --git a/public/themes/pterodactyl/js/frontend/serverlist.js b/public/themes/pterodactyl/js/frontend/serverlist.js new file mode 100644 index 000000000..12929c2ab --- /dev/null +++ b/public/themes/pterodactyl/js/frontend/serverlist.js @@ -0,0 +1,75 @@ +// Copyright (c) 2015 - 2016 Dane Everitt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +var Status = { + 0: 'Offline', + 1: 'Online', + 2: 'Starting', + 3: 'Stopping' +}; + +(function updateServerStatus () { + $('.dynamic-update').each(function (index, data) { + var element = $(this); + var serverShortUUID = $(this).data('server'); + $.ajax({ + type: 'GET', + url: Router.route('server.ajax.status', { server: serverShortUUID }), + timeout: 5000, + headers: { + 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'), + } + }).done(function (data) { + if (typeof data.status === 'undefined') { + element.find('[data-action="status"]').html('Error'); + return; + } + switch (data.status) { + case 0: + element.find('[data-action="status"]').html('Offline'); + break; + case 1: + element.find('[data-action="status"]').html('Online'); + break; + case 2: + element.find('[data-action="status"]').html('Starting'); + break; + case 3: + element.find('[data-action="status"]').html('Stopping'); + break; + } + if (data.status !== 0) { + var cpuMax = element.find('[data-action="cpu"]').data('cpumax'); + var currentCpu = data.proc.cpu.total; + if (cpuMax !== 0) { + currentCpu = parseFloat(((data.proc.cpu.total / cpuMax) * 100).toFixed(2).toString()); + } + element.find('[data-action="memory"]').html(parseInt(data.proc.memory.total / (1024 * 1024))); + element.find('[data-action="cpu"]').html(currentCpu); + } else { + element.find('[data-action="memory"]').html('--'); + element.find('[data-action="cpu"]').html('--'); + } + }).fail(function (jqXHR) { + console.error(jqXHR); + element.find('[data-action="status"]').html('Error'); + }); + }); + setTimeout(updateServerStatus, 10000); +})(); diff --git a/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css b/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css new file mode 100755 index 000000000..c41ca33fa --- /dev/null +++ b/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css @@ -0,0 +1 @@ +.skin-blue-light .main-header .navbar{background-color:#3c8dbc}.skin-blue-light .main-header .navbar .nav>li>a{color:#fff}.skin-blue-light .main-header .navbar .nav>li>a:hover,.skin-blue-light .main-header .navbar .nav>li>a:active,.skin-blue-light .main-header .navbar .nav>li>a:focus,.skin-blue-light .main-header .navbar .nav .open>a,.skin-blue-light .main-header .navbar .nav .open>a:hover,.skin-blue-light .main-header .navbar .nav .open>a:focus,.skin-blue-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-blue-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-blue-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue-light .main-header .navbar .sidebar-toggle:hover{background-color:#367fa9}@media (max-width:767px){.skin-blue-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-blue-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-blue-light .main-header .navbar .dropdown-menu li a:hover{background:#367fa9}}.skin-blue-light .main-header .logo{background-color:#3c8dbc;color:#fff;border-bottom:0 solid transparent}.skin-blue-light .main-header .logo:hover{background-color:#3b8ab8}.skin-blue-light .main-header li.user-header{background-color:#3c8dbc}.skin-blue-light .content-header{background:transparent}.skin-blue-light .wrapper,.skin-blue-light .main-sidebar,.skin-blue-light .left-side{background-color:#f9fafc}.skin-blue-light .content-wrapper,.skin-blue-light .main-footer{border-left:1px solid #d2d6de}.skin-blue-light .user-panel>.info,.skin-blue-light .user-panel>.info>a{color:#444}.skin-blue-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-blue-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-blue-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-blue-light .sidebar-menu>li:hover>a,.skin-blue-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-blue-light .sidebar-menu>li.active{border-left-color:#3c8dbc}.skin-blue-light .sidebar-menu>li.active>a{font-weight:600}.skin-blue-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-blue-light .sidebar a{color:#444}.skin-blue-light .sidebar a:hover{text-decoration:none}.skin-blue-light .treeview-menu>li>a{color:#777}.skin-blue-light .treeview-menu>li.active>a,.skin-blue-light .treeview-menu>li>a:hover{color:#000}.skin-blue-light .treeview-menu>li.active>a{font-weight:600}.skin-blue-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-blue-light .sidebar-form input[type="text"],.skin-blue-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-blue-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-blue-light .sidebar-form input[type="text"]:focus,.skin-blue-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-blue-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-blue-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-blue-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}.skin-blue-light .main-footer{border-top-color:#d2d6de}.skin-blue.layout-top-nav .main-header>.logo{background-color:#3c8dbc;color:#fff;border-bottom:0 solid transparent}.skin-blue.layout-top-nav .main-header>.logo:hover{background-color:#3b8ab8} \ No newline at end of file diff --git a/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css b/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css new file mode 100755 index 000000000..44524fe38 --- /dev/null +++ b/public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css @@ -0,0 +1 @@ +.skin-blue .main-header .navbar{background-color:#3c8dbc}.skin-blue .main-header .navbar .nav>li>a{color:#fff}.skin-blue .main-header .navbar .nav>li>a:hover,.skin-blue .main-header .navbar .nav>li>a:active,.skin-blue .main-header .navbar .nav>li>a:focus,.skin-blue .main-header .navbar .nav .open>a,.skin-blue .main-header .navbar .nav .open>a:hover,.skin-blue .main-header .navbar .nav .open>a:focus,.skin-blue .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-blue .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-blue .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue .main-header .navbar .sidebar-toggle:hover{background-color:#367fa9}@media (max-width:767px){.skin-blue .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-blue .main-header .navbar .dropdown-menu li a{color:#fff}.skin-blue .main-header .navbar .dropdown-menu li a:hover{background:#367fa9}}.skin-blue .main-header .logo{background-color:#367fa9;color:#fff;border-bottom:0 solid transparent}.skin-blue .main-header .logo:hover{background-color:#357ca5}.skin-blue .main-header li.user-header{background-color:#3c8dbc}.skin-blue .content-header{background:transparent}.skin-blue .wrapper,.skin-blue .main-sidebar,.skin-blue .left-side{background-color:#222d32}.skin-blue .user-panel>.info,.skin-blue .user-panel>.info>a{color:#fff}.skin-blue .sidebar-menu>li.header{color:#4b646f;background:#1a2226}.skin-blue .sidebar-menu>li>a{border-left:3px solid transparent}.skin-blue .sidebar-menu>li:hover>a,.skin-blue .sidebar-menu>li.active>a{color:#fff;background:#1e282c;border-left-color:#3c8dbc}.skin-blue .sidebar-menu>li>.treeview-menu{margin:0 1px;background:#2c3b41}.skin-blue .sidebar a{color:#b8c7ce}.skin-blue .sidebar a:hover{text-decoration:none}.skin-blue .treeview-menu>li>a{color:#8aa4af}.skin-blue .treeview-menu>li.active>a,.skin-blue .treeview-menu>li>a:hover{color:#fff}.skin-blue .sidebar-form{border-radius:3px;border:1px solid #374850;margin:10px 10px}.skin-blue .sidebar-form input[type="text"],.skin-blue .sidebar-form .btn{box-shadow:none;background-color:#374850;border:1px solid transparent;height:35px}.skin-blue .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-blue .sidebar-form input[type="text"]:focus,.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-blue .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}.skin-blue.layout-top-nav .main-header>.logo{background-color:#3c8dbc;color:#fff;border-bottom:0 solid transparent}.skin-blue.layout-top-nav .main-header>.logo:hover{background-color:#3b8ab8} \ No newline at end of file diff --git a/public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js b/public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js new file mode 100755 index 000000000..7531ab35f --- /dev/null +++ b/public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js @@ -0,0 +1,16 @@ +/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Version: 1.3.8 + * + */ +(function(e){e.fn.extend({slimScroll:function(f){var a=e.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},f);this.each(function(){function v(d){if(r){d=d||window.event; +var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);e(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&n(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function n(d,g,e){k=!1;var f=b.outerHeight()-c.outerHeight();g&&(g=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),g=Math.min(Math.max(g,0),f),g=0=b.outerHeight()?k=!0:(c.stop(!0, +!0).fadeIn("fast"),a.railVisible&&m.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(B=setTimeout(function(){a.disableFadeOut&&r||y||z||(c.fadeOut("slow"),m.fadeOut("slow"))},1E3))}var r,y,z,B,A,u,l,C,k=!1,b=e(this);if(b.parent().hasClass(a.wrapperClass)){var q=b.scrollTop(),c=b.siblings("."+a.barClass),m=b.siblings("."+a.railClass);x();if(e.isPlainObject(f)){if("height"in f&&"auto"==f.height){b.parent().css("height","auto");b.css("height","auto");var h=b.parent().parent().height();b.parent().css("height", +h);b.css("height",h)}else"height"in f&&(h=f.height,b.parent().css("height",h),b.css("height",h));if("scrollTo"in f)q=parseInt(a.scrollTo);else if("scrollBy"in f)q+=parseInt(a.scrollBy);else if("destroy"in f){c.remove();m.remove();b.unwrap();return}n(q,!1,!0)}}else if(!(e.isPlainObject(f)&&"destroy"in f)){a.height="auto"==a.height?b.parent().height():a.height;q=e("
").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden", +width:a.width,height:a.height});var m=e("
").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=e("
").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius, +WebkitBorderRadius:a.borderRadius,zIndex:99}),h="right"==a.position?{right:a.distance}:{left:a.distance};m.css(h);c.css(h);b.wrap(q);b.parent().append(c);b.parent().append(m);a.railDraggable&&c.bind("mousedown",function(a){var b=e(document);z=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);n(0,c.position().top,!1)});b.bind("mouseup.slimscroll",function(a){z=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll", +function(a){a.stopPropagation();a.preventDefault();return!1});m.hover(function(){w()},function(){p()});c.hover(function(){y=!0},function(){y=!1});b.hover(function(){r=!0;w();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(A=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&(n((A-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),A=b.originalEvent.touches[0].pageY)}); +x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),n(0,!0)):"top"!==a.start&&(n(e(a.start).position().top,null,!0),a.alwaysVisible||c.hide());window.addEventListener?(this.addEventListener("DOMMouseScroll",v,!1),this.addEventListener("mousewheel",v,!1)):document.attachEvent("onmousewheel",v)}});return this}});e.fn.extend({slimscroll:e.fn.slimScroll})})(jQuery); \ No newline at end of file diff --git a/resources/lang/en/base.php b/resources/lang/en/base.php new file mode 100644 index 000000000..49f90ff33 --- /dev/null +++ b/resources/lang/en/base.php @@ -0,0 +1,33 @@ + 'There was an error with one or more fields in the request.', + 'index' => [ + 'header' => 'Your Servers', + 'header_sub' => 'Servers you own and have access to.', + 'list' => 'Server List', + ], + 'account' => [ + 'header' => 'Your Account', + 'header_sub' => 'Manage your account details.', + 'update_pass' => 'Update Password', + 'update_email' => 'Update Email Address', + 'current_password' => 'Current Password', + 'new_password' => 'New Password', + 'new_password_again' => 'Repeat New Password', + 'new_email' => 'New Email Address', + ], + 'security' => [ + 'header' => 'Account Security', + 'header_sub' => 'Control active sessions and 2-Factor Authentication.', + 'sessions' => 'Active Sessions', + '2fa_header' => '2-Factor Authentication', + '2fa_token_help' => 'Enter the 2FA Token generated by your app (Google Authenticatior, Authy, etc.).', + 'disable_2fa' => 'Disable 2-Factor Authentication', + '2fa_enabled' => '2-Factor Authentication is enabled on this account and will be required in order to login to the panel. If you would like to disable 2FA, simply enter a valid token below and submit the form.', + '2fa_disabled' => '2-Factor Authentication is disabled on your account! You should enable 2FA in order to add an extra level of protection on your account.', + 'enable_2fa' => 'Enable 2-Factor Authentication', + '2fa_qr' => 'Confgure 2FA on Your Device', + '2fa_checkpoint_help' => 'Use the 2FA application on your phone to take a picture of the QR code to the left, or manually enter the code under it. Once you have done so, generate a token and enter it below.', + ], +]; diff --git a/resources/lang/en/strings.php b/resources/lang/en/strings.php index fc7f54f4c..80d3c651d 100644 --- a/resources/lang/en/strings.php +++ b/resources/lang/en/strings.php @@ -5,4 +5,23 @@ return [ 'password' => 'Password', 'confirm_password' => 'Confirm Password', 'login' => 'Login', + 'home' => 'Home', + 'servers' => 'Servers', + 'id' => 'ID', + 'name' => 'Name', + 'node' => 'Node', + 'connection' => 'Connection', + 'memory' => 'Memory', + 'cpu' => 'CPU', + 'status' => 'Status', + 'search' => 'Search', + 'suspended' => 'Suspended', + 'account' => 'Account', + 'security' => 'Security', + 'ip' => 'IP Address', + 'last_activity' => 'Last Activitiy', + 'revoke' => 'Revoke', + '2fa_token' => 'Authentication Token', + 'submit' => 'Submit', + 'close' => 'Close', ]; diff --git a/resources/themes/pterodactyl/base/account.blade.php b/resources/themes/pterodactyl/base/account.blade.php new file mode 100644 index 000000000..9ab86ee87 --- /dev/null +++ b/resources/themes/pterodactyl/base/account.blade.php @@ -0,0 +1,98 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.master') + +@section('title') + {{ trans('base.account.header') }} +@endsection + +@section('content-header') +

{{ trans('base.account.header') }}{{ trans('base.account.header_sub')}}

+ +@endsection + +@section('content') +
+
+
+
+

{{ trans('base.account.update_pass') }}

+
+
+
+
+ +
+ +
+
+
+ +
+ +

{{ trans('auth.password_requirements') }}

+
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+
+

{{ trans('base.account.update_email') }}

+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+@endsection diff --git a/resources/themes/pterodactyl/base/index.blade.php b/resources/themes/pterodactyl/base/index.blade.php index e69de29bb..0ac1b3e08 100644 --- a/resources/themes/pterodactyl/base/index.blade.php +++ b/resources/themes/pterodactyl/base/index.blade.php @@ -0,0 +1,89 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.master') + +@section('title') + {{ trans('base.index.header') }} +@endsection + +@section('content-header') +

{{ trans('base.index.header') }}{{ trans('base.index.header_sub')}}

+ +@endsection + +@section('content') +
+
+
+
+

{{ trans('base.index.list') }}

+
+
+ +
+ +
+
+
+
+
+ + + + + + + + + + + + @foreach($servers as $server) + + + + + + + + + + @endforeach + +
{{ trans('strings.id') }}{{ trans('strings.name') }}{{ trans('strings.node') }}{{ trans('strings.connection') }}{{ trans('strings.status') }}
{{ $server->uuidShort }}{{ $server->name }}{{ $server->nodeName }}@if(!is_null($server->ip_alias)){{ $server->ip_alias }}@else{{ $server->ip }}@endif:{{ $server->port }} + @if($server->suspended === 1) + {{ trans('strings.suspended') }} + @else + + @endif +
+
+
+
+
+@endsection + +@section('footer-scripts') + @parent + {!! Theme::js('js/frontend/serverlist.js') !!} +@endsection diff --git a/resources/themes/pterodactyl/base/security.blade.php b/resources/themes/pterodactyl/base/security.blade.php new file mode 100644 index 000000000..d32ffe31f --- /dev/null +++ b/resources/themes/pterodactyl/base/security.blade.php @@ -0,0 +1,143 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} +@extends('layouts.master') + +@section('title') + {{ trans('base.security.header') }} +@endsection + +@section('content-header') +

{{ trans('base.security.header') }}{{ trans('base.security.header_sub')}}

+ +@endsection + +@section('content') +
+
+
+
+

{{ trans('base.security.sessions') }}

+
+
+ + + + + + + + + @foreach($sessions as $session) + + + + + + + @endforeach + +
{{ trans('strings.id') }}{{ trans('strings.ip') }}{{ trans('strings.last_activity') }}
{{ substr($session->id, 0, 6) }}{{ $session->ip_address }}{{ Carbon::createFromTimestamp($session->last_activity)->diffForHumans() }} + + + +
+
+
+
+
+
+
+

{{ trans('base.security.2fa_header') }}

+
+ @if(Auth::user()->use_totp) +
+
+

{{ trans('base.security.2fa_enabled') }}

+
+ +
+ +

{{ trans('base.security.2fa_token_help') }}

+
+
+
+ +
+ @else +
+
+ {{ trans('base.security.2fa_disabled') }} +
+ +
+ @endif +
+
+
+ +@endsection + +@section('footer-scripts') + @parent + {!! Theme::js('js/frontend/2fa-modal.js') !!} +@endsection diff --git a/resources/themes/pterodactyl/layouts/master.blade.php b/resources/themes/pterodactyl/layouts/master.blade.php new file mode 100644 index 000000000..6e63bdce0 --- /dev/null +++ b/resources/themes/pterodactyl/layouts/master.blade.php @@ -0,0 +1,253 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}} +{{-- of this software and associated documentation files (the "Software"), to deal --}} +{{-- in the Software without restriction, including without limitation the rights --}} +{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}} +{{-- copies of the Software, and to permit persons to whom the Software is --}} +{{-- furnished to do so, subject to the following conditions: --}} + +{{-- The above copyright notice and this permission notice shall be included in all --}} +{{-- copies or substantial portions of the Software. --}} + +{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}} +{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}} +{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}} +{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}} +{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}} +{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}} +{{-- SOFTWARE. --}} + + + + + + {{ Settings::get('company', 'Pterodactyl') }} - @yield('title') + + + @section('scripts') + {!! Theme::css('vendor/bootstrap/bootstrap.min.css') !!} + {!! Theme::css('vendor/adminlte/admin.min.css') !!} + {!! Theme::css('vendor/adminlte/colors/skin-blue.min.css') !!} + {!! Theme::css('css/pterodactyl.css') !!} + + + + + @show + + +
+
+ + +
+ +
+
+ @yield('content-header') +
+
+
+
+ @if (count($errors) > 0) +
+ {{ trans('base.validation_error') }}

+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + @foreach (Alert::getMessages() as $type => $messages) + @foreach ($messages as $message) + + @endforeach + @endforeach +
+
+ @yield('content') +
+
+ + +
+
+ @section('footer-scripts') + {!! Theme::js('js/laroute.js') !!} + {!! Theme::js('js/vendor/jquery/jquery.min.js') !!} + {!! Theme::js('vendor/bootstrap/bootstrap.min.js') !!} + {!! Theme::js('vendor/slimscroll/jquery.slimscroll.min.js') !!} + {!! Theme::js('vendor/adminlte/app.min.js') !!} + @show + +