Merge branch '1.0-develop' into develop
This commit is contained in:
commit
4138fb7497
14 changed files with 149 additions and 46 deletions
|
@ -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
|
||||
|
|
11
CHANGELOG.md
11
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.
|
||||
|
|
|
@ -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: |
|
||||
|
||||
|
||||
|
|
|
@ -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')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -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',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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' => [
|
||||
|
|
|
@ -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' => [
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
}
|
||||
};
|
|
@ -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()
|
||||
}),
|
||||
|
|
Loading…
Reference in a new issue