mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-13 12:14:28 +00:00
Merge remote-tracking branch 'origin/next' into jean/allow-dots-username
This commit is contained in:
commit
9aa40bb5f0
411 files changed
+21821
-8593
No files matched your search
@@ -2,11 +2,15 @@
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\StartSentinel;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Charts extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public $chartId = 'server';
|
||||
@@ -28,6 +32,29 @@ class Charts extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleMetrics(): void
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->settings->is_metrics_enabled = ! $this->server->settings->is_metrics_enabled;
|
||||
$this->server->settings->save();
|
||||
$this->server->refresh();
|
||||
|
||||
if ($this->server->isMetricsEnabled()) {
|
||||
StartSentinel::run($this->server, true);
|
||||
$this->dispatch('success', 'Metrics enabled. Starting Sentinel.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
$this->redirect(route('server.metrics', ['server_uuid' => $this->server->uuid]), navigate: true);
|
||||
} else {
|
||||
$this->server->restartSentinel();
|
||||
$this->dispatch('success', 'Metrics disabled. Restarting Sentinel.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function pollData()
|
||||
{
|
||||
if ($this->poll || $this->interval <= 10) {
|
||||
|
||||
@@ -45,7 +45,7 @@ class Destinations extends Component
|
||||
} else {
|
||||
SwarmDocker::create([
|
||||
'name' => $this->server->name.'-'.$name,
|
||||
'network' => $this->name,
|
||||
'network' => $name,
|
||||
'server_id' => $this->server->id,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -28,12 +28,11 @@ class DynamicConfigurationNavbar extends Component
|
||||
|
||||
// Decode filename: pipes are used to encode dots for Livewire property binding
|
||||
// (e.g., 'my|service.yaml' -> 'my.service.yaml')
|
||||
// This must happen BEFORE validation because validateShellSafePath() correctly
|
||||
// rejects pipe characters as dangerous shell metacharacters
|
||||
// This must happen BEFORE validation because validateFilenameSafe()
|
||||
// rejects pipe characters through validateShellSafePath().
|
||||
$file = str_replace('|', '.', $fileName);
|
||||
|
||||
// Validate filename to prevent command injection
|
||||
validateShellSafePath($file, 'proxy configuration filename');
|
||||
validateFilenameSafe($file, 'proxy configuration filename');
|
||||
|
||||
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
||||
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
||||
|
||||
@@ -43,8 +43,7 @@ class NewDynamicConfiguration extends Component
|
||||
'value' => 'required',
|
||||
]);
|
||||
|
||||
// Additional security validation to prevent command injection
|
||||
validateShellSafePath($this->fileName, 'proxy configuration filename');
|
||||
validateFilenameSafe($this->fileName, 'proxy configuration filename');
|
||||
|
||||
if (data_get($this->parameters, 'server_uuid')) {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(data_get($this->parameters, 'server_uuid'))->first();
|
||||
|
||||
@@ -15,8 +15,6 @@ class Sentinel extends Component
|
||||
|
||||
public Server $server;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public bool $isMetricsEnabled;
|
||||
|
||||
#[Validate(['required', 'string', 'max:500', 'regex:/\A[a-zA-Z0-9._\-+=\/]+\z/'])]
|
||||
@@ -51,15 +49,9 @@ class Sentinel extends Component
|
||||
];
|
||||
}
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->syncData();
|
||||
} catch (\Throwable) {
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->syncData();
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
@@ -93,7 +85,9 @@ class Sentinel extends Component
|
||||
{
|
||||
if ($event['serverUuid'] === $this->server->uuid) {
|
||||
$this->server->refresh();
|
||||
$this->syncData();
|
||||
// Only refresh display-only state; never re-sync text-input properties
|
||||
// (would clobber any unsaved typing — see coolify#6062 / #6354 / #9695).
|
||||
$this->sentinelUpdatedAt = $this->server->sentinel_updated_at;
|
||||
$this->dispatch('success', 'Sentinel has been restarted successfully.');
|
||||
}
|
||||
}
|
||||
@@ -110,27 +104,29 @@ class Sentinel extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedIsSentinelEnabled($value)
|
||||
public function toggleSentinel(): void
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageSentinel', $this->server);
|
||||
if ($value === true) {
|
||||
if (! $this->isSentinelEnabled) {
|
||||
if ($this->server->isBuildServer()) {
|
||||
$this->isSentinelEnabled = false;
|
||||
$this->dispatch('error', 'Sentinel cannot be enabled on build servers.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->isSentinelEnabled = true;
|
||||
$customImage = isDev() ? $this->sentinelCustomDockerImage : null;
|
||||
StartSentinel::run($this->server, true, null, $customImage);
|
||||
} else {
|
||||
$this->isSentinelEnabled = false;
|
||||
$this->isMetricsEnabled = false;
|
||||
$this->isSentinelDebugEnabled = false;
|
||||
StopSentinel::dispatch($this->server);
|
||||
}
|
||||
$this->submit();
|
||||
$this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server\Sentinel;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class Logs extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('livewire.server.sentinel.logs');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server\Sentinel;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
|
||||
public array $parameters = [];
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('livewire.server.sentinel.show');
|
||||
}
|
||||
}
|
||||
@@ -278,7 +278,9 @@ class Show extends Component
|
||||
// Only refresh if the event is for this server
|
||||
if (isset($event['serverUuid']) && $event['serverUuid'] === $this->server->uuid) {
|
||||
$this->server->refresh();
|
||||
$this->syncData();
|
||||
// Only refresh display-only state; never re-sync text-input properties
|
||||
// (would clobber any unsaved typing — see coolify#6062 / #6354 / #9695).
|
||||
$this->sentinelUpdatedAt = $this->server->sentinel_updated_at;
|
||||
$this->dispatch('success', 'Sentinel has been restarted successfully.');
|
||||
}
|
||||
}
|
||||
@@ -458,12 +460,15 @@ class Show extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
// Refresh server data
|
||||
// Refresh server data and only the display-only state that validation produces.
|
||||
// Never re-sync text-input properties via syncData() — would clobber any
|
||||
// unsaved typing (see coolify#6062 / #6354 / #9695).
|
||||
$this->server->refresh();
|
||||
$this->syncData();
|
||||
|
||||
// Update validation state
|
||||
$this->server->settings->refresh();
|
||||
$this->isValidating = $this->server->is_validating ?? false;
|
||||
$this->validationLogs = $this->server->validation_logs;
|
||||
$this->isReachable = $this->server->settings->is_reachable;
|
||||
$this->isUsable = $this->server->settings->is_usable;
|
||||
|
||||
// Reload Hetzner tokens in case the linking section should now be shown
|
||||
$this->loadHetznerTokens();
|
||||
|
||||
Reference in new issue
Block a user