From e04abcbcf9665e2f6ae765f754ced89bfbc20209 Mon Sep 17 00:00:00 2001 From: MartinOscar <40749467+rmartinoscar@users.noreply.github.com> Date: Sat, 15 Mar 2025 19:51:10 +0100 Subject: [PATCH] Replace existing Egg `Reserved_Env_Variables` with `SERVER_` prefix (#1070) * Add migration that updates egg->variables->env_variable, egg->startup, egg->servers->startup * Update `EggImporterService` to replace `EggVariable::RESERVED_ENV_NAMES` * Use `EggImporterService::parseReservedEnvNames` * Refactor & Remove `Migration` --- .../Resources/EggResource/Pages/CreateEgg.php | 2 +- .../Resources/EggResource/Pages/EditEgg.php | 2 +- app/Models/EggVariable.php | 19 +++++++++-- .../Eggs/Sharing/EggImporterService.php | 33 ++++++++++++++++--- .../Variables/VariableCreationService.php | 2 +- .../Eggs/Variables/VariableUpdateService.php | 2 +- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/app/Filament/Admin/Resources/EggResource/Pages/CreateEgg.php b/app/Filament/Admin/Resources/EggResource/Pages/CreateEgg.php index d750d85f6..8d1f1b582 100644 --- a/app/Filament/Admin/Resources/EggResource/Pages/CreateEgg.php +++ b/app/Filament/Admin/Resources/EggResource/Pages/CreateEgg.php @@ -192,7 +192,7 @@ class CreateEgg extends CreateRecord ->hintIcon('tabler-code') ->hintIconTooltip(fn ($state) => "{{{$state}}}") ->unique(modifyRuleUsing: fn (Unique $rule, Get $get) => $rule->where('egg_id', $get('../../id')), ignoreRecord: true) - ->rules(EggVariable::$validationRules['env_variable']) + ->rules(EggVariable::getRulesForField('env_variable')) ->validationMessages([ 'unique' => trans('admin/egg.error_unique'), 'required' => trans('admin/egg.error_required'), diff --git a/app/Filament/Admin/Resources/EggResource/Pages/EditEgg.php b/app/Filament/Admin/Resources/EggResource/Pages/EditEgg.php index 49ecefb12..357600b70 100644 --- a/app/Filament/Admin/Resources/EggResource/Pages/EditEgg.php +++ b/app/Filament/Admin/Resources/EggResource/Pages/EditEgg.php @@ -183,7 +183,7 @@ class EditEgg extends EditRecord ->hintIcon('tabler-code') ->hintIconTooltip(fn ($state) => "{{{$state}}}") ->unique(modifyRuleUsing: fn (Unique $rule, Get $get) => $rule->where('egg_id', $get('../../id')), ignoreRecord: true) - ->rules(EggVariable::$validationRules['env_variable']) + ->rules(EggVariable::getRulesForField('env_variable')) ->validationMessages([ 'unique' => trans('admin/egg.error_unique'), 'required' => trans('admin/egg.error_required'), diff --git a/app/Models/EggVariable.php b/app/Models/EggVariable.php index 308fe8b2a..ce464d606 100644 --- a/app/Models/EggVariable.php +++ b/app/Models/EggVariable.php @@ -33,7 +33,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class EggVariable extends Model implements Validatable { use HasFactory; - use HasValidation; + use HasValidation { getRules as getValidationRules; } /** * The resource name for this model when it is transformed into an @@ -44,7 +44,7 @@ class EggVariable extends Model implements Validatable /** * Reserved environment variable names. */ - public const RESERVED_ENV_NAMES = 'P_SERVER_UUID,P_SERVER_ALLOCATION_LIMIT,SERVER_MEMORY,SERVER_IP,SERVER_PORT,ENV,HOME,USER,STARTUP,MODIFIED_STARTUP,SERVER_UUID,UUID,INTERNAL_IP,HOSTNAME,TERM,LANG,PWD,TZ,TIMEZONE'; + public const RESERVED_ENV_NAMES = ['P_SERVER_UUID', 'P_SERVER_ALLOCATION_LIMIT', 'SERVER_MEMORY', 'SERVER_IP', 'SERVER_PORT', 'ENV', 'HOME', 'USER', 'STARTUP', 'MODIFIED_STARTUP', 'SERVER_UUID', 'UUID', 'INTERNAL_IP', 'HOSTNAME', 'TERM', 'LANG', 'PWD', 'TZ', 'TIMEZONE']; /** * Fields that are not mass assignable. @@ -57,7 +57,6 @@ class EggVariable extends Model implements Validatable 'sort' => ['nullable'], 'name' => ['required', 'string', 'between:1,255'], 'description' => ['string'], - 'env_variable' => ['required', 'alphaDash', 'between:1,255', 'notIn:' . self::RESERVED_ENV_NAMES], 'default_value' => ['string'], 'user_viewable' => ['boolean'], 'user_editable' => ['boolean'], @@ -65,6 +64,20 @@ class EggVariable extends Model implements Validatable 'rules.*' => ['string'], ]; + /** + * Implement language verification by overriding Eloquence's gather rules function. + * + * @return array + */ + public static function getRules(): array + { + $rules = self::getValidationRules(); + + $rules['env_variable'] = ['required', 'alphaDash', 'between:1,255', 'notIn:' . implode(',', EggVariable::RESERVED_ENV_NAMES)]; + + return $rules; + } + protected $attributes = [ 'user_editable' => 0, 'user_viewable' => 0, diff --git a/app/Services/Eggs/Sharing/EggImporterService.php b/app/Services/Eggs/Sharing/EggImporterService.php index c95b556e9..98fdad1fb 100644 --- a/app/Services/Eggs/Sharing/EggImporterService.php +++ b/app/Services/Eggs/Sharing/EggImporterService.php @@ -122,11 +122,34 @@ class EggImporterService }; // Make sure we only use recent variable format from now on - $parsed['config']['files'] = str_replace( - array_keys(self::UPGRADE_VARIABLES), - array_values(self::UPGRADE_VARIABLES), - $parsed['config']['files'] ?? '', - ); + if (array_get($parsed['config'], 'files')) { + $parsed['config']['files'] = str_replace( + array_keys(self::UPGRADE_VARIABLES), + array_values(self::UPGRADE_VARIABLES), + $parsed['config']['files'], + ); + } + + [$forbidden, $allowed] = collect($parsed['variables']) + ->map(fn ($variable) => array_merge( + $variable, + ['env_variable' => strtoupper($variable['env_variable'])] + )) + ->partition(fn ($variable) => in_array($variable['env_variable'], EggVariable::RESERVED_ENV_NAMES)); + + $updatedVariables = $forbidden->map(fn ($variable) => array_merge( + $variable, + ['env_variable' => 'SERVER_' . $variable['env_variable']] + )); + + if ($forbidden->count()) { + $parsed['variables'] = $allowed->merge($updatedVariables)->all(); + + if (!empty($parsed['startup'])) { + $pattern = '/\b(' . collect($forbidden)->map(fn ($variable) => preg_quote($variable['env_variable']))->join('|') . ')\b/'; + $parsed['startup'] = preg_replace($pattern, 'SERVER_$1', $parsed['startup']) ?? $parsed['startup']; + } + } return $parsed; } diff --git a/app/Services/Eggs/Variables/VariableCreationService.php b/app/Services/Eggs/Variables/VariableCreationService.php index 63e0afcd2..9fec14366 100644 --- a/app/Services/Eggs/Variables/VariableCreationService.php +++ b/app/Services/Eggs/Variables/VariableCreationService.php @@ -42,7 +42,7 @@ class VariableCreationService */ public function handle(int $egg, array $data): EggVariable { - if (in_array(strtoupper(array_get($data, 'env_variable')), explode(',', EggVariable::RESERVED_ENV_NAMES))) { + if (in_array(strtoupper(array_get($data, 'env_variable')), EggVariable::RESERVED_ENV_NAMES)) { throw new ReservedVariableNameException(sprintf('Cannot use the protected name %s for this environment variable.', array_get($data, 'env_variable'))); } diff --git a/app/Services/Eggs/Variables/VariableUpdateService.php b/app/Services/Eggs/Variables/VariableUpdateService.php index b14bf5bb2..782451e74 100644 --- a/app/Services/Eggs/Variables/VariableUpdateService.php +++ b/app/Services/Eggs/Variables/VariableUpdateService.php @@ -45,7 +45,7 @@ class VariableUpdateService public function handle(EggVariable $variable, array $data): EggVariable { if (!is_null(array_get($data, 'env_variable'))) { - if (in_array(strtoupper(array_get($data, 'env_variable')), explode(',', EggVariable::RESERVED_ENV_NAMES))) { + if (in_array(strtoupper(array_get($data, 'env_variable')), EggVariable::RESERVED_ENV_NAMES)) { throw new ReservedVariableNameException(trans('exceptions.service.variables.reserved_name', ['name' => array_get($data, 'env_variable')])); }