diff --git a/module/Rest/config/dependencies.config.php b/module/Rest/config/dependencies.config.php index b69cf36d..df482a46 100644 --- a/module/Rest/config/dependencies.config.php +++ b/module/Rest/config/dependencies.config.php @@ -9,6 +9,7 @@ use Laminas\ServiceManager\Factory\InvokableFactory; use Mezzio\ProblemDetails\ProblemDetailsResponseFactory; use Mezzio\Router\Middleware\ImplicitOptionsMiddleware; use Psr\Log\LoggerInterface; +use Shlinkio\Shlink\Common\Doctrine\EntityRepositoryFactory; use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider; use Shlinkio\Shlink\Core\Config; use Shlinkio\Shlink\Core\Domain\DomainService; @@ -17,6 +18,7 @@ use Shlinkio\Shlink\Core\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer; use Shlinkio\Shlink\Core\Tag\TagService; use Shlinkio\Shlink\Core\Visit; +use Shlinkio\Shlink\Rest\ApiKey\Repository\ApiKeyRepository; use Shlinkio\Shlink\Rest\Service\ApiKeyService; return [ @@ -24,6 +26,7 @@ return [ 'dependencies' => [ 'factories' => [ ApiKeyService::class => ConfigAbstractFactory::class, + ApiKeyRepository::class => [EntityRepositoryFactory::class, Entity\ApiKey::class], Action\HealthAction::class => ConfigAbstractFactory::class, Action\MercureInfoAction::class => ConfigAbstractFactory::class, @@ -62,7 +65,7 @@ return [ ], ConfigAbstractFactory::class => [ - ApiKeyService::class => ['em'], + ApiKeyService::class => ['em', ApiKeyRepository::class], Action\HealthAction::class => ['em', Config\Options\AppOptions::class], Action\MercureInfoAction::class => [LcobucciJwtProvider::class, 'config.mercure'], diff --git a/module/Rest/src/Service/ApiKeyService.php b/module/Rest/src/Service/ApiKeyService.php index 66cb1b18..e1a2f57a 100644 --- a/module/Rest/src/Service/ApiKeyService.php +++ b/module/Rest/src/Service/ApiKeyService.php @@ -12,7 +12,7 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; readonly class ApiKeyService implements ApiKeyServiceInterface { - public function __construct(private EntityManagerInterface $em) + public function __construct(private EntityManagerInterface $em, private ApiKeyRepositoryInterface $repo) { } @@ -28,14 +28,12 @@ readonly class ApiKeyService implements ApiKeyServiceInterface public function createInitial(string $key): ApiKey|null { - /** @var ApiKeyRepositoryInterface $repo */ - $repo = $this->em->getRepository(ApiKey::class); - return $repo->createInitialApiKey($key); + return $this->repo->createInitialApiKey($key); } public function check(string $key): ApiKeyCheckResult { - $apiKey = $this->getByKey($key); + $apiKey = $this->findByKey($key); return new ApiKeyCheckResult($apiKey); } @@ -44,9 +42,7 @@ readonly class ApiKeyService implements ApiKeyServiceInterface */ public function disableByName(string $apiKeyName): ApiKey { - return $this->disableApiKey($this->em->getRepository(ApiKey::class)->findOneBy([ - 'name' => $apiKeyName, - ])); + return $this->disableApiKey($this->findByName($apiKeyName)); } /** @@ -54,7 +50,7 @@ readonly class ApiKeyService implements ApiKeyServiceInterface */ public function disableByKey(string $key): ApiKey { - return $this->disableApiKey($this->getByKey($key)); + return $this->disableApiKey($this->findByKey($key)); } private function disableApiKey(ApiKey|null $apiKey): ApiKey @@ -75,13 +71,16 @@ readonly class ApiKeyService implements ApiKeyServiceInterface public function listKeys(bool $enabledOnly = false): array { $conditions = $enabledOnly ? ['enabled' => true] : []; - return $this->em->getRepository(ApiKey::class)->findBy($conditions); + return $this->repo->findBy($conditions); } - private function getByKey(string $key): ApiKey|null + private function findByKey(string $key): ApiKey|null { - return $this->em->getRepository(ApiKey::class)->findOneBy([ - 'key' => ApiKey::hashKey($key), - ]); + return $this->repo->findOneBy(['key' => ApiKey::hashKey($key)]); + } + + private function findByName(string $name): ApiKey|null + { + return $this->repo->findOneBy(['name' => $name]); } } diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index ba57fec4..d3c62af2 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -14,7 +14,7 @@ use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; -use Shlinkio\Shlink\Rest\ApiKey\Repository\ApiKeyRepository; +use Shlinkio\Shlink\Rest\ApiKey\Repository\ApiKeyRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; use Shlinkio\Shlink\Rest\Service\ApiKeyService; @@ -24,13 +24,13 @@ class ApiKeyServiceTest extends TestCase { private ApiKeyService $service; private MockObject & EntityManager $em; - private MockObject & ApiKeyRepository $repo; + private MockObject & ApiKeyRepositoryInterface $repo; protected function setUp(): void { $this->em = $this->createMock(EntityManager::class); - $this->repo = $this->createMock(ApiKeyRepository::class); - $this->service = new ApiKeyService($this->em); + $this->repo = $this->createMock(ApiKeyRepositoryInterface::class); + $this->service = new ApiKeyService($this->em, $this->repo); } /** @@ -77,7 +77,6 @@ class ApiKeyServiceTest extends TestCase $this->repo->expects($this->once())->method('findOneBy')->with(['key' => ApiKey::hashKey('12345')])->willReturn( $invalidKey, ); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->check('12345'); @@ -102,7 +101,6 @@ class ApiKeyServiceTest extends TestCase $this->repo->expects($this->once())->method('findOneBy')->with(['key' => ApiKey::hashKey('12345')])->willReturn( $apiKey, ); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->check('12345'); @@ -114,7 +112,6 @@ class ApiKeyServiceTest extends TestCase public function disableThrowsExceptionWhenNoApiKeyIsFound(string $disableMethod, array $findOneByArg): void { $this->repo->expects($this->once())->method('findOneBy')->with($findOneByArg)->willReturn(null); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $this->expectException(InvalidArgumentException::class); @@ -126,7 +123,6 @@ class ApiKeyServiceTest extends TestCase { $key = ApiKey::create(); $this->repo->expects($this->once())->method('findOneBy')->with($findOneByArg)->willReturn($key); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $this->em->expects($this->once())->method('flush'); self::assertTrue($key->isEnabled()); @@ -147,7 +143,6 @@ class ApiKeyServiceTest extends TestCase $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; $this->repo->expects($this->once())->method('findBy')->with([])->willReturn($expectedApiKeys); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->listKeys(); @@ -160,7 +155,6 @@ class ApiKeyServiceTest extends TestCase $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; $this->repo->expects($this->once())->method('findBy')->with(['enabled' => true])->willReturn($expectedApiKeys); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->listKeys(enabledOnly: true); @@ -171,7 +165,6 @@ class ApiKeyServiceTest extends TestCase public function createInitialDelegatesToRepository(ApiKey|null $apiKey): void { $this->repo->expects($this->once())->method('createInitialApiKey')->with('the_key')->willReturn($apiKey); - $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->createInitial('the_key');