coolify/app/Http/Controllers/UploadController.php

99 lines
3.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Support\DatabaseBackupFileValidator;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Controller as BaseController;
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
private const ALLOWED_EXTENSIONS = DatabaseBackupFileValidator::ALLOWED_EXTENSIONS;
public function upload(Request $request)
{
$databaseIdentifier = request()->route('databaseUuid');
$resource = getResourceByUuid($databaseIdentifier, data_get(auth()->user()->currentTeam(), 'id'));
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);
}
$receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException;
}
$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);
}
$handler = $save->handler();
return response()->json([
'done' => $handler->getPercentageDone(),
'status' => true,
]);
}
protected function saveFile(UploadedFile $file, string $resourceIdentifier)
{
if (! DatabaseBackupFileValidator::isUploadAllowed($file, self::MAX_BYTES)) {
@unlink($file->getPathname());
return response()->json([
'error' => 'Uploaded file failed validation.',
], 422);
}
$mime = str_replace('/', '-', $file->getMimeType());
$filePath = "upload/{$resourceIdentifier}";
$finalPath = storage_path('app/'.$filePath);
$file->move($finalPath, 'restore');
return response()->json([
'mime_type' => $mime,
]);
}
private static function hasAllowedExtension(string $name): bool
{
return DatabaseBackupFileValidator::hasAllowedExtension($name);
}
private static function formatMaxSize(): string
{
return (self::MAX_BYTES / (1024 * 1024 * 1024)).' GiB';
}
}