diff --git a/.env.example b/.env.example index b852f8d86..533799999 100644 --- a/.env.example +++ b/.env.example @@ -41,4 +41,4 @@ MAIL_FROM_NAME="Pterodactyl Panel" # mail servers such as Gmail to reject your mail. # # @see: https://github.com/pterodactyl/panel/pull/3110 -# SERVER_NAME=panel.example.com +# MAIL_EHLO_DOMAIN=panel.example.com diff --git a/CHANGELOG.md b/CHANGELOG.md index 100100347..523071887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v1.11.2 +### Changed +* Telemetry no longer sends a map of Egg and Nest UUIDs to the number of servers using them. +* Increased the timeout for the decompress files endpoint in the client API from 15 seconds to 15 minutes. + +### Fixed +* Fixed Panel Docker image having a `v` prefix in the version displayed in the admin area. +* Fixed emails using the wrong queue name, causing them to not be sent. +* Fixed the settings keys used for configuring SMTP settings, causing settings to not save properly. +* Fixed the `MAIL_EHLO_DOMAIN` environment variable not being properly backwards compatible with the old `SERVER_NAME` variable. + ## v1.11.1 ### Fixed * Fixed Panel Docker image showing `canary` as it's version. diff --git a/SECURITY.md b/SECURITY.md index 9d06612dc..e5a9eb0fa 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,11 +1,13 @@ # Security Policy ## Supported Versions + The following versions of Pterodactyl are receiving active support and maintenance. Any security vulnerabilities discovered must be reproducible in supported versions. | Panel | Daemon | Supported | |--------|--------------|--------------------| | 1.10.x | wings@1.7.x | :white_check_mark: | +| 1.11.x | wings@1.11.x | :white_check_mark: | | 0.7.x | daemon@0.6.x | :x: | diff --git a/app/Console/Commands/Environment/EmailSettingsCommand.php b/app/Console/Commands/Environment/EmailSettingsCommand.php index 1fd9a2aee..cffb03a6b 100644 --- a/app/Console/Commands/Environment/EmailSettingsCommand.php +++ b/app/Console/Commands/Environment/EmailSettingsCommand.php @@ -67,12 +67,6 @@ class EmailSettingsCommand extends Command $this->config->get('mail.from.name') ); - $this->variables['MAIL_ENCRYPTION'] = $this->option('encryption') ?? $this->choice( - trans('command/messages.environment.mail.ask_encryption'), - ['tls' => 'TLS', 'ssl' => 'SSL', '' => 'None'], - $this->config->get('mail.encryption', 'tls') - ); - $this->writeToEnvironment($this->variables); $this->line('Updating stored environment configuration file.'); @@ -102,6 +96,12 @@ class EmailSettingsCommand extends Command $this->variables['MAIL_PASSWORD'] = $this->option('password') ?? $this->secret( trans('command/messages.environment.mail.ask_smtp_password') ); + + $this->variables['MAIL_ENCRYPTION'] = $this->option('encryption') ?? $this->choice( + trans('command/messages.environment.mail.ask_encryption'), + ['tls' => 'TLS', 'ssl' => 'SSL', '' => 'None'], + $this->config->get('mail.mailers.smtp.encryption', 'tls') + ); } /** diff --git a/app/Http/Controllers/Admin/Settings/MailController.php b/app/Http/Controllers/Admin/Settings/MailController.php index 762da8aeb..3e97ec54f 100644 --- a/app/Http/Controllers/Admin/Settings/MailController.php +++ b/app/Http/Controllers/Admin/Settings/MailController.php @@ -54,8 +54,8 @@ class MailController extends Controller } $values = $request->normalize(); - if (array_get($values, 'mail:password') === '!e') { - $values['mail:password'] = ''; + if (array_get($values, 'mail:mailers:smtp:password') === '!e') { + $values['mail:mailers:smtp:password'] = ''; } foreach ($values as $key => $value) { diff --git a/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php b/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php index 4475b08fd..3f014e982 100644 --- a/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php +++ b/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php @@ -13,11 +13,11 @@ class MailSettingsFormRequest extends AdminFormRequest public function rules(): array { return [ - 'mail:host' => 'required|string', - 'mail:port' => 'required|integer|between:1,65535', - 'mail:encryption' => ['present', Rule::in([null, 'tls', 'ssl'])], - 'mail:username' => 'nullable|string|max:191', - 'mail:password' => 'nullable|string|max:191', + 'mail:mailers:smtp:host' => 'required|string', + 'mail:mailers:smtp:port' => 'required|integer|between:1,65535', + 'mail:mailers:smtp:encryption' => ['present', Rule::in([null, 'tls', 'ssl'])], + 'mail:mailers:smtp:username' => 'nullable|string|max:191', + 'mail:mailers:smtp:password' => 'nullable|string|max:191', 'mail:from:address' => 'required|string|email', 'mail:from:name' => 'nullable|string|max:191', ]; @@ -31,8 +31,8 @@ class MailSettingsFormRequest extends AdminFormRequest { $keys = array_flip(array_keys($this->rules())); - if (empty($this->input('mail:password'))) { - unset($keys['mail:password']); + if (empty($this->input('mail:mailers:smtp:password'))) { + unset($keys['mail:mailers:smtp:password']); } return $this->only(array_flip($keys)); diff --git a/app/Models/Setting.php b/app/Models/Setting.php index ec85a2ecf..b8812bc66 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -2,7 +2,13 @@ namespace Pterodactyl\Models; -/** @property string $value */ +/** + * Pterodactyl\Models\Setting. + * + * @property int $id + * @property string $key + * @property string $value + */ class Setting extends Model { /** diff --git a/app/Providers/SettingsServiceProvider.php b/app/Providers/SettingsServiceProvider.php index e2bcdafe6..dc310495d 100644 --- a/app/Providers/SettingsServiceProvider.php +++ b/app/Providers/SettingsServiceProvider.php @@ -37,13 +37,13 @@ class SettingsServiceProvider extends ServiceProvider * when using the SMTP driver. */ protected array $emailKeys = [ - 'mail:host', - 'mail:port', + 'mail:mailers:smtp:host', + 'mail:mailers:smtp:port', + 'mail:mailers:smtp:encryption', + 'mail:mailers:smtp:username', + 'mail:mailers:smtp:password', 'mail:from:address', 'mail:from:name', - 'mail:encryption', - 'mail:username', - 'mail:password', ]; /** @@ -51,7 +51,7 @@ class SettingsServiceProvider extends ServiceProvider * configuration array. */ protected static array $encrypted = [ - 'mail:password', + 'mail:mailers:smtp:password', ]; /** diff --git a/app/Repositories/Wings/DaemonFileRepository.php b/app/Repositories/Wings/DaemonFileRepository.php index 3bd897881..77949478f 100644 --- a/app/Repositories/Wings/DaemonFileRepository.php +++ b/app/Repositories/Wings/DaemonFileRepository.php @@ -231,6 +231,9 @@ class DaemonFileRepository extends DaemonRepository 'root' => $root ?? '/', 'file' => $file, ], + // Wait for up to 15 minutes for the decompress to be completed when calling this endpoint + // since it will likely take quite awhile for large directories. + 'timeout' => 60 * 15, ] ); } catch (TransferException $exception) { diff --git a/app/Services/Telemetry/TelemetryCollectionService.php b/app/Services/Telemetry/TelemetryCollectionService.php index f90bec033..c2fd12830 100644 --- a/app/Services/Telemetry/TelemetryCollectionService.php +++ b/app/Services/Telemetry/TelemetryCollectionService.php @@ -140,10 +140,12 @@ class TelemetryCollectionService 'eggs' => [ 'count' => Egg::count(), - 'server_usage' => Egg::all() - ->flatMap(fn (Egg $egg) => [$egg->uuid => $egg->servers->count()]) - ->filter(fn (int $count) => $count > 0) - ->toArray(), + // Egg UUIDs are generated randomly on import, so there is not a consistent way to + // determine if servers are using default eggs or not. +// 'server_usage' => Egg::all() +// ->flatMap(fn (Egg $egg) => [$egg->uuid => $egg->servers->count()]) +// ->filter(fn (int $count) => $count > 0) +// ->toArray(), ], 'locations' => [ @@ -156,10 +158,12 @@ class TelemetryCollectionService 'nests' => [ 'count' => Nest::count(), - 'server_usage' => Nest::all() - ->flatMap(fn (Nest $nest) => [$nest->uuid => $nest->eggs->sum(fn (Egg $egg) => $egg->servers->count())]) - ->filter(fn (int $count) => $count > 0) - ->toArray(), + // Nest UUIDs are generated randomly on import, so there is not a consistent way to + // determine if servers are using default eggs or not. +// 'server_usage' => Nest::all() +// ->flatMap(fn (Nest $nest) => [$nest->uuid => $nest->eggs->sum(fn (Egg $egg) => $egg->servers->count())]) +// ->filter(fn (int $count) => $count > 0) +// ->toArray(), ], 'nodes' => [ diff --git a/config/mail.php b/config/mail.php index 95c6f303c..ee612fdcc 100644 --- a/config/mail.php +++ b/config/mail.php @@ -41,7 +41,7 @@ return [ 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'timeout' => null, - 'local_domain' => env('MAIL_EHLO_DOMAIN'), + 'local_domain' => env('MAIL_EHLO_DOMAIN', env('SERVER_NAME')), ], 'ses' => [ diff --git a/config/queue.php b/config/queue.php index 39b93eefb..74da2e825 100644 --- a/config/queue.php +++ b/config/queue.php @@ -33,7 +33,7 @@ return [ 'database' => [ 'driver' => 'database', 'table' => 'jobs', - 'queue' => env('QUEUE_STANDARD', 'default'), + 'queue' => env('QUEUE_STANDARD', 'standard'), 'retry_after' => 90, 'after_commit' => false, ], @@ -43,7 +43,7 @@ return [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), - 'queue' => env('SQS_QUEUE', env('QUEUE_STANDARD', 'default')), + 'queue' => env('SQS_QUEUE', env('QUEUE_STANDARD', 'standard')), 'suffix' => env('SQS_SUFFIX'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'after_commit' => false, @@ -52,7 +52,7 @@ return [ 'redis' => [ 'driver' => 'redis', 'connection' => 'default', - 'queue' => env('REDIS_QUEUE', env('QUEUE_STANDARD', 'default')), + 'queue' => env('REDIS_QUEUE', env('QUEUE_STANDARD', 'standard')), 'retry_after' => 90, 'block_for' => null, 'after_commit' => false, diff --git a/database/migrations/2022_12_12_213937_update_mail_settings_to_new_format.php b/database/migrations/2022_12_12_213937_update_mail_settings_to_new_format.php new file mode 100644 index 000000000..97b651033 --- /dev/null +++ b/database/migrations/2022_12_12_213937_update_mail_settings_to_new_format.php @@ -0,0 +1,77 @@ +keys, 0); + $oldSettings = $settings->filter(fn (Setting $setting) => in_array($setting->key, $oldKeys)); + + // Gets the second column in our key table and gets all matching settings. + $newKeys = array_column($this->keys, 1); + $newSettings = $settings->filter(fn (Setting $setting) => in_array($setting->key, $newKeys)); + + // Map all the old settings to their new key. + $oldSettings->map(function (Setting $setting) use ($oldKeys) { + $row = array_search($setting->key, $oldKeys, true); + $setting->key = $this->keys[$row][1]; + + return $setting; + // Check if any settings with the new key already exist. + })->filter(function (Setting $setting) use ($newSettings) { + if ($newSettings->contains('key', $setting->key)) { + return false; + } + + return true; + // Update the settings to use their new keys if they don't already exist. + })->each(fn (Setting $setting) => $setting->save()); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::transaction(function () { + $settings = Setting::all(); + + // Gets the second column in our key table and gets all matching settings. + $newKeys = array_column($this->keys, 0); + $newSettings = $settings->filter(fn (Setting $setting) => in_array($setting->key, $newKeys)); + + // Delete all settings that already have the new key. + $newSettings->each(fn (Setting $setting) => $setting->delete()); + + // Gets the first column in our key table and gets all matching settings. + $oldKeys = array_column($this->keys, 1); + $oldSettings = $settings->filter(fn (Setting $setting) => in_array($setting->key, $oldKeys)); + + // Map all the old settings to their new key. + $oldSettings->map(function (Setting $setting) use ($oldKeys) { + $row = array_search($setting->key, $oldKeys, true); + $setting->key = $this->keys[$row][0]; + + return $setting; + // Update the settings to use their new keys if they don't already exist. + })->each(fn (Setting $setting) => $setting->save()); + }); + } +}; diff --git a/resources/views/admin/settings/mail.blade.php b/resources/views/admin/settings/mail.blade.php index b13446995..9e99acd30 100644 --- a/resources/views/admin/settings/mail.blade.php +++ b/resources/views/admin/settings/mail.blade.php @@ -38,14 +38,14 @@
- +

Enter the SMTP server address that mail should be sent through.

- +

Enter the SMTP server port that mail should be sent through.

@@ -53,9 +53,9 @@
@php - $encryption = old('mail:encryption', config('mail.mailers.smtp.encryption')); + $encryption = old('mail:mailers:smtp:encryption', config('mail.mailers.smtp.encryption')); @endphp - @@ -66,14 +66,14 @@
- +

The username to use when connecting to the SMTP server.

- +

The password to use in conjunction with the SMTP username. Leave blank to continue using the existing password. To set the password to an empty value enter !e into the field.

@@ -120,11 +120,11 @@ url: '/admin/settings/mail', contentType: 'application/json', data: JSON.stringify({ - 'mail:host': $('input[name="mail:host"]').val(), - 'mail:port': $('input[name="mail:port"]').val(), - 'mail:encryption': $('select[name="mail:encryption"]').val(), - 'mail:username': $('input[name="mail:username"]').val(), - 'mail:password': $('input[name="mail:password"]').val(), + 'mail:mailers:smtp:host': $('input[name="mail:mailers:smtp:host"]').val(), + 'mail:mailers:smtp:port': $('input[name="mail:mailers:smtp:port"]').val(), + 'mail:mailers:smtp:encryption': $('select[name="mail:mailers:smtp:encryption"]').val(), + 'mail:mailers:smtp:username': $('input[name="mail:mailers:smtp:username"]').val(), + 'mail:mailers:smtp:password': $('input[name="mail:mailers:smtp:password"]').val(), 'mail:from:address': $('input[name="mail:from:address"]').val(), 'mail:from:name': $('input[name="mail:from:name"]').val() }),