Skip to content
Snippets Groups Projects
Select Git revision
  • 034f67e5f8529100444517d27e51e70dfeb560ae
  • main default protected
  • register-logging-channel
  • expr-lang
  • ci-82
  • attr-events
  • locale-wip
  • custom-routes
  • v0.1.85
  • v0.1.84
  • v0.1.83
  • v0.1.82
  • v0.1.81
  • v0.1.80
  • v0.1.79
  • v0.1.78
  • v0.1.77
  • v0.1.76
  • v0.1.75
  • v0.1.74
  • v0.1.73
  • v0.1.72
  • v0.1.71
  • v0.1.70
  • v0.1.69
  • v0.1.68
  • v0.1.67
  • v0.1.65
28 results

ExpressionLanguageTest.php

Blame
  • FileDataDataProvider.php 6.34 KiB
    <?php
    
    declare(strict_types=1);
    
    namespace Dbp\Relay\BlobBundle\DataProvider;
    
    use Dbp\Relay\BlobBundle\Entity\FileData;
    use Dbp\Relay\BlobBundle\Helper\DenyAccessUnlessCheckSignature;
    use Dbp\Relay\BlobBundle\Service\BlobService;
    use Dbp\Relay\CoreBundle\DataProvider\AbstractDataProvider;
    use Dbp\Relay\CoreBundle\Exception\ApiError;
    use Symfony\Component\HttpFoundation\RequestStack;
    use Symfony\Component\HttpFoundation\Response;
    
    class FileDataDataProvider extends AbstractDataProvider
    {
        /**
         * @var BlobService
         */
        private $blobService;
    
        /**
         * @var RequestStack
         */
        private $requestStack;
    
        public function __construct(BlobService $blobService, RequestStack $requestStack)
        {
            parent::__construct($requestStack);
    
            $this->blobService = $blobService;
            $this->requestStack = $requestStack;
        }
    
        protected function onOperationStart(int $operation)
        {
        }
    
        protected function getResourceClass(): string
        {
            return FileData::class;
        }
    
        /* getItemById() is overwritten with getFileDataById() because we want filters here for checking the signature */
        public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?object
        {
            $this->onOperationStart(self::GET_ITEM_OPERATION);
    
            $filters = $context['filters'] ?? [];
    
            return $this->getFileDataById($id, $filters);
        }
    
        protected function getFileDataById($id, array $filters): object
        {
    //        echo "     FileDataProvider::getFileDataById($id, filters)\n";
            $sig = $this->requestStack->getCurrentRequest()->headers->get('x-dbp-signature', '');
            if (!$sig) {
                throw ApiError::withDetails(Response::HTTP_UNAUTHORIZED, 'Signature missing', 'blob:createFileData-missing-sig');
            }
            $bucketId = $filters['bucketID'] ?? '';
            assert(is_string($bucketId));
            if (!$bucketId) {
                throw ApiError::withDetails(Response::HTTP_BAD_REQUEST, 'BucketID is missing', 'blob:get-files-by-prefix-missing-bucketID');
            }
            $bucket = $this->blobService->configurationService->getBucketByID($bucketId);
            if (!$bucket) {
                throw ApiError::withDetails(Response::HTTP_BAD_REQUEST, 'BucketID is not configured', 'blob:get-files-by-prefix-not-configured-bucketID');
            }
    
            $secret = $bucket->getPublicKey();
            $this->checkSignature($secret, $filters);
    
            $fileData = $this->blobService->getFileData($id);
    
            if (!$fileData) {
                throw ApiError::withDetails(Response::HTTP_NOT_FOUND, 'FileData was not found!', 'blob:fileData-not-found');
            }
    
            $fileData = $this->blobService->setBucket($fileData);
            if ($this->requestStack->getCurrentRequest()->getMethod() !== 'DELETE') {
                $fileData = $this->blobService->getLink($fileData);
                $this->blobService->saveFileData($fileData);
            }
    
            return $fileData;
        }
    
        protected function getItemById($id, array $options = []): object
        {
            throw ApiError::withDetails(Response::HTTP_NOT_FOUND, 'Should not be called!', 'blob:wrong-function');
        }
    
        protected function getPage(int $currentPageNumber, int $maxNumItemsPerPage, array $filters = [], array $options = []): array
        {
            $sig = $this->requestStack->getCurrentRequest()->headers->get('x-dbp-signature', '');
            if (!$sig) {
                throw ApiError::withDetails(Response::HTTP_UNAUTHORIZED, 'Signature missing', 'blob:createFileData-missing-sig');
            }
            $bucketId = $filters['bucketID'] ?? '';
            assert(is_string($bucketId));
            if (!$bucketId) {
                throw ApiError::withDetails(Response::HTTP_BAD_REQUEST, 'BucketID is missing', 'blob:get-files-by-prefix-missing-bucketID');
            }
            $bucket = $this->blobService->configurationService->getBucketByID($bucketId);
            if (!$bucket) {
                throw ApiError::withDetails(Response::HTTP_BAD_REQUEST, 'BucketID is not configured', 'blob:get-files-by-prefix-not-configured-bucketID');
            }
    
            $secret = $bucket->getPublicKey();
            $this->checkSignature($secret, $filters);
    
            $prefix = $filters['prefix'] ?? '';
    
            if (!$bucket->getService()) {
                throw ApiError::withDetails(Response::HTTP_BAD_REQUEST, 'BucketService is not configured', 'blob:get-files-by-prefix-no-bucket-service');
            }
    
            $fileDatas = $this->blobService->getFileDataByBucketIDAndPrefixWithPagination($bucketId, $prefix, $currentPageNumber, $maxNumItemsPerPage);
    
            //create sharelinks
            foreach ($fileDatas as $fileData) {
                assert($fileData instanceof FileData);
                $fileData->setBucket($bucket);
                $fileData = $this->blobService->getLink($fileData);
    //            $this->blobService->saveFileData($fileData);
            }
    
            return $fileDatas;
        }
    
        /**
         * Check dbp-signature on GET request.
         *
         * @throws \JsonException
         */
        private function checkSignature(string $secret, array $filters): void
        {
            $sig = $this->requestStack->getCurrentRequest()->headers->get('x-dbp-signature', '');
            if (!$sig) {
                throw ApiError::withDetails(Response::HTTP_UNAUTHORIZED, 'Signature missing', 'blob:createFileData-missing-sig');
            }
            $bucketId = $filters['bucketID'] ?? '';
            $creationTime = $filters['creationTime'] ?? '0';
    
            if (!$bucketId || !$creationTime) {
                throw ApiError::withDetails(Response::HTTP_FORBIDDEN, 'Signature parameter missing', 'blob:dataprovider-missing-signature-params');
            }
    
            $data = DenyAccessUnlessCheckSignature::verify($secret, $sig);
    //        dump($data);
    
            // check if signed params aer equal to request params
            if ($data['bucketID'] !== $bucketId) {
                /** @noinspection ForgottenDebugOutputInspection */
                dump($data['bucketID'], $bucketId);
                throw ApiError::withDetails(Response::HTTP_FORBIDDEN, 'BucketId change forbidden', 'blob:bucketid-change-forbidden');
            }
            if ((int) $data['creationTime'] !== (int) $creationTime) {
                /** @noinspection ForgottenDebugOutputInspection */
                dump($data['creationTime'], $creationTime);
                throw ApiError::withDetails(Response::HTTP_FORBIDDEN, 'Creation Time change forbidden', 'blob:creationtime-change-forbidden');
            }
            // TODO check if request is NOT too old
        }
    }