From b2d8d21f04c4d23a33435e92aa0c866715c5460d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Sun, 16 Mar 2025 22:47:57 +0100 Subject: [PATCH] Add export generation creation from saved export endpoint Introduce a new controller for creating export generations from saved exports using a POST endpoint. Updates include a new route, serialization groups, and a corresponding test to validate functionality. --- ...erationCreateFromSavedExportController.php | 62 ++++++++++++++ .../Entity/ExportGeneration.php | 10 ++- ...ionCreateFromSavedExportControllerTest.php | 81 +++++++++++++++++++ .../ChillMainBundle/chill.api.specs.yaml | 22 +++++ 4 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillMainBundle/Controller/ExportGenerationCreateFromSavedExportController.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Authorization/ExportGenerationCreateFromSavedExportControllerTest.php diff --git a/src/Bundle/ChillMainBundle/Controller/ExportGenerationCreateFromSavedExportController.php b/src/Bundle/ChillMainBundle/Controller/ExportGenerationCreateFromSavedExportController.php new file mode 100644 index 000000000..737cbbea1 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/ExportGenerationCreateFromSavedExportController.php @@ -0,0 +1,62 @@ +security->isGranted(SavedExportVoter::GENERATE, $export)) { + throw new AccessDeniedHttpException('Not allowed to generate an export from this saved export'); + } + $user = $this->security->getUser(); + + if (!$user instanceof User) { + throw new AccessDeniedHttpException('Only users can create exports'); + } + + $exportGeneration = ExportGeneration::fromSavedExport($export, $this->clock->now()->add(new \DateInterval('P6M'))); + + $this->entityManager->persist($exportGeneration); + $this->entityManager->flush(); + + $this->messageBus->dispatch(new ExportRequestGenerationMessage($exportGeneration, $user)); + + return new JsonResponse( + $this->serializer->serialize($exportGeneration, 'json', ['groups' => ['read']]), + json: true, + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Entity/ExportGeneration.php b/src/Bundle/ChillMainBundle/Entity/ExportGeneration.php index f2f517107..cd9ed5782 100644 --- a/src/Bundle/ChillMainBundle/Entity/ExportGeneration.php +++ b/src/Bundle/ChillMainBundle/Entity/ExportGeneration.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; use Doctrine\ORM\Mapping as ORM; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; +use Symfony\Component\Serializer\Annotation as Serializer; /** * Contains the single execution of an export. @@ -29,21 +30,25 @@ use Ramsey\Uuid\UuidInterface; */ #[ORM\Entity()] #[ORM\Table('chill_main_export_generation')] +#[Serializer\DiscriminatorMap('type', ['export_generation' => ExportGeneration::class])] class ExportGeneration implements TrackCreationInterface { use TrackCreationTrait; #[ORM\Id] #[ORM\Column(type: 'uuid', unique: true)] + #[Serializer\Groups(['read'])] private UuidInterface $id; #[ORM\ManyToOne(targetEntity: StoredObject::class, cascade: ['persist', 'refresh'])] #[ORM\JoinColumn(nullable: false)] + #[Serializer\Groups(['read'])] private StoredObject $storedObject; public function __construct( #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])] + #[Serializer\Groups(['read'])] private string $exportAlias, #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '[]'])] private array $options = [], @@ -103,6 +108,9 @@ class ExportGeneration implements TrackCreationInterface public static function fromSavedExport(SavedExport $savedExport, ?\DateTimeImmutable $deletedAt = null): self { - return new self($savedExport->getExportAlias(), $savedExport->getOptions(), $deletedAt, $savedExport); + $generation = new self($savedExport->getExportAlias(), $savedExport->getOptions(), $deletedAt, $savedExport); + $generation->getStoredObject()->setTitle($savedExport->getTitle()); + + return $generation; } } diff --git a/src/Bundle/ChillMainBundle/Tests/Authorization/ExportGenerationCreateFromSavedExportControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Authorization/ExportGenerationCreateFromSavedExportControllerTest.php new file mode 100644 index 000000000..8e9e65963 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Authorization/ExportGenerationCreateFromSavedExportControllerTest.php @@ -0,0 +1,81 @@ +setOptions($exportOptions = ['test' => 'content'])->setExportAlias('dummy_export_alias'); + + $user = new User(); + $reflection = new \ReflectionClass($user); + $id = $reflection->getProperty('id'); + $id->setValue($user, 1); + + $security = $this->prophesize(Security::class); + $security->isGranted(SavedExportVoter::GENERATE, $savedExport)->shouldBeCalled()->willReturn(true); + $security->getUser()->willReturn($user); + + $entityManager = $this->prophesize(EntityManagerInterface::class); + $entityManager->persist(Argument::that( + static fn ($arg) => $arg instanceof ExportGeneration && $arg->getOptions() === $exportOptions && $arg->getSavedExport() === $savedExport, + ))->shouldBeCalled(); + $entityManager->flush()->shouldBeCalled(); + + $messenger = $this->prophesize(MessageBusInterface::class); + $messenger->dispatch(Argument::type(ExportRequestGenerationMessage::class))->shouldBeCalled()->will( + static fn (array $args): Envelope => new Envelope($args[0]), + ); + + $serializer = $this->prophesize(SerializerInterface::class); + $serializer->serialize(Argument::type(ExportGeneration::class), 'json', ['groups' => ['read']])->shouldBeCalled()->willReturn('{"test": "export-generation"}'); + + $controller = new ExportGenerationCreateFromSavedExportController( + $security->reveal(), + $entityManager->reveal(), + $messenger->reveal(), + new MockClock(), + $serializer->reveal() + ); + + $response = $controller($savedExport); + + self::assertInstanceOf(JsonResponse::class, $response); + self::assertEquals('{"test": "export-generation"}', $response->getContent()); + } +} diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml index 7a9341beb..43b4d20f2 100644 --- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml @@ -1123,3 +1123,25 @@ paths: application/json: schema: type: object + /1.0/main/export/export-generation/create-from-saved-export/{id}: + post: + tags: + - export + summary: Create an export generation from an existing saved export + parameters: + - name: id + in: path + required: true + description: The entity saved export's id + schema: + type: string + format: uuid + responses: + 403: + description: Access denied + 200: + description: "ok" + content: + application/json: + schema: + type: object