diff --git a/Security/AbstractClientAuthenticator.php b/Security/AbstractClientAuthenticator.php index 386ac03..4aaafb8 100644 --- a/Security/AbstractClientAuthenticator.php +++ b/Security/AbstractClientAuthenticator.php @@ -22,19 +22,10 @@ abstract class AbstractClientAuthenticator extends AbstractAuthenticator $this->errorResponseFactory = $errorResponseFactory; } - /** - * {@inheritdoc } - */ abstract public function supports(Request $request): ?bool; - /** - * {@inheritdoc } - */ abstract public function authenticate(Request $request): Passport; - /** - * {@inheritdoc } - */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response { $error = new Error(); @@ -43,9 +34,6 @@ abstract class AbstractClientAuthenticator extends AbstractAuthenticator return $this->errorResponseFactory->create($error,Response::HTTP_FORBIDDEN); } - /** - * {@inheritdoc } - */ public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): ?Response { return null; diff --git a/Security/CallbackClientAuthenticator.php b/Security/CallbackClientAuthenticator.php index 1fc51bb..ece82be 100644 --- a/Security/CallbackClientAuthenticator.php +++ b/Security/CallbackClientAuthenticator.php @@ -2,37 +2,38 @@ namespace RetailCrm\ServiceBundle\Security; +use Doctrine\Persistence\ObjectRepository; +use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; +use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; class CallbackClientAuthenticator extends AbstractClientAuthenticator { - /** - * {@inheritdoc } - */ + public function __construct( + ErrorJsonResponseFactory $errorResponseFactory, + private ObjectRepository $repository, + ) { + parent::__construct($errorResponseFactory); + } + public function supports(Request $request): bool { return $request->request->has(static::AUTH_FIELD) || $request->query->has(static::AUTH_FIELD); } - /** - * {@inheritdoc } - */ - public function supportsRememberMe(): bool - { - return false; - } - - /** - * {@inheritdoc } - */ public function authenticate(Request $request): Passport { $identifier = $request->request->get(static::AUTH_FIELD); + if (null === $identifier) { + throw new AuthenticationException('Request does not contain authentication data'); + } return new SelfValidatingPassport( new UserBadge($identifier, function ($userIdentifier) { - return $this->repository->findByIdentifier($userIdentifier); + return $this->repository->findOneBy([static::AUTH_FIELD => $userIdentifier]); }), [] ); diff --git a/Security/FrontApiClientAuthenticator.php b/Security/FrontApiClientAuthenticator.php index c707f1a..a2a2e67 100644 --- a/Security/FrontApiClientAuthenticator.php +++ b/Security/FrontApiClientAuthenticator.php @@ -2,9 +2,10 @@ namespace RetailCrm\ServiceBundle\Security; -use App\Repository\ConnectionRepository; +use Doctrine\Persistence\ObjectRepository; use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; @@ -13,23 +14,14 @@ use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPasspor class FrontApiClientAuthenticator extends AbstractClientAuthenticator { - private $security; - private $repository; - public function __construct( ErrorJsonResponseFactory $errorResponseFactory, - Security $security, - ConnectionRepository $repository + private Security $security, + private ObjectRepository $repository ) { parent::__construct($errorResponseFactory); - - $this->security = $security; - $this->repository = $repository; } - /** - * {@inheritdoc } - */ public function supports(Request $request): bool { if ($this->security->getUser()) { @@ -39,16 +31,16 @@ class FrontApiClientAuthenticator extends AbstractClientAuthenticator return $request->request->has(static::AUTH_FIELD); } - /** - * {@inheritdoc } - */ public function authenticate(Request $request): Passport { $identifier = $request->request->get(static::AUTH_FIELD); + if (null === $identifier) { + throw new AuthenticationException('Request does not contain authentication data'); + } return new SelfValidatingPassport( new UserBadge($identifier, function ($userIdentifier) { - return $this->repository->findByIdentifier($userIdentifier); + return $this->repository->findOneBy([static::AUTH_FIELD => $userIdentifier]); }), [new RememberMeBadge()] ); diff --git a/Tests/DataFixtures/User.php b/Tests/DataFixtures/User.php index 8951ea5..ad17192 100644 --- a/Tests/DataFixtures/User.php +++ b/Tests/DataFixtures/User.php @@ -4,11 +4,6 @@ namespace RetailCrm\ServiceBundle\Tests\DataFixtures; use Symfony\Component\Security\Core\User\UserInterface; -/** - * Class User - * - * @package RetailCrm\ServiceBundle\Tests\DataFixtures - */ class User implements UserInterface { public function getRoles(): array @@ -16,16 +11,6 @@ class User implements UserInterface return ["USER"]; } - public function getPassword(): string - { - return "123"; - } - - public function getSalt(): string - { - return "salt"; - } - public function getUsername(): string { return "user"; @@ -34,4 +19,9 @@ class User implements UserInterface public function eraseCredentials(): void { } + + public function getUserIdentifier(): string + { + return 'identifier'; + } } diff --git a/Tests/Security/CallbackClientAuthenticatorTest.php b/Tests/Security/CallbackClientAuthenticatorTest.php index bc2f532..a604a21 100644 --- a/Tests/Security/CallbackClientAuthenticatorTest.php +++ b/Tests/Security/CallbackClientAuthenticatorTest.php @@ -2,6 +2,7 @@ namespace RetailCrm\ServiceBundle\Tests\Security; +use Doctrine\Persistence\ObjectRepository; use PHPUnit\Framework\TestCase; use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory; use RetailCrm\ServiceBundle\Security\CallbackClientAuthenticator; @@ -11,83 +12,9 @@ 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 - * - * @package RetailCrm\ServiceBundle\Tests\Security - */ 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); @@ -101,7 +28,8 @@ class CallbackClientAuthenticatorTest extends TestCase ) ); - $auth = new CallbackClientAuthenticator($errorResponseFactory); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new CallbackClientAuthenticator($errorResponseFactory, $userRepository); $result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException()); static::assertInstanceOf(JsonResponse::class, $result); @@ -112,7 +40,8 @@ class CallbackClientAuthenticatorTest extends TestCase { $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); - $auth = new CallbackClientAuthenticator($errorResponseFactory); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new CallbackClientAuthenticator($errorResponseFactory, $userRepository); $result = $auth->supports(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123'])); static::assertTrue($result); @@ -126,32 +55,26 @@ class CallbackClientAuthenticatorTest extends TestCase static::assertFalse($result); } - public function testSupportsRememberMe(): void - { - $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); - - $auth = new CallbackClientAuthenticator($errorResponseFactory); - $result = $auth->supportsRememberMe(); - - static::assertFalse($result); - } - - public function testGetUser(): void + public function testAuthenticate(): void { $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); $user = new User(); - $auth = new CallbackClientAuthenticator($errorResponseFactory); - $userProvider = $this->createMock(UserProviderInterface::class); - $userProvider + $userRepository = $this->createMock(ObjectRepository::class); + $userRepository ->expects(static::once()) - ->method('loadUserByUsername') - ->with('clientId') + ->method('findOneBy') ->willReturn($user) ; - $result = $auth->getUser('clientId', $userProvider); - static::assertEquals($user, $result); + $auth = new CallbackClientAuthenticator($errorResponseFactory, $userRepository); + + $passport = $auth->authenticate(new Request([], [CallbackClientAuthenticator::AUTH_FIELD => '123'])); + $authUser = $passport->getUser(); + static::assertEquals($user, $authUser); + + $this->expectException(AuthenticationException::class); + $auth->authenticate(new Request()); } public function testOnAuthenticationSuccess(): void @@ -159,7 +82,8 @@ class CallbackClientAuthenticatorTest extends TestCase $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); $request = $this->createMock(Request::class); $token = $this->createMock(TokenInterface::class); - $auth = new CallbackClientAuthenticator($errorResponseFactory); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new CallbackClientAuthenticator($errorResponseFactory, $userRepository); $result = $auth->onAuthenticationSuccess($request, $token, 'key'); diff --git a/Tests/Security/FrontApiClientAuthenticatorTest.php b/Tests/Security/FrontApiClientAuthenticatorTest.php index c57bf6d..219fb6a 100644 --- a/Tests/Security/FrontApiClientAuthenticatorTest.php +++ b/Tests/Security/FrontApiClientAuthenticatorTest.php @@ -2,6 +2,7 @@ namespace RetailCrm\ServiceBundle\Tests\Security; +use Doctrine\Persistence\ObjectRepository; use PHPUnit\Framework\TestCase; use RetailCrm\ServiceBundle\Response\ErrorJsonResponseFactory; use RetailCrm\ServiceBundle\Security\FrontApiClientAuthenticator; @@ -12,59 +13,9 @@ 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\UserProviderInterface; -/** - * Class FrontApiClientAuthenticatorTest - * - * @package RetailCrm\ServiceBundle\Tests\Security - */ 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([], [FrontApiClientAuthenticator::AUTH_FIELD => '123'])); - - static::assertEquals('123', $result); - - $result = $auth->getCredentials(new Request([FrontApiClientAuthenticator::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); @@ -78,9 +29,9 @@ class FrontApiClientAuthenticatorTest extends TestCase ) ); $security = $this->createMock(Security::class); - - $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security); - $result = $auth->start(new Request(), new AuthenticationException()); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security, $userRepository); + $result = $auth->onAuthenticationFailure(new Request(), new AuthenticationException()); static::assertInstanceOf(JsonResponse::class, $result); static::assertEquals(Response::HTTP_FORBIDDEN, $result->getStatusCode()); @@ -91,8 +42,8 @@ class FrontApiClientAuthenticatorTest extends TestCase $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); $security = $this->createMock(Security::class); $security->method('getUser')->willReturn(new User()); - - $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security, $userRepository); $result = $auth->supports(new Request()); static::assertFalse($result); @@ -103,42 +54,34 @@ class FrontApiClientAuthenticatorTest extends TestCase $errorResponseFactory = $this->createMock(ErrorJsonResponseFactory::class); $security = $this->createMock(Security::class); $security->method('getUser')->willReturn(null); - - $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security, $userRepository); $result = $auth->supports(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123'])); 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); - } - - public function testGetUser(): void + public function testAuthenticate(): 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 + $userRepository = $this->createMock(ObjectRepository::class); + $userRepository ->expects(static::once()) - ->method('loadUserByUsername') - ->with('clientId') + ->method('findOneBy') + ->with([FrontApiClientAuthenticator::AUTH_FIELD => '123']) ->willReturn($user) ; + $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security, $userRepository); - $result = $auth->getUser('clientId', $userProvider); - static::assertEquals($user, $result); + $passport = $auth->authenticate(new Request([], [FrontApiClientAuthenticator::AUTH_FIELD => '123'])); + $authUser = $passport->getUser(); + static::assertEquals($user, $authUser); + + $this->expectException(AuthenticationException::class); + $auth->authenticate(new Request()); } public function testOnAuthenticationSuccess(): void @@ -147,7 +90,8 @@ class FrontApiClientAuthenticatorTest extends TestCase $security = $this->createMock(Security::class); $request = $this->createMock(Request::class); $token = $this->createMock(TokenInterface::class); - $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security); + $userRepository = $this->createMock(ObjectRepository::class); + $auth = new FrontApiClientAuthenticator($errorResponseFactory, $security, $userRepository); $result = $auth->onAuthenticationSuccess($request, $token, 'key');