Push 'Account' and 'Security' pages as well as 'My Servers'
This commit is contained in:
parent
1c85b1fbc4
commit
2fc852c6a4
19 changed files with 1068 additions and 3 deletions
|
@ -79,7 +79,9 @@ class SecurityController extends Controller
|
||||||
public function setTotp(Request $request)
|
public function setTotp(Request $request)
|
||||||
{
|
{
|
||||||
if (! $request->has('token')) {
|
if (! $request->has('token')) {
|
||||||
return response(null, 500);
|
return response()->json([
|
||||||
|
'error' => 'Request is missing token parameter.'
|
||||||
|
], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
@ -101,7 +103,7 @@ class SecurityController extends Controller
|
||||||
if (! $request->has('token')) {
|
if (! $request->has('token')) {
|
||||||
Alert::danger('Missing required `token` field in request.')->flash();
|
Alert::danger('Missing required `token` field in request.')->flash();
|
||||||
|
|
||||||
return redirect()->route('account.totp');
|
return redirect()->route('account.security');
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
|
@ -64,9 +64,11 @@ class BaseRoutes
|
||||||
'uses' => 'Base\AccountController@index',
|
'uses' => 'Base\AccountController@index',
|
||||||
]);
|
]);
|
||||||
$router->post('/password', [
|
$router->post('/password', [
|
||||||
|
'as' => 'account.password',
|
||||||
'uses' => 'Base\AccountController@password',
|
'uses' => 'Base\AccountController@password',
|
||||||
]);
|
]);
|
||||||
$router->post('/email', [
|
$router->post('/email', [
|
||||||
|
'as' => 'account.email',
|
||||||
'uses' => 'Base\AccountController@email',
|
'uses' => 'Base\AccountController@email',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -113,6 +115,7 @@ class BaseRoutes
|
||||||
'uses' => 'Base\SecurityController@revoke',
|
'uses' => 'Base\SecurityController@revoke',
|
||||||
]);
|
]);
|
||||||
$router->put('/totp', [
|
$router->put('/totp', [
|
||||||
|
'as' => 'account.security.totp',
|
||||||
'uses' => 'Base\SecurityController@generateTotp',
|
'uses' => 'Base\SecurityController@generateTotp',
|
||||||
]);
|
]);
|
||||||
$router->post('/totp', [
|
$router->post('/totp', [
|
||||||
|
|
|
@ -153,6 +153,7 @@ class ServerRoutes
|
||||||
$router->group(['prefix' => 'ajax'], function ($server) use ($router) {
|
$router->group(['prefix' => 'ajax'], function ($server) use ($router) {
|
||||||
// Returns Server Status
|
// Returns Server Status
|
||||||
$router->get('status', [
|
$router->get('status', [
|
||||||
|
'as' => 'server.ajax.status',
|
||||||
'uses' => 'Server\AjaxController@getStatus',
|
'uses' => 'Server\AjaxController@getStatus',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
"dingo/api": "1.0.0-beta6",
|
"dingo/api": "1.0.0-beta6",
|
||||||
"aws/aws-sdk-php": "3.19.20",
|
"aws/aws-sdk-php": "3.19.20",
|
||||||
"predis/predis": "1.1.1",
|
"predis/predis": "1.1.1",
|
||||||
"laracasts/utilities": "2.1.0"
|
"laracasts/utilities": "2.1.0",
|
||||||
|
"lord/laroute": "^2.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fzaninotto/faker": "~1.4",
|
"fzaninotto/faker": "~1.4",
|
||||||
|
|
|
@ -159,6 +159,7 @@ return [
|
||||||
Prologue\Alerts\AlertsServiceProvider::class,
|
Prologue\Alerts\AlertsServiceProvider::class,
|
||||||
Krucas\Settings\Providers\SettingsServiceProvider::class,
|
Krucas\Settings\Providers\SettingsServiceProvider::class,
|
||||||
Laracasts\Utilities\JavaScript\JavaScriptServiceProvider::class,
|
Laracasts\Utilities\JavaScript\JavaScriptServiceProvider::class,
|
||||||
|
Lord\Laroute\LarouteServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
58
config/laroute.php
Normal file
58
config/laroute.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The destination path for the javascript file.
|
||||||
|
*/
|
||||||
|
'path' => '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' => '',
|
||||||
|
|
||||||
|
];
|
186
public/js/laroute.js
Normal file
186
public/js/laroute.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -36,3 +36,12 @@
|
||||||
.btn-clear {
|
.btn-clear {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-panel > .info {
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 85%;
|
||||||
|
}
|
||||||
|
|
76
public/themes/pterodactyl/js/frontend/2fa-modal.js
Normal file
76
public/themes/pterodactyl/js/frontend/2fa-modal.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
$(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('<i class="fa fa-spinner fa-spin"></i> 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('<div class="alert alert-success">2-Factor Authentication has been enabled on your account. Press \'Close\' below to reload the page.</div>').slideDown();
|
||||||
|
} else {
|
||||||
|
$('#notice_box_2fa').html('<div class="alert alert-danger">The token provided was invalid.</div>').slideDown();
|
||||||
|
}
|
||||||
|
}).fail(function (jqXHR) {
|
||||||
|
$('#notice_box_2fa').html('<div class="alert alert-danger">There was an error while attempting to enable 2-Factor Authentication on this account.</div>').slideDown();
|
||||||
|
console.error(jqXHR);
|
||||||
|
}).always(function () {
|
||||||
|
$('#submit_action').html('Submit').removeClass('disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
75
public/themes/pterodactyl/js/frontend/serverlist.js
Normal file
75
public/themes/pterodactyl/js/frontend/serverlist.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
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('<span class="label label-default">Error</span>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (data.status) {
|
||||||
|
case 0:
|
||||||
|
element.find('[data-action="status"]').html('<span class="label label-danger">Offline</span>');
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
element.find('[data-action="status"]').html('<span class="label label-success">Online</span>');
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
element.find('[data-action="status"]').html('<span class="label label-info">Starting</span>');
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
element.find('[data-action="status"]').html('<span class="label label-info">Stopping</span>');
|
||||||
|
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('<span class="label label-default">Error</span>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setTimeout(updateServerStatus, 10000);
|
||||||
|
})();
|
1
public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css
vendored
Executable file
1
public/themes/pterodactyl/vendor/adminlte/colors/skin-blue-light.min.css
vendored
Executable file
|
@ -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}
|
1
public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css
vendored
Executable file
1
public/themes/pterodactyl/vendor/adminlte/colors/skin-blue.min.css
vendored
Executable file
|
@ -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}
|
16
public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js
vendored
Executable file
16
public/themes/pterodactyl/vendor/slimscroll/jquery.slimscroll.min.js
vendored
Executable file
|
@ -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<d?Math.ceil(g):Math.floor(g),c.css({top:g+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());g=
|
||||||
|
l*(b[0].scrollHeight-b.outerHeight());e&&(g=d,d=g/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),f),c.css({top:d+"px"}));b.scrollTop(g);b.trigger("slimscrolling",~~g);w();p()}function x(){u=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),30);c.css({height:u+"px"});var a=u==b.outerHeight()?"none":"block";c.css({display:a})}function w(){x();clearTimeout(B);l==~~l?(k=a.allowPageScroll,C!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;C=l;u>=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("<div></div>").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("<div></div>").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("<div></div>").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);
|
33
resources/lang/en/base.php
Normal file
33
resources/lang/en/base.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'validation_error' => '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.',
|
||||||
|
],
|
||||||
|
];
|
|
@ -5,4 +5,23 @@ return [
|
||||||
'password' => 'Password',
|
'password' => 'Password',
|
||||||
'confirm_password' => 'Confirm Password',
|
'confirm_password' => 'Confirm Password',
|
||||||
'login' => 'Login',
|
'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',
|
||||||
];
|
];
|
||||||
|
|
98
resources/themes/pterodactyl/base/account.blade.php
Normal file
98
resources/themes/pterodactyl/base/account.blade.php
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
|
||||||
|
|
||||||
|
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||||
|
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||||
|
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||||
|
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||||
|
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||||
|
{{-- furnished to do so, subject to the following conditions: --}}
|
||||||
|
|
||||||
|
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||||
|
{{-- copies or substantial portions of the Software. --}}
|
||||||
|
|
||||||
|
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||||
|
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||||
|
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||||
|
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||||
|
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||||
|
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||||
|
{{-- SOFTWARE. --}}
|
||||||
|
@extends('layouts.master')
|
||||||
|
|
||||||
|
@section('title')
|
||||||
|
{{ trans('base.account.header') }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content-header')
|
||||||
|
<h1>{{ trans('base.account.header') }}<small>{{ trans('base.account.header_sub')}}</small></h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="{{ route('index') }}">{{ trans('strings.home') }}</a></li>
|
||||||
|
<li class="active">{{ trans('strings.account') }}</li>
|
||||||
|
</ol>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('base.account.update_pass') }}</h3>
|
||||||
|
</div>
|
||||||
|
<form action="{{ route('account.password') }}" method="post">
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="current_password" class="control-label">{{ trans('base.account.current_password') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="password" class="form-control" name="current_password" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_password" class="control-label">{{ trans('base.account.new_password') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="password" class="form-control" name="new_password" />
|
||||||
|
<p class="text-muted"><small>{{ trans('auth.password_requirements') }}</small></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_password_again" class="control-label">{{ trans('base.account.new_password_again') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="password" class="form-control" name="new_password_confirmation" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
<input type="submit" class="btn btn-primary btn-sm" value="{{ trans('base.account.update_pass') }}" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('base.account.update_email') }}</h3>
|
||||||
|
</div>
|
||||||
|
<form action="{{ route('account.email') }}" method="post">
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_email" class="control-label">{{ trans('base.account.new_email') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control" name="new_email" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password" class="control-label">{{ trans('base.account.current_password') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="password" class="form-control" name="password" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
<input type="submit" class="btn btn-primary btn-sm" value="{{ trans('base.account.update_email') }}" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -0,0 +1,89 @@
|
||||||
|
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
|
||||||
|
|
||||||
|
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||||
|
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||||
|
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||||
|
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||||
|
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||||
|
{{-- furnished to do so, subject to the following conditions: --}}
|
||||||
|
|
||||||
|
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||||
|
{{-- copies or substantial portions of the Software. --}}
|
||||||
|
|
||||||
|
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||||
|
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||||
|
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||||
|
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||||
|
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||||
|
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||||
|
{{-- SOFTWARE. --}}
|
||||||
|
@extends('layouts.master')
|
||||||
|
|
||||||
|
@section('title')
|
||||||
|
{{ trans('base.index.header') }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content-header')
|
||||||
|
<h1>{{ trans('base.index.header') }}<small>{{ trans('base.index.header_sub')}}</small></h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="{{ route('index') }}">{{ trans('strings.home') }}</a></li>
|
||||||
|
<li class="active">{{ trans('strings.servers') }}</li>
|
||||||
|
</ol>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h3 class="box-title">{{ trans('base.index.list') }}</h3>
|
||||||
|
<div class="box-tools">
|
||||||
|
<div class="input-group input-group-sm" style="width: 150px;">
|
||||||
|
<input type="text" name="table_search" class="form-control pull-right" placeholder="{{ trans('strings.search') }}">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button type="submit" class="btn btn-default"><i class="fa fa-search"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body table-responsive no-padding">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{{ trans('strings.id') }}</th>
|
||||||
|
<th>{{ trans('strings.name') }}</th>
|
||||||
|
<th>{{ trans('strings.node') }}</th>
|
||||||
|
<th>{{ trans('strings.connection') }}</th>
|
||||||
|
<th class="text-center hidden-sm hidden-xs">{{ trans('strings.memory') }}</th>
|
||||||
|
<th class="text-center hidden-sm hidden-xs">{{ trans('strings.cpu') }}</th>
|
||||||
|
<th class="text-center">{{ trans('strings.status') }}</th>
|
||||||
|
</tr>
|
||||||
|
@foreach($servers as $server)
|
||||||
|
<tr class="dynamic-update" data-server="{{ $server->uuidShort }}">
|
||||||
|
<td><code>{{ $server->uuidShort }}</code></td>
|
||||||
|
<td><a href="/server/{{ $server->uuidShort }}">{{ $server->name }}</a></td>
|
||||||
|
<td>{{ $server->nodeName }}</td>
|
||||||
|
<td><code>@if(!is_null($server->ip_alias)){{ $server->ip_alias }}@else{{ $server->ip }}@endif:{{ $server->port }}</code></td>
|
||||||
|
<td class="text-center hidden-sm hidden-xs"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
||||||
|
<td class="text-center hidden-sm hidden-xs"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
|
||||||
|
<td class="text-center" data-action="status">
|
||||||
|
@if($server->suspended === 1)
|
||||||
|
<span class="label label-warning">{{ trans('strings.suspended') }}</span>
|
||||||
|
@else
|
||||||
|
<span class="label label-default"><i class="fa fa-refresh fa-fw fa-spin"></i></span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('footer-scripts')
|
||||||
|
@parent
|
||||||
|
{!! Theme::js('js/frontend/serverlist.js') !!}
|
||||||
|
@endsection
|
143
resources/themes/pterodactyl/base/security.blade.php
Normal file
143
resources/themes/pterodactyl/base/security.blade.php
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
|
||||||
|
|
||||||
|
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||||
|
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||||
|
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||||
|
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||||
|
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||||
|
{{-- furnished to do so, subject to the following conditions: --}}
|
||||||
|
|
||||||
|
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||||
|
{{-- copies or substantial portions of the Software. --}}
|
||||||
|
|
||||||
|
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||||
|
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||||
|
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||||
|
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||||
|
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||||
|
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||||
|
{{-- SOFTWARE. --}}
|
||||||
|
@extends('layouts.master')
|
||||||
|
|
||||||
|
@section('title')
|
||||||
|
{{ trans('base.security.header') }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content-header')
|
||||||
|
<h1>{{ trans('base.security.header') }}<small>{{ trans('base.security.header_sub')}}</small></h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a href="{{ route('index') }}">{{ trans('strings.home') }}</a></li>
|
||||||
|
<li><a href="{{ route('account') }}">{{ trans('strings.account') }}</a></li>
|
||||||
|
<li class="active">{{ trans('strings.security') }}</li>
|
||||||
|
</ol>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('base.security.sessions') }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body table-responsive no-padding">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{{ trans('strings.id') }}</th>
|
||||||
|
<th>{{ trans('strings.ip') }}</th>
|
||||||
|
<th>{{ trans('strings.last_activity') }}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
@foreach($sessions as $session)
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ substr($session->id, 0, 6) }}</code></td>
|
||||||
|
<td>{{ $session->ip_address }}</td>
|
||||||
|
<td>{{ Carbon::createFromTimestamp($session->last_activity)->diffForHumans() }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('account.security.revoke', $session->id) }}">
|
||||||
|
<button class="btn btn-xs btn-danger"><i class="fa fa-trash-o"></i> {{ trans('strings.revoke') }}</button>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="box {{ (Auth::user()->use_totp) ? 'box-success' : 'box-danger' }}">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('base.security.2fa_header') }}</h3>
|
||||||
|
</div>
|
||||||
|
@if(Auth::user()->use_totp)
|
||||||
|
<form action="{{ route('account.security.totp') }}" method="post">
|
||||||
|
<div class="box-body">
|
||||||
|
<p>{{ trans('base.security.2fa_enabled') }}</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_password_again" class="control-label">{{ trans('strings.2fa_token') }}</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control" name="token" />
|
||||||
|
<p class="text-muted small">{{ trans('base.security.2fa_token_help') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
{{ method_field('DELETE') }}
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm">{{ trans('base.security.disable_2fa') }}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@else
|
||||||
|
<form action="#" method="post" id="do_2fa">
|
||||||
|
<div class="box-body">
|
||||||
|
{{ trans('base.security.2fa_disabled') }}
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
<button type="submit" class="btn btn-success btn-sm">{{ trans('base.security.enable_2fa') }}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="open2fa" tabindex="-1" role="dialog" aria-labelledby="open2fa" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form action="#" method="post" id="2fa_token_verify">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">{{ trans('base.security.2fa_qr') }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="modal_insert_content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12" id="notice_box_2fa" style="display:none;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<center><span id="hide_img_load"><i class="fa fa-spinner fa-spin"></i> Loading QR Code...</span><img src="" id="qr_image_insert" style="display:none;"/><br /><code id="2fa_secret_insert"></code></center>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="alert alert-info">{{ trans('base.security.2fa_checkpoint_help') }}</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label" for="2fa_token">{{ trans('strings.2fa_token') }}</label>
|
||||||
|
{!! csrf_field() !!}
|
||||||
|
<input class="form-control" type="text" name="2fa_token" id="2fa_token" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm" id="submit_action">{{ trans('strings.submit') }}</button>
|
||||||
|
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal" id="close_reload">{{ trans('strings.close') }}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('footer-scripts')
|
||||||
|
@parent
|
||||||
|
{!! Theme::js('js/frontend/2fa-modal.js') !!}
|
||||||
|
@endsection
|
253
resources/themes/pterodactyl/layouts/master.blade.php
Normal file
253
resources/themes/pterodactyl/layouts/master.blade.php
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
|
||||||
|
|
||||||
|
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||||
|
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||||
|
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||||
|
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||||
|
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||||
|
{{-- furnished to do so, subject to the following conditions: --}}
|
||||||
|
|
||||||
|
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||||
|
{{-- copies or substantial portions of the Software. --}}
|
||||||
|
|
||||||
|
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||||
|
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||||
|
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||||
|
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||||
|
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||||
|
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||||
|
{{-- SOFTWARE. --}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title>{{ Settings::get('company', 'Pterodactyl') }} - @yield('title')</title>
|
||||||
|
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||||
|
<meta name="_token" content="{{ csrf_token() }}">
|
||||||
|
@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') !!}
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
@show
|
||||||
|
</head>
|
||||||
|
<body class="hold-transition skin-blue fixed sidebar-mini">
|
||||||
|
<div class="wrapper">
|
||||||
|
<header class="main-header">
|
||||||
|
<a href="{{ route('index') }}" class="logo">
|
||||||
|
<span>{{ Settings::get('company', 'Pterodactyl') }}</span>
|
||||||
|
</a>
|
||||||
|
<nav class="navbar navbar-static-top">
|
||||||
|
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<div class="navbar-custom-menu">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li class="dropdown user user-menu">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<img src="https://www.gravatar.com/avatar/{{ md5(Auth::user()->email) }}?s=160" class="user-image" alt="User Image">
|
||||||
|
<span class="hidden-xs">{{ Auth::user()->name_first }} {{ Auth::user()->name_last }}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="user-header">
|
||||||
|
<p>
|
||||||
|
<small>Member since Nov. 2012</small>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="user-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="#">Followers</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="#">Sales</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4 text-center">
|
||||||
|
<a href="#">Friends</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="user-footer">
|
||||||
|
<div class="pull-left">
|
||||||
|
<a href="{{ route('admin.index') }}" class="btn btn-default btn-flat">Admin Control</a>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="{{ route('auth.logout') }}" class="btn btn-default btn-flat">Sign out</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" data-toggle="control-sidebar"><i class="fa fa-gears" style="margin-top:4px;padding-bottom:2px;"></i></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<aside class="main-sidebar">
|
||||||
|
<section class="sidebar">
|
||||||
|
@if (isset($server->name) && isset($node->name))
|
||||||
|
<div class="user-panel">
|
||||||
|
<div class="info">
|
||||||
|
<p>{{ $server->name }}</p>
|
||||||
|
<a href="#"><i class="fa fa-circle text-success"></i> Online</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<ul class="sidebar-menu">
|
||||||
|
<li class="header">ACCOUNT MANAGEMENT</li>
|
||||||
|
<li class="{{ Route::currentRouteName() !== 'account' ?: 'active' }}">
|
||||||
|
<a href="{{ route('account')}}">
|
||||||
|
<i class="fa fa-user"></i> <span>My Account</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ Route::currentRouteName() !== 'account.security' ?: 'active' }}">
|
||||||
|
<a href="{{ route('account.security')}}">
|
||||||
|
<i class="fa fa-lock"></i> <span>Security Controls</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ Route::currentRouteName() !== 'account.api' ?: 'active' }}">
|
||||||
|
<a href="{{ route('account.api')}}">
|
||||||
|
<i class="fa fa-code"></i> <span>API Access</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="{{ Route::currentRouteName() !== 'index' ?: 'active' }}">
|
||||||
|
<a href="{{ route('index')}}">
|
||||||
|
<i class="fa fa-server"></i> <span>My Servers</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@if (isset($server->name) && isset($node->name))
|
||||||
|
<li class="header">SERVER MANAGEMENT</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('server.index', $server->uuidShort) }}">
|
||||||
|
<i class="fa fa-terminal"></i> <span>Console</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-files-o"></i>
|
||||||
|
<span>File Management</span>
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li><a href="{{ route('server.files.index', $server->uuidShort) }}"><i class="fa fa-angle-right"></i> File Browser</a></li>
|
||||||
|
<li><a href="{{ route('server.files.add', $server->uuidShort) }}"><i class="fa fa-angle-right"></i> Create File</a></li>
|
||||||
|
<li><a href=""><i class="fa fa-angle-right"></i> Upload Files</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('server.subusers', $server->uuidShort)}}">
|
||||||
|
<i class="fa fa-users"></i> <span>Subusers</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('server.tasks', $server->uuidShort)}}">
|
||||||
|
<i class="fa fa-clock-o"></i> <span>Task Management</span>
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<span class="label label-primary pull-right">4</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="treeview">
|
||||||
|
<a href="#">
|
||||||
|
<i class="fa fa-gears"></i>
|
||||||
|
<span>Configuration</span>
|
||||||
|
<span class="pull-right-container">
|
||||||
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<ul class="treeview-menu">
|
||||||
|
<li><a href="{{ route('server.settings', $server->uuidShort) }}"><i class="fa fa-angle-right"></i> SFTP Settings</a></li>
|
||||||
|
<li><a href=""><i class="fa fa-angle-right"></i> Startup Parameters</a></li>
|
||||||
|
<li><a href=""><i class="fa fa-angle-right"></i> Databases</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
@endif
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</aside>
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<section class="content-header">
|
||||||
|
@yield('content-header')
|
||||||
|
</section>
|
||||||
|
<section class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
@if (count($errors) > 0)
|
||||||
|
<div class="callout callout-danger">
|
||||||
|
{{ trans('base.validation_error') }}<br><br>
|
||||||
|
<ul>
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@foreach (Alert::getMessages() as $type => $messages)
|
||||||
|
@foreach ($messages as $message)
|
||||||
|
<div class="callout callout-{{ $type }} alert-dismissable" role="alert">
|
||||||
|
{!! $message !!}
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@yield('content')
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="pull-right hidden-xs small text-gray">
|
||||||
|
<strong>v</strong> {{ config('app.version') }}
|
||||||
|
</div>
|
||||||
|
Copyright © 2015 - {{ date('Y') }} <a href="https://pterodactyl.io/">Pterodactyl Software & Design</a>.
|
||||||
|
</footer>
|
||||||
|
<aside class="control-sidebar control-sidebar-dark">
|
||||||
|
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
|
||||||
|
<li><a href="#control-sidebar-servers-tab" data-toggle="tab"><i class="fa fa-server"></i></a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active" id="control-sidebar-servers-tab">
|
||||||
|
<ul class="control-sidebar-menu">
|
||||||
|
@foreach (Pterodactyl\Models\Server::getUserServers() as $s)
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('server.index', $s->uuidShort) }}">
|
||||||
|
@if($s->owner === Auth::user()->id)
|
||||||
|
<i class="menu-icon fa fa-user bg-blue"></i>
|
||||||
|
@else
|
||||||
|
<i class="menu-icon fa fa-user-o bg-gray"></i>
|
||||||
|
@endif
|
||||||
|
<div class="menu-info">
|
||||||
|
<h4 class="control-sidebar-subheading">{{ $s->name }}</h4>
|
||||||
|
<p>{{ $s->uuidShort }}</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="control-sidebar-bg"></div>
|
||||||
|
</div>
|
||||||
|
@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
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue