From d17d21142944806445bc8406d4ce4944890a2a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 15 Apr 2026 18:09:30 +0200 Subject: [PATCH] Add `getStoredObject` endpoint to `StoredObjectApiController` with tests - Introduced the `/1.0/doc-store/stored-object/{uuid}` endpoint to retrieve stored objects by UUID. - Added access control to ensure users have appropriate permissions to view stored objects. - Extended the OpenAPI specification with new endpoint definitions, request parameters, and response schemas. - Developed unit tests to validate the endpoint's behavior, covering access denial and successful retrieval --- .../Controller/StoredObjectApiController.php | 18 +++++++++-- .../StoredObjectApiControllerTest.php | 32 ++++++++++++++++++- .../ChillDocStoreBundle/chill.api.specs.yaml | 26 +++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php b/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php index b67298f4c..5bbbbcb50 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php @@ -12,16 +12,17 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Controller; use Chill\DocStoreBundle\Entity\StoredObject; -use Chill\MainBundle\CRUD\Controller\ApiController; +use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\SerializerInterface; -class StoredObjectApiController extends ApiController +class StoredObjectApiController { public function __construct( private readonly Security $security, @@ -53,4 +54,17 @@ class StoredObjectApiController extends ApiController json: true ); } + + #[Route('/api/1.0/doc-store/stored-object/{uuid}', methods: ['GET', 'HEAD'])] + public function getStoredObject(StoredObject $storedObject, Request $request): JsonResponse + { + if (!$this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) { + throw new AccessDeniedHttpException('No permission to see the stored object'); + } + + return new JsonResponse( + $this->serializer->serialize($storedObject, 'json', [AbstractNormalizer::GROUPS => ['read']]), + json: true + ); + } } diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php index 74dbd9b46..8876005da 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php @@ -13,16 +13,18 @@ namespace Chill\DocStoreBundle\Tests\Controller; use Chill\DocStoreBundle\Controller\StoredObjectApiController; use Chill\DocStoreBundle\Entity\StoredObject; +use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Doctrine\ORM\EntityManagerInterface; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\SerializerInterface; /** * @internal * - * @coversNothing + * @covers \Chill\DocStoreBundle\Controller\StoredObjectApiController */ class StoredObjectApiControllerTest extends TestCase { @@ -52,4 +54,32 @@ class StoredObjectApiControllerTest extends TestCase self::assertInstanceOf(JsonResponse::class, $actual); self::assertEquals($r, $actual->getContent()); } + + public function testGet(): void + { + $storedObject = new StoredObject(); + $request = new Request(); + + $security = $this->createMock(Security::class); + $security->expects($this->once())->method('isGranted') + ->with($this->identicalTo(StoredObjectRoleEnum::SEE->value), $this->identicalTo($storedObject)) + ->willReturn(true) + ; + + $entityManager = $this->createMock(EntityManagerInterface::class); + + $serializer = $this->createMock(SerializerInterface::class); + $serializer->expects($this->once())->method('serialize') + ->with($this->identicalTo($storedObject), 'json', $this->anything()) + ->willReturn($r = <<<'JSON' + {"type": "stored-object", "id": 1} + JSON); + + $controller = new StoredObjectApiController($security, $serializer, $entityManager); + + $actual = $controller->getStoredObject($storedObject, $request); + + self::assertInstanceOf(JsonResponse::class, $actual); + self::assertEquals($r, $actual->getContent()); + } } diff --git a/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml b/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml index 327b2c630..801421551 100644 --- a/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml @@ -121,6 +121,32 @@ paths: 404: description: "Not found" + /1.0/doc-store/stored-object/{uuid}: + get: + tags: + - storedobject + summary: Get a stored object + parameters: + - in: path + name: uuid + required: true + allowEmptyValue: false + description: The UUID of the storedObject + schema: + type: string + format: uuid + responses: + 200: + description: "OK" + content: + application/json: + schema: + $ref: "#/components/schemas/StoredObject" + 403: + description: "Unauthorized" + 404: + description: "Not found" + /1.0/doc-store/stored-object/{uuid}/versions: get: tags: