diff --git a/CHANGELOG.md b/CHANGELOG.md index 02bf5734d..7de55fe63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - The daemon templates in the admin settings no longer prefill the HaRP shared key or HaProxy password. #1083 - HaRP receives the verb of each ExApp route, so HaRP 0.4.8 and newer check the HTTP method of a request as the ExApp proxy does. #1138 - The ExApp proxy accepts `HEAD` on routes that list `GET` and reads a route's verb as a list of methods, as HaRP does. #1144 +- The HaRP version check in the admin overview warns about HaRP older than 0.4.8, which checks the HTTP method of requests to ExApps. #1149 ### Fixed diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 4e8238ad1..fcdf7609d 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -46,7 +46,7 @@ class Application extends App implements IBootstrap { public const APP_ID = 'app_api'; public const TEST_DEPLOY_APPID = 'test-deploy'; public const TEST_DEPLOY_INFO_XML = 'https://raw.githubusercontent.com/nextcloud/test-deploy/main/appinfo/info.xml'; - public const MINIMUM_HARP_VERSION = '0.3.0'; + public const MINIMUM_HARP_VERSION = '0.4.8'; public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); diff --git a/lib/SetupChecks/HarpVersionCheck.php b/lib/SetupChecks/HarpVersionCheck.php index 424c3576a..9ff1dd551 100644 --- a/lib/SetupChecks/HarpVersionCheck.php +++ b/lib/SetupChecks/HarpVersionCheck.php @@ -91,12 +91,13 @@ private function fulfillsMinimumVersionRequirement(string $version): bool { } private function getHarpVersion(DaemonConfig $daemonConfig): ?string { - $cacheKey = $daemonConfig->getName() . '_' . (string)crc32(json_encode($daemonConfig)); + // With the minimum in the key, a version cached against an older minimum is asked again. + $cacheKey = $daemonConfig->getName() . '_' . (string)crc32(json_encode($daemonConfig)) . '_' . Application::MINIMUM_HARP_VERSION; $version = $this->cache?->get($cacheKey); if ($version === null) { $version = $this->harpService->getHarpVersion($daemonConfig); - $oneWeek = 60 * 60 * 24 * 7; - $this->cache?->set($cacheKey, $version, $oneWeek); + $ttl = $version !== null && $this->fulfillsMinimumVersionRequirement($version) ? 60 * 60 * 24 * 7 : 60 * 60; + $this->cache?->set($cacheKey, $version, $ttl); } return $version; } diff --git a/tests/php/SetupChecks/HarpVersionCheckTest.php b/tests/php/SetupChecks/HarpVersionCheckTest.php new file mode 100644 index 000000000..b8f20a53f --- /dev/null +++ b/tests/php/SetupChecks/HarpVersionCheckTest.php @@ -0,0 +1,63 @@ +createMock(IL10N::class); + $l10n->method('t')->willReturnCallback(fn (string $text, array $parameters = []) => vsprintf($text, $parameters)); + $daemonConfigService = $this->createMock(DaemonConfigService::class); + $daemonConfigService->method('getRegisteredDaemonConfigs')->willReturn([ + new DaemonConfig(['name' => 'harp_proxy', 'deploy_config' => ['harp' => ['exapp_direct' => false]]]), + ]); + $harpService = $this->createMock(HarpService::class); + $harpService->method('getHarpVersion')->willReturn($harpVersion); + $cache = $this->createMock(ICache::class); + $cache->method('get')->willReturn(null); + // The minimum is part of the key, so a version cached by an older AppAPI is not reused after an upgrade. + $cache->expects(self::once())->method('set')->with(self::stringEndsWith('_' . Application::MINIMUM_HARP_VERSION), $harpVersion, $expectedCacheTtl); + $cacheFactory = $this->createMock(ICacheFactory::class); + $cacheFactory->method('isAvailable')->willReturn(true); + $cacheFactory->method('createDistributed')->willReturn($cache); + + $check = new HarpVersionCheck($l10n, $this->createMock(LoggerInterface::class), $daemonConfigService, $harpService, $cacheFactory); + return $check->run(); + } + + public function testHarpWithoutRouteVerbChecksIsTooOld(): void { + $result = $this->runCheck('0.4.7', 60 * 60); + self::assertSame(SetupResult::WARNING, $result->getSeverity()); + self::assertStringContainsString('"0.4.7", which is too old. The minimum required version is "0.4.8"', $result->getDescription()); + } + + public function testUnreachableHarpIsReported(): void { + $result = $this->runCheck(null, 60 * 60); + self::assertSame(SetupResult::WARNING, $result->getSeverity()); + self::assertStringContainsString('Could not retrieve HaRP version from daemon "harp_proxy"', $result->getDescription()); + } + + public function testCurrentHarpPasses(): void { + $result = $this->runCheck('0.4.8', 60 * 60 * 24 * 7); + self::assertSame(SetupResult::SUCCESS, $result->getSeverity()); + } +}