mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-23 12:23:46 +00:00
fix(backups): enforce authorization and safe retention
- Gate volume backup retention and S3 controls by update permission - Preserve backup records when S3 deletion fails - Share SFTP download streaming with consistent missing-file handling - Handle schedule creation errors and link service database backups
This commit is contained in:
@@ -17,6 +17,10 @@ use App\Models\SwarmDocker;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Throwable;
|
||||
|
||||
function create_standalone_postgresql($environmentId, StandaloneDocker|SwarmDocker $destination, ?array $otherData = null, string $databaseImage = 'postgres:16-alpine'): StandalonePostgresql
|
||||
{
|
||||
@@ -194,6 +198,41 @@ function deleteBackupsLocally(string|array|null $filenames, Server $server, bool
|
||||
$foldersToCheck->each(fn ($folder) => deleteEmptyBackupFolder($folder, $server));
|
||||
}
|
||||
|
||||
function streamBackupFromServer(Server $server, string $filename, string $contentType): StreamedResponse
|
||||
{
|
||||
$disk = Storage::build([
|
||||
'driver' => 'sftp',
|
||||
'host' => $server->ip,
|
||||
'port' => (int) $server->port,
|
||||
'username' => $server->user,
|
||||
'privateKey' => $server->privateKey->getKeyLocation(),
|
||||
'root' => '/',
|
||||
]);
|
||||
|
||||
if (! $disk->exists($filename)) {
|
||||
throw new FileNotFoundException($filename);
|
||||
}
|
||||
|
||||
return new StreamedResponse(function () use ($disk, $filename) {
|
||||
if (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
$stream = $disk->readStream($filename);
|
||||
if ($stream === false || is_null($stream)) {
|
||||
abort(500, 'Failed to open stream for the requested file.');
|
||||
}
|
||||
while (! feof($stream)) {
|
||||
echo fread($stream, 2048);
|
||||
flush();
|
||||
}
|
||||
|
||||
fclose($stream);
|
||||
}, 200, [
|
||||
'Content-Type' => $contentType,
|
||||
'Content-Disposition' => 'attachment; filename="'.basename($filename).'"',
|
||||
]);
|
||||
}
|
||||
|
||||
function deleteBackupsS3(string|array|null $filenames, S3Storage $s3): void
|
||||
{
|
||||
if (empty($filenames) || ! $s3) {
|
||||
@@ -430,8 +469,12 @@ function deleteOldBackupsFromS3($backup): Collection
|
||||
->all();
|
||||
|
||||
if (! empty($filesToDelete)) {
|
||||
deleteBackupsS3($filesToDelete, $backup->s3);
|
||||
$processedBackups = $backupsToDelete;
|
||||
try {
|
||||
deleteBackupsS3($filesToDelete, $backup->s3);
|
||||
$processedBackups = $backupsToDelete;
|
||||
} catch (Throwable $e) {
|
||||
report($e);
|
||||
}
|
||||
}
|
||||
|
||||
return $processedBackups;
|
||||
|
||||
Reference in New Issue
Block a user