From b6ac96550b21049eb26977d8fa65e5068bfbaad4 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 11 Dec 2015 23:28:58 -0500 Subject: [PATCH] Fairly basic implementation of adding a server. Does not actually do anything yet. Pushing this for commit sake. --- app/Exceptions/DisplayValidationException.php | 8 ++ .../Controllers/Admin/ServersController.php | 10 ++- app/Models/Server.php | 84 ++++++++++++++++--- 3 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 app/Exceptions/DisplayValidationException.php diff --git a/app/Exceptions/DisplayValidationException.php b/app/Exceptions/DisplayValidationException.php new file mode 100644 index 000000000..c1195c7e5 --- /dev/null +++ b/app/Exceptions/DisplayValidationException.php @@ -0,0 +1,8 @@ +all()); + + try { + $resp = Server::addServer($request->all()); + echo $resp . '
'; + } catch (\Exception $e) { + Debugbar::addException($e); + } + return json_encode($request->all()); + } /** diff --git a/app/Models/Server.php b/app/Models/Server.php index fa59c50fb..3b0313e63 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -3,14 +3,16 @@ namespace Pterodactyl\Models; use Auth; -use Validator; +use DB; use Debugbar; +use Validator; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\AccountNotFoundException; -use Pterodactyl\Models\User; -use Pterodactyl\Models\Permission; -use Pterodactyl\Models\Subuser; +use Pterodactyl\Exceptions\DisplayValidationException; + +use Pterodactyl\Models; + use Illuminate\Database\Eloquent\Model; class Server extends Model @@ -48,6 +50,18 @@ class Server extends Model self::$user = Auth::user(); } + protected static function generateSFTPUsername($name) + { + + $name = preg_replace('/\s+/', '', $name); + if (strlen($name) > 6) { + return strtolower('ptdl-' . substr($name, 0, 6) . '_' . str_random(5)); + } + + return strtolower('ptdl-' . $name . '_' . str_random((11 - strlen($name)))); + + } + /** * Determine if we need to change the server's daemonSecret value to * match that of the user if they are a subuser. @@ -62,7 +76,7 @@ class Server extends Model return $server->daemonSecret; } - $subuser = Subuser::where('server_id', $server->id)->where('user_id', self::$user->id)->first(); + $subuser = Models\Subuser::where('server_id', $server->id)->where('user_id', self::$user->id)->first(); if (is_null($subuser)) { return null; @@ -87,7 +101,7 @@ class Server extends Model ->where('active', 1); if (self::$user->root_admin !== 1) { - $query->whereIn('servers.id', Subuser::accessServers()); + $query->whereIn('servers.id', Models\Subuser::accessServers()); } return $query->get(); @@ -110,7 +124,7 @@ class Server extends Model $query = self::where('uuidShort', $uuid)->where('active', 1); if (self::$user->root_admin !== 1) { - $query->whereIn('servers.id', Subuser::accessServers()); + $query->whereIn('servers.id', Models\Subuser::accessServers()); } $result = $query->first(); @@ -154,7 +168,7 @@ class Server extends Model // Validate Fields $validator = Validator::make($data, [ 'owner' => 'required|email|exists:users,email', - 'node' => 'required|numeric|min:1', + 'node' => 'required|numeric|min:1|exists:nodes,id', 'name' => 'required|regex:([\w -]{4,35})', 'memory' => 'required|numeric|min:1', 'disk' => 'required|numeric|min:1', @@ -167,14 +181,60 @@ class Server extends Model 'custom_image_name' => 'required_if:use_custom_image,on', ]); - // @TODO: Have this return a JSON response. + // Run validator, throw catchable and displayable exception if it fails. + // Exception includes a JSON result of failed validation rules. if ($validator->fails()) { - foreach($validator->errors()->all() as $error) { - Debugbar::info($error); + throw new DisplayValidationException(json_encode($validator->errors()->all())); + } + + // Get the User ID; user exists since we passed the 'exists:users,email' part of the validation + $user = Models\User::select('id')->where('email', $data['owner'])->first(); + + // Verify IP & Port are a.) free and b.) assigned to the node. + // We know the node exists because of 'exists:nodes,id' in the validation + $node = Models\Node::find($data['node']); + $allocation = Models\Allocation::where('ip', $data['ip'])->where('port', $data['port'])->where('node', $data['node'])->whereNull('assigned_to')->first(); + + // Something failed in the query, either that combo doesn't exist, or it is in use. + if (!$allocation) { + throw new DisplayException('The selected IP/Port combination (' . $data['ip'] . ':' . $data['port'] . ') is either already in use, or unavaliable for this node.'); + } + + // Validate those Service Option Variables + // We know the service and option exists because of the validation. + // We need to verify that the option exists for the service, and then check for + // any required variable fields. (fields are labeled env_) + $option = Models\ServiceOptions::where('id', $data['option'])->where('parent_service', $data['service'])->first(); + if (!$option) { + throw new DisplayException('The requested service option does not exist for the specified service.'); + } + + // Check those Variables + $variables = Models\ServiceVariables::where('option_id', $data['option'])->get(); + if ($variables) { + foreach($variables as $variable) { + + // Is the variable required? + if (!$data['env_' . $variable->env_variable]) { + if ($variable->required === 1) { + throw new DisplayException('A required service option variable field (env_' . $variable->env_variable . ') was missing from the request.'); + } + + $data['env_' . $variable->env_variable] = $variable->default_value; + continue; + } + + // Check aganist Regex Pattern + if (!is_null($variable->regex) && !preg_match($variable->regex, $data['env_' . $variable->env_variable])) { + throw new DisplayException('Failed to validate service option variable field (env_' . $variable->env_variable . ') aganist regex (' . $variable->regex . ').'); + } + + continue; + } } - return; + return self::generateSFTPUsername($data['name']); }