ServerController.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Classes\Pterodactyl;
  4. use App\Models\Configuration;
  5. use App\Models\Egg;
  6. use App\Models\Location;
  7. use App\Models\Nest;
  8. use App\Models\Node;
  9. use App\Models\Product;
  10. use App\Models\Server;
  11. use App\Notifications\ServerCreationError;
  12. use Exception;
  13. use Illuminate\Database\Eloquent\Builder;
  14. use Illuminate\Http\Client\Response;
  15. use Illuminate\Http\RedirectResponse;
  16. use Illuminate\Http\Request;
  17. use Illuminate\Support\Facades\Auth;
  18. use Illuminate\Support\Facades\Request as FacadesRequest;
  19. class ServerController extends Controller
  20. {
  21. /** Display a listing of the resource. */
  22. public function index()
  23. {
  24. return view('servers.index')->with([
  25. 'servers' => Auth::user()->Servers
  26. ]);
  27. }
  28. /** Show the form for creating a new resource. */
  29. public function create()
  30. {
  31. if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
  32. $productCount = Product::query()->where('disabled', '=', false)->count();
  33. $locations = Location::all();
  34. $nodeCount = Node::query()
  35. ->whereHas('products', function (Builder $builder) {
  36. $builder->where('disabled', '=', false);
  37. })->count();
  38. $eggs = Egg::query()
  39. ->whereHas('products', function (Builder $builder) {
  40. $builder->where('disabled', '=', false);
  41. })->get();
  42. $nests = Nest::query()
  43. ->whereHas('eggs', function (Builder $builder) {
  44. $builder->whereHas('products', function (Builder $builder) {
  45. $builder->where('disabled', '=', false);
  46. });
  47. })->get();
  48. return view('servers.create')->with([
  49. 'productCount' => $productCount,
  50. 'nodeCount' => $nodeCount,
  51. 'nests' => $nests,
  52. 'locations' => $locations,
  53. 'eggs' => $eggs,
  54. 'user' => Auth::user(),
  55. ]);
  56. }
  57. /**
  58. * @return null|RedirectResponse
  59. */
  60. private function validateConfigurationRules()
  61. {
  62. //limit validation
  63. if (Auth::user()->servers()->count() >= Auth::user()->server_limit) {
  64. return redirect()->route('servers.index')->with('error', __('Server limit reached!'));
  65. }
  66. // minimum credits
  67. if (FacadesRequest::has("product")) {
  68. $product = Product::findOrFail(FacadesRequest::input("product"));
  69. if (
  70. Auth::user()->credits <
  71. ($product->minimum_credits == -1
  72. ? Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
  73. : $product->minimum_credits)
  74. ) {
  75. return redirect()->route('servers.index')->with('error', "You do not have the required amount of " . CREDITS_DISPLAY_NAME . " to use this product!");
  76. }
  77. }
  78. //Required Verification for creating an server
  79. if (Configuration::getValueByKey('FORCE_EMAIL_VERIFICATION', 'false') === 'true' && !Auth::user()->hasVerifiedEmail()) {
  80. return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can create a server."));
  81. }
  82. //Required Verification for creating an server
  83. if (Configuration::getValueByKey('FORCE_DISCORD_VERIFICATION', 'false') === 'true' && !Auth::user()->discordUser) {
  84. return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can create a server."));
  85. }
  86. return null;
  87. }
  88. /** Store a newly created resource in storage. */
  89. public function store(Request $request)
  90. {
  91. /** @var Node $node */
  92. /** @var Egg $egg */
  93. /** @var Product $product */
  94. if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
  95. $request->validate([
  96. "name" => "required|max:191",
  97. "node" => "required|exists:nodes,id",
  98. "egg" => "required|exists:eggs,id",
  99. "product" => "required|exists:products,id"
  100. ]);
  101. //get required resources
  102. $product = Product::query()->findOrFail($request->input('product'));
  103. $egg = $product->eggs()->findOrFail($request->input('egg'));
  104. $node = $product->nodes()->findOrFail($request->input('node'));
  105. $server = $request->user()->servers()->create([
  106. 'name' => $request->input('name'),
  107. 'product_id' => $request->input('product'),
  108. ]);
  109. //get free allocation ID
  110. $allocationId = Pterodactyl::getFreeAllocationId($node);
  111. if (!$allocationId) return $this->noAllocationsError($server);
  112. //create server on pterodactyl
  113. $response = Pterodactyl::createServer($server, $egg, $allocationId);
  114. if ($response->failed()) return $this->serverCreationFailed($response, $server);
  115. //update server with pterodactyl_id
  116. $server->update([
  117. 'pterodactyl_id' => $response->json()['attributes']['id'],
  118. 'identifier' => $response->json()['attributes']['identifier']
  119. ]);
  120. if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
  121. if ($request->user()->credits >= $server->product->getHourlyPrice()) {
  122. $request->user()->decrement('credits', $server->product->getHourlyPrice());
  123. }
  124. }
  125. return redirect()->route('servers.index')->with('success', __('Server created'));
  126. }
  127. /**
  128. * return redirect with error
  129. * @param Server $server
  130. * @return RedirectResponse
  131. */
  132. private function noAllocationsError(Server $server)
  133. {
  134. $server->delete();
  135. Auth::user()->notify(new ServerCreationError($server));
  136. return redirect()->route('servers.index')->with('error', __('No allocations satisfying the requirements for automatic deployment on this node were found.'));
  137. }
  138. /**
  139. * return redirect with error
  140. * @param Response $response
  141. * @param Server $server
  142. * @return RedirectResponse
  143. */
  144. private function serverCreationFailed(Response $response, Server $server)
  145. {
  146. $server->delete();
  147. return redirect()->route('servers.index')->with('error', json_encode($response->json()));
  148. }
  149. /** Remove the specified resource from storage. */
  150. public function destroy(Server $server)
  151. {
  152. try {
  153. $server->delete();
  154. return redirect()->route('servers.index')->with('success', __('Server removed'));
  155. } catch (Exception $e) {
  156. return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource "') . $e->getMessage() . '"');
  157. }
  158. }
  159. }