mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 10:18:20 +00:00
Merge branch 'next' into shadow/improve-service-postgresus
This commit is contained in:
37 files changed
+1456
-162
No files matched your search
@@ -107,6 +107,25 @@ class BackupEdit extends Component
|
||||
$this->backup->save_s3 = $this->saveS3;
|
||||
$this->backup->disable_local_backup = $this->disableLocalBackup;
|
||||
$this->backup->s3_storage_id = $this->s3StorageId;
|
||||
|
||||
// Validate databases_to_backup to prevent command injection
|
||||
if (filled($this->databasesToBackup)) {
|
||||
$databases = str($this->databasesToBackup)->explode(',');
|
||||
foreach ($databases as $index => $db) {
|
||||
$dbName = trim($db);
|
||||
try {
|
||||
validateShellSafePath($dbName, 'database name');
|
||||
} catch (\Exception $e) {
|
||||
// Provide specific error message indicating which database failed validation
|
||||
$position = $index + 1;
|
||||
throw new \Exception(
|
||||
"Database #{$position} ('{$dbName}') validation failed: ".
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->backup->databases_to_backup = $this->databasesToBackup;
|
||||
$this->backup->dump_all = $this->dumpAll;
|
||||
$this->backup->timeout = $this->timeout;
|
||||
|
||||
@@ -328,12 +328,15 @@ class General extends Component
|
||||
$configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
if ($oldScript && $oldScript['filename'] !== $script['filename']) {
|
||||
$old_file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$oldScript['filename']}";
|
||||
$delete_command = "rm -f $old_file_path";
|
||||
try {
|
||||
// Validate and escape filename to prevent command injection
|
||||
validateShellSafePath($oldScript['filename'], 'init script filename');
|
||||
$old_file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$oldScript['filename']}";
|
||||
$escapedOldPath = escapeshellarg($old_file_path);
|
||||
$delete_command = "rm -f {$escapedOldPath}";
|
||||
instant_remote_process([$delete_command], $this->server);
|
||||
} catch (Exception $e) {
|
||||
$this->dispatch('error', 'Failed to remove old init script from server: '.$e->getMessage());
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -370,13 +373,17 @@ class General extends Component
|
||||
if ($found) {
|
||||
$container_name = $this->database->uuid;
|
||||
$configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
$file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$script['filename']}";
|
||||
|
||||
$command = "rm -f $file_path";
|
||||
try {
|
||||
// Validate and escape filename to prevent command injection
|
||||
validateShellSafePath($script['filename'], 'init script filename');
|
||||
$file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$script['filename']}";
|
||||
$escapedPath = escapeshellarg($file_path);
|
||||
|
||||
$command = "rm -f {$escapedPath}";
|
||||
instant_remote_process([$command], $this->server);
|
||||
} catch (Exception $e) {
|
||||
$this->dispatch('error', 'Failed to remove init script from server: '.$e->getMessage());
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -405,6 +412,16 @@ class General extends Component
|
||||
'new_filename' => 'required|string',
|
||||
'new_content' => 'required|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
// Validate filename to prevent command injection
|
||||
validateShellSafePath($this->new_filename, 'init script filename');
|
||||
} catch (Exception $e) {
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$found = collect($this->initScripts)->firstWhere('filename', $this->new_filename);
|
||||
if ($found) {
|
||||
$this->dispatch('error', 'Filename already exists.');
|
||||
|
||||
@@ -81,7 +81,7 @@ class Create extends Component
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => $destination->getMorphClass(),
|
||||
];
|
||||
if ($oneClickServiceName === 'cloudflared' || $oneClickServiceName === 'pgadmin' || $oneClickServiceName === 'postgresus') {
|
||||
if ($oneClickServiceName === 'pgadmin' || $oneClickServiceName === 'postgresus') {
|
||||
data_set($service_payload, 'connect_to_docker_network', true);
|
||||
}
|
||||
$service = Service::create($service_payload);
|
||||
|
||||
@@ -179,6 +179,10 @@ class Storage extends Component
|
||||
$this->file_storage_directory_destination = trim($this->file_storage_directory_destination);
|
||||
$this->file_storage_directory_destination = str($this->file_storage_directory_destination)->start('/')->value();
|
||||
|
||||
// Validate paths to prevent command injection
|
||||
validateShellSafePath($this->file_storage_directory_source, 'storage source path');
|
||||
validateShellSafePath($this->file_storage_directory_destination, 'storage destination path');
|
||||
|
||||
\App\Models\LocalFileVolume::create([
|
||||
'fs_path' => $this->file_storage_directory_source,
|
||||
'mount_path' => $this->file_storage_directory_destination,
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
||||
|
||||
use App\Models\Environment;
|
||||
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
||||
use App\Models\Project;
|
||||
use App\Models\SharedEnvironmentVariable;
|
||||
use App\Traits\EnvironmentVariableAnalyzer;
|
||||
use App\Traits\EnvironmentVariableProtection;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
@@ -184,6 +187,7 @@ class Show extends Component
|
||||
|
||||
$this->serialize();
|
||||
$this->syncData(true);
|
||||
$this->syncData(false);
|
||||
$this->dispatch('success', 'Environment variable updated.');
|
||||
$this->dispatch('envsUpdated');
|
||||
$this->dispatch('configurationChanged');
|
||||
@@ -192,6 +196,72 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
public function availableSharedVariables(): array
|
||||
{
|
||||
$team = currentTeam();
|
||||
$result = [
|
||||
'team' => [],
|
||||
'project' => [],
|
||||
'environment' => [],
|
||||
];
|
||||
|
||||
// Early return if no team
|
||||
if (! $team) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Check if user can view team variables
|
||||
try {
|
||||
$this->authorize('view', $team);
|
||||
$result['team'] = $team->environment_variables()
|
||||
->pluck('key')
|
||||
->toArray();
|
||||
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
|
||||
// User not authorized to view team variables
|
||||
}
|
||||
|
||||
// Get project variables if we have a project_uuid in route
|
||||
$projectUuid = data_get($this->parameters, 'project_uuid');
|
||||
if ($projectUuid) {
|
||||
$project = Project::where('team_id', $team->id)
|
||||
->where('uuid', $projectUuid)
|
||||
->first();
|
||||
|
||||
if ($project) {
|
||||
try {
|
||||
$this->authorize('view', $project);
|
||||
$result['project'] = $project->environment_variables()
|
||||
->pluck('key')
|
||||
->toArray();
|
||||
|
||||
// Get environment variables if we have an environment_uuid in route
|
||||
$environmentUuid = data_get($this->parameters, 'environment_uuid');
|
||||
if ($environmentUuid) {
|
||||
$environment = $project->environments()
|
||||
->where('uuid', $environmentUuid)
|
||||
->first();
|
||||
|
||||
if ($environment) {
|
||||
try {
|
||||
$this->authorize('view', $environment);
|
||||
$result['environment'] = $environment->environment_variables()
|
||||
->pluck('key')
|
||||
->toArray();
|
||||
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
|
||||
// User not authorized to view environment variables
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Illuminate\Auth\Access\AuthorizationException $e) {
|
||||
// User not authorized to view project variables
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user