diff --git a/CHANGELOG.md b/CHANGELOG.md index 99614a6e..f8d58fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this Non-error responses are not affected. * [#1513](https://github.com/shlinkio/shlink/issues/1513) Added publishing of the docker image in GHCR. +* [#1114](https://github.com/shlinkio/shlink/issues/1114) Added support to provide an initial API key via `INITIAL_API_KEY` env var, when running Shlink with openswoole or RoadRunner. + + Also, the installer tool now allows to generate an initial API key that can be copy-pasted (this tool is run interactively), in case you use php-fpm or you don't want to use env vars. ### Changed * [#1339](https://github.com/shlinkio/shlink/issues/1339) Added new test suite for CLI E2E tests. diff --git a/composer.json b/composer.json index a9b60f12..a5bc5b62 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "shlinkio/shlink-config": "dev-main#33004e6 as 2.1", "shlinkio/shlink-event-dispatcher": "dev-main#48c0137 as 2.6", "shlinkio/shlink-importer": "^4.0", - "shlinkio/shlink-installer": "dev-develop#f1cc5c7 as 8.2", + "shlinkio/shlink-installer": "dev-develop#a01bca9 as 8.2", "shlinkio/shlink-ip-geolocation": "^3.0", "spiral/roadrunner": "^2.11", "spiral/roadrunner-jobs": "^2.3", @@ -92,6 +92,7 @@ "ShlinkioCliTest\\Shlink\\CLI\\": "module/CLI/test-cli", "ShlinkioTest\\Shlink\\Rest\\": "module/Rest/test", "ShlinkioApiTest\\Shlink\\Rest\\": "module/Rest/test-api", + "ShlinkioDbTest\\Shlink\\Rest\\": "module/Rest/test-db", "ShlinkioTest\\Shlink\\Core\\": "module/Core/test", "ShlinkioDbTest\\Shlink\\Core\\": "module/Core/test-db" }, diff --git a/config/autoload/common.global.php b/config/autoload/common.global.php index b35807fd..19404d8c 100644 --- a/config/autoload/common.global.php +++ b/config/autoload/common.global.php @@ -8,8 +8,8 @@ return [ 'debug' => false, - // Disabling config cache for cli, ensures it's never used for openswoole and also that console commands don't - // generate a cache file that's then used by non-openswoole web executions + // Disabling config cache for cli, ensures it's never used for openswoole/RoadRunner, and also that console + // commands don't generate a cache file that's then used by php-fpm web executions ConfigAggregator::ENABLE_CACHE => PHP_SAPI !== 'cli', ]; diff --git a/config/autoload/installer.global.php b/config/autoload/installer.global.php index 40c2f4bd..fbc5fa03 100644 --- a/config/autoload/installer.global.php +++ b/config/autoload/installer.global.php @@ -82,6 +82,9 @@ return [ InstallationCommand::GEOLITE_DOWNLOAD_DB->value => [ 'command' => 'bin/cli ' . Command\Visit\DownloadGeoLiteDbCommand::NAME, ], + InstallationCommand::API_KEY_GENERATE->value => [ + 'command' => 'bin/cli ' . Command\Api\GenerateKeyCommand::NAME, + ], ], ], diff --git a/module/CLI/test/Command/Api/DisableKeyCommandTest.php b/module/CLI/test/Command/Api/DisableKeyCommandTest.php index 90942dc9..41a4f982 100644 --- a/module/CLI/test/Command/Api/DisableKeyCommandTest.php +++ b/module/CLI/test/Command/Api/DisableKeyCommandTest.php @@ -19,7 +19,7 @@ class DisableKeyCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $apiKeyService; - public function setUp(): void + protected function setUp(): void { $this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class); $this->commandTester = $this->testerForCommand(new DisableKeyCommand($this->apiKeyService->reveal())); diff --git a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php index e5c543d5..6db8581b 100644 --- a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php +++ b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php @@ -23,7 +23,7 @@ class GenerateKeyCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $apiKeyService; - public function setUp(): void + protected function setUp(): void { $this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class); $roleResolver = $this->prophesize(RoleResolverInterface::class); diff --git a/module/CLI/test/Command/Api/ListKeysCommandTest.php b/module/CLI/test/Command/Api/ListKeysCommandTest.php index 68c1e844..7122f392 100644 --- a/module/CLI/test/Command/Api/ListKeysCommandTest.php +++ b/module/CLI/test/Command/Api/ListKeysCommandTest.php @@ -23,7 +23,7 @@ class ListKeysCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $apiKeyService; - public function setUp(): void + protected function setUp(): void { $this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class); $this->commandTester = $this->testerForCommand(new ListKeysCommand($this->apiKeyService->reveal())); diff --git a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php index 93e07d4d..f500775a 100644 --- a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php +++ b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php @@ -33,7 +33,7 @@ class CreateDatabaseCommandTest extends TestCase private ObjectProphecy $schemaManager; private ObjectProphecy $driver; - public function setUp(): void + protected function setUp(): void { $locker = $this->prophesize(LockFactory::class); $lock = $this->prophesize(LockInterface::class); diff --git a/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php b/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php index d301f55e..1a8dfb0e 100644 --- a/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php +++ b/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php @@ -23,7 +23,7 @@ class MigrateDatabaseCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $processHelper; - public function setUp(): void + protected function setUp(): void { $locker = $this->prophesize(LockFactory::class); $lock = $this->prophesize(LockInterface::class); diff --git a/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php b/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php index 6b6e1036..afcce551 100644 --- a/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php +++ b/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php @@ -24,7 +24,7 @@ class DomainRedirectsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $domainService; - public function setUp(): void + protected function setUp(): void { $this->domainService = $this->prophesize(DomainServiceInterface::class); $this->commandTester = $this->testerForCommand(new DomainRedirectsCommand($this->domainService->reveal())); diff --git a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php index 6d56ea69..adaa1d00 100644 --- a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php +++ b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php @@ -23,7 +23,7 @@ class ListDomainsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $domainService; - public function setUp(): void + protected function setUp(): void { $this->domainService = $this->prophesize(DomainServiceInterface::class); $this->commandTester = $this->testerForCommand(new ListDomainsCommand($this->domainService->reveal())); diff --git a/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php index 73d2b785..e529f0ad 100644 --- a/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/CreateShortUrlCommandTest.php @@ -30,7 +30,7 @@ class CreateShortUrlCommandTest extends TestCase private ObjectProphecy $urlShortener; private ObjectProphecy $stringifier; - public function setUp(): void + protected function setUp(): void { $this->urlShortener = $this->prophesize(UrlShortener::class); $this->stringifier = $this->prophesize(ShortUrlStringifierInterface::class); diff --git a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php index 947b7443..80d4878c 100644 --- a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php @@ -26,7 +26,7 @@ class DeleteShortUrlCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $service; - public function setUp(): void + protected function setUp(): void { $this->service = $this->prophesize(DeleteShortUrlServiceInterface::class); $this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service->reveal())); diff --git a/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php b/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php index 316c762e..644a0b8f 100644 --- a/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php @@ -33,7 +33,7 @@ class GetShortUrlVisitsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $visitsHelper; - public function setUp(): void + protected function setUp(): void { $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); $command = new GetShortUrlVisitsCommand($this->visitsHelper->reveal()); diff --git a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php index f9d701cb..51b02799 100644 --- a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php @@ -33,7 +33,7 @@ class ListShortUrlsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $shortUrlService; - public function setUp(): void + protected function setUp(): void { $this->shortUrlService = $this->prophesize(ShortUrlServiceInterface::class); $command = new ListShortUrlsCommand($this->shortUrlService->reveal(), new ShortUrlDataTransformer( diff --git a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php index 12e29eaf..24974692 100644 --- a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php @@ -25,7 +25,7 @@ class ResolveUrlCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $urlResolver; - public function setUp(): void + protected function setUp(): void { $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class); $this->commandTester = $this->testerForCommand(new ResolveUrlCommand($this->urlResolver->reveal())); diff --git a/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php b/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php index 46f61814..b03bf1ee 100644 --- a/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php +++ b/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php @@ -18,7 +18,7 @@ class DeleteTagsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->commandTester = $this->testerForCommand(new DeleteTagsCommand($this->tagService->reveal())); diff --git a/module/CLI/test/Command/Tag/ListTagsCommandTest.php b/module/CLI/test/Command/Tag/ListTagsCommandTest.php index 499442d0..58ae1ef1 100644 --- a/module/CLI/test/Command/Tag/ListTagsCommandTest.php +++ b/module/CLI/test/Command/Tag/ListTagsCommandTest.php @@ -22,7 +22,7 @@ class ListTagsCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->commandTester = $this->testerForCommand(new ListTagsCommand($this->tagService->reveal())); diff --git a/module/CLI/test/Command/Tag/RenameTagCommandTest.php b/module/CLI/test/Command/Tag/RenameTagCommandTest.php index 3a52aba3..4d647fe7 100644 --- a/module/CLI/test/Command/Tag/RenameTagCommandTest.php +++ b/module/CLI/test/Command/Tag/RenameTagCommandTest.php @@ -21,7 +21,7 @@ class RenameTagCommandTest extends TestCase private CommandTester $commandTester; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->commandTester = $this->testerForCommand(new RenameTagCommand($this->tagService->reveal())); diff --git a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php index fa666516..4111c1dc 100644 --- a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php @@ -40,7 +40,7 @@ class LocateVisitsCommandTest extends TestCase private ObjectProphecy $lock; private ObjectProphecy $downloadDbCommand; - public function setUp(): void + protected function setUp(): void { $this->visitService = $this->prophesize(VisitLocator::class); $this->ipResolver = $this->prophesize(IpLocationResolverInterface::class); diff --git a/module/CLI/test/ConfigProviderTest.php b/module/CLI/test/ConfigProviderTest.php index 863b8a1f..f01649e0 100644 --- a/module/CLI/test/ConfigProviderTest.php +++ b/module/CLI/test/ConfigProviderTest.php @@ -12,7 +12,7 @@ class ConfigProviderTest extends TestCase { private ConfigProvider $configProvider; - public function setUp(): void + protected function setUp(): void { $this->configProvider = new ConfigProvider(); } diff --git a/module/CLI/test/Factory/ApplicationFactoryTest.php b/module/CLI/test/Factory/ApplicationFactoryTest.php index fbb5ace9..cb08a692 100644 --- a/module/CLI/test/Factory/ApplicationFactoryTest.php +++ b/module/CLI/test/Factory/ApplicationFactoryTest.php @@ -16,7 +16,7 @@ class ApplicationFactoryTest extends TestCase private ApplicationFactory $factory; - public function setUp(): void + protected function setUp(): void { $this->factory = new ApplicationFactory(); } diff --git a/module/CLI/test/Util/GeolocationDbUpdaterTest.php b/module/CLI/test/Util/GeolocationDbUpdaterTest.php index c5e3bdb4..fde39775 100644 --- a/module/CLI/test/Util/GeolocationDbUpdaterTest.php +++ b/module/CLI/test/Util/GeolocationDbUpdaterTest.php @@ -32,7 +32,7 @@ class GeolocationDbUpdaterTest extends TestCase private TrackingOptions $trackingOptions; private ObjectProphecy $lock; - public function setUp(): void + protected function setUp(): void { $this->dbUpdater = $this->prophesize(DbUpdaterInterface::class); $this->geoLiteDbReader = $this->prophesize(Reader::class); diff --git a/module/CLI/test/Util/ShlinkTableTest.php b/module/CLI/test/Util/ShlinkTableTest.php index 1ca612d4..ffe1f30d 100644 --- a/module/CLI/test/Util/ShlinkTableTest.php +++ b/module/CLI/test/Util/ShlinkTableTest.php @@ -21,7 +21,7 @@ class ShlinkTableTest extends TestCase private ShlinkTable $shlinkTable; private ObjectProphecy $baseTable; - public function setUp(): void + protected function setUp(): void { $this->baseTable = $this->prophesize(Table::class); $this->shlinkTable = ShlinkTable::fromBaseTable($this->baseTable->reveal()); diff --git a/module/Core/src/Config/EnvVars.php b/module/Core/src/Config/EnvVars.php index 7cbd0af4..228a5921 100644 --- a/module/Core/src/Config/EnvVars.php +++ b/module/Core/src/Config/EnvVars.php @@ -47,6 +47,7 @@ enum EnvVars: string case PORT = 'PORT'; case TASK_WORKER_NUM = 'TASK_WORKER_NUM'; case WEB_WORKER_NUM = 'WEB_WORKER_NUM'; + case INITIAL_API_KEY = 'INITIAL_API_KEY'; case ANONYMIZE_REMOTE_ADDR = 'ANONYMIZE_REMOTE_ADDR'; case TRACK_ORPHAN_VISITS = 'TRACK_ORPHAN_VISITS'; case DISABLE_TRACK_PARAM = 'DISABLE_TRACK_PARAM'; diff --git a/module/Core/src/Repository/TagRepository.php b/module/Core/src/Repository/TagRepository.php index 2c4e8db6..946cee7e 100644 --- a/module/Core/src/Repository/TagRepository.php +++ b/module/Core/src/Repository/TagRepository.php @@ -110,7 +110,7 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito return map( $this->getEntityManager()->createNativeQuery($nativeQb->getSQL(), $rsm)->getResult(), - static fn (array $row) => new TagInfo($row['tag'], (int) $row['shortUrlsCount'], (int) $row['visitsCount']), + TagInfo::fromRawData(...), ); } diff --git a/module/Core/src/Tag/Model/TagInfo.php b/module/Core/src/Tag/Model/TagInfo.php index 8a4f196b..5e71ea5b 100644 --- a/module/Core/src/Tag/Model/TagInfo.php +++ b/module/Core/src/Tag/Model/TagInfo.php @@ -15,6 +15,11 @@ final class TagInfo implements JsonSerializable ) { } + public static function fromRawData(array $data): self + { + return new self($data['tag'], (int) $data['shortUrlsCount'], (int) $data['visitsCount']); + } + public function jsonSerialize(): array { return [ diff --git a/module/Core/src/Tag/Model/TagsParams.php b/module/Core/src/Tag/Model/TagsParams.php index 633fd5f2..3b1d84b2 100644 --- a/module/Core/src/Tag/Model/TagsParams.php +++ b/module/Core/src/Tag/Model/TagsParams.php @@ -14,6 +14,7 @@ final class TagsParams extends AbstractInfinitePaginableListParams private function __construct( public readonly ?string $searchTerm, public readonly Ordering $orderBy, + /** @deprecated */ public readonly bool $withStats, ?int $page, ?int $itemsPerPage, diff --git a/module/Core/test/Action/PixelActionTest.php b/module/Core/test/Action/PixelActionTest.php index fdd291a5..2972d4fd 100644 --- a/module/Core/test/Action/PixelActionTest.php +++ b/module/Core/test/Action/PixelActionTest.php @@ -25,7 +25,7 @@ class PixelActionTest extends TestCase private ObjectProphecy $urlResolver; private ObjectProphecy $requestTracker; - public function setUp(): void + protected function setUp(): void { $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class); $this->requestTracker = $this->prophesize(RequestTrackerInterface::class); diff --git a/module/Core/test/Action/QrCodeActionTest.php b/module/Core/test/Action/QrCodeActionTest.php index fb9e4e6a..1962fdc7 100644 --- a/module/Core/test/Action/QrCodeActionTest.php +++ b/module/Core/test/Action/QrCodeActionTest.php @@ -39,7 +39,7 @@ class QrCodeActionTest extends TestCase private ObjectProphecy $urlResolver; private QrCodeOptions $options; - public function setUp(): void + protected function setUp(): void { $router = $this->prophesize(RouterInterface::class); $router->generateUri(Argument::cetera())->willReturn('/foo/bar'); diff --git a/module/Core/test/Action/RedirectActionTest.php b/module/Core/test/Action/RedirectActionTest.php index cde2b9aa..aa2c9d07 100644 --- a/module/Core/test/Action/RedirectActionTest.php +++ b/module/Core/test/Action/RedirectActionTest.php @@ -31,7 +31,7 @@ class RedirectActionTest extends TestCase private ObjectProphecy $requestTracker; private ObjectProphecy $redirectRespHelper; - public function setUp(): void + protected function setUp(): void { $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class); $this->requestTracker = $this->prophesize(RequestTrackerInterface::class); diff --git a/module/Core/test/Config/BasePathPrefixerTest.php b/module/Core/test/Config/BasePathPrefixerTest.php index 36b038c8..2298a59c 100644 --- a/module/Core/test/Config/BasePathPrefixerTest.php +++ b/module/Core/test/Config/BasePathPrefixerTest.php @@ -11,7 +11,7 @@ class BasePathPrefixerTest extends TestCase { private BasePathPrefixer $prefixer; - public function setUp(): void + protected function setUp(): void { $this->prefixer = new BasePathPrefixer(); } diff --git a/module/Core/test/ConfigProviderTest.php b/module/Core/test/ConfigProviderTest.php index 33714f88..3bb0dbb4 100644 --- a/module/Core/test/ConfigProviderTest.php +++ b/module/Core/test/ConfigProviderTest.php @@ -12,7 +12,7 @@ class ConfigProviderTest extends TestCase { private ConfigProvider $configProvider; - public function setUp(): void + protected function setUp(): void { $this->configProvider = new ConfigProvider(); } diff --git a/module/Core/test/Domain/DomainServiceTest.php b/module/Core/test/Domain/DomainServiceTest.php index ea3cfe02..43a052ae 100644 --- a/module/Core/test/Domain/DomainServiceTest.php +++ b/module/Core/test/Domain/DomainServiceTest.php @@ -27,7 +27,7 @@ class DomainServiceTest extends TestCase private DomainService $domainService; private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->domainService = new DomainService($this->em->reveal(), 'default.com'); diff --git a/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php b/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php index 70063764..d40fce56 100644 --- a/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php +++ b/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php @@ -31,7 +31,7 @@ class NotFoundRedirectHandlerTest extends TestCase private ObjectProphecy $next; private ServerRequestInterface $req; - public function setUp(): void + protected function setUp(): void { $this->redirectOptions = new NotFoundRedirectOptions(); $this->resolver = $this->prophesize(NotFoundRedirectResolverInterface::class); diff --git a/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php b/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php index dcf42b54..12865171 100644 --- a/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php +++ b/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php @@ -21,7 +21,7 @@ class NotFoundTemplateHandlerTest extends TestCase private NotFoundTemplateHandler $handler; private bool $readFileCalled; - public function setUp(): void + protected function setUp(): void { $this->readFileCalled = false; $readFile = function (string $fileName): string { diff --git a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php index c928200e..b826802b 100644 --- a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php +++ b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php @@ -18,7 +18,7 @@ class CloseDbConnectionEventListenerDelegatorTest extends TestCase private CloseDbConnectionEventListenerDelegator $delegator; private ObjectProphecy $container; - public function setUp(): void + protected function setUp(): void { $this->container = $this->prophesize(ContainerInterface::class); $this->delegator = new CloseDbConnectionEventListenerDelegator(); diff --git a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php index d0c7c374..7c4d74c8 100644 --- a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php +++ b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php @@ -20,7 +20,7 @@ class CloseDbConnectionEventListenerTest extends TestCase private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(ReopeningEntityManagerInterface::class); } diff --git a/module/Core/test/EventDispatcher/LocateVisitTest.php b/module/Core/test/EventDispatcher/LocateVisitTest.php index 09a8086d..5cf243d0 100644 --- a/module/Core/test/EventDispatcher/LocateVisitTest.php +++ b/module/Core/test/EventDispatcher/LocateVisitTest.php @@ -36,7 +36,7 @@ class LocateVisitTest extends TestCase private ObjectProphecy $dbUpdater; private ObjectProphecy $eventDispatcher; - public function setUp(): void + protected function setUp(): void { $this->ipLocationResolver = $this->prophesize(IpLocationResolverInterface::class); $this->em = $this->prophesize(EntityManagerInterface::class); diff --git a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php index 1ce29d0d..0d8d9cfa 100644 --- a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php +++ b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php @@ -31,7 +31,7 @@ class NotifyVisitToMercureTest extends TestCase private ObjectProphecy $em; private ObjectProphecy $logger; - public function setUp(): void + protected function setUp(): void { $this->helper = $this->prophesize(PublishingHelperInterface::class); $this->updatesGenerator = $this->prophesize(PublishingUpdatesGeneratorInterface::class); diff --git a/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php b/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php index 56324e40..6be8719a 100644 --- a/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php +++ b/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php @@ -38,7 +38,7 @@ class NotifyVisitToWebHooksTest extends TestCase private ObjectProphecy $em; private ObjectProphecy $logger; - public function setUp(): void + protected function setUp(): void { $this->httpClient = $this->prophesize(ClientInterface::class); $this->em = $this->prophesize(EntityManagerInterface::class); diff --git a/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php b/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php index e4b616e8..5638b0fe 100644 --- a/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php +++ b/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php @@ -21,7 +21,7 @@ class PublishingUpdatesGeneratorTest extends TestCase { private PublishingUpdatesGenerator $generator; - public function setUp(): void + protected function setUp(): void { $this->generator = new PublishingUpdatesGenerator( new ShortUrlDataTransformer(new ShortUrlStringifier([])), diff --git a/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php b/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php index cd4d6193..391d52fd 100644 --- a/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php +++ b/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php @@ -31,7 +31,7 @@ class DeleteShortUrlServiceTest extends TestCase private ObjectProphecy $urlResolver; private string $shortCode; - public function setUp(): void + protected function setUp(): void { $shortUrl = ShortUrl::createEmpty()->setVisits(new ArrayCollection( map(range(0, 10), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())), diff --git a/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php b/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php index bdccfa3f..d2c3bda5 100644 --- a/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php +++ b/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php @@ -32,7 +32,7 @@ class ShortUrlResolverTest extends TestCase private ShortUrlResolver $urlResolver; private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->urlResolver = new ShortUrlResolver($this->em->reveal()); diff --git a/module/Core/test/Service/ShortUrlServiceTest.php b/module/Core/test/Service/ShortUrlServiceTest.php index 90000423..a042dd1f 100644 --- a/module/Core/test/Service/ShortUrlServiceTest.php +++ b/module/Core/test/Service/ShortUrlServiceTest.php @@ -34,7 +34,7 @@ class ShortUrlServiceTest extends TestCase private ObjectProphecy $urlResolver; private ObjectProphecy $titleResolutionHelper; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->em->persist(Argument::any())->willReturn(null); diff --git a/module/Core/test/Service/UrlShortenerTest.php b/module/Core/test/Service/UrlShortenerTest.php index fbe9b1c4..86a057e5 100644 --- a/module/Core/test/Service/UrlShortenerTest.php +++ b/module/Core/test/Service/UrlShortenerTest.php @@ -30,7 +30,7 @@ class UrlShortenerTest extends TestCase private ObjectProphecy $shortCodeHelper; private ObjectProphecy $eventDispatcher; - public function setUp(): void + protected function setUp(): void { $this->titleResolutionHelper = $this->prophesize(ShortUrlTitleResolutionHelperInterface::class); $this->titleResolutionHelper->processTitleAndValidateUrl(Argument::cetera())->willReturnArgument(); diff --git a/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php b/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php index 2675b04a..2abc08c3 100644 --- a/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php +++ b/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php @@ -22,7 +22,7 @@ class ShortUrlRepositoryAdapterTest extends TestCase private ObjectProphecy $repo; - public function setUp(): void + protected function setUp(): void { $this->repo = $this->prophesize(ShortUrlRepositoryInterface::class); } diff --git a/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php b/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php index 9aaf9495..39bb1b3f 100644 --- a/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php +++ b/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php @@ -25,7 +25,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase private PersistenceShortUrlRelationResolver $resolver; private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->em->getEventManager()->willReturn(new EventManager()); diff --git a/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php b/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php index 483cb67a..669fdd6e 100644 --- a/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php +++ b/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php @@ -13,7 +13,7 @@ class SimpleShortUrlRelationResolverTest extends TestCase { private SimpleShortUrlRelationResolver $resolver; - public function setUp(): void + protected function setUp(): void { $this->resolver = new SimpleShortUrlRelationResolver(); } diff --git a/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php b/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php index 81c0d203..b48cd839 100644 --- a/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php +++ b/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php @@ -17,7 +17,7 @@ class ShortUrlDataTransformerTest extends TestCase { private ShortUrlDataTransformer $transformer; - public function setUp(): void + protected function setUp(): void { $this->transformer = new ShortUrlDataTransformer(new ShortUrlStringifier([])); } diff --git a/module/Core/test/Tag/TagServiceTest.php b/module/Core/test/Tag/TagServiceTest.php index 8c301f0f..d3e1b841 100644 --- a/module/Core/test/Tag/TagServiceTest.php +++ b/module/Core/test/Tag/TagServiceTest.php @@ -33,7 +33,7 @@ class TagServiceTest extends TestCase private ObjectProphecy $em; private ObjectProphecy $repo; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->repo = $this->prophesize(TagRepository::class); diff --git a/module/Core/test/Util/UrlValidatorTest.php b/module/Core/test/Util/UrlValidatorTest.php index 8aba6598..de5cad23 100644 --- a/module/Core/test/Util/UrlValidatorTest.php +++ b/module/Core/test/Util/UrlValidatorTest.php @@ -27,7 +27,7 @@ class UrlValidatorTest extends TestCase private ObjectProphecy $httpClient; private UrlShortenerOptions $options; - public function setUp(): void + protected function setUp(): void { $this->httpClient = $this->prophesize(ClientInterface::class); $this->options = new UrlShortenerOptions(['validate_url' => true]); diff --git a/module/Core/test/Visit/VisitLocatorTest.php b/module/Core/test/Visit/VisitLocatorTest.php index 5c51b848..b740d143 100644 --- a/module/Core/test/Visit/VisitLocatorTest.php +++ b/module/Core/test/Visit/VisitLocatorTest.php @@ -38,7 +38,7 @@ class VisitLocatorTest extends TestCase private ObjectProphecy $em; private ObjectProphecy $repo; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManager::class); $this->repo = $this->prophesize(VisitRepositoryInterface::class); diff --git a/module/Core/test/Visit/VisitsStatsHelperTest.php b/module/Core/test/Visit/VisitsStatsHelperTest.php index 42c821bb..47288cb3 100644 --- a/module/Core/test/Visit/VisitsStatsHelperTest.php +++ b/module/Core/test/Visit/VisitsStatsHelperTest.php @@ -43,7 +43,7 @@ class VisitsStatsHelperTest extends TestCase private VisitsStatsHelper $helper; private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManagerInterface::class); $this->helper = new VisitsStatsHelper($this->em->reveal()); diff --git a/module/Core/test/Visit/VisitsTrackerTest.php b/module/Core/test/Visit/VisitsTrackerTest.php index 904f92d1..2bb13220 100644 --- a/module/Core/test/Visit/VisitsTrackerTest.php +++ b/module/Core/test/Visit/VisitsTrackerTest.php @@ -26,7 +26,7 @@ class VisitsTrackerTest extends TestCase private ObjectProphecy $eventDispatcher; private TrackingOptions $options; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManager::class); diff --git a/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php b/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php index 63716e74..1e0b041b 100644 --- a/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php +++ b/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php @@ -15,7 +15,8 @@ use function Shlinkio\Shlink\Core\determineTableName; return static function (ClassMetadata $metadata, array $emConfig): void { $builder = new ClassMetadataBuilder($metadata); - $builder->setTable(determineTableName('api_keys', $emConfig)); + $builder->setTable(determineTableName('api_keys', $emConfig)) + ->setCustomRepositoryClass(ApiKey\Repository\ApiKeyRepository::class); $builder->createField('id', Types::BIGINT) ->makePrimaryKey() diff --git a/module/Rest/config/initial-api-key.config.php b/module/Rest/config/initial-api-key.config.php new file mode 100644 index 00000000..a44f877f --- /dev/null +++ b/module/Rest/config/initial-api-key.config.php @@ -0,0 +1,26 @@ + PHP_SAPI !== 'cli' ? null : EnvVars::INITIAL_API_KEY->loadFromEnv(), + + 'dependencies' => [ + 'delegators' => [ + Application::class => [ + ApiKey\InitialApiKeyDelegator::class, + ], + ], + ], + +]; diff --git a/module/Rest/src/ApiKey/InitialApiKeyDelegator.php b/module/Rest/src/ApiKey/InitialApiKeyDelegator.php new file mode 100644 index 00000000..9129d7d3 --- /dev/null +++ b/module/Rest/src/ApiKey/InitialApiKeyDelegator.php @@ -0,0 +1,31 @@ +get('config')['initial_api_key'] ?? null; + if ($initialApiKey !== null) { + $this->createInitialApiKey($initialApiKey, $container); + } + + return $callback(); + } + + private function createInitialApiKey(string $initialApiKey, ContainerInterface $container): void + { + /** @var ApiKeyRepositoryInterface $repo */ + $repo = $container->get(EntityManager::class)->getRepository(ApiKey::class); + $repo->createInitialApiKey($initialApiKey); + } +} diff --git a/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php b/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php new file mode 100644 index 00000000..ec49145e --- /dev/null +++ b/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php @@ -0,0 +1,32 @@ +getEntityManager(); + $em->wrapInTransaction(function () use ($apiKey, $em): void { + // Ideally this would be a SELECT COUNT(...), but MsSQL and Postgres do not allow locking on aggregates + // Because of that we check if at least one result exists + $firstResult = $em->createQueryBuilder()->select('a.id') + ->from(ApiKey::class, 'a') + ->setMaxResults(1) + ->getQuery() + ->setLockMode(LockMode::PESSIMISTIC_WRITE) + ->getOneOrNullResult(); + + if ($firstResult === null) { + $em->persist(ApiKey::fromKey($apiKey)); + $em->flush(); + } + }); + } +} diff --git a/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php new file mode 100644 index 00000000..f5beb3e9 --- /dev/null +++ b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php @@ -0,0 +1,16 @@ +key = Uuid::uuid4()->toString(); - $this->expirationDate = $expirationDate; - $this->name = $name; + $this->key = $key ?? Uuid::uuid4()->toString(); $this->enabled = true; $this->roles = new ArrayCollection(); } @@ -44,7 +42,10 @@ class ApiKey extends AbstractEntity public static function fromMeta(ApiKeyMeta $meta): self { - $apiKey = new self($meta->name, $meta->expirationDate); + $apiKey = self::create(); + $apiKey->name = $meta->name; + $apiKey->expirationDate = $meta->expirationDate; + foreach ($meta->roleDefinitions as $roleDefinition) { $apiKey->registerRole($roleDefinition); } @@ -52,6 +53,11 @@ class ApiKey extends AbstractEntity return $apiKey; } + public static function fromKey(string $key): self + { + return new self($key); + } + public function getExpirationDate(): ?Chronos { return $this->expirationDate; diff --git a/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php b/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php new file mode 100644 index 00000000..ae6ab0a0 --- /dev/null +++ b/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php @@ -0,0 +1,31 @@ +repo = $this->getEntityManager()->getRepository(ApiKey::class); + } + + /** @test */ + public function initialApiKeyIsCreatedOnlyOfNoApiKeysExistYet(): void + { + self::assertCount(0, $this->repo->findAll()); + $this->repo->createInitialApiKey('initial_value'); + self::assertCount(1, $this->repo->findAll()); + self::assertCount(1, $this->repo->findBy(['key' => 'initial_value'])); + $this->repo->createInitialApiKey('another_one'); + self::assertCount(1, $this->repo->findAll()); + self::assertCount(0, $this->repo->findBy(['key' => 'another_one'])); + } +} diff --git a/module/Rest/test/Action/Domain/ListDomainsActionTest.php b/module/Rest/test/Action/Domain/ListDomainsActionTest.php index bc852b34..a6903b46 100644 --- a/module/Rest/test/Action/Domain/ListDomainsActionTest.php +++ b/module/Rest/test/Action/Domain/ListDomainsActionTest.php @@ -25,7 +25,7 @@ class ListDomainsActionTest extends TestCase private ObjectProphecy $domainService; private NotFoundRedirectOptions $options; - public function setUp(): void + protected function setUp(): void { $this->domainService = $this->prophesize(DomainServiceInterface::class); $this->options = new NotFoundRedirectOptions(); diff --git a/module/Rest/test/Action/HealthActionTest.php b/module/Rest/test/Action/HealthActionTest.php index a233087a..8298b2d1 100644 --- a/module/Rest/test/Action/HealthActionTest.php +++ b/module/Rest/test/Action/HealthActionTest.php @@ -25,7 +25,7 @@ class HealthActionTest extends TestCase private HealthAction $action; private ObjectProphecy $conn; - public function setUp(): void + protected function setUp(): void { $this->conn = $this->prophesize(Connection::class); $this->conn->executeQuery(Argument::cetera())->willReturn($this->prophesize(Result::class)->reveal()); diff --git a/module/Rest/test/Action/MercureInfoActionTest.php b/module/Rest/test/Action/MercureInfoActionTest.php index 33083c79..e586a641 100644 --- a/module/Rest/test/Action/MercureInfoActionTest.php +++ b/module/Rest/test/Action/MercureInfoActionTest.php @@ -21,7 +21,7 @@ class MercureInfoActionTest extends TestCase private ObjectProphecy $provider; - public function setUp(): void + protected function setUp(): void { $this->provider = $this->prophesize(JwtProviderInterface::class); } diff --git a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php index 206b016f..eb0d8622 100644 --- a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php @@ -29,7 +29,7 @@ class CreateShortUrlActionTest extends TestCase private ObjectProphecy $urlShortener; private ObjectProphecy $transformer; - public function setUp(): void + protected function setUp(): void { $this->urlShortener = $this->prophesize(UrlShortener::class); $this->transformer = $this->prophesize(DataTransformerInterface::class); diff --git a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php index 9705cd59..ae49cf4b 100644 --- a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php @@ -20,7 +20,7 @@ class DeleteShortUrlActionTest extends TestCase private DeleteShortUrlAction $action; private ObjectProphecy $service; - public function setUp(): void + protected function setUp(): void { $this->service = $this->prophesize(DeleteShortUrlServiceInterface::class); $this->action = new DeleteShortUrlAction($this->service->reveal()); diff --git a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php index e1f434df..4d09042d 100644 --- a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php @@ -24,7 +24,7 @@ class EditShortUrlActionTest extends TestCase private EditShortUrlAction $action; private ObjectProphecy $shortUrlService; - public function setUp(): void + protected function setUp(): void { $this->shortUrlService = $this->prophesize(ShortUrlServiceInterface::class); $this->action = new EditShortUrlAction($this->shortUrlService->reveal(), new ShortUrlDataTransformer( diff --git a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php index 59876b55..8b295358 100644 --- a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php @@ -26,7 +26,7 @@ class ListShortUrlsActionTest extends TestCase private ListShortUrlsAction $action; private ObjectProphecy $service; - public function setUp(): void + protected function setUp(): void { $this->service = $this->prophesize(ShortUrlService::class); diff --git a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php index 19422d9d..78898f7a 100644 --- a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php @@ -23,7 +23,7 @@ class ResolveShortUrlActionTest extends TestCase private ResolveShortUrlAction $action; private ObjectProphecy $urlResolver; - public function setUp(): void + protected function setUp(): void { $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class); $this->action = new ResolveShortUrlAction($this->urlResolver->reveal(), new ShortUrlDataTransformer( diff --git a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php index e3fd3e10..f62a5da6 100644 --- a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php @@ -25,7 +25,7 @@ class SingleStepCreateShortUrlActionTest extends TestCase private ObjectProphecy $urlShortener; private ObjectProphecy $transformer; - public function setUp(): void + protected function setUp(): void { $this->urlShortener = $this->prophesize(UrlShortenerInterface::class); $this->transformer = $this->prophesize(DataTransformerInterface::class); diff --git a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php index 4812649d..457507e8 100644 --- a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php +++ b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php @@ -20,7 +20,7 @@ class DeleteTagsActionTest extends TestCase private DeleteTagsAction $action; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->action = new DeleteTagsAction($this->tagService->reveal()); diff --git a/module/Rest/test/Action/Tag/ListTagsActionTest.php b/module/Rest/test/Action/Tag/ListTagsActionTest.php index 123e4945..3da8594c 100644 --- a/module/Rest/test/Action/Tag/ListTagsActionTest.php +++ b/module/Rest/test/Action/Tag/ListTagsActionTest.php @@ -28,7 +28,7 @@ class ListTagsActionTest extends TestCase private ListTagsAction $action; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->action = new ListTagsAction($this->tagService->reveal()); diff --git a/module/Rest/test/Action/Tag/TagsStatsActionTest.php b/module/Rest/test/Action/Tag/TagsStatsActionTest.php index 2cb3ad64..44e6afb0 100644 --- a/module/Rest/test/Action/Tag/TagsStatsActionTest.php +++ b/module/Rest/test/Action/Tag/TagsStatsActionTest.php @@ -27,7 +27,7 @@ class TagsStatsActionTest extends TestCase private TagsStatsAction $action; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->action = new TagsStatsAction($this->tagService->reveal()); diff --git a/module/Rest/test/Action/Tag/UpdateTagActionTest.php b/module/Rest/test/Action/Tag/UpdateTagActionTest.php index d7b398db..a3bce658 100644 --- a/module/Rest/test/Action/Tag/UpdateTagActionTest.php +++ b/module/Rest/test/Action/Tag/UpdateTagActionTest.php @@ -24,7 +24,7 @@ class UpdateTagActionTest extends TestCase private UpdateTagAction $action; private ObjectProphecy $tagService; - public function setUp(): void + protected function setUp(): void { $this->tagService = $this->prophesize(TagServiceInterface::class); $this->action = new UpdateTagAction($this->tagService->reveal()); diff --git a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php index 829b820b..d5f94250 100644 --- a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php @@ -21,7 +21,7 @@ class GlobalVisitsActionTest extends TestCase private GlobalVisitsAction $action; private ObjectProphecy $helper; - public function setUp(): void + protected function setUp(): void { $this->helper = $this->prophesize(VisitsStatsHelperInterface::class); $this->action = new GlobalVisitsAction($this->helper->reveal()); diff --git a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php index 5b3487f0..60224bef 100644 --- a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php @@ -24,7 +24,7 @@ class NonOrphanVisitsActionTest extends TestCase private NonOrphanVisitsAction $action; private ObjectProphecy $visitsHelper; - public function setUp(): void + protected function setUp(): void { $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); $this->action = new NonOrphanVisitsAction($this->visitsHelper->reveal()); diff --git a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php index 299c42d1..d9f248e6 100644 --- a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php @@ -27,7 +27,7 @@ class ShortUrlVisitsActionTest extends TestCase private ShortUrlVisitsAction $action; private ObjectProphecy $visitsHelper; - public function setUp(): void + protected function setUp(): void { $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); $this->action = new ShortUrlVisitsAction($this->visitsHelper->reveal()); diff --git a/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php new file mode 100644 index 00000000..7614fc9d --- /dev/null +++ b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php @@ -0,0 +1,61 @@ +delegator = new InitialApiKeyDelegator(); + $this->container = $this->prophesize(ContainerInterface::class); + } + + /** + * @test + * @dataProvider provideConfigs + */ + public function apiKeyIsInitializedWhenAppropriate(array $config, int $expectedCalls): void + { + $app = $this->prophesize(Application::class)->reveal(); + $apiKeyRepo = $this->prophesize(ApiKeyRepositoryInterface::class); + $em = $this->prophesize(EntityManagerInterface::class); + + $getConfig = $this->container->get('config')->willReturn($config); + $getRepo = $em->getRepository(ApiKey::class)->willReturn($apiKeyRepo->reveal()); + $getEm = $this->container->get(EntityManager::class)->willReturn($em->reveal()); + + $result = ($this->delegator)($this->container->reveal(), '', fn () => $app); + + self::assertSame($result, $app); + $getConfig->shouldHaveBeenCalledOnce(); + $getRepo->shouldHaveBeenCalledTimes($expectedCalls); + $getEm->shouldHaveBeenCalledTimes($expectedCalls); + $apiKeyRepo->createInitialApiKey(Argument::any())->shouldHaveBeenCalledTimes($expectedCalls); + } + + public function provideConfigs(): iterable + { + yield [[], 0]; + yield [['initial_api_key' => null], 0]; + yield [['initial_api_key' => 'the_initial_key'], 1]; + } +} diff --git a/module/Rest/test/ConfigProviderTest.php b/module/Rest/test/ConfigProviderTest.php index d3288151..1f7044f9 100644 --- a/module/Rest/test/ConfigProviderTest.php +++ b/module/Rest/test/ConfigProviderTest.php @@ -12,7 +12,7 @@ class ConfigProviderTest extends TestCase { private ConfigProvider $configProvider; - public function setUp(): void + protected function setUp(): void { $this->configProvider = new ConfigProvider(); } @@ -22,10 +22,11 @@ class ConfigProviderTest extends TestCase { $config = ($this->configProvider)(); - self::assertCount(4, $config); + self::assertCount(5, $config); self::assertArrayHasKey('dependencies', $config); self::assertArrayHasKey('auth', $config); self::assertArrayHasKey('entity_manager', $config); + self::assertArrayHasKey('initial_api_key', $config); self::assertArrayHasKey(ConfigAbstractFactory::class, $config); } diff --git a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php index c915098a..eef78ab7 100644 --- a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php +++ b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php @@ -35,7 +35,7 @@ class AuthenticationMiddlewareTest extends TestCase private ObjectProphecy $apiKeyService; private ObjectProphecy $handler; - public function setUp(): void + protected function setUp(): void { $this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class); $this->middleware = new AuthenticationMiddleware( diff --git a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php index 04c9478d..f254197e 100644 --- a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php +++ b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php @@ -23,7 +23,7 @@ class BodyParserMiddlewareTest extends TestCase private BodyParserMiddleware $middleware; - public function setUp(): void + protected function setUp(): void { $this->middleware = new BodyParserMiddleware(); } diff --git a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php index acdc9600..286652bf 100644 --- a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php @@ -20,7 +20,7 @@ class CrossDomainMiddlewareTest extends TestCase private CrossDomainMiddleware $middleware; private ObjectProphecy $handler; - public function setUp(): void + protected function setUp(): void { $this->middleware = new CrossDomainMiddleware(['max_age' => 1000]); $this->handler = $this->prophesize(RequestHandlerInterface::class); diff --git a/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php b/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php index 4928f2ef..b2093461 100644 --- a/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php +++ b/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php @@ -15,7 +15,7 @@ class EmptyResponseImplicitOptionsMiddlewareFactoryTest extends TestCase { private EmptyResponseImplicitOptionsMiddlewareFactory $factory; - public function setUp(): void + protected function setUp(): void { $this->factory = new EmptyResponseImplicitOptionsMiddlewareFactory(); } diff --git a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php index dc4733ff..b77d79a9 100644 --- a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php @@ -22,7 +22,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase private CreateShortUrlContentNegotiationMiddleware $middleware; private ObjectProphecy $requestHandler; - public function setUp(): void + protected function setUp(): void { $this->middleware = new CreateShortUrlContentNegotiationMiddleware(); $this->requestHandler = $this->prophesize(RequestHandlerInterface::class); diff --git a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php index e10e9f73..2aef77b7 100644 --- a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php @@ -23,7 +23,7 @@ class DefaultShortCodesLengthMiddlewareTest extends TestCase private DefaultShortCodesLengthMiddleware $middleware; private ObjectProphecy $handler; - public function setUp(): void + protected function setUp(): void { $this->handler = $this->prophesize(RequestHandlerInterface::class); $this->middleware = new DefaultShortCodesLengthMiddleware(8); diff --git a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php index 24f3aecd..9418a16a 100644 --- a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php @@ -22,7 +22,7 @@ class DropDefaultDomainFromRequestMiddlewareTest extends TestCase private DropDefaultDomainFromRequestMiddleware $middleware; private ObjectProphecy $next; - public function setUp(): void + protected function setUp(): void { $this->next = $this->prophesize(RequestHandlerInterface::class); $this->middleware = new DropDefaultDomainFromRequestMiddleware('doma.in'); diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index aba79036..f384a45a 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -25,7 +25,7 @@ class ApiKeyServiceTest extends TestCase private ApiKeyService $service; private ObjectProphecy $em; - public function setUp(): void + protected function setUp(): void { $this->em = $this->prophesize(EntityManager::class); $this->service = new ApiKeyService($this->em->reveal());