mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-14 08:42:38 -04:00
Livewire rebuilds listener names from the session team on every event call. After a team switch in another tab, open pages still listen on the old team channel, so events failed with EventHandlerDoesNotExist (500), or ran handlers that load resources scoped to the new team (404). Store the team at mount and build team channel listeners from it. Events for a team that is no longer the session team are ignored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
207 lines
6.1 KiB
PHP
207 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Project\Database;
|
|
|
|
use App\Actions\Database\RestartDatabase;
|
|
use App\Actions\Database\StartDatabase;
|
|
use App\Actions\Database\StopDatabase;
|
|
use App\Actions\Docker\GetContainersStatus;
|
|
use App\Events\ServiceStatusChanged;
|
|
use App\Support\ResourceStartActivity;
|
|
use App\Traits\ListensToTeamChannel;
|
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|
use Livewire\Component;
|
|
|
|
class Heading extends Component
|
|
{
|
|
use AuthorizesRequests;
|
|
use ListensToTeamChannel;
|
|
|
|
public $database;
|
|
|
|
public array $parameters;
|
|
|
|
public $docker_cleanup = true;
|
|
|
|
public $isDeploymentProgress = false;
|
|
|
|
public $runningActivityId = null;
|
|
|
|
public function getListeners()
|
|
{
|
|
return [
|
|
'refresh' => '$refresh',
|
|
'compose_loaded' => '$refresh',
|
|
'update_links' => '$refresh',
|
|
...$this->teamChannelListeners([
|
|
'ServiceStatusChanged' => 'checkStatus',
|
|
'ServiceChecked' => 'activityFinished',
|
|
]),
|
|
];
|
|
}
|
|
|
|
public function activityFinished()
|
|
{
|
|
if (auth()->user()->cannot('update', $this->database)) {
|
|
$this->dispatch('refresh');
|
|
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Only set started_at if database is actually running
|
|
if ($this->database->isRunning()) {
|
|
$this->database->started_at ??= now();
|
|
}
|
|
$this->database->save();
|
|
|
|
if (is_null($this->database->config_hash) || $this->database->isConfigurationChanged()) {
|
|
$this->database->isConfigurationChanged(true);
|
|
}
|
|
$this->dispatch('configurationChanged');
|
|
} catch (\Exception $e) {
|
|
return handleError($e, $this);
|
|
} finally {
|
|
$this->dispatch('refresh');
|
|
}
|
|
}
|
|
|
|
public function checkStatus()
|
|
{
|
|
$this->checkDeployments();
|
|
|
|
if ($this->database->destination->server->isFunctional()) {
|
|
GetContainersStatus::dispatch($this->database->destination->server);
|
|
} else {
|
|
$this->dispatch('error', 'Server is not functional.');
|
|
}
|
|
}
|
|
|
|
public function checkDeployments()
|
|
{
|
|
try {
|
|
$activity = ResourceStartActivity::latestRunning($this->database->uuid);
|
|
$this->isDeploymentProgress = $activity !== null;
|
|
$this->runningActivityId = $activity?->id;
|
|
} catch (\Throwable) {
|
|
$this->isDeploymentProgress = false;
|
|
$this->runningActivityId = null;
|
|
}
|
|
|
|
return $this->isDeploymentProgress;
|
|
}
|
|
|
|
/**
|
|
* Re-attach the live log dialog to a start/restart that is already running,
|
|
* so the log reappears after the dialog was closed.
|
|
*/
|
|
public function reopenDeployment()
|
|
{
|
|
$this->authorize('view', $this->database);
|
|
|
|
$this->checkDeployments();
|
|
|
|
if ($this->isDeploymentProgress && $this->runningActivityId) {
|
|
$this->dispatch('activityMonitor', $this->runningActivityId, ServiceStatusChanged::class);
|
|
$this->js("window.dispatchEvent(new CustomEvent('startdatabase'))");
|
|
} else {
|
|
$this->dispatch('info', 'No operation is currently running.');
|
|
}
|
|
}
|
|
|
|
private function markDeploymentRunning($activity): void
|
|
{
|
|
if (is_object($activity)) {
|
|
$this->isDeploymentProgress = true;
|
|
$this->runningActivityId = $activity->id;
|
|
}
|
|
}
|
|
|
|
public function manualCheckStatus()
|
|
{
|
|
$this->checkStatus();
|
|
}
|
|
|
|
public function mount()
|
|
{
|
|
$this->parameters = [
|
|
'project_uuid' => $this->database->environment->project->uuid,
|
|
'environment_uuid' => $this->database->environment->uuid,
|
|
'database_uuid' => $this->database->uuid,
|
|
];
|
|
|
|
$this->checkDeployments();
|
|
}
|
|
|
|
public function stop()
|
|
{
|
|
try {
|
|
$this->authorize('manage', $this->database);
|
|
|
|
$this->dispatch('info', 'Gracefully stopping database.');
|
|
StopDatabase::dispatch($this->database, false, $this->docker_cleanup);
|
|
$this->auditDatabaseAction('ui.database.stopped');
|
|
} catch (\Exception $e) {
|
|
$this->dispatch('error', $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function restart()
|
|
{
|
|
try {
|
|
$this->authorize('manage', $this->database);
|
|
|
|
$activity = RestartDatabase::run($this->database);
|
|
if (is_string($activity)) {
|
|
$this->dispatch('error', $activity);
|
|
|
|
return;
|
|
}
|
|
$this->auditDatabaseAction('ui.database.restarted');
|
|
$this->markDeploymentRunning($activity);
|
|
$this->js("window.dispatchEvent(new CustomEvent('startdatabase'))");
|
|
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
|
} catch (\Throwable $e) {
|
|
return handleError($e, $this);
|
|
}
|
|
}
|
|
|
|
public function start()
|
|
{
|
|
try {
|
|
$this->authorize('manage', $this->database);
|
|
|
|
$activity = StartDatabase::run($this->database);
|
|
if (is_string($activity)) {
|
|
$this->dispatch('error', $activity);
|
|
|
|
return;
|
|
}
|
|
$this->auditDatabaseAction('ui.database.started');
|
|
$this->markDeploymentRunning($activity);
|
|
$this->js("window.dispatchEvent(new CustomEvent('startdatabase'))");
|
|
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
|
} catch (\Throwable $e) {
|
|
return handleError($e, $this);
|
|
}
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.project.database.heading', [
|
|
'checkboxes' => [
|
|
['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')],
|
|
],
|
|
]);
|
|
}
|
|
|
|
private function auditDatabaseAction(string $event): void
|
|
{
|
|
auditLog($event, [
|
|
'team_id' => $this->database->team()?->id,
|
|
'database_uuid' => $this->database->uuid,
|
|
'database_name' => $this->database->name,
|
|
]);
|
|
}
|
|
}
|