Merge branch '1.0-develop' into develop

This commit is contained in:
Matthew Penner 2022-12-12 16:23:11 -07:00
commit 4138fb7497
No known key found for this signature in database
14 changed files with 149 additions and 46 deletions

View file

@ -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

View file

@ -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.

View file

@ -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: |

View file

@ -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')
);
}
/**

View file

@ -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) {

View file

@ -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));

View file

@ -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
{
/**

View file

@ -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',
];
/**

View file

@ -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) {

View file

@ -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' => [

View file

@ -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' => [

View file

@ -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,

View file

@ -0,0 +1,77 @@
<?php
use Pterodactyl\Models\Setting;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
private array $keys = [
['mail:host', 'mail:mailers:smtp:host'],
['mail:port', 'mail:mailers:smtp:port'],
['mail:encryption', 'mail:mailers:smtp:encryption'],
['mail:username', 'mail:mailers:smtp:username'],
['mail:password', 'mail:mailers:smtp:password'],
];
/**
* Run the migrations.
*/
public function up(): void
{
$settings = Setting::all();
// Gets the first column in our key table and gets all matching settings.
$oldKeys = array_column($this->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());
});
}
};

View file

@ -38,14 +38,14 @@
<div class="form-group col-md-6">
<label class="control-label">SMTP Host</label>
<div>
<input required type="text" class="form-control" name="mail:host" value="{{ old('mail:host', config('mail.mailers.smtp.host')) }}" />
<input required type="text" class="form-control" name="mail:mailers:smtp:host" value="{{ old('mail:mailers:smtp:host', config('mail.mailers.smtp.host')) }}" />
<p class="text-muted small">Enter the SMTP server address that mail should be sent through.</p>
</div>
</div>
<div class="form-group col-md-2">
<label class="control-label">SMTP Port</label>
<div>
<input required type="number" class="form-control" name="mail:port" value="{{ old('mail:port', config('mail.mailers.smtp.port')) }}" />
<input required type="number" class="form-control" name="mail:mailers:smtp:port" value="{{ old('mail:mailers:smtp:port', config('mail.mailers.smtp.port')) }}" />
<p class="text-muted small">Enter the SMTP server port that mail should be sent through.</p>
</div>
</div>
@ -53,9 +53,9 @@
<label class="control-label">Encryption</label>
<div>
@php
$encryption = old('mail:encryption', config('mail.mailers.smtp.encryption'));
$encryption = old('mail:mailers:smtp:encryption', config('mail.mailers.smtp.encryption'));
@endphp
<select name="mail:encryption" class="form-control">
<select name="mail:mailers:smtp:encryption" class="form-control">
<option value="" @if($encryption === '') selected @endif>None</option>
<option value="tls" @if($encryption === 'tls') selected @endif>Transport Layer Security (TLS)</option>
<option value="ssl" @if($encryption === 'ssl') selected @endif>Secure Sockets Layer (SSL)</option>
@ -66,14 +66,14 @@
<div class="form-group col-md-6">
<label class="control-label">Username <span class="field-optional"></span></label>
<div>
<input type="text" class="form-control" name="mail:username" value="{{ old('mail:username', config('mail.mailers.smtp.username')) }}" />
<input type="text" class="form-control" name="mail:mailers:smtp:username" value="{{ old('mail:mailers:smtp:username', config('mail.mailers.smtp.username')) }}" />
<p class="text-muted small">The username to use when connecting to the SMTP server.</p>
</div>
</div>
<div class="form-group col-md-6">
<label class="control-label">Password <span class="field-optional"></span></label>
<div>
<input type="password" class="form-control" name="mail:password"/>
<input type="password" class="form-control" name="mail:mailers:smtp:password"/>
<p class="text-muted small">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 <code>!e</code> into the field.</p>
</div>
</div>
@ -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()
}),