mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-15 02:16:43 +00:00
Merge remote-tracking branch 'origin/next' into feat/search-to-envs
This commit is contained in:
commit
ad4a21d15f
341 files changed
+15824
-6630
No files matched your search
@@ -21,8 +21,6 @@ class ConfigurationChecker extends Component
|
||||
|
||||
public array $configurationDiff = [];
|
||||
|
||||
public array $groupedConfigurationChanges = [];
|
||||
|
||||
public Application|Service|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource;
|
||||
|
||||
public function getListeners(): array
|
||||
@@ -50,21 +48,56 @@ class ConfigurationChecker extends Component
|
||||
$this->configurationChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Members must never see environment variable values, so redact every
|
||||
* environment-section change before it is serialized to the browser.
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $changes
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function redactEnvironmentChanges(array $changes, bool $redact): array
|
||||
{
|
||||
if (! $redact) {
|
||||
return $changes;
|
||||
}
|
||||
|
||||
return collect($changes)
|
||||
->map(function (array $change): array {
|
||||
if (data_get($change, 'section') !== 'environment') {
|
||||
return $change;
|
||||
}
|
||||
|
||||
$change['old_display_value'] = data_get($change, 'old_display_value') === '-' ? '-' : '••••••••';
|
||||
$change['new_display_value'] = data_get($change, 'new_display_value') === '-' ? '-' : '••••••••';
|
||||
$change['old_full_value'] = null;
|
||||
$change['new_full_value'] = null;
|
||||
$change['expandable'] = false;
|
||||
$change['display_summary'] = data_get($change, 'type') === 'changed' ? 'Changed' : null;
|
||||
|
||||
return $change;
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
public function configurationChanged(): void
|
||||
{
|
||||
$this->resource->refresh();
|
||||
|
||||
if ($this->resource instanceof Application) {
|
||||
$diff = $this->resource->pendingDeploymentConfigurationDiff();
|
||||
// Fail closed: only owners/admins may see unlocked env values.
|
||||
$redactEnvironment = ! (bool) auth()->user()?->isAdmin();
|
||||
|
||||
$array = $diff->toArray();
|
||||
$array['changes'] = $this->redactEnvironmentChanges($array['changes'] ?? [], $redactEnvironment);
|
||||
|
||||
$this->isConfigurationChanged = $diff->isChanged();
|
||||
$this->configurationDiff = $diff->toArray();
|
||||
$this->groupedConfigurationChanges = $diff->groupedChanges();
|
||||
$this->configurationDiff = $array;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->isConfigurationChanged = $this->resource->isConfigurationChanged();
|
||||
$this->configurationDiff = [];
|
||||
$this->groupedConfigurationChanges = [];
|
||||
}
|
||||
}
|
||||
@@ -110,15 +110,27 @@ class Destination extends Component
|
||||
|
||||
public function promote(int $network_id, int $server_id)
|
||||
{
|
||||
$main_destination = $this->resource->destination;
|
||||
$this->resource->update([
|
||||
'destination_id' => $network_id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
]);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]);
|
||||
$this->refreshServers();
|
||||
$this->resource->refresh();
|
||||
try {
|
||||
$server = Server::ownedByCurrentTeam()->findOrFail($server_id);
|
||||
$network = StandaloneDocker::ownedByCurrentTeam()->where('server_id', $server->id)->findOrFail($network_id);
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->resource->getConnection()->transaction(function () use ($network, $server) {
|
||||
$main_destination = $this->resource->destination;
|
||||
$this->resource->update([
|
||||
'destination_id' => $network->id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
]);
|
||||
$this->resource->additional_networks()
|
||||
->wherePivot('server_id', $server->id)
|
||||
->detach($network->id);
|
||||
$this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]);
|
||||
});
|
||||
$this->resource->refresh();
|
||||
$this->refreshServers();
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshServers()
|
||||
@@ -130,8 +142,16 @@ class Destination extends Component
|
||||
|
||||
public function addServer(int $network_id, int $server_id)
|
||||
{
|
||||
$this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]);
|
||||
$this->dispatch('refresh');
|
||||
try {
|
||||
$server = Server::ownedByCurrentTeam()->findOrFail($server_id);
|
||||
$network = StandaloneDocker::ownedByCurrentTeam()->where('server_id', $server->id)->findOrFail($network_id);
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->resource->additional_networks()->attach($network->id, ['server_id' => $server->id]);
|
||||
$this->dispatch('refresh');
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeServer(int $network_id, int $server_id, $password, $selectedActions = [])
|
||||
@@ -148,7 +168,9 @@ class Destination extends Component
|
||||
}
|
||||
$server = Server::ownedByCurrentTeam()->findOrFail($server_id);
|
||||
StopApplicationOneServer::run($this->resource, $server);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->additional_networks()
|
||||
->wherePivot('server_id', $server_id)
|
||||
->detach($network_id);
|
||||
$this->loadData();
|
||||
$this->dispatch('refresh');
|
||||
ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id'));
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use App\Models\Service;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class ResourceDetails extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
public ?string $project_uuid = null;
|
||||
|
||||
public ?string $project_name = null;
|
||||
|
||||
public ?string $environment_uuid = null;
|
||||
|
||||
public ?string $environment_name = null;
|
||||
|
||||
public ?string $server_uuid = null;
|
||||
|
||||
public ?string $server_name = null;
|
||||
|
||||
public array $stack_applications = [];
|
||||
|
||||
public array $stack_databases = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('view', $this->resource);
|
||||
|
||||
$environment = $this->resource->environment ?? null;
|
||||
if ($environment) {
|
||||
$this->environment_uuid = $environment->uuid;
|
||||
$this->environment_name = $environment->name;
|
||||
$project = $environment->project ?? null;
|
||||
if ($project) {
|
||||
$this->project_uuid = $project->uuid;
|
||||
$this->project_name = $project->name;
|
||||
}
|
||||
}
|
||||
|
||||
$server = $this->resolveServer();
|
||||
if ($server) {
|
||||
$this->server_uuid = $server->uuid;
|
||||
$this->server_name = $server->name;
|
||||
}
|
||||
|
||||
if ($this->resource instanceof Service) {
|
||||
$this->stack_applications = $this->resource->applications
|
||||
->map(fn ($app) => [
|
||||
'name' => $app->human_name ?: $app->name,
|
||||
'uuid' => $app->uuid,
|
||||
])
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$this->stack_databases = $this->resource->databases
|
||||
->map(fn ($db) => [
|
||||
'name' => $db->human_name ?: $db->name,
|
||||
'uuid' => $db->uuid,
|
||||
])
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
|
||||
private function resolveServer()
|
||||
{
|
||||
try {
|
||||
if (isset($this->resource->destination) && $this->resource->destination && isset($this->resource->destination->server)) {
|
||||
return $this->resource->destination->server;
|
||||
}
|
||||
if (method_exists($this->resource, 'server') && $this->resource->server) {
|
||||
return $this->resource->server;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.shared.resource-details');
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ class Terminal extends Component
|
||||
{
|
||||
public bool $hasShell = true;
|
||||
|
||||
public bool $isTerminalConnected = false;
|
||||
|
||||
private function checkShellAvailability(Server $server, string $container): bool
|
||||
{
|
||||
$escapedContainer = escapeshellarg($container);
|
||||
@@ -65,12 +67,20 @@ class Terminal extends Component
|
||||
$dockerCommand = "sudo {$dockerCommand}";
|
||||
}
|
||||
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, $dockerCommand);
|
||||
$command = SshMultiplexingHelper::generateSshCommand(
|
||||
$server,
|
||||
$dockerCommand,
|
||||
commandTimeout: (int) config('constants.terminal.command_timeout')
|
||||
);
|
||||
} else {
|
||||
$shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '.
|
||||
'if [ -f ~/.profile ]; then . ~/.profile; fi && '.
|
||||
'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi';
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, $shellCommand);
|
||||
$command = SshMultiplexingHelper::generateSshCommand(
|
||||
$server,
|
||||
$shellCommand,
|
||||
commandTimeout: (int) config('constants.terminal.command_timeout')
|
||||
);
|
||||
}
|
||||
// ssh command is sent back to frontend then to websocket
|
||||
// this is done because the websocket connection is not available here
|
||||
@@ -84,6 +94,23 @@ class Terminal extends Component
|
||||
$this->dispatch('send-back-command', $command);
|
||||
}
|
||||
|
||||
#[On('terminalConnected')]
|
||||
public function markTerminalConnected(): void
|
||||
{
|
||||
$this->isTerminalConnected = true;
|
||||
}
|
||||
|
||||
#[On('terminalDisconnected')]
|
||||
public function markTerminalDisconnected(): void
|
||||
{
|
||||
$this->isTerminalConnected = false;
|
||||
}
|
||||
|
||||
public function keepTerminalPageAlive(): void
|
||||
{
|
||||
$this->isTerminalConnected = true;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.shared.terminal');
|
||||
|
||||
Reference in new issue
Block a user