prophesize(Security::class); $security->isGranted('SEE_AND_EDIT', $storedObject)->willReturn(true)->shouldBeCalled(); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $actual = $controller->getSignedUrlPost(new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800]), $storedObject); $decodedActual = json_decode($actual->getContent(), true, JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR); self::assertArrayHasKey('method', $decodedActual); self::assertEquals('POST', $decodedActual['method']); } public function testGetSignedUrlGetSimpleScenarioHappy(): void { $storedObject = new StoredObject(); $storedObject->registerVersion(); $security = $this->prophesize(Security::class); $security->isGranted('SEE', $storedObject)->willReturn(true)->shouldBeCalled(); $security->getUser()->willReturn(new User()); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $actual = $controller->getSignedUrlGet(new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800]), $storedObject, 'get'); $decodedActual = json_decode($actual->getContent(), true, JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR); self::assertArrayHasKey('method', $decodedActual); self::assertEquals('GET', $decodedActual['method']); } public function testGetSignedUrlGetSimpleScenarioNotAuthorized(): void { $this->expectException(AccessDeniedHttpException::class); $storedObject = new StoredObject(); $storedObject->registerVersion(); $security = $this->prophesize(Security::class); $security->isGranted('SEE', $storedObject)->willReturn(false)->shouldBeCalled(); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $controller->getSignedUrlGet(new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800]), $storedObject, 'get'); } public function testGetSignedUrlGetForSpecificVersionOfTheStoredObjectStoredInDatabase(): void { $storedObject = new StoredObject(); $version = $storedObject->registerVersion(); // we add a version to be sure that the we do not get the last one $storedObject->registerVersion(); $security = $this->prophesize(Security::class); $security->isGranted('SEE', $storedObject)->willReturn(true)->shouldBeCalled(); $security->getUser()->willReturn(new User()); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $actual = $controller->getSignedUrlGet( new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800, 'version' => $version->getFilename()]), $storedObject, 'get' ); $decodedActual = json_decode($actual->getContent(), true, JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR); self::assertArrayHasKey('method', $decodedActual); self::assertEquals('GET', $decodedActual['method']); self::assertArrayHasKey('object_name', $decodedActual); self::assertEquals($version->getFilename(), $decodedActual['object_name']); } public function testGetSignedUrlGetForSpecificVersionOfTheStoredObjectNotYetStoredInDatabase(): void { $storedObject = new StoredObject(); $storedObject->registerVersion(); // we generate a valid name $version = $storedObject->getPrefix().'/some-version'; $security = $this->prophesize(Security::class); $security->isGranted('SEE', $storedObject)->willReturn(true)->shouldBeCalled(); $security->getUser()->willReturn(new User()); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $actual = $controller->getSignedUrlGet( new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800, 'version' => $version]), $storedObject, 'get' ); $decodedActual = json_decode($actual->getContent(), true, JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR); self::assertArrayHasKey('method', $decodedActual); self::assertEquals('GET', $decodedActual['method']); self::assertArrayHasKey('object_name', $decodedActual); self::assertEquals($version, $decodedActual['object_name']); } public function testGetSignedUrlGetForSpecificVersionNotBelongingToTheStoreObject(): void { $this->expectException(AccessDeniedHttpException::class); $storedObject = new StoredObject(); $storedObject->registerVersion(); // we generate a random version $version = 'something/else'; $security = $this->prophesize(Security::class); $security->isGranted('SEE', $storedObject)->willReturn(true)->shouldBeCalled(); $controller = new AsyncUploadController( $this->buildTempUrlGenerator(), $this->buildSerializer(), $security->reveal(), new NullLogger(), ); $controller->getSignedUrlGet( new Request(query: ['expires_delay' => 10, 'submit_delay' => 1800, 'version' => $version]), $storedObject, 'get' ); } public function buildTempUrlGenerator(): TempUrlGeneratorInterface { return new class () implements TempUrlGeneratorInterface { public function generatePost(?int $expire_delay = null, ?int $submit_delay = null, int $max_file_count = 1, ?string $object_name = null): SignedUrlPost { return new SignedUrlPost( 'https://object.store.example', new \DateTimeImmutable('1 hour'), $object_name ?? 'abc', 150, 1, 1800, '', 'abc', 'abc' ); } public function generate(string $method, string $object_name, ?int $expire_delay = null): SignedUrl { return new SignedUrl( strtoupper($method), 'https://object.store.example', new \DateTimeImmutable('1 hour'), $object_name ); } }; } private function buildSerializer(): SerializerInterface { $serializer = $this->prophesize(SerializerInterface::class); $serializer->serialize(Argument::type(SignedUrl::class), 'json', Argument::type('array')) ->will(fn (array $args): string => json_encode( ['method' => $args[0]->method, 'object_name' => $args[0]->object_name], JSON_THROW_ON_ERROR, 3 )); return $serializer->reveal(); } }