mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Add signature messenger request serialization and processing
This update introduces a new serializer class for request messages (from messenger component). New features-includes encoding and decoding of request messages and handling unexpected value exceptions. A new test class for the serializer and it also adds functionality to process signature requests in the controller.
This commit is contained in:
parent
610239930b
commit
18a03fd740
@ -0,0 +1,46 @@
|
|||||||
|
<?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\Controller;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||||
|
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class SignatureRequestController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private MessageBusInterface $messageBus,
|
||||||
|
private StoredObjectManagerInterface $storedObjectManager,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')]
|
||||||
|
public function processSignature(StoredObject $storedObject): Response
|
||||||
|
{
|
||||||
|
$content = $this->storedObjectManager->read($storedObject);
|
||||||
|
|
||||||
|
$this->messageBus->dispatch(new RequestPdfSignMessage(
|
||||||
|
0,
|
||||||
|
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||||
|
0,
|
||||||
|
'test signature',
|
||||||
|
'Mme Caroline Diallo',
|
||||||
|
$content
|
||||||
|
));
|
||||||
|
|
||||||
|
return new Response('<html><head><title>test</title></head><body><p>ok</p></body></html>');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?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\Service\Signature\Driver\BaseSigner;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||||
|
|
||||||
|
final readonly class RequestPdfSignMessage
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public int $signatureId,
|
||||||
|
public PDFSignatureZone $PDFSignatureZone,
|
||||||
|
public int $signatureZoneIndex,
|
||||||
|
public string $reason,
|
||||||
|
public string $signerText,
|
||||||
|
public string $content,
|
||||||
|
) {}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
<?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\Service\Signature\Driver\BaseSigner;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||||
|
use Symfony\Component\Messenger\Envelope;
|
||||||
|
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
|
||||||
|
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
|
||||||
|
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
|
||||||
|
final readonly class RequestPdfSignMessageSerializer implements SerializerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private NormalizerInterface $normalizer,
|
||||||
|
private DenormalizerInterface $denormalizer,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function decode(array $encodedEnvelope): Envelope
|
||||||
|
{
|
||||||
|
$body = $encodedEnvelope['body'];
|
||||||
|
$headers = $encodedEnvelope['headers'];
|
||||||
|
|
||||||
|
if (RequestPdfSignMessage::class !== ($headers['Message'] ?? null)) {
|
||||||
|
throw new MessageDecodingFailedException('serializer does not support this message');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($body, true);
|
||||||
|
|
||||||
|
$zoneSignature = $this->denormalizer->denormalize($data['signatureZone'], PDFSignatureZone::class, 'json', [
|
||||||
|
AbstractNormalizer::GROUPS => ['write'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$content = base64_decode($data['content'], true);
|
||||||
|
|
||||||
|
if (false === $content) {
|
||||||
|
throw new MessageDecodingFailedException('the content could not be converted from base64 encoding');
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = new RequestPdfSignMessage(
|
||||||
|
$data['signatureId'],
|
||||||
|
$zoneSignature,
|
||||||
|
$data['signatureZoneIndex'],
|
||||||
|
$data['reason'],
|
||||||
|
$data['signerText'],
|
||||||
|
$content,
|
||||||
|
);
|
||||||
|
|
||||||
|
// in case of redelivery, unserialize any stamps
|
||||||
|
$stamps = [];
|
||||||
|
if (isset($headers['stamps'])) {
|
||||||
|
$stamps = unserialize($headers['stamps']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Envelope($message, $stamps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(Envelope $envelope): array
|
||||||
|
{
|
||||||
|
$message = $envelope->getMessage();
|
||||||
|
|
||||||
|
if (!$message instanceof RequestPdfSignMessage) {
|
||||||
|
throw new MessageDecodingFailedException('Message is not a RequestPdfSignMessage');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'signatureId' => $message->signatureId,
|
||||||
|
'signatureZoneIndex' => $message->signatureZoneIndex,
|
||||||
|
'signatureZone' => $this->normalizer->normalize($message->PDFSignatureZone, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
'reason' => $message->reason,
|
||||||
|
'signerText' => $message->signerText,
|
||||||
|
'content' => base64_encode($message->content),
|
||||||
|
];
|
||||||
|
|
||||||
|
$allStamps = [];
|
||||||
|
foreach ($envelope->all() as $stamp) {
|
||||||
|
if ($stamp instanceof NonSendableStampInterface) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$allStamps = [...$allStamps, ...$stamp];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'body' => json_encode($data, JSON_THROW_ON_ERROR, 512),
|
||||||
|
'headers' => [
|
||||||
|
'stamps' => serialize($allStamps),
|
||||||
|
'Message' => RequestPdfSignMessage::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,137 @@
|
|||||||
|
<?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\Service\Signature\Driver\BaseSigner;
|
||||||
|
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||||
|
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessageSerializer;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Messenger\Envelope;
|
||||||
|
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\Serializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class RequestPdfSignMessageSerializerTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testEncode(): void
|
||||||
|
{
|
||||||
|
$serializer = $this->buildSerializer();
|
||||||
|
|
||||||
|
$envelope = new Envelope(
|
||||||
|
$request = new RequestPdfSignMessage(
|
||||||
|
0,
|
||||||
|
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||||
|
0,
|
||||||
|
'metadata to add to the signature',
|
||||||
|
'Mme Caroline Diallo',
|
||||||
|
'abc'
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$actual = $serializer->encode($envelope);
|
||||||
|
$expectedBody = json_encode([
|
||||||
|
'signatureId' => $request->signatureId,
|
||||||
|
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||||
|
'signatureZone' => ['x' => 10.0],
|
||||||
|
'reason' => $request->reason,
|
||||||
|
'signerText' => $request->signerText,
|
||||||
|
'content' => base64_encode($request->content),
|
||||||
|
]);
|
||||||
|
|
||||||
|
self::assertIsArray($actual);
|
||||||
|
self::assertArrayHasKey('body', $actual);
|
||||||
|
self::assertArrayHasKey('headers', $actual);
|
||||||
|
self::assertEquals($expectedBody, $actual['body']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDecode(): void
|
||||||
|
{
|
||||||
|
$serializer = $this->buildSerializer();
|
||||||
|
|
||||||
|
$request = new RequestPdfSignMessage(
|
||||||
|
0,
|
||||||
|
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||||
|
0,
|
||||||
|
'metadata to add to the signature',
|
||||||
|
'Mme Caroline Diallo',
|
||||||
|
'abc'
|
||||||
|
);
|
||||||
|
|
||||||
|
$bodyAsString = json_encode([
|
||||||
|
'signatureId' => $request->signatureId,
|
||||||
|
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||||
|
'signatureZone' => ['x' => 10.0],
|
||||||
|
'reason' => $request->reason,
|
||||||
|
'signerText' => $request->signerText,
|
||||||
|
'content' => base64_encode($request->content),
|
||||||
|
], JSON_THROW_ON_ERROR);
|
||||||
|
|
||||||
|
$actual = $serializer->decode([
|
||||||
|
'body' => $bodyAsString,
|
||||||
|
'headers' => [
|
||||||
|
'Message' => RequestPdfSignMessage::class,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
self::assertInstanceOf(RequestPdfSignMessage::class, $actual->getMessage());
|
||||||
|
self::assertEquals($request->signatureId, $actual->getMessage()->signatureId);
|
||||||
|
self::assertEquals($request->signatureZoneIndex, $actual->getMessage()->signatureZoneIndex);
|
||||||
|
self::assertEquals($request->reason, $actual->getMessage()->reason);
|
||||||
|
self::assertEquals($request->signerText, $actual->getMessage()->signerText);
|
||||||
|
self::assertEquals($request->content, $actual->getMessage()->content);
|
||||||
|
self::assertNotNull($actual->getMessage()->PDFSignatureZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildSerializer(): RequestPdfSignMessageSerializer
|
||||||
|
{
|
||||||
|
$normalizer =
|
||||||
|
new class () implements NormalizerInterface {
|
||||||
|
public function normalize($object, ?string $format = null, array $context = []): array
|
||||||
|
{
|
||||||
|
if (!$object instanceof PDFSignatureZone) {
|
||||||
|
throw new UnexpectedValueException('expected RequestPdfSignMessage');
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'x' => $object->x,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsNormalization($data, ?string $format = null): bool
|
||||||
|
{
|
||||||
|
return $data instanceof PDFSignatureZone;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$denormalizer = new class () implements DenormalizerInterface {
|
||||||
|
public function denormalize($data, string $type, ?string $format = null, array $context = [])
|
||||||
|
{
|
||||||
|
return new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsDenormalization($data, string $type, ?string $format = null)
|
||||||
|
{
|
||||||
|
return PDFSignatureZone::class === $type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$serializer = new Serializer([$normalizer, $denormalizer]);
|
||||||
|
|
||||||
|
return new RequestPdfSignMessageSerializer($serializer, $serializer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user