diff --git a/module/Core/src/Repository/EntityRepositoryInterface.php b/module/Core/src/Repository/EntityRepositoryInterface.php new file mode 100644 index 00000000..c6693c44 --- /dev/null +++ b/module/Core/src/Repository/EntityRepositoryInterface.php @@ -0,0 +1,20 @@ + + */ +interface EntityRepositoryInterface extends ObjectRepository +{ + /** + * @todo This should be part of ObjectRepository, so adding here until that interface defines it. + * EntityRepository already implements the method, so classes extending it won't have to add anything. + */ + public function count(array $criteria = []): int; +} diff --git a/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php index 04e55519..0f81dc10 100644 --- a/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php +++ b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php @@ -4,14 +4,14 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Rest\ApiKey\Repository; -use Doctrine\Persistence\ObjectRepository; use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface; +use Shlinkio\Shlink\Core\Repository\EntityRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; /** - * @extends ObjectRepository + * @extends EntityRepositoryInterface */ -interface ApiKeyRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface +interface ApiKeyRepositoryInterface extends EntityRepositoryInterface, EntitySpecificationRepositoryInterface { /** * Will create provided API key only if there's no API keys yet diff --git a/module/Rest/src/Service/ApiKeyService.php b/module/Rest/src/Service/ApiKeyService.php index e1a2f57a..4b786c6d 100644 --- a/module/Rest/src/Service/ApiKeyService.php +++ b/module/Rest/src/Service/ApiKeyService.php @@ -42,7 +42,7 @@ readonly class ApiKeyService implements ApiKeyServiceInterface */ public function disableByName(string $apiKeyName): ApiKey { - return $this->disableApiKey($this->findByName($apiKeyName)); + return $this->disableApiKey($this->repo->findOneBy(['name' => $apiKeyName])); } /** @@ -79,8 +79,11 @@ readonly class ApiKeyService implements ApiKeyServiceInterface return $this->repo->findOneBy(['key' => ApiKey::hashKey($key)]); } - private function findByName(string $name): ApiKey|null + /** + * @inheritDoc + */ + public function existsWithName(string $apiKeyName): bool { - return $this->repo->findOneBy(['name' => $name]); + return $this->repo->count(['name' => $apiKeyName]) > 0; } } diff --git a/module/Rest/src/Service/ApiKeyServiceInterface.php b/module/Rest/src/Service/ApiKeyServiceInterface.php index 1fefc5f4..73773fba 100644 --- a/module/Rest/src/Service/ApiKeyServiceInterface.php +++ b/module/Rest/src/Service/ApiKeyServiceInterface.php @@ -31,4 +31,9 @@ interface ApiKeyServiceInterface * @return ApiKey[] */ public function listKeys(bool $enabledOnly = false): array; + + /** + * Check if an API key exists for provided name + */ + public function existsWithName(string $apiKeyName): bool; } diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index d3c62af2..e304a651 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -8,6 +8,7 @@ use Cake\Chronos\Chronos; use Doctrine\ORM\EntityManager; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; @@ -176,4 +177,15 @@ class ApiKeyServiceTest extends TestCase yield 'first api key' => [ApiKey::create()]; yield 'existing api keys' => [null]; } + + #[Test] + #[TestWith([0, false])] + #[TestWith([1, true])] + #[TestWith([27, true])] + public function existsWithNameCountsEntriesInRepository(int $count, bool $expected): void + { + $name = 'the_key'; + $this->repo->expects($this->once())->method('count')->with(['name' => $name])->willReturn($count); + self::assertEquals($this->service->existsWithName($name), $expected); + } }