mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-15 09:12:32 -04:00
Addresses CodeRabbit review on #11513: - Add Livewire feature tests for Heading::flush() covering success + audit event, non-cache guard, denied manage permission, and menu visibility for cache vs non-cache databases. - Document the pre-existing parseCommandsByLineForSudo() limitation that mutates passwords containing shell sequences on non-root servers.
63 lines
2.3 KiB
PHP
63 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace App\Actions\Database;
|
|
|
|
use App\Models\StandaloneDragonfly;
|
|
use App\Models\StandaloneKeydb;
|
|
use App\Models\StandaloneRedis;
|
|
use Lorisleiva\Actions\Concerns\AsAction;
|
|
|
|
class FlushCacheDatabase
|
|
{
|
|
use AsAction;
|
|
|
|
public function handle(StandaloneRedis|StandaloneKeydb|StandaloneDragonfly $database): void
|
|
{
|
|
$server = $database->destination->server;
|
|
|
|
if (! $server->isFunctional()) {
|
|
throw new \RuntimeException('Server is not functional.');
|
|
}
|
|
|
|
if (! $database->isRunning()) {
|
|
throw new \RuntimeException('Database is not running.');
|
|
}
|
|
|
|
$command = $this->buildFlushCommand($database->uuid, $this->resolvePassword($database));
|
|
|
|
instant_remote_process(command: [$command], server: $server, throwError: true);
|
|
}
|
|
|
|
/**
|
|
* Build the `redis-cli FLUSHALL ASYNC` command executed inside the running container.
|
|
*
|
|
* The command connects over the container's local plaintext port (available even when
|
|
* SSL is enabled, because Coolify never disables it), so no TLS flags are needed. The
|
|
* password is shell-escaped so it cannot break out of the argument and inject commands.
|
|
*
|
|
* Note: on non-root servers the command passes through parseCommandsByLineForSudo(),
|
|
* which rewrites `$(`, ` | `, `&&` and `||` line-wide, so a password containing those
|
|
* sequences is mutated even inside the escaped quotes and the flush fails to authenticate.
|
|
* This is a limitation shared with every other password-carrying remote command in the
|
|
* codebase (e.g. DatabaseBackupJob); the escaping still holds, so no command is injected.
|
|
*/
|
|
public function buildFlushCommand(string $containerName, ?string $password): string
|
|
{
|
|
$redisCli = 'redis-cli';
|
|
if (filled($password)) {
|
|
$redisCli .= ' -a '.escapeshellarg($password);
|
|
}
|
|
|
|
return "docker exec {$containerName} {$redisCli} FLUSHALL ASYNC";
|
|
}
|
|
|
|
private function resolvePassword(StandaloneRedis|StandaloneKeydb|StandaloneDragonfly $database): ?string
|
|
{
|
|
return match (true) {
|
|
$database instanceof StandaloneRedis => $database->redis_password,
|
|
$database instanceof StandaloneKeydb => $database->keydb_password,
|
|
$database instanceof StandaloneDragonfly => $database->dragonfly_password,
|
|
};
|
|
}
|
|
}
|