diff --git a/app/Http/Controllers/Admin/ServersController.php b/app/Http/Controllers/Admin/ServersController.php index 6b1808516..56dfdbad3 100644 --- a/app/Http/Controllers/Admin/ServersController.php +++ b/app/Http/Controllers/Admin/ServersController.php @@ -493,6 +493,8 @@ class ServersController extends Controller $repo->updateStartup($id, $request->except('_token'), true); Alert::success('Startup variables were successfully modified and assigned for this server.')->flash(); + } catch (DisplayValidationException $ex) { + return redirect()->route('admin.servers.view.startup', $id)->withErrors(json_decode($ex->getMessage())); } catch (DisplayException $ex) { Alert::danger($ex->getMessage())->flash(); } catch (TransferException $ex) { diff --git a/app/Http/Controllers/Server/ServerController.php b/app/Http/Controllers/Server/ServerController.php index 7be93ff61..c2a597928 100644 --- a/app/Http/Controllers/Server/ServerController.php +++ b/app/Http/Controllers/Server/ServerController.php @@ -209,37 +209,20 @@ class ServerController extends Controller public function getStartup(Request $request, $uuid) { $server = Models\Server::byUuid($uuid); - $server->load(['allocations' => function ($query) use ($server) { - $query->where('id', $server->allocation_id); - }]); + $server->load(['node', 'allocation', 'variables.variable']); + $this->authorize('view-startup', $server); - $variables = Models\ServiceVariable::select( - 'service_variables.*', - DB::raw('COALESCE(server_variables.variable_value, service_variables.default_value) as a_serverValue') - )->leftJoin('server_variables', 'server_variables.variable_id', '=', 'service_variables.id') - ->where('service_variables.option_id', $server->option_id) - ->where('server_variables.server_id', $server->id) - ->get(); - - $service = Models\Service::select( - DB::raw('IFNULL(service_options.executable, services.executable) as executable') - )->leftJoin('service_options', 'service_options.service_id', '=', 'services.id') - ->where('service_options.id', $server->option_id) - ->where('services.id', $server->service_id) - ->first(); - - $allocation = $server->allocations->pop(); - $ServerVariable = [ + $replacements = [ '{{SERVER_MEMORY}}' => $server->memory, - '{{SERVER_IP}}' => $allocation->ip, - '{{SERVER_PORT}}' => $allocation->port, + '{{SERVER_IP}}' => $server->allocation->ip, + '{{SERVER_PORT}}' => $server->allocation->port, ]; - $processed = str_replace(array_keys($ServerVariable), array_values($ServerVariable), $server->startup); - foreach ($variables as &$variable) { - $replace = ($variable->user_viewable === 1) ? $variable->a_serverValue : '[hidden]'; - $processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed); + $processed = str_replace(array_keys($replacements), array_values($replacements), $server->startup); + foreach ($server->variables as $v) { + $replace = ($v->user_can_view) ? $v->variable_value : '[hidden]'; + $processed = str_replace('{{' . $v->variable->env_variable . '}}', $replace, $processed); } $server->js(); @@ -247,8 +230,8 @@ class ServerController extends Controller return view('server.settings.startup', [ 'server' => $server, 'node' => $server->node, - 'variables' => $variables->where('user_viewable', 1), - 'service' => $service, + 'variables' => $server->variables->where('user_can_view', true), + 'service' => $server->service, 'processedStartup' => $processed, ]); } @@ -311,6 +294,8 @@ class ServerController extends Controller $repo = new ServerRepository; $repo->updateStartup($server->id, $request->except('_token')); Alert::success('Server startup variables were successfully updated.')->flash(); + } catch (DisplayValidationException $ex) { + return redirect()->route('server.settings.startup', $uuid)->withErrors(json_decode($ex->getMessage())); } catch (DisplayException $ex) { Alert::danger($ex->getMessage())->flash(); } catch (\Exception $ex) { diff --git a/app/Models/Server.php b/app/Models/Server.php index 524708cde..4e0ae9e2c 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -111,7 +111,7 @@ class Server extends Model * @param string $uuid The Short-UUID of the server to return an object about. * @return \Illuminate\Database\Eloquent\Collection */ - public static function byUuid($uuid) + public static function byUuid($uuid, array $with = [], array $withCount = []) { if (! Auth::check()) { throw new \Exception('You must call Server:byUuid as an authenticated user.'); diff --git a/app/Models/ServerVariable.php b/app/Models/ServerVariable.php index e92c5caf2..165d5b3df 100644 --- a/app/Models/ServerVariable.php +++ b/app/Models/ServerVariable.php @@ -52,6 +52,36 @@ class ServerVariable extends Model 'variable_id' => 'integer', ]; + /** + * Determine if variable is viewable by users. + * + * @return bool + */ + public function getUserCanViewAttribute() + { + return (bool) $this->variable->user_viewable; + } + + /** + * Determine if variable is editable by users. + * + * @return bool + */ + public function getUserCanEditAttribute() + { + return (bool) $this->variable->user_editable; + } + + /** + * Determine if variable is required. + * + * @return bool + */ + public function getRequiredAttribute() + { + return $this->variable->required; + } + /** * Returns information about a given variables parent. * diff --git a/app/Models/ServiceOption.php b/app/Models/ServiceOption.php index adf646d88..521efef39 100644 --- a/app/Models/ServiceOption.php +++ b/app/Models/ServiceOption.php @@ -51,17 +51,6 @@ class ServiceOption extends Model 'service_id' => 'integer', ]; - /** - * Returns the display executable for the option and will use the parent - * service one if the option does not have one defined. - * - * @return string - */ - public function getDisplayExecutableAttribute($value) - { - return (is_null($this->executable)) ? $this->service->executable : $this->executable; - } - /** * Returns the display startup string for the option and will use the parent * service one if the option does not have one defined. diff --git a/app/Models/ServiceVariable.php b/app/Models/ServiceVariable.php index aedfc6351..7e35e48dc 100644 --- a/app/Models/ServiceVariable.php +++ b/app/Models/ServiceVariable.php @@ -47,13 +47,29 @@ class ServiceVariable extends Model * * @var array */ - protected $casts = [ - 'option_id' => 'integer', - 'user_viewable' => 'integer', - 'user_editable' => 'integer', - 'required' => 'integer', - ]; + protected $casts = [ + 'option_id' => 'integer', + 'user_viewable' => 'integer', + 'user_editable' => 'integer', + 'required' => 'integer', + ]; + /** + * Returns the display executable for the option and will use the parent + * service one if the option does not have one defined. + * + * @return string + */ + public function getRequiredAttribute($value) + { + return ($this->rules === 'required' || str_contains($this->rules, ['required|', '|required'])); + } + + /** + * Return server variables associated with this variable. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ public function serverVariable() { return $this->hasMany(ServerVariable::class, 'variable_id'); diff --git a/app/Repositories/ServerRepository.php b/app/Repositories/ServerRepository.php index 0e4e0f099..478bddc11 100644 --- a/app/Repositories/ServerRepository.php +++ b/app/Repositories/ServerRepository.php @@ -627,23 +627,25 @@ class ServerRepository foreach ($server->option->variables as &$variable) { $set = isset($data['env_' . $variable->id]); - // Variable is required but was not passed into the function. - if ($variable->required && ! $set) { - throw new DisplayException('A required variable (' . $variable->env_variable . ') was not passed in the request.'); - } - // If user is not an admin and are trying to edit a non-editable field // or an invisible field just silently skip the variable. if (! $admin && (! $variable->user_editable || ! $variable->user_viewable)) { continue; } - // Confirm value is valid when compared aganist regex. - // @TODO: switch to Laravel validation rules. - if ($set && ! is_null($variable->regex)) { - if (! preg_match($variable->regex, $data['env_' . $variable->id])) { - throw new DisplayException('The value passed for a variable (' . $variable->env_variable . ') could not be matched aganist the regex for that field (' . $variable->regex . ').'); - } + // Perform Field Validation + $validator = Validator::make([ + 'variable_value' => ($set) ? $data['env_' . $variable->id] : null, + ], [ + 'variable_value' => $variable->rules, + ]); + + if ($validator->fails()) { + throw new DisplayValidationException(json_encode( + collect([ + 'notice' => ['There was a validation error with the `' . $variable->name . '` variable.'] + ])->merge($validator->errors()->toArray()) + )); } $svar = Models\ServerVariable::firstOrNew([ diff --git a/app/Repositories/VariableRepository.php b/app/Repositories/VariableRepository.php index 91490b4b1..c707788d3 100644 --- a/app/Repositories/VariableRepository.php +++ b/app/Repositories/VariableRepository.php @@ -80,7 +80,6 @@ class VariableRepository $data['option_id'] = $option->id; $data['user_viewable'] = (in_array('user_viewable', $data['options'])); $data['user_editable'] = (in_array('user_editable', $data['options'])); - $data['required'] = (in_array('required', $data['options'])); // Remove field that isn't used. unset($data['options']); @@ -156,7 +155,6 @@ class VariableRepository $data['user_viewable'] = (in_array('user_viewable', $data['options'])); $data['user_editable'] = (in_array('user_editable', $data['options'])); - $data['required'] = (in_array('required', $data['options'])); // Remove field that isn't used. unset($data['options']); diff --git a/database/migrations/2017_03_11_215455_ChangeServiceVariablesValidationRules.php b/database/migrations/2017_03_11_215455_ChangeServiceVariablesValidationRules.php index a9c1dae84..225a1edc0 100644 --- a/database/migrations/2017_03_11_215455_ChangeServiceVariablesValidationRules.php +++ b/database/migrations/2017_03_11_215455_ChangeServiceVariablesValidationRules.php @@ -24,6 +24,10 @@ class ChangeServiceVariablesValidationRules extends Migration $variable->save(); } }); + + Schema::table('service_variables', function (Blueprint $table) { + $table->dropColumn('required'); + }); } /** @@ -35,6 +39,7 @@ class ChangeServiceVariablesValidationRules extends Migration { Schema::table('service_variables', function (Blueprint $table) { $table->renameColumn('rules', 'regex'); + $table->boolean('required')->default(true)->before('regex'); }); DB::transaction(function () { diff --git a/database/seeds/MinecraftServiceTableSeeder.php b/database/seeds/MinecraftServiceTableSeeder.php index 7595f64bc..0a004947a 100644 --- a/database/seeds/MinecraftServiceTableSeeder.php +++ b/database/seeds/MinecraftServiceTableSeeder.php @@ -246,7 +246,7 @@ EOF; 'user_viewable' => 0, 'user_editable' => 0, 'required' => 0, - 'rules' => 'required|string', + 'rules' => 'string', ]); } diff --git a/resources/lang/en/server.php b/resources/lang/en/server.php index d8cae3ae2..43913b64e 100644 --- a/resources/lang/en/server.php +++ b/resources/lang/en/server.php @@ -234,7 +234,7 @@ return [ 'edit_params' => 'Edit Parameters', 'update' => 'Update Startup Parameters', 'startup_var' => 'Startup Command Variable', - 'startup_regex' => 'Verification Regex', + 'startup_regex' => 'Input Rules', ], 'sftp' => [ 'header' => 'SFTP Configuration', diff --git a/resources/themes/pterodactyl/admin/servers/view/startup.blade.php b/resources/themes/pterodactyl/admin/servers/view/startup.blade.php index 5e4175ad2..61cb650f3 100644 --- a/resources/themes/pterodactyl/admin/servers/view/startup.blade.php +++ b/resources/themes/pterodactyl/admin/servers/view/startup.blade.php @@ -62,10 +62,7 @@
-
- {{ $server->option->display_executable }} - -
+

Edit your server's startup command here. The following variables are available by default: @{{SERVER_MEMORY}}, @{{SERVER_IP}}, and @{{SERVER_PORT}}.

diff --git a/resources/themes/pterodactyl/admin/services/options/variables.blade.php b/resources/themes/pterodactyl/admin/services/options/variables.blade.php index c763e6cee..830bec458 100644 --- a/resources/themes/pterodactyl/admin/services/options/variables.blade.php +++ b/resources/themes/pterodactyl/admin/services/options/variables.blade.php @@ -81,7 +81,6 @@
@@ -135,7 +134,6 @@
diff --git a/resources/themes/pterodactyl/server/settings/startup.blade.php b/resources/themes/pterodactyl/server/settings/startup.blade.php index 981d8e60c..b9377fa6e 100644 --- a/resources/themes/pterodactyl/server/settings/startup.blade.php +++ b/resources/themes/pterodactyl/server/settings/startup.blade.php @@ -42,9 +42,8 @@

@lang('server.config.startup.command')

-
- {{ $service->executable }} - +
+
@can('edit-startup', $server) @@ -56,35 +55,35 @@
@can('edit-startup', $server) - @foreach($variables as $variable) + @foreach($variables as $v)
-

{{ $variable->name }}

+

{{ $v->variable->name }}

- user_editable) - name="env_{{ $variable->id }}" + user_can_edit) + name="env_{{ $v->variable->id }}" @else readonly @endif - class="form-control" type="text" value="{{ old('env_' . $variable->id, $variable->server_value) }}" /> -

{{ $variable->description }}

+ class="form-control" type="text" value="{{ old('env_' . $v->id, $v->variable_value) }}" /> +

{{ $v->variable->description }}

- @if($variable->required && $variable->user_editable) + @if($v->required && $v->user_can_edit) @lang('strings.required') - @elseif(! $variable->required && $variable->user_editable) + @elseif(! $v->required && $v->user_can_edit) @lang('strings.optional') @endif - @if(! $variable->user_editable) + @if(! $v->user_can_edit) @lang('strings.read_only') @endif

@@ -97,14 +96,4 @@ @section('footer-scripts') @parent {!! Theme::js('js/frontend/server.socket.js') !!} - @endsection