mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-23 18:54:24 +00:00
339 lines
12 KiB
PHP
339 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\DocStoreBundle\Tests\Controller;
|
|
|
|
use Chill\DocStoreBundle\AsyncUpload\Driver\LocalStorage\StoredObjectManager;
|
|
use Chill\DocStoreBundle\AsyncUpload\Driver\LocalStorage\TempUrlLocalStorageGenerator;
|
|
use Chill\DocStoreBundle\Controller\StoredObjectContentToLocalStorageController;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Prophecy\Argument;
|
|
use Prophecy\PhpUnit\ProphecyTrait;
|
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* @coversNothing
|
|
*/
|
|
class StoredObjectContentToLocalStorageControllerTest extends TestCase
|
|
{
|
|
use ProphecyTrait;
|
|
|
|
/**
|
|
* @dataProvider generateOperateContentWithExceptionDataProvider
|
|
*/
|
|
public function testOperateContentWithException(Request $request, string $expectedException, string $expectedExceptionMessage, bool $existContent, string $readContent, bool $signatureValidity): void
|
|
{
|
|
$storedObjectManager = $this->prophesize(StoredObjectManager::class);
|
|
$storedObjectManager->existsContent(Argument::any())->willReturn($existContent);
|
|
$storedObjectManager->readContent(Argument::any())->willReturn($readContent);
|
|
|
|
$tempUrlLocalStorageGenerator = $this->prophesize(TempUrlLocalStorageGenerator::class);
|
|
$tempUrlLocalStorageGenerator->validateSignature(
|
|
$request->query->get('sig', ''),
|
|
$request->getMethod(),
|
|
$request->query->get('object_name', ''),
|
|
$request->query->getInt('exp', 0)
|
|
)
|
|
->willReturn($signatureValidity);
|
|
|
|
$this->expectException($expectedException);
|
|
$this->expectExceptionMessage($expectedExceptionMessage);
|
|
|
|
$controller = new StoredObjectContentToLocalStorageController(
|
|
$storedObjectManager->reveal(),
|
|
$tempUrlLocalStorageGenerator->reveal()
|
|
);
|
|
|
|
$controller->contentOperate($request);
|
|
}
|
|
|
|
public static function generateOperateContentWithExceptionDataProvider(): iterable
|
|
{
|
|
yield [
|
|
new Request(['object_name' => '', 'sig' => '', 'exp' => 0]),
|
|
BadRequestHttpException::class,
|
|
'Object name parameter is missing',
|
|
false,
|
|
'',
|
|
false,
|
|
];
|
|
|
|
yield [
|
|
new Request(['object_name' => 'testABC', 'sig' => '', 'exp' => 0]),
|
|
BadRequestHttpException::class,
|
|
'Expiration is not set or equal to zero',
|
|
false,
|
|
'',
|
|
false,
|
|
];
|
|
|
|
yield [
|
|
new Request(['object_name' => 'testABC', 'sig' => '', 'exp' => (new \DateTimeImmutable())->getTimestamp()]),
|
|
BadRequestHttpException::class,
|
|
'Signature is not set or is a blank string',
|
|
false,
|
|
'',
|
|
false,
|
|
];
|
|
|
|
yield [
|
|
new Request(['object_name' => 'testABC', 'sig' => '1234', 'exp' => (new \DateTimeImmutable())->getTimestamp()]),
|
|
AccessDeniedHttpException::class,
|
|
'Invalid signature',
|
|
false,
|
|
'',
|
|
false,
|
|
];
|
|
|
|
|
|
yield [
|
|
new Request(['object_name' => 'testABC', 'sig' => '1234', 'exp' => (new \DateTimeImmutable())->getTimestamp()]),
|
|
NotFoundHttpException::class,
|
|
'Object does not exists on disk',
|
|
false,
|
|
'',
|
|
true,
|
|
];
|
|
}
|
|
|
|
public function testOperateContentGetHappyScenario(): void
|
|
{
|
|
$objectName = 'testABC';
|
|
$expiration = new \DateTimeImmutable();
|
|
$storedObjectManager = $this->prophesize(StoredObjectManager::class);
|
|
$storedObjectManager->existsContent($objectName)->willReturn(true);
|
|
$storedObjectManager->readContent($objectName)->willReturn('123456789');
|
|
|
|
$tempUrlLocalStorageGenerator = $this->prophesize(TempUrlLocalStorageGenerator::class);
|
|
$tempUrlLocalStorageGenerator->validateSignature('signature', 'GET', $objectName, $expiration->getTimestamp())
|
|
->shouldBeCalled()
|
|
->willReturn(true);
|
|
|
|
$controller = new StoredObjectContentToLocalStorageController(
|
|
$storedObjectManager->reveal(),
|
|
$tempUrlLocalStorageGenerator->reveal()
|
|
);
|
|
|
|
$response = $controller->contentOperate(new Request(['object_name' => $objectName, 'sig' => 'signature', 'exp' => $expiration->getTimestamp()]));
|
|
|
|
self::assertEquals(200, $response->getStatusCode());
|
|
self::assertEquals('123456789', $response->getContent());
|
|
}
|
|
|
|
public function testOperateContentHeadHappyScenario(): void
|
|
{
|
|
$objectName = 'testABC';
|
|
$expiration = new \DateTimeImmutable();
|
|
$storedObjectManager = $this->prophesize(StoredObjectManager::class);
|
|
$storedObjectManager->existsContent($objectName)->willReturn(true);
|
|
$storedObjectManager->readContent($objectName)->willReturn('123456789');
|
|
|
|
$tempUrlLocalStorageGenerator = $this->prophesize(TempUrlLocalStorageGenerator::class);
|
|
$tempUrlLocalStorageGenerator->validateSignature('signature', 'HEAD', $objectName, $expiration->getTimestamp())
|
|
->shouldBeCalled()
|
|
->willReturn(true);
|
|
|
|
$controller = new StoredObjectContentToLocalStorageController(
|
|
$storedObjectManager->reveal(),
|
|
$tempUrlLocalStorageGenerator->reveal()
|
|
);
|
|
|
|
$request = new Request(['object_name' => $objectName, 'sig' => 'signature', 'exp' => $expiration->getTimestamp()]);
|
|
$request->setMethod('HEAD');
|
|
$response = $controller->contentOperate($request);
|
|
|
|
self::assertEquals(200, $response->getStatusCode());
|
|
self::assertEquals('', $response->getContent());
|
|
}
|
|
|
|
public function testPostContentHappyScenario(): void
|
|
{
|
|
$expiration = 171899000;
|
|
$storedObjectManager = $this->prophesize(StoredObjectManager::class);
|
|
$storedObjectManager->writeContent('filePrefix/abcSUFFIX', Argument::containingString('fake_encrypted_content'))
|
|
->shouldBeCalled();
|
|
|
|
$tempUrlGenerator = $this->prophesize(TempUrlLocalStorageGenerator::class);
|
|
$tempUrlGenerator->validateSignaturePost('signature', 'filePrefix/abc', $expiration, 15_000_000, 1)
|
|
->shouldBeCalled()
|
|
->willReturn(true);
|
|
|
|
$controller = new StoredObjectContentToLocalStorageController($storedObjectManager->reveal(), $tempUrlGenerator->reveal());
|
|
|
|
$request = new Request(
|
|
['prefix' => 'filePrefix/abc'],
|
|
['signature' => 'signature', 'expires' => $expiration, 'max_file_size' => 15_000_000, 'max_file_count' => 1],
|
|
files: [
|
|
'filePrefix/abcSUFFIX' => new UploadedFile(
|
|
__DIR__.'/data/StoredObjectContentToLocalStorageControllerTest/dummy_file',
|
|
'Document.odt',
|
|
test: true
|
|
),
|
|
]
|
|
);
|
|
|
|
$response = $controller->postContent($request);
|
|
|
|
self::assertEquals(204, $response->getStatusCode());
|
|
}
|
|
|
|
/**
|
|
* @dataProvider generatePostContentWithExceptionDataProvider
|
|
*/
|
|
public function testPostContentWithException(Request $request, bool $isSignatureValid, string $expectedException, string $expectedExceptionMessage): void
|
|
{
|
|
$storedObjectManager = $this->prophesize(StoredObjectManager::class);
|
|
$storedObjectManager->writeContent(Argument::any(), Argument::any())->shouldNotBeCalled();
|
|
|
|
$tempUrlGenerator = $this->prophesize(TempUrlLocalStorageGenerator::class);
|
|
$tempUrlGenerator->validateSignaturePost('signature', Argument::any(), Argument::any(), Argument::any(), Argument::any())
|
|
->willReturn($isSignatureValid);
|
|
|
|
$controller = new StoredObjectContentToLocalStorageController(
|
|
$storedObjectManager->reveal(),
|
|
$tempUrlGenerator->reveal()
|
|
);
|
|
|
|
$this->expectException($expectedException);
|
|
$this->expectExceptionMessage($expectedExceptionMessage);
|
|
|
|
$controller->postContent($request);
|
|
}
|
|
|
|
public static function generatePostContentWithExceptionDataProvider(): iterable
|
|
{
|
|
$query = ['prefix' => 'filePrefix/abc'];
|
|
$attributes = ['signature' => 'signature', 'expires' => 15088556855, 'max_file_size' => 15_000_000, 'max_file_count' => 1];
|
|
|
|
$request = new Request([]);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Prefix parameter is missing',
|
|
];
|
|
|
|
|
|
$attrCloned = [...$attributes];
|
|
unset($attrCloned['max_file_size']);
|
|
$request = new Request($query, $attrCloned);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Max file size is not set or equal to zero',
|
|
];
|
|
|
|
$attrCloned = [...$attributes];
|
|
unset($attrCloned['max_file_count']);
|
|
$request = new Request($query, $attrCloned);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Max file count is not set or equal to zero',
|
|
];
|
|
|
|
$attrCloned = [...$attributes];
|
|
unset($attrCloned['expires']);
|
|
$request = new Request($query, $attrCloned);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Expiration is not set or equal to zero',
|
|
];
|
|
|
|
$attrCloned = [...$attributes];
|
|
unset($attrCloned['signature']);
|
|
$request = new Request($query, $attrCloned);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Signature is not set or is a blank string',
|
|
];
|
|
|
|
$request = new Request($query, $attributes);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
false,
|
|
AccessDeniedHttpException::class,
|
|
'Invalid signature',
|
|
];
|
|
|
|
$request = new Request($query, $attributes, files: []);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
BadRequestHttpException::class,
|
|
'Zero files given',
|
|
];
|
|
|
|
$request = new Request($query, $attributes, files: [
|
|
'filePrefix/abcSUFFIX_1' => new UploadedFile(__DIR__.'/data/StoredObjectContentToLocalStorageControllerTest/dummy_file', 'Some content', test: true),
|
|
'filePrefix/abcSUFFIX_2' => new UploadedFile(__DIR__.'/data/StoredObjectContentToLocalStorageControllerTest/dummy_file', 'Some content2', test: true),
|
|
]);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
AccessDeniedHttpException::class,
|
|
'More files than max file count',
|
|
];
|
|
|
|
$request = new Request($query, [...$attributes, 'max_file_size' => 3], files: [
|
|
'filePrefix/abcSUFFIX_1' => new UploadedFile(__DIR__.'/data/StoredObjectContentToLocalStorageControllerTest/dummy_file', 'Some content', test: true),
|
|
]);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
AccessDeniedHttpException::class,
|
|
'File is too big',
|
|
];
|
|
|
|
$request = new Request($query, [...$attributes], files: [
|
|
'some/other/prefix_SUFFIX' => new UploadedFile(__DIR__.'/data/StoredObjectContentToLocalStorageControllerTest/dummy_file', 'Some content', test: true),
|
|
]);
|
|
$request->setMethod('POST');
|
|
|
|
yield [
|
|
$request,
|
|
true,
|
|
AccessDeniedHttpException::class,
|
|
'Filename does not start with signed prefix',
|
|
];
|
|
}
|
|
}
|