diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index 557d96d..96d7c6b 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -53,6 +53,12 @@ class Configuration implements ConfigurationInterface
->end()
->end()
->end()
+ ->arrayNode('messenger')
+ ->children()
+ ->scalarNode('message_handler')->isRequired()->defaultValue('simple_console_runner')->end()
+ ->scalarNode('process_timeout')->end()
+ ->end()
+ ->end()
->end();
return $treeBuilder;
diff --git a/DependencyInjection/RetailCrmServiceExtension.php b/DependencyInjection/RetailCrmServiceExtension.php
index d32f08e..4e27c45 100644
--- a/DependencyInjection/RetailCrmServiceExtension.php
+++ b/DependencyInjection/RetailCrmServiceExtension.php
@@ -4,6 +4,7 @@ namespace RetailCrm\ServiceBundle\DependencyInjection;
use RetailCrm\ServiceBundle\ArgumentResolver\CallbackValueResolver;
use RetailCrm\ServiceBundle\ArgumentResolver\ClientValueResolver;
+use RetailCrm\ServiceBundle\Messenger\MessageHandler;
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
@@ -49,6 +50,18 @@ class RetailCrmServiceExtension extends Extension
$config['request_schema']['client']['serializer']
);
+ $container->setParameter(
+ 'retail_crm_service.messenger.message_handler',
+ $config['messenger']['message_handler']
+ );
+
+ if (isset($config['messenger']['process_timeout'])) {
+ $container->setParameter(
+ 'retail_crm_service.messenger.process_timeout',
+ $config['messenger']['process_timeout']
+ );
+ }
+
$container
->register(SymfonySerializerAdapter::class)
->setAutowired(true);
@@ -90,5 +103,28 @@ class RetailCrmServiceExtension extends Extension
$container
->register(FrontApiClientAuthenticator::class)
->setAutowired(true);
+
+ $container
+ ->register(MessageHandler\SimpleConsoleRunner::class)
+ ->setAutowired(true);
+ $container->setAlias('simple_console_runner', MessageHandler\SimpleConsoleRunner::class);
+
+ $timeout = $container->hasParameter('retail_crm_service.messenger.process_timeout')
+ ? $container->getParameter('retail_crm_service.messenger.process_timeout')
+ : null;
+
+ $container
+ ->register(MessageHandler\InNewProcessRunner::class)
+ ->setArgument('$timeout', $timeout)
+ ->setAutowired(true);
+ $container->setAlias('in_new_process_runner', MessageHandler\InNewProcessRunner::class);
+
+ $container
+ ->register(MessageHandler::class)
+ ->addTag('messenger.message_handler')
+ ->setArguments([
+ new Reference($container->getParameter('retail_crm_service.messenger.message_handler'))
+ ])
+ ->setAutowired(true);
}
}
diff --git a/Messenger/CommandMessage.php b/Messenger/CommandMessage.php
new file mode 100644
index 0000000..9ea7cde
--- /dev/null
+++ b/Messenger/CommandMessage.php
@@ -0,0 +1,99 @@
+commandName;
+ }
+
+ /**
+ * @param string $commandName
+ */
+ public function setCommandName(string $commandName): void
+ {
+ $this->commandName = $commandName;
+ }
+
+ /**
+ * @return array
+ */
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+
+ /**
+ * @param array $options
+ */
+ public function setOptions(array $options): void
+ {
+ $this->options = $options;
+ }
+
+ /**
+ * @return array
+ */
+ public function getArguments(): array
+ {
+ return $this->arguments;
+ }
+
+ /**
+ * @param array $arguments
+ */
+ public function setArguments(array $arguments): void
+ {
+ $this->arguments = $arguments;
+ }
+
+ /**
+ * @param string $key
+ * @param string $value
+ */
+ public function addOption(string $key, string $value): void
+ {
+ $this->options[$key] = $value;
+ }
+
+ /**
+ * @param string $key
+ * @param string $value
+ */
+ public function addArgument(string $key, string $value): void
+ {
+ $this->arguments[$key] = $value;
+ }
+
+ /**
+ * @return array
+ */
+ public function getFormattedOptions(): array
+ {
+ $options = [];
+ foreach ($this->options as $option => $value) {
+ $options['--' . $option] = $value;
+ }
+
+ return $options;
+ }
+}
diff --git a/Messenger/MessageHandler.php b/Messenger/MessageHandler.php
new file mode 100644
index 0000000..6f38fa3
--- /dev/null
+++ b/Messenger/MessageHandler.php
@@ -0,0 +1,40 @@
+runner = $runner;
+ }
+
+ /**
+ * @param CommandMessage $message
+ *
+ * @throws Exception
+ */
+ public function __invoke(CommandMessage $message): void
+ {
+ $this->runner->run($message);
+ }
+}
diff --git a/Messenger/MessageHandler/InNewProcessRunner.php b/Messenger/MessageHandler/InNewProcessRunner.php
new file mode 100644
index 0000000..da0abff
--- /dev/null
+++ b/Messenger/MessageHandler/InNewProcessRunner.php
@@ -0,0 +1,109 @@
+logger = $logger;
+ $this->kernel = $kernel;
+
+ if (null !== $timeout) {
+ $this->timeout = $timeout;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run(CommandMessage $message): void
+ {
+ $phpBinaryPath = (new PhpExecutableFinder)->find();
+ $consoleCommand = [
+ 'php' => $phpBinaryPath ?: 'php',
+ 'console' => sprintf('%s/bin/console', $this->kernel->getContainer()->getParameter('kernel.project_dir')),
+ 'command' => $message->getCommandName()
+ ];
+
+ $process = new Process(
+ array_merge(
+ array_values($consoleCommand),
+ array_values($message->getArguments()),
+ array_values($this->getOptions($message)),
+ )
+ );
+
+ try {
+ $process
+ ->setTimeout($this->timeout)
+ ->run(static function(string $type, string $buffer) {
+ echo $buffer;
+ })
+ ;
+ } catch (ProcessTimedOutException $processTimedOutException) {
+ $this->logger->error(
+ sprintf(
+ 'Process "%s" killed after %d seconds of execution',
+ $processTimedOutException->getProcess()->getCommandLine(),
+ $processTimedOutException->getProcess()->getTimeout()
+ )
+ );
+ }
+ }
+
+ /**
+ * @param CommandMessage $message
+ *
+ * @return array
+ */
+ private function getOptions(CommandMessage $message): array
+ {
+ $options = [];
+ foreach ($message->getFormattedOptions() as $option => $value) {
+ $options[] = $option . '=' . $value;
+ }
+
+ return $options;
+ }
+}
diff --git a/Messenger/MessageHandler/JobRunner.php b/Messenger/MessageHandler/JobRunner.php
new file mode 100644
index 0000000..350e847
--- /dev/null
+++ b/Messenger/MessageHandler/JobRunner.php
@@ -0,0 +1,18 @@
+logger = $logger;
+ $this->kernel = $kernel;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run(CommandMessage $message): void
+ {
+ $application = new Application($this->kernel);
+ $application->setAutoExit(false);
+
+ $input = new ArrayInput(
+ array_merge(
+ ['command' => $message->getCommandName()],
+ $message->getFormattedOptions(),
+ $message->getArguments()
+ )
+ );
+
+ $output = new BufferedOutput();
+ if ($application->run($input, $output) > 0) {
+ $this->logger->error($output->fetch());
+
+ return;
+ }
+
+ echo $output->fetch();
+ }
+}
diff --git a/Resources/doc/Messenger.md b/Resources/doc/Messenger.md
new file mode 100644
index 0000000..d68f900
--- /dev/null
+++ b/Resources/doc/Messenger.md
@@ -0,0 +1,60 @@
+### Messenger
+
+#### Messages
+
+The library provides a basic message for executing console commands as message handlers - `RetailCrm\ServiceBundle\Messenger\CommandMessage`.
+This makes it easier to create new message types. For example:
+
+* Create your message
+
+```php
+
+namespace App\Message;
+
+use RetailCrm\ServiceBundle\Messenger\CommandMessage;
+
+class MyMessage extends CommandMessage
+{
+ public function __construct()
+ {
+ $this->commandName = \App\Command\MyCommand::getDefaultName();
+ $this->options = ['optionName' => 'optionValue'];
+ $this->arguments = ['argumentName' => 'argumentValue'];
+ }
+}
+
+```
+
+* Add a message to a routing
+
+```yaml
+# config/packages/messenger.yaml
+framework:
+ messenger:
+ transports:
+ async: "%env(MESSENGER_TRANSPORT_DSN)%"
+
+ routing:
+ 'App\Message\MyMessage': async
+```
+
+Now when sending this message through messenger (```$messageBus->dispatch(new MyMessage())```) the message handler will run the associated command
+
+#### Message handlers
+
+Two messages handlers are is supported:
+
+* all messages handling in one worker process
+* each message is a processed in a separate process
+
+By default, messages will be processed in one process. To set up a handler to run in a separate process, add to the bundle config:
+
+```yaml
+retail_crm_service:
+ messenger:
+ message_handler: in_new_process_runner
+ process_timeout: 60
+```
+
+`process_timeout` - an optional parameter that only makes sense when `message_handler` is equal `in_new_process_runner` and determines the lifetime of the process.
+By default, process timeout - 3600 (in seconds).
diff --git a/Resources/doc/Requests.md b/Resources/doc/Requests.md
new file mode 100644
index 0000000..a70866d
--- /dev/null
+++ b/Resources/doc/Requests.md
@@ -0,0 +1,71 @@
+### Deserialize incoming requests
+
+#### Callbacks (form data)
+
+To automatically get the callback request parameter
+
+```php
+
+class AppController extends AbstractController
+{
+ public function activityAction(\App\Dto\Callback\Activity $activity): Response
+ {
+ // handle activity
+ }
+}
+
+```
+
+add to the config:
+
+```yaml
+retail_crm_service:
+ request_schema:
+ callback:
+ supports:
+ - { type: App\Dto\Callback\Activity, params: ["activity"] }
+```
+
+request automatically will be deserialization to $activity.
+
+#### Body json content
+
+```php
+
+class AppController extends AbstractController
+{
+ public function someAction(\App\Dto\Body $activity): Response
+ {
+ // handle activity
+ }
+}
+
+```
+
+add to the config:
+
+```yaml
+retail_crm_service:
+ request_schema:
+ client:
+ supports:
+ - App\Dto\Body
+```
+
+#### Serializers
+At this time supported [Symfony serializer](https://symfony.com/doc/current/components/serializer.html) and [JMS serializer](https://jmsyst.com/libs/serializer).
+By default, the library using a Symfony serializer. For use JMS install JMS serializer bundle - `composer require jms/serializer-bundle`
+You can explicitly specify the type of serializer used for request schema:
+
+```yaml
+retail_crm_service:
+ request_schema:
+ client:
+ supports:
+ # types
+ serializer: retail_crm_service.symfony_serializer.adapter # or retail_crm_service.jms_serializer.adapter
+ callback:
+ supports:
+ # types
+ serializer: retail_crm_service.jms_serializer.adapter # or retail_crm_service.symfony_serializer.adapter
+```
diff --git a/Resources/doc/Security.md b/Resources/doc/Security.md
new file mode 100644
index 0000000..9de58c1
--- /dev/null
+++ b/Resources/doc/Security.md
@@ -0,0 +1,70 @@
+### Authentication
+
+Example security configuration:
+
+```yaml
+security:
+ providers:
+ client:
+ entity:
+ class: 'App\Entity\Connection' # must implements UserInterface
+ property: 'clientId'
+ firewalls:
+ api:
+ pattern: ^/api
+ provider: client
+ anonymous: ~
+ lazy: true
+ stateless: false
+ guard:
+ authenticators:
+ - RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator
+ callback:
+ pattern: ^/callback
+ provider: client
+ anonymous: ~
+ lazy: true
+ stateless: true
+ guard:
+ authenticators:
+ - RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator
+ main:
+ anonymous: true
+ lazy: true
+
+ access_control:
+ - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } # login for programmatically authentication user
+ - { path: ^/api, roles: ROLE_USER }
+ - { path: ^/callback, roles: ROLE_USER }
+```
+
+To authenticate the user after creating it, you can use the following code
+
+```php
+
+use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
+use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class AppController extends AbstractController
+{
+ public function someAction(
+ Request $request,
+ GuardAuthenticatorHandler $guardAuthenticatorHandler,
+ FrontApiClientAuthenticator $frontApiClientAuthenticator,
+ ConnectionManager $manager
+ ): Response {
+ $user = $manager->getUser(); // getting user
+
+ $guardAuthenticatorHandler->authenticateUserAndHandleSuccess(
+ $user,
+ $request,
+ $frontApiClientAuthenticator,
+ 'api'
+ );
+ // ...
+ }
+}
+
+```
diff --git a/Resources/doc/index.md b/Resources/doc/index.md
index 443faab..53c0418 100644
--- a/Resources/doc/index.md
+++ b/Resources/doc/index.md
@@ -2,8 +2,6 @@
`composer require retailcrm/service-bundle`
-## Usage
-
Enable bundle in `config/bundles.php`:
```php
@@ -23,147 +21,10 @@ retail_crm_service:
request_schema:
callback: ~
client: ~
+ messenger: ~
```
-### Deserializing incoming requests
-
-#### Callbacks (form data)
-
-To automatically get the callback request parameter
-
-```php
-
-class AppController extends AbstractController
-{
- public function activityAction(\App\Dto\Callback\Activity $activity): Response
- {
- // handle activity
- }
-}
-
-```
-
-add to the config:
-
-```yaml
-retail_crm_service:
- request_schema:
- callback:
- supports:
- - { type: App\Dto\Callback\Activity, params: ["activity"] }
-```
-
-request automatically will be deserialization to $activity.
-
-#### Body json content
-
-```php
-
-class AppController extends AbstractController
-{
- public function someAction(\App\Dto\Body $activity): Response
- {
- // handle activity
- }
-}
-
-```
-
-add to the config:
-
-```yaml
-retail_crm_service:
- request_schema:
- client:
- supports:
- - App\Dto\Body
-```
-
-#### Serializers
-At this time supported [Symfony serializer](https://symfony.com/doc/current/components/serializer.html) and [JMS serializer](https://jmsyst.com/libs/serializer).
-By default, the library using a Symfony serializer. For use JMS install JMS serializer bundle - `composer require jms/serializer-bundle`
-You can explicitly specify the type of serializer used for request schema:
-
-```yaml
-retail_crm_service:
- request_schema:
- client:
- supports:
- # types
- serializer: retail_crm_service.symfony_serializer.adapter # or retail_crm_service.jms_serializer.adapter
- callback:
- supports:
- # types
- serializer: retail_crm_service.jms_serializer.adapter # or retail_crm_service.symfony_serializer.adapter
-```
-
-### Authentication
-
-Example security configuration:
-
-```yaml
-security:
- providers:
- client:
- entity:
- class: 'App\Entity\Connection' # must implements UserInterface
- property: 'clientId'
- firewalls:
- api:
- pattern: ^/api
- provider: client
- anonymous: ~
- lazy: true
- stateless: false
- guard:
- authenticators:
- - RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator
- callback:
- pattern: ^/callback
- provider: client
- anonymous: ~
- lazy: true
- stateless: true
- guard:
- authenticators:
- - RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator
- main:
- anonymous: true
- lazy: true
-
- access_control:
- - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } # login for programmatically authentication user
- - { path: ^/api, roles: ROLE_USER }
- - { path: ^/callback, roles: ROLE_USER }
-```
-
-To authenticate the user after creating it, you can use the following code
-
-```php
-
-use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
-use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-
-class AppController extends AbstractController
-{
- public function someAction(
- Request $request,
- GuardAuthenticatorHandler $guardAuthenticatorHandler,
- FrontApiClientAuthenticator $frontApiClientAuthenticator,
- ConnectionManager $manager
- ): Response {
- $user = $manager->getUser(); // getting user
-
- $guardAuthenticatorHandler->authenticateUserAndHandleSuccess(
- $user,
- $request,
- $frontApiClientAuthenticator,
- 'api'
- );
- // ...
- }
-}
-
-```
+## Usage
+* [Handling incoming requests data](./Requests.md)
+* [Security](./Security.md)
+* [Messenger](./Messenger.md)
diff --git a/Tests/DataFixtures/TestMessage.php b/Tests/DataFixtures/TestMessage.php
new file mode 100644
index 0000000..b69877e
--- /dev/null
+++ b/Tests/DataFixtures/TestMessage.php
@@ -0,0 +1,15 @@
+commandName = 'test';
+ $this->arguments = ['argument' => 'argument'];
+ $this->options = ['option' => 'option'];
+ }
+}
diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php
index 5af77cf..1468dde 100644
--- a/Tests/DependencyInjection/ConfigurationTest.php
+++ b/Tests/DependencyInjection/ConfigurationTest.php
@@ -34,6 +34,10 @@ class ConfigurationTest extends TestCase
'type2'
]
]
+ ],
+ 'messenger' => [
+ 'message_handler' => 'simple_console_runner',
+ 'process_timeout' => 60
]
]
];
@@ -71,6 +75,9 @@ class ConfigurationTest extends TestCase
'type',
]
]
+ ],
+ 'messenger' => [
+ 'message_handler' => 'simple_console_runner'
]
]
];
diff --git a/Tests/DependencyInjection/RetailCrmServiceExtensionTest.php b/Tests/DependencyInjection/RetailCrmServiceExtensionTest.php
index ba0dcd0..75141e7 100644
--- a/Tests/DependencyInjection/RetailCrmServiceExtensionTest.php
+++ b/Tests/DependencyInjection/RetailCrmServiceExtensionTest.php
@@ -34,6 +34,9 @@ class RetailCrmServiceExtensionTest extends TestCase
'request_schema' => [
'callback' => [],
'client' => []
+ ],
+ 'messenger' => [
+ 'message_handler' => 'simple_console_runner'
]
]
],
diff --git a/Tests/Fixtures/App/Kernel.php b/Tests/Fixtures/App/Kernel.php
new file mode 100644
index 0000000..d10c683
--- /dev/null
+++ b/Tests/Fixtures/App/Kernel.php
@@ -0,0 +1,33 @@
+register(TestCommand::class, TestCommand::class)
+ ->addTag('console.command', ['command' => TestCommand::getDefaultName()])
+ ;
+
+ $container->setParameter('kernel.project_dir', __DIR__ . '/..');
+ }
+
+// public function registerContainerConfiguration(LoaderInterface $loader)
+// {
+// }
+}
diff --git a/Tests/Fixtures/App/TestCommand.php b/Tests/Fixtures/App/TestCommand.php
new file mode 100644
index 0000000..a47c371
--- /dev/null
+++ b/Tests/Fixtures/App/TestCommand.php
@@ -0,0 +1,36 @@
+addArgument(
+ 'argument',
+ InputArgument::REQUIRED
+ )
+ ->addOption(
+ 'option',
+ null,
+ InputOption::VALUE_REQUIRED
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ echo self::$defaultName . ' ' . $input->getArgument('argument') . ' ' . $input->getOption('option');
+
+ return Command::SUCCESS;
+ }
+}
diff --git a/Tests/Fixtures/App/TestCommandMessage.php b/Tests/Fixtures/App/TestCommandMessage.php
new file mode 100644
index 0000000..e03e282
--- /dev/null
+++ b/Tests/Fixtures/App/TestCommandMessage.php
@@ -0,0 +1,15 @@
+commandName = 'test';
+ $this->arguments = ['argument' => 'test'];
+ $this->options = ['option' => 'test'];
+ }
+}
diff --git a/Tests/Fixtures/bin/console b/Tests/Fixtures/bin/console
new file mode 100644
index 0000000..b5a1057
--- /dev/null
+++ b/Tests/Fixtures/bin/console
@@ -0,0 +1,9 @@
+#!/usr/bin/env php
+run($input);
diff --git a/Tests/Messenger/CommandMessageTest.php b/Tests/Messenger/CommandMessageTest.php
new file mode 100644
index 0000000..fdd13b1
--- /dev/null
+++ b/Tests/Messenger/CommandMessageTest.php
@@ -0,0 +1,38 @@
+getCommandName());
+ static::assertEquals(['argument' => 'argument'], $message->getArguments());
+ static::assertEquals(['option' => 'option'], $message->getOptions());
+ static::assertEquals(['--option' => 'option'], $message->getFormattedOptions());
+
+ $message->addOption('option2', 'option2');
+ $message->addArgument('argument2', 'argument2');
+
+ static::assertEquals(['argument' => 'argument', 'argument2' => 'argument2'], $message->getArguments());
+ static::assertEquals(['option' => 'option', 'option2' => 'option2'], $message->getOptions());
+ static::assertEquals(['--option' => 'option', '--option2' => 'option2'], $message->getFormattedOptions());
+
+ $message->setOptions(['option' => 'option']);
+ $message->setArguments(['argument' => 'argument']);
+
+ static::assertEquals(['argument' => 'argument'], $message->getArguments());
+ static::assertEquals(['option' => 'option'], $message->getOptions());
+ static::assertEquals(['--option' => 'option'], $message->getFormattedOptions());
+ }
+}
diff --git a/Tests/Messenger/MessageHandler/InNewProcessRunnerTest.php b/Tests/Messenger/MessageHandler/InNewProcessRunnerTest.php
new file mode 100644
index 0000000..cada1a3
--- /dev/null
+++ b/Tests/Messenger/MessageHandler/InNewProcessRunnerTest.php
@@ -0,0 +1,32 @@
+ 'test']);
+ }
+
+ public function testRun(): void
+ {
+ $runner = new InNewProcessRunner(new NullLogger, self::$kernel);
+
+ ob_clean();
+ ob_start();
+ $runner->run(new TestCommandMessage());
+
+ static::assertEquals('test test test', ob_get_clean());
+ }
+}
diff --git a/Tests/Messenger/MessageHandler/SimpleConsoleRunnerTest.php b/Tests/Messenger/MessageHandler/SimpleConsoleRunnerTest.php
new file mode 100644
index 0000000..d5256b7
--- /dev/null
+++ b/Tests/Messenger/MessageHandler/SimpleConsoleRunnerTest.php
@@ -0,0 +1,32 @@
+ 'test']);
+ }
+
+ public function testRun(): void
+ {
+ $runner = new SimpleConsoleRunner(new NullLogger, self::$kernel);
+
+ ob_clean();
+ ob_start();
+ $runner->run(new TestCommandMessage());
+
+ static::assertEquals('test test test', ob_get_clean());
+ }
+}
diff --git a/Tests/Messenger/MessageHandlerTest.php b/Tests/Messenger/MessageHandlerTest.php
new file mode 100644
index 0000000..1f66d97
--- /dev/null
+++ b/Tests/Messenger/MessageHandlerTest.php
@@ -0,0 +1,26 @@
+createMock(JobRunner::class);
+ $runner->expects(static::once())->method('run');
+ $message = $this->createMock(CommandMessage::class);
+
+ $handler = new MessageHandler($runner);
+ $handler->__invoke($message);
+ }
+}
diff --git a/Tests/Security/CallbackClientAuthenticatorTest.php b/Tests/Security/CallbackClientAuthenticatorTest.php
index 12befe7..bc2f532 100644
--- a/Tests/Security/CallbackClientAuthenticatorTest.php
+++ b/Tests/Security/CallbackClientAuthenticatorTest.php
@@ -5,11 +5,14 @@ namespace RetailCrm\ServiceBundle\Tests\Security;
use PHPUnit\Framework\TestCase;
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
+use RetailCrm\ServiceBundle\Tests\DataFixtures\User;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* Class CallbackClientAuthenticatorTest
@@ -99,7 +102,7 @@ class CallbackClientAuthenticatorTest extends TestCase
);
$auth = new CallbackClientAuthenticator($errorResponseFactory);
- $result = $auth->start(new Request(), new AuthenticationException());
+ $result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException());
static::assertInstanceOf(JsonResponse::class, $result);
static::assertEquals(Response::HTTP_FORBIDDEN, $result->getStatusCode());
@@ -132,4 +135,34 @@ class CallbackClientAuthenticatorTest extends TestCase
static::assertFalse($result);
}
+
+ public function testGetUser(): void
+ {
+ $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
+ $user = new User();
+ $auth = new CallbackClientAuthenticator($errorResponseFactory);
+
+ $userProvider = $this->createMock(UserProviderInterface::class);
+ $userProvider
+ ->expects(static::once())
+ ->method('loadUserByUsername')
+ ->with('clientId')
+ ->willReturn($user)
+ ;
+
+ $result = $auth->getUser('clientId', $userProvider);
+ static::assertEquals($user, $result);
+ }
+
+ public function testOnAuthenticationSuccess(): void
+ {
+ $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
+ $request = $this->createMock(Request::class);
+ $token = $this->createMock(TokenInterface::class);
+ $auth = new CallbackClientAuthenticator($errorResponseFactory);
+
+ $result = $auth->onAuthenticationSuccess($request, $token, 'key');
+
+ static::assertNull($result);
+ }
}
diff --git a/Tests/Security/FrontApiClientAuthenticatorTest.php b/Tests/Security/FrontApiClientAuthenticatorTest.php
index 6ee8a4e..c57bf6d 100644
--- a/Tests/Security/FrontApiClientAuthenticatorTest.php
+++ b/Tests/Security/FrontApiClientAuthenticatorTest.php
@@ -4,15 +4,15 @@ namespace RetailCrm\ServiceBundle\Tests\Security;
use PHPUnit\Framework\TestCase;
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
-use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
use RetailCrm\ServiceBundle\Tests\DataFixtures\User;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
-use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* Class FrontApiClientAuthenticatorTest
@@ -45,11 +45,11 @@ class FrontApiClientAuthenticatorTest extends TestCase
$security = $this->createMock(Security::class);
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
- $result = $auth->getCredentials(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
+ $result = $auth->getCredentials(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123']));
static::assertEquals('123', $result);
- $result = $auth->getCredentials(new Request([CallbackClientAuthenticator::AUTH_FIELD => '123']));
+ $result = $auth->getCredentials(new Request([FrontApiClientAuthenticator::AUTH_FIELD => '123']));
static::assertEquals('123', $result);
}
@@ -120,4 +120,37 @@ class FrontApiClientAuthenticatorTest extends TestCase
static::assertTrue($result);
}
+
+ public function testGetUser(): void
+ {
+ $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
+ $security = $this->createMock(Security::class);
+
+ $user = new User();
+ $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
+
+ $userProvider = $this->createMock(UserProviderInterface::class);
+ $userProvider
+ ->expects(static::once())
+ ->method('loadUserByUsername')
+ ->with('clientId')
+ ->willReturn($user)
+ ;
+
+ $result = $auth->getUser('clientId', $userProvider);
+ static::assertEquals($user, $result);
+ }
+
+ public function testOnAuthenticationSuccess(): void
+ {
+ $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
+ $security = $this->createMock(Security::class);
+ $request = $this->createMock(Request::class);
+ $token = $this->createMock(TokenInterface::class);
+ $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
+
+ $result = $auth->onAuthenticationSuccess($request, $token, 'key');
+
+ static::assertNull($result);
+ }
}
diff --git a/composer.json b/composer.json
index cdfb4a4..c90c1ab 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,11 @@
"symfony/serializer": "^5.2",
"symfony/http-kernel": "^4.0|^5.0",
"symfony/validator": "^4.0|^5.0",
- "symfony/security-guard": "^4.0|^5.0"
+ "symfony/security-guard": "^4.0|^5.0",
+ "symfony/console": "^5.2",
+ "symfony/messenger": "^5.2",
+ "symfony/process": "^5.2",
+ "symfony/event-dispatcher": "^5.2"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index ada38ee..56d86c0 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -10,6 +10,9 @@
stopOnFailure="false"
bootstrap="vendor/autoload.php"
>
+
+
+
./