mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-02 21:13:57 +00:00
Refactor backend for getting signed url
This commit is contained in:
@@ -11,9 +11,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\DocStoreBundle\Controller;
|
||||
|
||||
use Chill\DocStoreBundle\AsyncUpload\Exception\TempUrlGeneratorException;
|
||||
use Chill\DocStoreBundle\AsyncUpload\TempUrlGeneratorInterface;
|
||||
use Chill\DocStoreBundle\Security\Authorization\AsyncUploadVoter;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Entity\StoredObjectVersion;
|
||||
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -30,62 +31,77 @@ final readonly class AsyncUploadController
|
||||
private TempUrlGeneratorInterface $tempUrlGenerator,
|
||||
private SerializerInterface $serializer,
|
||||
private Security $security,
|
||||
private LoggerInterface $logger,
|
||||
private LoggerInterface $chillLogger,
|
||||
) {}
|
||||
|
||||
#[Route(path: '/asyncupload/temp_url/generate/{method}', name: 'async_upload.generate_url')]
|
||||
public function getSignedUrl(string $method, Request $request): JsonResponse
|
||||
#[Route(path: '/api/1.0/doc-store/async-upload/temp_url/{uuid}/generate/post', name: 'chill_docstore_asyncupload_getsignedurlpost')]
|
||||
public function getSignedUrlPost(Request $request, StoredObject $storedObject): JsonResponse
|
||||
{
|
||||
try {
|
||||
switch (strtolower($method)) {
|
||||
case 'post':
|
||||
$p = $this->tempUrlGenerator
|
||||
->generatePost(
|
||||
$request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null,
|
||||
$request->query->has('submit_delay') ? $request->query->getInt('submit_delay') : null
|
||||
)
|
||||
;
|
||||
break;
|
||||
case 'get':
|
||||
case 'head':
|
||||
$object_name = $request->query->get('object_name', null);
|
||||
if (!$this->security->isGranted(StoredObjectRoleEnum::EDIT->value, $storedObject)) {
|
||||
throw new AccessDeniedHttpException('not able to edit the given stored object');
|
||||
}
|
||||
|
||||
if (null === $object_name) {
|
||||
return (new JsonResponse((object) [
|
||||
'message' => 'the object_name is null',
|
||||
]))
|
||||
->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
$p = $this->tempUrlGenerator->generate(
|
||||
$method,
|
||||
$object_name,
|
||||
$request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return (new JsonResponse((object) ['message' => 'the method '
|
||||
."{$method} is not valid"]))
|
||||
->setStatusCode(JsonResponse::HTTP_BAD_REQUEST);
|
||||
// we create a dummy version, to generate a filename
|
||||
$version = $storedObject->registerVersion();
|
||||
|
||||
$p = $this->tempUrlGenerator
|
||||
->generatePost(
|
||||
$request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null,
|
||||
$request->query->has('submit_delay') ? $request->query->getInt('submit_delay') : null,
|
||||
object_name: $version->getFilename()
|
||||
);
|
||||
|
||||
$this->chillLogger->notice('[Privacy Event] a request to upload a document has been generated', [
|
||||
'doc_uuid' => $storedObject->getUuid(),
|
||||
]);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->serializer->serialize($p, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||
Response::HTTP_OK,
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(path: '/api/1.0/doc-store/async-upload/temp_url/{uuid}/generate/{method}', name: 'chill_docstore_asyncupload_getsignedurlget', requirements: ['method' => 'get|head'])]
|
||||
public function getSignedUrlGet(Request $request, StoredObject $storedObject, string $method): JsonResponse
|
||||
{
|
||||
if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
|
||||
throw new AccessDeniedHttpException('not able to read the given stored object');
|
||||
}
|
||||
|
||||
// we really want to be sure that there are no other method than get or head:
|
||||
if (!in_array($method, ['get', 'head'], true)) {
|
||||
throw new AccessDeniedHttpException('Only methods get and head are allowed');
|
||||
}
|
||||
|
||||
if ($request->query->has('version')) {
|
||||
$filename = $request->query->get('version');
|
||||
|
||||
$storedObjectVersion = $storedObject->getVersions()->findFirst(fn(int $index, StoredObjectVersion $version): bool => $version->getFilename() === $filename);
|
||||
|
||||
if (null === $storedObjectVersion) {
|
||||
// we are here in the case where the version is not stored into the database
|
||||
// as the version is prefixed by the stored object prefix, we just have to check that this prefix
|
||||
// is the same. It means that the user had previously the permission to "SEE_AND_EDIT" this stored
|
||||
// object with same prefix that we checked before
|
||||
if (!str_starts_with($filename, $storedObject->getPrefix())) {
|
||||
throw new AccessDeniedHttpException('not able to match the version with the same filename');
|
||||
}
|
||||
}
|
||||
} catch (TempUrlGeneratorException $e) {
|
||||
$this->logger->warning('The client requested a temp url'
|
||||
.' which sparkle an error.', [
|
||||
'message' => $e->getMessage(),
|
||||
'expire_delay' => $request->query->getInt('expire_delay', 0),
|
||||
'file_count' => $request->query->getInt('file_count', 1),
|
||||
'method' => $method,
|
||||
]);
|
||||
|
||||
$p = new \stdClass();
|
||||
$p->message = $e->getMessage();
|
||||
$p->status = JsonResponse::HTTP_BAD_REQUEST;
|
||||
|
||||
return new JsonResponse($p, JsonResponse::HTTP_BAD_REQUEST);
|
||||
} else {
|
||||
$filename = $storedObject->getCurrentVersion()->getFilename();
|
||||
}
|
||||
|
||||
if (!$this->security->isGranted(AsyncUploadVoter::GENERATE_SIGNATURE, $p)) {
|
||||
throw new AccessDeniedHttpException('not allowed to generate this signature');
|
||||
}
|
||||
$p = $this->tempUrlGenerator->generate(
|
||||
$method,
|
||||
$filename,
|
||||
$request->query->has('expires_delay') ? $request->query->getInt('expires_delay') : null
|
||||
);
|
||||
|
||||
$this->chillLogger->notice('[Privacy Event] a request to see a document has been granted', [
|
||||
'doc_uuid' => $storedObject->getUuid(),
|
||||
]);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->serializer->serialize($p, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||
|
Reference in New Issue
Block a user