Files
coolify/app/Livewire/Destination/Show.php
T
Andras BacsaiandClaude Opus 5.5 5f78e3dfb3 fix(settings): stop saving read-only credentials from client input
Instance backup settings, started ClickHouse/KeyDB/Dragonfly databases,
and destinations saved read-only fields back to the database, so a
password manager autofill could overwrite stored credentials.

Closes #12173

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:23:06 +02:00

121 lines
3.7 KiB
PHP

<?php
namespace App\Livewire\Destination;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Show extends Component
{
use AuthorizesRequests;
#[Locked]
public $destination;
#[Validate(['string', 'required'])]
public string $name;
#[Locked]
public string $network;
#[Locked]
public string $serverIp;
public function mount(string $destination_uuid)
{
try {
$destination = find_destination_for_current_team($destination_uuid);
if (! $destination) {
return redirect()->route('destination.index');
}
$this->authorize('view', $destination);
$this->destination = $destination;
$this->syncData();
} catch (AuthorizationException) {
abort(403);
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
private function syncData(bool $toModel = false): void
{
if ($toModel) {
$this->validate();
$this->destination->name = $this->name;
$changedFields = auditChangedFields($this->destination);
$this->destination->save();
if ($changedFields !== []) {
auditLog('ui.destination.updated', $this->auditContext([
'changed_fields' => $changedFields,
]));
}
} else {
$this->name = $this->destination->name;
$this->network = $this->destination->network;
$this->serverIp = $this->destination->server->ip;
}
}
public function submit()
{
try {
$this->authorize('update', $this->destination);
$this->syncData(true);
$this->dispatch('success', 'Destination saved.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function delete()
{
try {
$this->authorize('delete', $this->destination);
if ($this->destination->getMorphClass() === StandaloneDocker::class) {
if ($this->destination->attachedTo()) {
return $this->dispatch('error', 'You must delete all resources before deleting this destination.');
}
$safeNetwork = escapeshellarg($this->destination->network);
instant_remote_process(["docker network disconnect {$safeNetwork} coolify-proxy"], $this->destination->server, throwError: false);
instant_remote_process([dockerNetworkRemoveCommand($this->destination->network)], $this->destination->server);
}
$auditContext = $this->auditContext();
$this->destination->delete();
auditLog('ui.destination.deleted', $auditContext);
return redirectRoute($this, 'destination.index');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
/**
* @param array<string, mixed> $context
* @return array<string, mixed>
*/
private function auditContext(array $context = []): array
{
return array_merge([
'team_id' => $this->destination->server?->team_id,
'destination_uuid' => $this->destination->uuid,
'destination_name' => $this->destination->name,
'destination_type' => $this->destination instanceof SwarmDocker ? 'swarm' : 'standalone',
'server_uuid' => $this->destination->server?->uuid,
], $context);
}
public function render()
{
return view('livewire.destination.show');
}
}