Skip to content

Commit 07c52c3

Browse files
Merge pull request #50407 from nextcloud/backport/50398/stable31
[stable31] fix: Correctly return app id and app version for `core` styles and images
2 parents 409bb9e + 99e76d7 commit 07c52c3

File tree

6 files changed

+148
-39
lines changed

6 files changed

+148
-39
lines changed

build/psalm-baseline.xml

-9
Original file line numberDiff line numberDiff line change
@@ -2576,15 +2576,6 @@
25762576
<code><![CDATA[$script]]></code>
25772577
</ParamNameMismatch>
25782578
</file>
2579-
<file src="lib/private/TemplateLayout.php">
2580-
<InvalidParamDefault>
2581-
<code><![CDATA[string]]></code>
2582-
<code><![CDATA[string]]></code>
2583-
</InvalidParamDefault>
2584-
<InvalidScalarArgument>
2585-
<code><![CDATA[$appId]]></code>
2586-
</InvalidScalarArgument>
2587-
</file>
25882579
<file src="lib/private/URLGenerator.php">
25892580
<InvalidReturnStatement>
25902581
<code><![CDATA[$path]]></code>

lib/private/App/AppManager.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use OCP\IURLGenerator;
2828
use OCP\IUser;
2929
use OCP\IUserSession;
30+
use OCP\ServerVersion;
3031
use OCP\Settings\IManager as ISettingsManager;
3132
use Psr\Log\LoggerInterface;
3233

@@ -80,6 +81,7 @@ public function __construct(
8081
private ICacheFactory $memCacheFactory,
8182
private IEventDispatcher $dispatcher,
8283
private LoggerInterface $logger,
84+
private ServerVersion $serverVersion,
8385
) {
8486
}
8587

@@ -786,8 +788,12 @@ public function getAppInfoByPath(string $path, ?string $lang = null): ?array {
786788

787789
public function getAppVersion(string $appId, bool $useCache = true): string {
788790
if (!$useCache || !isset($this->appVersions[$appId])) {
789-
$appInfo = $this->getAppInfo($appId);
790-
$this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
791+
if ($appId === 'core') {
792+
$this->appVersions[$appId] = $this->serverVersion->getVersionString();
793+
} else {
794+
$appInfo = $this->getAppInfo($appId);
795+
$this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
796+
}
791797
}
792798
return $this->appVersions[$appId];
793799
}

lib/private/Server.php

+1
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ public function __construct($webRoot, \OC\Config $config) {
791791
$c->get(ICacheFactory::class),
792792
$c->get(IEventDispatcher::class),
793793
$c->get(LoggerInterface::class),
794+
$c->get(ServerVersion::class),
794795
);
795796
});
796797
$this->registerAlias(IAppManager::class, AppManager::class);

lib/private/TemplateLayout.php

+17-15
Original file line numberDiff line numberDiff line change
@@ -304,12 +304,7 @@ public function __construct($renderAs, $appId = '') {
304304
$this->assign('id-app-navigation', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-navigation' : null);
305305
}
306306

307-
/**
308-
* @param string $path
309-
* @param string $file
310-
* @return string
311-
*/
312-
protected function getVersionHashSuffix($path = false, $file = false) {
307+
protected function getVersionHashSuffix(string $path = '', string $file = ''): string {
313308
if ($this->config->getSystemValueBool('debug', false)) {
314309
// allows chrome workspace mapping in debug mode
315310
return '';
@@ -322,11 +317,11 @@ protected function getVersionHashSuffix($path = false, $file = false) {
322317

323318
$hash = false;
324319
// Try the web-root first
325-
if (is_string($path) && $path !== '') {
320+
if ($path !== '') {
326321
$hash = $this->getVersionHashByPath($path);
327322
}
328323
// If not found try the file
329-
if ($hash === false && is_string($file) && $file !== '') {
324+
if ($hash === false && $file !== '') {
330325
$hash = $this->getVersionHashByPath($file);
331326
}
332327
// As a last resort we use the server version hash
@@ -349,13 +344,18 @@ private function getVersionHashByPath(string $path): string|false {
349344
return false;
350345
}
351346

352-
$appVersion = $this->appManager->getAppVersion($appId);
353-
// For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version
354-
if ($this->appManager->isShipped($appId)) {
355-
$appVersion .= '-' . self::$versionHash;
356-
}
347+
if ($appId === 'core') {
348+
// core is not a real app but the server itself
349+
$hash = self::$versionHash;
350+
} else {
351+
$appVersion = $this->appManager->getAppVersion($appId);
352+
// For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version
353+
if ($this->appManager->isShipped($appId)) {
354+
$appVersion .= '-' . self::$versionHash;
355+
}
357356

358-
$hash = substr(md5($appVersion), 0, 8);
357+
$hash = substr(md5($appVersion), 0, 8);
358+
}
359359
self::$cacheBusterCache[$path] = $hash;
360360
}
361361

@@ -376,14 +376,16 @@ public static function findStylesheetFiles($styles, $compileScss = true) {
376376

377377
/**
378378
* @param string $path
379-
* @return string|boolean
379+
* @return string|false
380380
*/
381381
public function getAppNamefromPath($path) {
382382
if ($path !== '' && is_string($path)) {
383383
$pathParts = explode('/', $path);
384384
if ($pathParts[0] === 'css') {
385385
// This is a scss request
386386
return $pathParts[1];
387+
} elseif ($pathParts[0] === 'core') {
388+
return 'core';
387389
}
388390
return end($pathParts);
389391
}

tests/lib/App/AppManagerTest.php

+103
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use OCP\IURLGenerator;
2626
use OCP\IUser;
2727
use OCP\IUserSession;
28+
use OCP\ServerVersion;
2829
use PHPUnit\Framework\MockObject\MockObject;
2930
use Psr\Log\LoggerInterface;
3031
use Test\TestCase;
@@ -100,6 +101,8 @@ protected function getAppConfig() {
100101

101102
protected IURLGenerator&MockObject $urlGenerator;
102103

104+
protected ServerVersion&MockObject $serverVersion;
105+
103106
/** @var IAppManager */
104107
protected $manager;
105108

@@ -115,6 +118,7 @@ protected function setUp(): void {
115118
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
116119
$this->logger = $this->createMock(LoggerInterface::class);
117120
$this->urlGenerator = $this->createMock(IURLGenerator::class);
121+
$this->serverVersion = $this->createMock(ServerVersion::class);
118122

119123
$this->overwriteService(AppConfig::class, $this->appConfig);
120124
$this->overwriteService(IURLGenerator::class, $this->urlGenerator);
@@ -136,6 +140,7 @@ protected function setUp(): void {
136140
$this->cacheFactory,
137141
$this->eventDispatcher,
138142
$this->logger,
143+
$this->serverVersion,
139144
);
140145
}
141146

@@ -278,6 +283,7 @@ public function testEnableAppForGroups(): void {
278283
$this->cacheFactory,
279284
$this->eventDispatcher,
280285
$this->logger,
286+
$this->serverVersion,
281287
])
282288
->onlyMethods([
283289
'getAppPath',
@@ -331,6 +337,7 @@ public function testEnableAppForGroupsAllowedTypes(array $appInfo): void {
331337
$this->cacheFactory,
332338
$this->eventDispatcher,
333339
$this->logger,
340+
$this->serverVersion,
334341
])
335342
->onlyMethods([
336343
'getAppPath',
@@ -392,6 +399,7 @@ public function testEnableAppForGroupsForbiddenTypes($type): void {
392399
$this->cacheFactory,
393400
$this->eventDispatcher,
394401
$this->logger,
402+
$this->serverVersion,
395403
])
396404
->onlyMethods([
397405
'getAppPath',
@@ -596,6 +604,7 @@ public function testGetAppsNeedingUpgrade(): void {
596604
$this->cacheFactory,
597605
$this->eventDispatcher,
598606
$this->logger,
607+
$this->serverVersion,
599608
])
600609
->onlyMethods(['getAppInfo'])
601610
->getMock();
@@ -655,6 +664,7 @@ public function testGetIncompatibleApps(): void {
655664
$this->cacheFactory,
656665
$this->eventDispatcher,
657666
$this->logger,
667+
$this->serverVersion,
658668
])
659669
->onlyMethods(['getAppInfo'])
660670
->getMock();
@@ -785,4 +795,97 @@ public function testIsBackendRequired(
785795

786796
$this->assertEquals($expected, $this->manager->isBackendRequired($backend));
787797
}
798+
799+
public function testGetAppVersion() {
800+
$manager = $this->getMockBuilder(AppManager::class)
801+
->setConstructorArgs([
802+
$this->userSession,
803+
$this->config,
804+
$this->groupManager,
805+
$this->cacheFactory,
806+
$this->eventDispatcher,
807+
$this->logger,
808+
$this->serverVersion,
809+
])
810+
->onlyMethods([
811+
'getAppInfo',
812+
])
813+
->getMock();
814+
815+
$manager->expects(self::once())
816+
->method('getAppInfo')
817+
->with('myapp')
818+
->willReturn(['version' => '99.99.99-rc.99']);
819+
820+
$this->serverVersion
821+
->expects(self::never())
822+
->method('getVersionString');
823+
824+
$this->assertEquals(
825+
'99.99.99-rc.99',
826+
$manager->getAppVersion('myapp'),
827+
);
828+
}
829+
830+
public function testGetAppVersionCore() {
831+
$manager = $this->getMockBuilder(AppManager::class)
832+
->setConstructorArgs([
833+
$this->userSession,
834+
$this->config,
835+
$this->groupManager,
836+
$this->cacheFactory,
837+
$this->eventDispatcher,
838+
$this->logger,
839+
$this->serverVersion,
840+
])
841+
->onlyMethods([
842+
'getAppInfo',
843+
])
844+
->getMock();
845+
846+
$manager->expects(self::never())
847+
->method('getAppInfo');
848+
849+
$this->serverVersion
850+
->expects(self::once())
851+
->method('getVersionString')
852+
->willReturn('1.2.3-beta.4');
853+
854+
$this->assertEquals(
855+
'1.2.3-beta.4',
856+
$manager->getAppVersion('core'),
857+
);
858+
}
859+
860+
public function testGetAppVersionUnknown() {
861+
$manager = $this->getMockBuilder(AppManager::class)
862+
->setConstructorArgs([
863+
$this->userSession,
864+
$this->config,
865+
$this->groupManager,
866+
$this->cacheFactory,
867+
$this->eventDispatcher,
868+
$this->logger,
869+
$this->serverVersion,
870+
])
871+
->onlyMethods([
872+
'getAppInfo',
873+
])
874+
->getMock();
875+
876+
$manager->expects(self::once())
877+
->method('getAppInfo')
878+
->with('unknown')
879+
->willReturn(null);
880+
881+
$this->serverVersion
882+
->expects(self::never())
883+
->method('getVersionString');
884+
885+
$this->assertEquals(
886+
'0',
887+
$manager->getAppVersion('unknown'),
888+
);
889+
}
890+
788891
}

tests/lib/AppTest.php

+19-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
use OC\AppConfig;
1313
use OCP\EventDispatcher\IEventDispatcher;
1414
use OCP\IAppConfig;
15-
use OCP\IURLGenerator;
15+
use OCP\ICacheFactory;
16+
use OCP\IConfig;
17+
use OCP\IDBConnection;
18+
use OCP\IGroupManager;
19+
use OCP\IUserManager;
20+
use OCP\IUserSession;
21+
use OCP\ServerVersion;
1622
use PHPUnit\Framework\MockObject\MockObject;
1723
use Psr\Log\LoggerInterface;
1824

@@ -463,8 +469,8 @@ public function appConfigValuesProvider() {
463469
* @dataProvider appConfigValuesProvider
464470
*/
465471
public function testEnabledApps($user, $expectedApps, $forceAll): void {
466-
$userManager = \OC::$server->getUserManager();
467-
$groupManager = \OC::$server->getGroupManager();
472+
$userManager = \OCP\Server::get(IUserManager::class);
473+
$groupManager = \OCP\Server::get(IGroupManager::class);
468474
$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
469475
$user2 = $userManager->createUser(self::TEST_USER2, 'NotAnEasyPassword123456_');
470476
$user3 = $userManager->createUser(self::TEST_USER3, 'NotAnEasyPassword123456?');
@@ -512,7 +518,7 @@ public function testEnabledApps($user, $expectedApps, $forceAll): void {
512518
* enabled apps more than once when a user is set.
513519
*/
514520
public function testEnabledAppsCache(): void {
515-
$userManager = \OC::$server->getUserManager();
521+
$userManager = \OCP\Server::get(IUserManager::class);
516522
$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
517523

518524
\OC_User::setUserId(self::TEST_USER1);
@@ -544,8 +550,8 @@ public function testEnabledAppsCache(): void {
544550
private function setupAppConfigMock() {
545551
/** @var AppConfig|MockObject */
546552
$appConfig = $this->getMockBuilder(AppConfig::class)
547-
->setMethods(['getValues'])
548-
->setConstructorArgs([\OC::$server->getDatabaseConnection()])
553+
->onlyMethods(['getValues'])
554+
->setConstructorArgs([\OCP\Server::get(IDBConnection::class)])
549555
->disableOriginalConstructor()
550556
->getMock();
551557

@@ -561,13 +567,13 @@ private function setupAppConfigMock() {
561567
private function registerAppConfig(AppConfig $appConfig) {
562568
$this->overwriteService(AppConfig::class, $appConfig);
563569
$this->overwriteService(AppManager::class, new AppManager(
564-
\OC::$server->getUserSession(),
565-
\OC::$server->getConfig(),
566-
\OC::$server->getGroupManager(),
567-
\OC::$server->getMemCacheFactory(),
568-
\OC::$server->get(IEventDispatcher::class),
569-
\OC::$server->get(LoggerInterface::class),
570-
\OC::$server->get(IURLGenerator::class),
570+
\OCP\Server::get(IUserSession::class),
571+
\OCP\Server::get(IConfig::class),
572+
\OCP\Server::get(IGroupManager::class),
573+
\OCP\Server::get(ICacheFactory::class),
574+
\OCP\Server::get(IEventDispatcher::class),
575+
\OCP\Server::get(LoggerInterface::class),
576+
\OCP\Server::get(ServerVersion::class),
571577
));
572578
}
573579

0 commit comments

Comments
 (0)