diff --git a/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php b/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php index 600b6e52d..cf5830c53 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/StoredObjectApiController.php @@ -11,6 +11,46 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Controller; +use Chill\DocStoreBundle\Entity\StoredObject; use Chill\MainBundle\CRUD\Controller\ApiController; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\HttpFoundation\JsonResponse; +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 extends ApiController +{ + public function __construct( + private readonly Security $security, + private readonly SerializerInterface $serializer, + private readonly EntityManagerInterface $entityManager + ) {} + + /** + * Creates a new stored object. + * + * @return JsonResponse the response containing the serialized object in JSON format + * + * @throws AccessDeniedHttpException if the user does not have the necessary role to create a stored object + */ + #[Route('/api/1.0/doc-store/stored-object/create', methods: ['POST'])] + public function createStoredObject(): JsonResponse + { + if (!($this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_USER'))) { + throw new AccessDeniedHttpException('Must be user or admin to create a stored object'); + } + + $object = new StoredObject(); + + $this->entityManager->persist($object); + $this->entityManager->flush(); + + return new JsonResponse( + $this->serializer->serialize($object, 'json', [AbstractNormalizer::GROUPS => ['read']]), + json: true + ); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php b/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php index b156af1ea..efeb6362d 100644 --- a/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php +++ b/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\DependencyInjection; -use Chill\DocStoreBundle\Controller\StoredObjectApiController; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoterInterface; @@ -19,7 +18,6 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\Extension; /** @@ -53,29 +51,6 @@ class ChillDocStoreExtension extends Extension implements PrependExtensionInterf $this->prependRoute($container); $this->prependAuthorization($container); $this->prependTwig($container); - $this->prependApis($container); - } - - protected function prependApis(ContainerBuilder $container) - { - $container->prependExtensionConfig('chill_main', [ - 'apis' => [ - [ - 'class' => \Chill\DocStoreBundle\Entity\StoredObject::class, - 'controller' => StoredObjectApiController::class, - 'name' => 'stored_object', - 'base_path' => '/api/1.0/docstore/stored-object', - 'base_role' => 'ROLE_USER', - 'actions' => [ - '_entity' => [ - 'methods' => [ - Request::METHOD_POST => true, - ], - ], - ], - ], - ], - ]); } protected function prependAuthorization(ContainerBuilder $container) diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php new file mode 100644 index 000000000..74dbd9b46 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Tests/Controller/StoredObjectApiControllerTest.php @@ -0,0 +1,55 @@ +createMock(Security::class); + $security->expects($this->atLeastOnce())->method('isGranted') + ->with($this->logicalOr($this->identicalTo('ROLE_ADMIN'), $this->identicalTo('ROLE_USER'))) + ->willReturn(true) + ; + + $entityManager = $this->createMock(EntityManagerInterface::class); + $entityManager->expects($this->once())->method('persist')->with($this->isInstanceOf(StoredObject::class)); + $entityManager->expects($this->once())->method('flush'); + + $serializer = $this->createMock(SerializerInterface::class); + $serializer->expects($this->once())->method('serialize') + ->with($this->isInstanceOf(StoredObject::class), 'json', $this->anything()) + ->willReturn($r = <<<'JSON' + {"type": "stored-object", "id": 1} + JSON); + + $controller = new StoredObjectApiController($security, $serializer, $entityManager); + + $actual = $controller->createStoredObject(); + + 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 d74311387..7864a18af 100644 --- a/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillDocStoreBundle/chill.api.specs.yaml @@ -21,18 +21,11 @@ components: type: string paths: - /1.0/docstore/stored-object.json: + /1.0/doc-store/stored-object/create: post: tags: - storedobject summary: Create a stored object - requestBody: - description: "A stored object" - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/StoredObject" responses: 200: description: "OK"