add authenticators, tests
This commit is contained in:
parent
22e03941b9
commit
b6c6dfac2d
17 changed files with 851 additions and 5 deletions
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace RetailCrm\ServiceBundle\ArgumentResolver;
|
||||
|
||||
use RetailCrm\ServiceBundle\Exceptions\InvalidRequestArgumentException;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class AbstractValueResolver
|
||||
{
|
||||
|
@ -21,7 +21,11 @@ abstract class AbstractValueResolver
|
|||
{
|
||||
$errors = $this->validator->validate($data);
|
||||
if (0 !== count($errors)) {
|
||||
throw new InvalidArgumentException($errors);
|
||||
throw new InvalidRequestArgumentException(
|
||||
sprintf("Invalid request parameter %s", \get_class($data)),
|
||||
400,
|
||||
$errors
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,10 +49,16 @@ class CallbackValueResolver extends AbstractValueResolver implements ArgumentVal
|
|||
yield $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ArgumentMetadata $argument
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function search(Request $request, ArgumentMetadata $argument): ?string
|
||||
{
|
||||
foreach ($this->requestSchema as $callback) {
|
||||
if (!$argument->getName() === $callback['type']) {
|
||||
if ($argument->getType() !== $callback['type']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
80
ArgumentResolver/ClientValueResolver.php
Normal file
80
ArgumentResolver/ClientValueResolver.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Generator;
|
||||
|
||||
class ClientValueResolver extends AbstractValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
private $serializer;
|
||||
private $denormalizer;
|
||||
private $requestSchema;
|
||||
|
||||
public function __construct(
|
||||
ValidatorInterface $validator,
|
||||
SerializerInterface $serializer,
|
||||
DenormalizerInterface $denormalizer,
|
||||
array $requestSchema
|
||||
) {
|
||||
parent::__construct($validator);
|
||||
|
||||
$this->serializer = $serializer;
|
||||
$this->denormalizer = $denormalizer;
|
||||
$this->requestSchema = $requestSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
return in_array($argument->getType(), $this->requestSchema, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): Generator
|
||||
{
|
||||
if (Request::METHOD_GET === $request->getMethod()) {
|
||||
$dto = $this->handleGetData($request->query->all(), $argument->getType());
|
||||
} else {
|
||||
$dto = $this->handlePostData($request->getContent(), $argument->getType());
|
||||
}
|
||||
|
||||
$this->validate($dto);
|
||||
|
||||
yield $dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $type
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
private function handleGetData(array $data, string $type): object
|
||||
{
|
||||
return $this->denormalizer->denormalize($data, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @param string $type
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
private function handlePostData(string $data, string $type): object
|
||||
{
|
||||
return $this->serializer->deserialize($data, $type, 'json');
|
||||
}
|
||||
}
|
|
@ -3,6 +3,10 @@
|
|||
namespace RetailCrm\ServiceBundle\DependencyInjection;
|
||||
|
||||
use RetailCrm\ServiceBundle\ArgumentResolver\CallbackValueResolver;
|
||||
use RetailCrm\ServiceBundle\ArgumentResolver\ClientValueResolver;
|
||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
||||
use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
|
||||
use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
|
||||
|
@ -32,5 +36,23 @@ class RetailCrmServiceExtension extends Extension
|
|||
->setArgument('$requestSchema', '%retail_crm_service.request_schema.callback%')
|
||||
->addTag('controller.argument_value_resolver', ['priority' => 50])
|
||||
->setAutowired(true);
|
||||
|
||||
$container
|
||||
->register(ClientValueResolver::class)
|
||||
->setArgument('$requestSchema', '%retail_crm_service.request_schema.client%')
|
||||
->addTag('controller.argument_value_resolver', ['priority' => 50])
|
||||
->setAutowired(true);
|
||||
|
||||
$container
|
||||
->register(ErrorJsonResponseFactory::class)
|
||||
->setAutowired(true);
|
||||
|
||||
$container
|
||||
->register(CallbackClientAuthenticator::class)
|
||||
->setAutowired(true);
|
||||
|
||||
$container
|
||||
->register(FrontApiClientAuthenticator::class)
|
||||
->setAutowired(true);
|
||||
}
|
||||
}
|
||||
|
|
35
Exceptions/InvalidRequestArgumentException.php
Normal file
35
Exceptions/InvalidRequestArgumentException.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Exceptions;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class InvalidRequestArgumentException
|
||||
*
|
||||
* @package RetailCrm\ServiceBundle\Exceptions
|
||||
*/
|
||||
class InvalidRequestArgumentException extends InvalidArgumentException
|
||||
{
|
||||
private $validateErrors;
|
||||
|
||||
/**
|
||||
* InvalidRequestArgumentException constructor.
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param array $errors
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, iterable $errors = [], Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
|
||||
$this->validateErrors = $errors;
|
||||
}
|
||||
|
||||
public function getValidateErrors(): iterable
|
||||
{
|
||||
return $this->validateErrors;
|
||||
}
|
||||
}
|
21
Models/Error.php
Normal file
21
Models/Error.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Models;
|
||||
|
||||
class Error
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $details;
|
||||
}
|
27
Response/ErrorJsonResponseFactory.php
Normal file
27
Response/ErrorJsonResponseFactory.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Response;
|
||||
|
||||
use RetailCrm\ServiceBundle\Models\Error;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
class ErrorJsonResponseFactory
|
||||
{
|
||||
private $serializer;
|
||||
|
||||
public function __construct(SerializerInterface $serializer)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
public function create(Error $error, int $statusCode = Response::HTTP_BAD_REQUEST, array $headers = []): Response
|
||||
{
|
||||
return JsonResponse::fromJsonString(
|
||||
$this->serializer->serialize($error, 'json'),
|
||||
$statusCode,
|
||||
$headers
|
||||
);
|
||||
}
|
||||
}
|
61
Security/AbstractClientAuthenticator.php
Normal file
61
Security/AbstractClientAuthenticator.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Security;
|
||||
|
||||
use RetailCrm\ServiceBundle\Models\Error;
|
||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
||||
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;
|
||||
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
|
||||
|
||||
abstract class AbstractClientAuthenticator extends AbstractGuardAuthenticator
|
||||
{
|
||||
public const AUTH_FIELD = 'clientId';
|
||||
|
||||
private $errorResponseFactory;
|
||||
|
||||
public function __construct(ErrorJsonResponseFactory $errorResponseFactory)
|
||||
{
|
||||
$this->errorResponseFactory = $errorResponseFactory;
|
||||
}
|
||||
|
||||
public function start(Request $request, AuthenticationException $authException = null): Response
|
||||
{
|
||||
$error = new Error();
|
||||
$error->message = 'Authentication required';
|
||||
|
||||
return $this->errorResponseFactory->create($error,Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
public function getCredentials(Request $request): string
|
||||
{
|
||||
return $request->get(static::AUTH_FIELD);
|
||||
}
|
||||
|
||||
public function getUser($credentials, UserProviderInterface $userProvider): ?UserInterface
|
||||
{
|
||||
return $userProvider->loadUserByUsername($credentials);
|
||||
}
|
||||
|
||||
public function checkCredentials($credentials, UserInterface $user): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
$error = new Error();
|
||||
$error->message = $exception->getMessageKey();
|
||||
|
||||
return $this->errorResponseFactory->create($error,Response::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): ?Response
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
18
Security/CallbackClientAuthenticator.php
Normal file
18
Security/CallbackClientAuthenticator.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Security;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class CallbackClientAuthenticator extends AbstractClientAuthenticator
|
||||
{
|
||||
public function supports(Request $request): bool
|
||||
{
|
||||
return $request->request->has(static::AUTH_FIELD) || $request->query->has(static::AUTH_FIELD);
|
||||
}
|
||||
|
||||
public function supportsRememberMe(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
35
Security/FrontApiClientAuthenticator.php
Normal file
35
Security/FrontApiClientAuthenticator.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Security;
|
||||
|
||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class FrontApiClientAuthenticator extends AbstractClientAuthenticator
|
||||
{
|
||||
private $security;
|
||||
|
||||
public function __construct(
|
||||
ErrorJsonResponseFactory $errorResponseFactory,
|
||||
Security $security
|
||||
) {
|
||||
parent::__construct($errorResponseFactory);
|
||||
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function supports(Request $request): bool
|
||||
{
|
||||
if ($this->security->getUser()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function supportsRememberMe(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
108
Tests/ArgumentResolver/CallbackValueResolverTest.php
Normal file
108
Tests/ArgumentResolver/CallbackValueResolverTest.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Tests\ArgumentResolver;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RetailCrm\ServiceBundle\ArgumentResolver\CallbackValueResolver;
|
||||
use RetailCrm\ServiceBundle\Exceptions\InvalidRequestArgumentException;
|
||||
use RetailCrm\ServiceBundle\Tests\DataFixtures\RequestDto;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validation;
|
||||
use Generator;
|
||||
|
||||
class CallbackValueResolverTest extends TestCase
|
||||
{
|
||||
private $resolver;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
|
||||
$this->resolver = new CallbackValueResolver(
|
||||
$serializer,
|
||||
Validation::createValidatorBuilder()
|
||||
->enableAnnotationMapping()
|
||||
->getValidator(),
|
||||
[
|
||||
[
|
||||
'type' => RequestDto::class,
|
||||
'params' => ['request_parameter']
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupports(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
['request_parameter' => json_encode(['param' => 'parameter'], JSON_THROW_ON_ERROR)],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST]
|
||||
);
|
||||
|
||||
$result = $this->resolver->supports($request, $argument);
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testNotSupports(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', 'NotFoundRequestDto', false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
['request_parameter' => json_encode(['param' => 'parameter'], JSON_THROW_ON_ERROR)],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST]
|
||||
);
|
||||
|
||||
$result = $this->resolver->supports($request, $argument);
|
||||
|
||||
static::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testResolve(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
['request_parameter' => json_encode(['param' => 'parameter'], JSON_THROW_ON_ERROR)],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST]
|
||||
);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
|
||||
static::assertInstanceOf(Generator::class, $result);
|
||||
static::assertInstanceOf(RequestDto::class, $result->current());
|
||||
static::assertEquals('parameter', $result->current()->param);
|
||||
}
|
||||
|
||||
public function testResolveFailure(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
['request_parameter' => json_encode(['param' => null], JSON_THROW_ON_ERROR)],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST]
|
||||
);
|
||||
|
||||
$this->expectException(InvalidRequestArgumentException::class);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
$result->current();
|
||||
}
|
||||
}
|
131
Tests/ArgumentResolver/ClientValueResolverTest.php
Normal file
131
Tests/ArgumentResolver/ClientValueResolverTest.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Tests\ArgumentResolver;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RetailCrm\ServiceBundle\ArgumentResolver\ClientValueResolver;
|
||||
use RetailCrm\ServiceBundle\Exceptions\InvalidRequestArgumentException;
|
||||
use RetailCrm\ServiceBundle\Tests\DataFixtures\RequestDto;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validation;
|
||||
use Generator;
|
||||
|
||||
class ClientValueResolverTest extends TestCase
|
||||
{
|
||||
private $resolver;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
|
||||
$this->resolver = new ClientValueResolver(
|
||||
Validation::createValidatorBuilder()
|
||||
->enableAnnotationMapping()
|
||||
->getValidator(),
|
||||
$serializer,
|
||||
$serializer,
|
||||
[
|
||||
RequestDto::class
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupports(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request();
|
||||
|
||||
$result = $this->resolver->supports($request, $argument);
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testNotSupports(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', 'NotFoundRequestDto', false, false, null);
|
||||
$request = new Request();
|
||||
|
||||
$result = $this->resolver->supports($request, $argument);
|
||||
|
||||
static::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testResolvePost(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST],
|
||||
json_encode(['param' => 'parameter'], JSON_THROW_ON_ERROR)
|
||||
);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
|
||||
static::assertInstanceOf(Generator::class, $result);
|
||||
static::assertInstanceOf(RequestDto::class, $result->current());
|
||||
static::assertEquals('parameter', $result->current()->param);
|
||||
}
|
||||
|
||||
public function testResolvePostFailure(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
['REQUEST_METHOD' => Request::METHOD_POST],
|
||||
json_encode(['param' => null], JSON_THROW_ON_ERROR)
|
||||
);
|
||||
|
||||
$this->expectException(InvalidRequestArgumentException::class);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
$result->current();
|
||||
}
|
||||
|
||||
public function testResolveGet(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
['param' => 'parameter'],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
|
||||
static::assertInstanceOf(Generator::class, $result);
|
||||
static::assertInstanceOf(RequestDto::class, $result->current());
|
||||
static::assertEquals('parameter', $result->current()->param);
|
||||
}
|
||||
|
||||
public function testResolveGetFailure(): void
|
||||
{
|
||||
$argument = new ArgumentMetadata('RequestDto', RequestDto::class, false, false, null);
|
||||
$request = new Request(
|
||||
['param' => null],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
$this->expectException(InvalidRequestArgumentException::class);
|
||||
|
||||
$result = $this->resolver->resolve($request, $argument);
|
||||
$result->current();
|
||||
}
|
||||
}
|
14
Tests/DataFixtures/RequestDto.php
Normal file
14
Tests/DataFixtures/RequestDto.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Tests\DataFixtures;
|
||||
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class RequestDto
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
public $param;
|
||||
}
|
32
Tests/DataFixtures/User.php
Normal file
32
Tests/DataFixtures/User.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Tests\DataFixtures;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class User implements UserInterface
|
||||
{
|
||||
public function getRoles(): array
|
||||
{
|
||||
return ["USER"];
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
return "123";
|
||||
}
|
||||
|
||||
public function getSalt(): string
|
||||
{
|
||||
return "salt";
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
{
|
||||
return "user";
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
}
|
||||
}
|
130
Tests/Security/CallbackClientAuthenticatorTest.php
Normal file
130
Tests/Security/CallbackClientAuthenticatorTest.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace RetailCrm\ServiceBundle\Tests\Security;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory;
|
||||
use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class CallbackClientAuthenticatorTest extends TestCase
|
||||
{
|
||||
public function testStart(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$errorResponseFactory
|
||||
->expects(static::once())
|
||||
->method('create')
|
||||
->willReturn(
|
||||
new JsonResponse(['message' => 'Authentication required'], Response::HTTP_UNAUTHORIZED)
|
||||
);
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->start(new Request(), new AuthenticationException());
|
||||
|
||||
static::assertInstanceOf(JsonResponse::class, $result);
|
||||
static::assertEquals(Response::HTTP_UNAUTHORIZED, $result->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetCredentials(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->getCredentials(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertEquals('123', $result);
|
||||
|
||||
$result = $auth->getCredentials(new Request([CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertEquals('123', $result);
|
||||
}
|
||||
|
||||
public function testCheckCredentials(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
|
||||
$user = new class implements UserInterface {
|
||||
public function getRoles(): array
|
||||
{
|
||||
return ["USER"];
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
return "123";
|
||||
}
|
||||
|
||||
public function getSalt(): string
|
||||
{
|
||||
return "salt";
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
{
|
||||
return "user";
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->checkCredentials(new Request(), $user);
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testOnAuthenticationFailure(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$errorResponseFactory
|
||||
->expects(static::once())
|
||||
->method('create')
|
||||
->willReturn(
|
||||
new JsonResponse(
|
||||
['message' => 'An authentication exception occurred.'],
|
||||
Response::HTTP_FORBIDDEN
|
||||
)
|
||||
);
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->start(new Request(), new AuthenticationException());
|
||||
|
||||
static::assertInstanceOf(JsonResponse::class, $result);
|
||||
static::assertEquals(Response::HTTP_FORBIDDEN, $result->getStatusCode());
|
||||
}
|
||||
|
||||
public function testSupports(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->supports(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertTrue($result);
|
||||
|
||||
$result = $auth->supports(new Request([CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertTrue($result);
|
||||
|
||||
$result = $auth->supports(new Request());
|
||||
|
||||
static::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testSupportsRememberMe(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
|
||||
$auth = new CallbackClientAuthenticator($errorResponseFactory);
|
||||
$result = $auth->supportsRememberMe();
|
||||
|
||||
static::assertFalse($result);
|
||||
}
|
||||
}
|
118
Tests/Security/FrontApiClientAuthenticatorTest.php
Normal file
118
Tests/Security/FrontApiClientAuthenticatorTest.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
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\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class FrontApiClientAuthenticatorTest extends TestCase
|
||||
{
|
||||
public function testStart(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$errorResponseFactory
|
||||
->expects(static::once())
|
||||
->method('create')
|
||||
->willReturn(
|
||||
new JsonResponse(['message' => 'Authentication required'], Response::HTTP_UNAUTHORIZED)
|
||||
);
|
||||
$security = $this->createMock(Security::class);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->start(new Request(), new AuthenticationException());
|
||||
|
||||
static::assertInstanceOf(JsonResponse::class, $result);
|
||||
static::assertEquals(Response::HTTP_UNAUTHORIZED, $result->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGetCredentials(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$security = $this->createMock(Security::class);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->getCredentials(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertEquals('123', $result);
|
||||
|
||||
$result = $auth->getCredentials(new Request([CallbackClientAuthenticator::AUTH_FIELD => '123']));
|
||||
|
||||
static::assertEquals('123', $result);
|
||||
}
|
||||
|
||||
public function testCheckCredentials(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$security = $this->createMock(Security::class);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->checkCredentials(new Request(), new User());
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testOnAuthenticationFailure(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$errorResponseFactory
|
||||
->expects(static::once())
|
||||
->method('create')
|
||||
->willReturn(
|
||||
new JsonResponse(
|
||||
['message' => 'An authentication exception occurred.'],
|
||||
Response::HTTP_FORBIDDEN
|
||||
)
|
||||
);
|
||||
$security = $this->createMock(Security::class);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->start(new Request(), new AuthenticationException());
|
||||
|
||||
static::assertInstanceOf(JsonResponse::class, $result);
|
||||
static::assertEquals(Response::HTTP_FORBIDDEN, $result->getStatusCode());
|
||||
}
|
||||
|
||||
public function testSupportsFalse(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->method('getUser')->willReturn(new User());
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->supports(new Request());
|
||||
|
||||
static::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testSupportsTrue(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->method('getUser')->willReturn(null);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->supports(new Request());
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testSupportsRememberMe(): void
|
||||
{
|
||||
$errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class);
|
||||
$security = $this->createMock(Security::class);
|
||||
|
||||
$auth = new FrontApiClientAuthenticator($errorResponseFactory, $security);
|
||||
$result = $auth->supportsRememberMe();
|
||||
|
||||
static::assertTrue($result);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,8 @@
|
|||
"symfony/framework-bundle": "^4.0|^5.0",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/http-kernel": "^4.0|^5.0",
|
||||
"symfony/validator": "^4.0|^5.0"
|
||||
"symfony/validator": "^4.0|^5.0",
|
||||
"symfony/security-guard": "^4.0|^5.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -31,7 +32,10 @@
|
|||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0 || ^9.0"
|
||||
"ext-json": "*",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"doctrine/annotations": "^1.11",
|
||||
"doctrine/cache": "^1.10"
|
||||
},
|
||||
"scripts": {
|
||||
"tests": "./vendor/bin/phpunit -c phpunit.xml.dist"
|
||||
|
|
Loading…
Add table
Reference in a new issue