2021-06-05 09:26:32 +00:00
< ? php
namespace App\Http\Controllers ;
use App\Classes\Pterodactyl ;
use App\Models\Egg ;
2021-11-07 15:29:18 +00:00
use App\Models\Location ;
2021-06-05 09:26:32 +00:00
use App\Models\Nest ;
use App\Models\Node ;
use App\Models\Product ;
use App\Models\Server ;
2022-01-05 07:57:41 +00:00
use App\Models\Settings ;
2021-06-05 09:26:32 +00:00
use App\Notifications\ServerCreationError ;
use Exception ;
2021-11-07 11:07:30 +00:00
use Illuminate\Database\Eloquent\Builder ;
2021-06-30 21:53:28 +00:00
use Illuminate\Http\Client\Response ;
2021-06-26 21:56:54 +00:00
use Illuminate\Http\RedirectResponse ;
2021-06-05 09:26:32 +00:00
use Illuminate\Http\Request ;
use Illuminate\Support\Facades\Auth ;
2021-10-01 21:21:49 +00:00
use Illuminate\Support\Facades\Request as FacadesRequest ;
2021-06-05 09:26:32 +00:00
class ServerController extends Controller
{
2021-06-06 18:17:52 +00:00
/** Display a listing of the resource. */
2021-06-06 21:26:36 +00:00
public function index ()
2021-06-05 09:26:32 +00:00
{
2021-12-21 18:41:04 +00:00
$servers = Auth :: user () -> servers ;
//Get and set server infos each server
foreach ( $servers as $server ) {
//Get server infos from ptero
2021-12-22 14:11:13 +00:00
$serverAttributes = Pterodactyl :: getServerAttributes ( $server -> pterodactyl_id );
2021-12-21 18:41:04 +00:00
$serverRelationships = $serverAttributes [ 'relationships' ];
$serverLocationAttributes = $serverRelationships [ 'location' ][ 'attributes' ];
//Set server infos
$server -> location = $serverLocationAttributes [ 'long' ] ?
$serverLocationAttributes [ 'long' ] :
$serverLocationAttributes [ 'short' ];
$server -> egg = $serverRelationships [ 'egg' ][ 'attributes' ][ 'name' ];
$server -> nest = $serverRelationships [ 'nest' ][ 'attributes' ][ 'name' ];
2021-12-23 13:48:04 +00:00
$server -> node = $serverRelationships [ 'node' ][ 'attributes' ][ 'name' ];
2021-12-21 18:41:04 +00:00
//get productname by product_id for server
2021-12-22 19:18:48 +00:00
$product = Product :: find ( $server -> product_id );
2021-12-21 18:41:04 +00:00
2021-12-22 19:18:48 +00:00
$server -> product = $product ;
2021-12-21 18:41:04 +00:00
}
2021-06-05 09:26:32 +00:00
return view ( 'servers.index' ) -> with ([
2021-12-21 18:41:04 +00:00
'servers' => $servers
2021-06-05 09:26:32 +00:00
]);
}
2021-06-06 18:17:52 +00:00
/** Show the form for creating a new resource. */
2021-06-06 21:26:36 +00:00
public function create ()
2021-06-05 09:26:32 +00:00
{
2021-06-26 21:56:54 +00:00
if ( ! is_null ( $this -> validateConfigurationRules ())) return $this -> validateConfigurationRules ();
2021-06-05 09:26:32 +00:00
2021-11-07 11:07:30 +00:00
$productCount = Product :: query () -> where ( 'disabled' , '=' , false ) -> count ();
2021-11-07 15:29:18 +00:00
$locations = Location :: all ();
2021-11-12 19:01:35 +00:00
$nodeCount = Node :: query ()
-> whereHas ( 'products' , function ( Builder $builder ) {
$builder -> where ( 'disabled' , '=' , false );
}) -> count ();
$eggs = Egg :: query ()
-> whereHas ( 'products' , function ( Builder $builder ) {
$builder -> where ( 'disabled' , '=' , false );
}) -> get ();
$nests = Nest :: query ()
-> whereHas ( 'eggs' , function ( Builder $builder ) {
$builder -> whereHas ( 'products' , function ( Builder $builder ) {
$builder -> where ( 'disabled' , '=' , false );
});
}) -> get ();
2021-11-07 11:07:30 +00:00
2021-06-05 09:26:32 +00:00
return view ( 'servers.create' ) -> with ([
2021-11-07 15:29:18 +00:00
'productCount' => $productCount ,
'nodeCount' => $nodeCount ,
'nests' => $nests ,
'locations' => $locations ,
'eggs' => $eggs ,
'user' => Auth :: user (),
2021-06-05 09:26:32 +00:00
]);
}
2021-06-26 21:56:54 +00:00
/**
2021-06-26 22:02:27 +00:00
* @ return null | RedirectResponse
2021-06-26 21:56:54 +00:00
*/
2021-10-01 21:21:49 +00:00
private function validateConfigurationRules ()
{
2021-06-26 21:56:54 +00:00
//limit validation
if ( Auth :: user () -> servers () -> count () >= Auth :: user () -> server_limit ) {
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'error' , __ ( 'Server limit reached!' ));
2021-06-26 21:56:54 +00:00
}
2022-08-11 06:10:24 +00:00
// minimum credits && Check for Allocation
2021-11-07 00:47:16 +00:00
if ( FacadesRequest :: has ( " product " )) {
$product = Product :: findOrFail ( FacadesRequest :: input ( " product " ));
2022-08-11 14:55:24 +00:00
2022-08-13 20:21:55 +00:00
// Get node resource allocation info
2022-08-11 14:55:24 +00:00
$node = $product -> nodes () -> findOrFail ( FacadesRequest :: input ( 'node' ));
$nodeName = $node -> name ;
// Check if node has enough memory and disk space
$checkResponse = Pterodactyl :: checkNodeResources ( $node , $product -> memory , $product -> disk );
if ( $checkResponse == False ) return redirect () -> route ( 'servers.index' ) -> with ( 'error' , __ ( " The node ' " . $nodeName . " ' doesn't have the required memory or disk left to allocate this product. " ));
2022-08-13 20:21:55 +00:00
2022-08-11 06:10:24 +00:00
// Min. Credits
2021-10-01 21:21:49 +00:00
if (
2021-10-03 13:18:08 +00:00
Auth :: user () -> credits <
2021-10-01 21:21:49 +00:00
( $product -> minimum_credits == - 1
2022-01-15 17:16:51 +00:00
? config ( 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER' , 50 )
2021-10-01 21:21:49 +00:00
: $product -> minimum_credits )
) {
2021-10-03 12:47:51 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'error' , " You do not have the required amount of " . CREDITS_DISPLAY_NAME . " to use this product! " );
2021-10-01 21:21:49 +00:00
}
2021-06-26 21:56:54 +00:00
}
//Required Verification for creating an server
2022-01-15 17:16:51 +00:00
if ( config ( 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION' , 'false' ) === 'true' && ! Auth :: user () -> hasVerifiedEmail ()) {
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'profile.index' ) -> with ( 'error' , __ ( " You are required to verify your email address before you can create a server. " ));
2021-06-26 21:56:54 +00:00
}
//Required Verification for creating an server
2022-01-15 17:16:51 +00:00
if ( config ( 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION' , 'false' ) === 'true' && ! Auth :: user () -> discordUser ) {
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'profile.index' ) -> with ( 'error' , __ ( " You are required to link your discord account before you can create a server. " ));
2021-06-26 21:56:54 +00:00
}
return null ;
}
2021-11-06 00:56:57 +00:00
/** Store a newly created resource in storage. */
public function store ( Request $request )
2021-06-05 09:26:32 +00:00
{
2021-11-07 11:07:30 +00:00
/** @var Node $node */
/** @var Egg $egg */
/** @var Product $product */
2021-11-06 00:56:57 +00:00
if ( ! is_null ( $this -> validateConfigurationRules ())) return $this -> validateConfigurationRules ();
$request -> validate ([
2021-11-07 00:47:16 +00:00
" name " => " required|max:191 " ,
" node " => " required|exists:nodes,id " ,
" egg " => " required|exists:eggs,id " ,
" product " => " required|exists:products,id "
2021-11-06 00:56:57 +00:00
]);
//get required resources
2021-11-07 11:07:30 +00:00
$product = Product :: query () -> findOrFail ( $request -> input ( 'product' ));
$egg = $product -> eggs () -> findOrFail ( $request -> input ( 'egg' ));
$node = $product -> nodes () -> findOrFail ( $request -> input ( 'node' ));
2021-11-07 00:47:16 +00:00
$server = $request -> user () -> servers () -> create ([
'name' => $request -> input ( 'name' ),
'product_id' => $request -> input ( 'product' ),
]);
2021-11-06 00:56:57 +00:00
//get free allocation ID
$allocationId = Pterodactyl :: getFreeAllocationId ( $node );
if ( ! $allocationId ) return $this -> noAllocationsError ( $server );
//create server on pterodactyl
$response = Pterodactyl :: createServer ( $server , $egg , $allocationId );
if ( $response -> failed ()) return $this -> serverCreationFailed ( $response , $server );
2021-12-21 18:52:30 +00:00
$serverAttributes = $response -> json ()[ 'attributes' ];
2021-11-06 00:56:57 +00:00
//update server with pterodactyl_id
$server -> update ([
2021-12-21 18:52:30 +00:00
'pterodactyl_id' => $serverAttributes [ 'id' ],
'identifier' => $serverAttributes [ 'identifier' ]
2021-11-06 00:56:57 +00:00
]);
2022-01-15 17:16:51 +00:00
if ( config ( 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR' , 'true' ) == 'true' ) {
2021-11-07 00:47:16 +00:00
if ( $request -> user () -> credits >= $server -> product -> getHourlyPrice ()) {
$request -> user () -> decrement ( 'credits' , $server -> product -> getHourlyPrice ());
2021-11-06 00:56:57 +00:00
}
2021-06-06 18:17:52 +00:00
}
2021-06-30 21:53:28 +00:00
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'success' , __ ( 'Server created' ));
2021-11-06 00:56:57 +00:00
}
2021-06-30 21:53:28 +00:00
/**
* return redirect with error
* @ param Server $server
* @ return RedirectResponse
*/
private function noAllocationsError ( Server $server )
{
$server -> delete ();
Auth :: user () -> notify ( new ServerCreationError ( $server ));
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'error' , __ ( 'No allocations satisfying the requirements for automatic deployment on this node were found.' ));
2021-06-30 21:53:28 +00:00
}
/**
* return redirect with error
* @ param Response $response
* @ param Server $server
* @ return RedirectResponse
*/
2021-10-01 21:21:49 +00:00
private function serverCreationFailed ( Response $response , Server $server )
2021-06-30 21:53:28 +00:00
{
$server -> delete ();
return redirect () -> route ( 'servers.index' ) -> with ( 'error' , json_encode ( $response -> json ()));
}
2021-11-06 00:56:57 +00:00
/** Remove the specified resource from storage. */
public function destroy ( Server $server )
{
try {
$server -> delete ();
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'success' , __ ( 'Server removed' ));
2021-11-06 00:56:57 +00:00
} catch ( Exception $e ) {
2021-12-13 10:47:35 +00:00
return redirect () -> route ( 'servers.index' ) -> with ( 'error' , __ ( 'An exception has occurred while trying to remove a resource "' ) . $e -> getMessage () . '"' );
2021-11-06 00:56:57 +00:00
}
}
2022-08-03 12:34:00 +00:00
/** Show Server Settings */
public function show ( Server $server )
{
2022-08-13 20:29:57 +00:00
if ( $server -> user_id != Auth :: user () -> id ){ return back () -> with ( 'error' , __ ( '´ This is not your Server!' ));}
2022-08-03 12:34:00 +00:00
$serverAttributes = Pterodactyl :: getServerAttributes ( $server -> pterodactyl_id );
$serverRelationships = $serverAttributes [ 'relationships' ];
$serverLocationAttributes = $serverRelationships [ 'location' ][ 'attributes' ];
//Set server infos
$server -> location = $serverLocationAttributes [ 'long' ] ?
$serverLocationAttributes [ 'long' ] :
$serverLocationAttributes [ 'short' ];
$server -> node = $serverRelationships [ 'node' ][ 'attributes' ][ 'name' ];
$server -> name = $serverAttributes [ 'name' ];
2022-08-03 14:40:57 +00:00
$server -> egg = $serverRelationships [ 'egg' ][ 'attributes' ][ 'name' ];
$products = Product :: orderBy ( " created_at " ) -> get ();
// Set the each product eggs array to just contain the eggs name
foreach ( $products as $product ) {
$product -> eggs = $product -> eggs -> pluck ( 'name' ) -> toArray ();
}
return view ( 'servers.settings' ) -> with ([
2022-08-03 12:34:00 +00:00
'server' => $server ,
2022-08-03 14:40:57 +00:00
'products' => $products
2022-08-03 12:34:00 +00:00
]);
}
public function upgrade ( Server $server , Request $request )
{
2022-08-16 20:33:59 +00:00
if ( $server -> user_id != Auth :: user () -> id ) return redirect () -> route ( 'servers.index' );
2022-08-03 12:34:00 +00:00
if ( ! isset ( $request -> product_upgrade ))
{
return redirect () -> route ( 'servers.show' , [ 'server' => $server -> id ]) -> with ( 'error' , __ ( 'this product is the only one' ));
}
$user = Auth :: user ();
$oldProduct = Product :: where ( 'id' , $server -> product -> id ) -> first ();
$newProduct = Product :: where ( 'id' , $request -> product_upgrade ) -> first ();
$serverAttributes = Pterodactyl :: getServerAttributes ( $server -> pterodactyl_id );
2022-08-15 13:36:14 +00:00
$serverRelationships = $serverAttributes [ 'relationships' ];
2022-08-16 20:21:14 +00:00
// Get node resource allocation info
2022-08-15 13:36:14 +00:00
$nodeId = $serverRelationships [ 'node' ][ 'attributes' ][ 'id' ];
$node = Node :: where ( 'id' , $nodeId ) -> firstOrFail ();
$nodeName = $node -> name ;
// Check if node has enough memory and disk space
$requireMemory = $newProduct -> memory - $oldProduct -> memory ;
$requiredisk = $newProduct -> disk - $oldProduct -> disk ;
$checkResponse = Pterodactyl :: checkNodeResources ( $node , $requireMemory , $requiredisk );
if ( $checkResponse == False ) return redirect () -> route ( 'servers.index' ) -> with ( 'error' , __ ( " The node ' " . $nodeName . " ' doesn't have the required memory or disk left to upgrade the server. " ));
2022-08-03 12:34:00 +00:00
$priceupgrade = $newProduct -> getHourlyPrice ();
if ( $priceupgrade < $oldProduct -> getHourlyPrice ()) {
$priceupgrade = 0 ;
}
if ( $user -> credits >= $priceupgrade )
{
$server -> product_id = $request -> product_upgrade ;
$server -> update ();
$server -> allocation = $serverAttributes [ 'allocation' ];
$response = Pterodactyl :: updateServer ( $server , $newProduct );
if ( $response -> failed ()) return $this -> serverCreationFailed ( $response , $server );
//update user balance
$user -> decrement ( 'credits' , $priceupgrade );
2022-08-11 13:50:33 +00:00
//restart the server
$response = Pterodactyl :: powerAction ( $server , " restart " );
2022-08-15 13:36:14 +00:00
if ( $response -> failed ()) return redirect () -> route ( 'servers.index' ) -> with ( 'error' , $response -> json ()[ 'errors' ][ 0 ][ 'detail' ]);
2022-08-03 12:34:00 +00:00
return redirect () -> route ( 'servers.show' , [ 'server' => $server -> id ]) -> with ( 'success' , __ ( 'Server Successfully Upgraded' ));
}
else
{
return redirect () -> route ( 'servers.show' , [ 'server' => $server -> id ]) -> with ( 'error' , __ ( 'Not Enough Balance for Upgrade' ));
}
}
2021-06-05 09:26:32 +00:00
}