2016-01-05 04:59:45 +00:00
< ? php
2016-01-20 00:10:39 +00:00
/**
2016-01-20 21:05:16 +00:00
* Pterodactyl - Panel
2017-01-24 22:57:08 +00:00
* Copyright ( c ) 2015 - 2017 Dane Everitt < dane @ daneeveritt . com >.
2016-01-20 00:10:39 +00:00
*
2016-01-20 20:56:40 +00:00
* 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 :
2016-01-20 00:10:39 +00:00
*
2016-01-20 20:56:40 +00:00
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
2016-01-20 00:10:39 +00:00
*
2016-01-20 20:56:40 +00:00
* 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 .
2016-01-20 00:10:39 +00:00
*/
2016-12-07 22:46:38 +00:00
2016-01-05 04:59:45 +00:00
namespace Pterodactyl\Http\Controllers\Admin ;
use DB ;
2016-12-07 22:46:38 +00:00
use Log ;
use Alert ;
2017-01-08 14:21:02 +00:00
use Carbon ;
2016-09-30 21:12:36 +00:00
use Validator ;
2016-01-05 04:59:45 +00:00
use Pterodactyl\Models ;
2016-12-07 22:46:38 +00:00
use Illuminate\Http\Request ;
2016-09-07 20:12:06 +00:00
use Pterodactyl\Exceptions\DisplayException ;
2016-01-05 04:59:45 +00:00
use Pterodactyl\Http\Controllers\Controller ;
2016-12-07 22:46:38 +00:00
use Pterodactyl\Repositories\NodeRepository ;
use Pterodactyl\Exceptions\DisplayValidationException ;
2016-01-05 04:59:45 +00:00
class NodesController extends Controller
{
/**
2016-12-07 22:46:38 +00:00
* Controller Constructor .
2016-01-05 04:59:45 +00:00
*/
public function __construct ()
{
//
}
2016-02-06 04:41:16 +00:00
public function getScript ( Request $request , $id )
{
2016-12-07 22:46:38 +00:00
return response () -> view ( 'admin.nodes.remote.deploy' , [ 'node' => Models\Node :: findOrFail ( $id )]) -> header ( 'Content-Type' , 'text/plain' );
2016-02-06 04:41:16 +00:00
}
2016-01-05 04:59:45 +00:00
public function getIndex ( Request $request )
{
return view ( 'admin.nodes.index' , [
'nodes' => Models\Node :: select (
'nodes.*' ,
'locations.long as a_locationName' ,
2017-02-03 00:46:46 +00:00
DB :: raw ( '(SELECT COUNT(*) FROM servers WHERE servers.node_id = nodes.id) as a_serverCount' )
2016-01-05 04:59:45 +00:00
) -> join ( 'locations' , 'nodes.location' , '=' , 'locations.id' ) -> paginate ( 20 ),
]);
}
public function getNew ( Request $request )
{
2016-12-07 22:46:38 +00:00
if ( ! Models\Location :: all () -> count ()) {
2016-09-30 20:05:39 +00:00
Alert :: warning ( 'You must add a location before you can add a new node.' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-09-30 20:05:39 +00:00
return redirect () -> route ( 'admin.locations' );
}
2016-01-05 04:59:45 +00:00
return view ( 'admin.nodes.new' , [
2016-12-07 22:46:38 +00:00
'locations' => Models\Location :: all (),
2016-01-05 04:59:45 +00:00
]);
}
public function postNew ( Request $request )
{
try {
$node = new NodeRepository ;
$new = $node -> create ( $request -> except ([
2016-12-07 22:46:38 +00:00
'_token' ,
2016-01-05 04:59:45 +00:00
]));
2016-09-29 21:47:47 +00:00
Alert :: success ( 'Successfully created new node. <strong>Before you can add any servers you need to first assign some IP addresses and ports.</strong>' ) -> flash ();
2017-01-07 17:27:19 +00:00
Alert :: info ( '<strong>To simplify the node setup you can generate a token on the configuration tab.</strong>' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-01-05 04:59:45 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
2016-09-29 21:47:47 +00:00
'id' => $new ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_allocation' ,
2016-01-05 04:59:45 +00:00
]);
2016-09-07 20:12:06 +00:00
} catch ( DisplayValidationException $e ) {
2016-01-05 04:59:45 +00:00
return redirect () -> route ( 'admin.nodes.new' ) -> withErrors ( json_decode ( $e -> getMessage ())) -> withInput ();
2016-09-07 20:12:06 +00:00
} catch ( DisplayException $e ) {
2016-01-05 04:59:45 +00:00
Alert :: danger ( $e -> getMessage ()) -> flash ();
} catch ( \Exception $e ) {
Log :: error ( $e );
Alert :: danger ( 'An unhandled exception occured while attempting to add this node. Please try again.' ) -> flash ();
}
2016-12-07 22:46:38 +00:00
2016-01-05 04:59:45 +00:00
return redirect () -> route ( 'admin.nodes.new' ) -> withInput ();
}
public function getView ( Request $request , $id )
{
$node = Models\Node :: findOrFail ( $id );
2016-09-30 01:34:20 +00:00
2016-01-05 04:59:45 +00:00
return view ( 'admin.nodes.view' , [
2016-01-05 05:52:20 +00:00
'node' => $node ,
'servers' => Models\Server :: select ( 'servers.*' , 'users.email as a_ownerEmail' , 'services.name as a_serviceName' )
2017-02-02 23:21:36 +00:00
-> join ( 'users' , 'users.id' , '=' , 'servers.owner_id' )
-> join ( 'services' , 'services.id' , '=' , 'servers.service_id' )
2017-02-03 00:46:46 +00:00
-> where ( 'node_id' , $id ) -> paginate ( 10 , [ '*' ], 'servers' ),
'stats' => Models\Server :: select ( DB :: raw ( 'SUM(memory) as memory, SUM(disk) as disk' )) -> where ( 'node_id' , $node -> id ) -> first (),
2016-01-05 23:31:25 +00:00
'locations' => Models\Location :: all (),
2016-09-30 01:34:20 +00:00
'allocations' => Models\Allocation :: select ( 'allocations.*' , 'servers.name as assigned_to_name' )
-> where ( 'allocations.node' , $node -> id )
-> leftJoin ( 'servers' , 'servers.id' , '=' , 'allocations.assigned_to' )
-> orderBy ( 'allocations.ip' , 'asc' )
-> orderBy ( 'allocations.port' , 'asc' )
-> paginate ( 20 , [ '*' ], 'allocations' ),
2016-09-30 21:12:36 +00:00
'allocation_ips' => Models\Allocation :: select ( 'id' , 'ip' )
-> where ( 'node' , $node -> id )
-> groupBy ( 'ip' )
-> get (),
2016-01-05 04:59:45 +00:00
]);
}
2016-01-05 23:31:25 +00:00
public function postView ( Request $request , $id )
{
try {
$node = new NodeRepository ;
$node -> update ( $id , $request -> except ([
2016-12-07 22:46:38 +00:00
'_token' ,
2016-01-05 23:31:25 +00:00
]));
Alert :: success ( 'Successfully update this node\'s information. If you changed any daemon settings you will need to restart it now.' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-01-05 23:31:25 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $id ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_settings' ,
2016-01-05 23:31:25 +00:00
]);
2016-09-07 20:12:06 +00:00
} catch ( DisplayValidationException $e ) {
2016-01-05 23:31:25 +00:00
return redirect () -> route ( 'admin.nodes.view' , $id ) -> withErrors ( json_decode ( $e -> getMessage ())) -> withInput ();
2016-09-07 20:12:06 +00:00
} catch ( DisplayException $e ) {
2016-01-05 23:31:25 +00:00
Alert :: danger ( $e -> getMessage ()) -> flash ();
} catch ( \Exception $e ) {
Log :: error ( $e );
Alert :: danger ( 'An unhandled exception occured while attempting to edit this node. Please try again.' ) -> flash ();
}
2016-12-07 22:46:38 +00:00
2016-01-05 23:31:25 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $id ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_settings' ,
2016-01-05 23:31:25 +00:00
]) -> withInput ();
}
2016-09-30 01:34:20 +00:00
public function deallocateSingle ( Request $request , $node , $allocation )
2016-01-09 01:01:18 +00:00
{
2016-09-30 01:34:20 +00:00
$query = Models\Allocation :: where ( 'node' , $node ) -> whereNull ( 'assigned_to' ) -> where ( 'id' , $allocation ) -> delete ();
if (( int ) $query === 0 ) {
2016-01-09 01:01:18 +00:00
return response () -> json ([
2016-12-07 22:46:38 +00:00
'error' => 'Unable to find an allocation matching those details to delete.' ,
2016-01-09 01:01:18 +00:00
], 400 );
}
2016-12-07 22:46:38 +00:00
2016-01-09 01:01:18 +00:00
return response ( '' , 204 );
}
2016-09-30 01:34:20 +00:00
public function deallocateBlock ( Request $request , $node )
{
$query = Models\Allocation :: where ( 'node' , $node ) -> whereNull ( 'assigned_to' ) -> where ( 'ip' , $request -> input ( 'ip' )) -> delete ();
if (( int ) $query === 0 ) {
Alert :: danger ( 'There was an error while attempting to delete allocations on that IP.' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-09-30 01:34:20 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $node ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_allocations' ,
2016-09-30 01:34:20 +00:00
]);
}
Alert :: success ( 'Deleted all unallocated ports for <code>' . $request -> input ( 'ip' ) . '</code>.' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-09-30 01:34:20 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $node ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_allocation' ,
2016-09-30 01:34:20 +00:00
]);
}
public function setAlias ( Request $request , $node )
{
2016-12-07 22:46:38 +00:00
if ( ! $request -> input ( 'allocation' )) {
2016-09-30 01:34:20 +00:00
return response ( 'Missing required parameters.' , 422 );
}
try {
$update = Models\Allocation :: findOrFail ( $request -> input ( 'allocation' ));
2016-09-30 20:01:36 +00:00
$update -> ip_alias = ( empty ( $request -> input ( 'alias' ))) ? null : $request -> input ( 'alias' );
2016-09-30 01:34:20 +00:00
$update -> save ();
return response ( '' , 204 );
} catch ( \Exception $ex ) {
throw $ex ;
}
}
2016-01-10 05:38:16 +00:00
public function getAllocationsJson ( Request $request , $id )
{
$allocations = Models\Allocation :: select ( 'ip' ) -> where ( 'node' , $id ) -> groupBy ( 'ip' ) -> get ();
2016-12-07 22:46:38 +00:00
2016-01-10 05:38:16 +00:00
return response () -> json ( $allocations );
}
public function postAllocations ( Request $request , $id )
{
2016-09-30 21:12:36 +00:00
$validator = Validator :: make ( $request -> all (), [
'allocate_ip.*' => 'required|string' ,
2016-12-07 22:46:38 +00:00
'allocate_port.*' => 'required' ,
2016-09-30 21:12:36 +00:00
]);
if ( $validator -> fails ()) {
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $id ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_allocation' ,
2016-09-30 21:12:36 +00:00
]) -> withErrors ( $validator -> errors ()) -> withInput ();
}
2016-01-10 05:38:16 +00:00
$processedData = [];
2016-12-07 22:46:38 +00:00
foreach ( $request -> input ( 'allocate_ip' ) as $ip ) {
if ( ! array_key_exists ( $ip , $processedData )) {
2016-01-10 05:38:16 +00:00
$processedData [ $ip ] = [];
}
}
2016-12-07 22:46:38 +00:00
foreach ( $request -> input ( 'allocate_port' ) as $portid => $ports ) {
2016-01-10 05:38:16 +00:00
if ( array_key_exists ( $portid , $request -> input ( 'allocate_ip' ))) {
$json = json_decode ( $ports );
2016-12-07 22:46:38 +00:00
if ( json_last_error () === 0 && ! empty ( $json )) {
foreach ( $json as & $parsed ) {
2016-01-10 05:38:16 +00:00
array_push ( $processedData [ $request -> input ( 'allocate_ip' )[ $portid ]], $parsed -> value );
}
}
}
}
try {
$node = new NodeRepository ;
$node -> addAllocations ( $id , $processedData );
Alert :: success ( 'Successfully added new allocations to this node.' ) -> flash ();
2016-09-07 20:12:06 +00:00
} catch ( DisplayException $e ) {
2016-01-10 05:38:16 +00:00
Alert :: danger ( $e -> getMessage ()) -> flash ();
} catch ( \Exception $e ) {
Log :: error ( $e );
Alert :: danger ( 'An unhandled exception occured while attempting to add allocations this node. Please try again.' ) -> flash ();
} finally {
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $id ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_allocation' ,
2016-01-10 05:38:16 +00:00
]);
}
}
2016-01-10 21:59:19 +00:00
public function deleteNode ( Request $request , $id )
{
2016-11-26 21:29:13 +00:00
try {
$repo = new NodeRepository ;
$repo -> delete ( $id );
Alert :: success ( 'Successfully deleted the requested node from the panel.' ) -> flash ();
2016-12-07 22:46:38 +00:00
2016-11-26 21:29:13 +00:00
return redirect () -> route ( 'admin.nodes' );
} catch ( DisplayException $e ) {
Alert :: danger ( $e -> getMessage ()) -> flash ();
} catch ( \Exception $e ) {
Log :: error ( $e );
Alert :: danger ( 'An unhandled exception occured while attempting to delete this node. Please try again.' ) -> flash ();
2016-01-10 21:59:19 +00:00
}
2016-11-26 21:29:13 +00:00
return redirect () -> route ( 'admin.nodes.view' , [
'id' => $id ,
2016-12-07 22:46:38 +00:00
'tab' => 'tab_delete' ,
2016-11-26 21:29:13 +00:00
]);
2016-01-10 21:59:19 +00:00
}
2017-01-07 17:10:11 +00:00
2017-01-07 17:39:41 +00:00
public function getConfigurationToken ( Request $request , $id )
{
2017-01-07 17:10:11 +00:00
// Check if Node exists. Will lead to 404 if not.
Models\Node :: findOrFail ( $id );
// Create a token
$token = new Models\NodeConfigurationToken ();
$token -> node = $id ;
$token -> token = str_random ( 32 );
$token -> expires_at = Carbon :: now () -> addMinutes ( 5 ); // Expire in 5 Minutes
$token -> save ();
2017-01-07 17:39:41 +00:00
$token_response = [
2017-01-07 17:10:11 +00:00
'token' => $token -> token ,
2017-01-07 17:39:41 +00:00
'expires_at' => $token -> expires_at -> toDateTimeString (),
];
2017-01-07 17:10:11 +00:00
2017-01-08 14:21:02 +00:00
return response () -> json ( $token_response , 200 );
2017-01-07 17:10:11 +00:00
}
2016-01-05 04:59:45 +00:00
}