coolify/app/Http/Controllers/UploadController.php

100 lines
3.4 KiB
PHP
Raw Permalink Normal View History

2024-04-11 10:13:11 +00:00
<?php
namespace App\Http\Controllers;
2026-06-29 08:27:01 +00:00
use App\Support\DatabaseBackupFileValidator;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
2024-04-11 10:13:11 +00:00
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
2024-06-10 20:43:34 +00:00
use Illuminate\Routing\Controller as BaseController;
2024-04-11 10:13:11 +00:00
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
class UploadController extends BaseController
{
use AuthorizesRequests;
private const MAX_BYTES = 10 * 1024 * 1024 * 1024; // 10 GiB
2026-06-29 08:27:01 +00:00
private const ALLOWED_EXTENSIONS = DatabaseBackupFileValidator::ALLOWED_EXTENSIONS;
2024-04-11 10:13:11 +00:00
public function upload(Request $request)
{
$databaseIdentifier = request()->route('databaseUuid');
$resource = getResourceByUuid($databaseIdentifier, data_get(auth()->user()->currentTeam(), 'id'));
2024-04-11 10:13:11 +00:00
if (is_null($resource)) {
return response()->json(['error' => 'You do not have permission for this database'], 500);
}
$this->authorize('uploadBackup', $resource);
$chunk = $request->file('file');
$originalName = $chunk instanceof UploadedFile ? $chunk->getClientOriginalName() : null;
if (blank($originalName) || ! self::hasAllowedExtension($originalName)) {
return response()->json([
'error' => 'Unsupported file type. Allowed extensions: '.implode(', ', self::ALLOWED_EXTENSIONS),
], 422);
}
$declaredTotalSize = (int) $request->input('dzTotalFilesize', 0);
if ($declaredTotalSize > self::MAX_BYTES) {
return response()->json([
'error' => 'File exceeds maximum allowed size of '.self::formatMaxSize().'.',
], 422);
}
2024-06-10 20:43:34 +00:00
$receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
2024-04-11 10:13:11 +00:00
if ($receiver->isUploaded() === false) {
2024-07-24 19:11:12 +00:00
throw new UploadMissingFileException;
2024-04-11 10:13:11 +00:00
}
$save = $receiver->receive();
if ($save->isFinished()) {
// Use the original identifier from the route to maintain path consistency
// For ServiceDatabase: {name}-{service_uuid}
// For standalone databases: {uuid}
return $this->saveFile($save->getFile(), $databaseIdentifier);
2024-04-11 10:13:11 +00:00
}
$handler = $save->handler();
2024-06-10 20:43:34 +00:00
2024-04-11 10:13:11 +00:00
return response()->json([
2024-06-10 20:43:34 +00:00
'done' => $handler->getPercentageDone(),
'status' => true,
2024-04-11 10:13:11 +00:00
]);
}
protected function saveFile(UploadedFile $file, string $resourceIdentifier)
2024-04-11 10:13:11 +00:00
{
2026-06-29 08:27:01 +00:00
if (! DatabaseBackupFileValidator::isUploadAllowed($file, self::MAX_BYTES)) {
@unlink($file->getPathname());
return response()->json([
'error' => 'Uploaded file failed validation.',
], 422);
}
2024-04-11 10:13:11 +00:00
$mime = str_replace('/', '-', $file->getMimeType());
$filePath = "upload/{$resourceIdentifier}";
2024-06-10 20:43:34 +00:00
$finalPath = storage_path('app/'.$filePath);
2024-04-11 10:13:11 +00:00
$file->move($finalPath, 'restore');
return response()->json([
2024-06-10 20:43:34 +00:00
'mime_type' => $mime,
2024-04-11 10:13:11 +00:00
]);
}
2024-06-10 20:43:34 +00:00
private static function hasAllowedExtension(string $name): bool
2024-04-11 10:13:11 +00:00
{
2026-06-29 08:27:01 +00:00
return DatabaseBackupFileValidator::hasAllowedExtension($name);
}
2024-04-11 10:13:11 +00:00
private static function formatMaxSize(): string
{
return (self::MAX_BYTES / (1024 * 1024 * 1024)).' GiB';
2024-04-11 10:13:11 +00:00
}
}