diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2021-10-08 11:35:27 +0200 |
---|---|---|
committer | John Molakvoæ <skjnldsv@protonmail.com> | 2021-10-13 11:13:33 +0200 |
commit | 1a6bac58747165b3d8a8304e7ebaeb296b6e07a8 (patch) | |
tree | 89d4b8b4f5b32aece60ceb1dbb877275bad4f978 | |
parent | 682944925839e5300c02a231b261bb6fc6dfdf20 (diff) | |
download | nextcloud-server-1a6bac58747165b3d8a8304e7ebaeb296b6e07a8.tar.gz nextcloud-server-1a6bac58747165b3d8a8304e7ebaeb296b6e07a8.zip |
Allow to whitelist apps from the apsptore
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
-rw-r--r-- | config/config.sample.php | 6 | ||||
-rw-r--r-- | lib/private/App/AppStore/Fetcher/AppFetcher.php | 26 | ||||
-rw-r--r-- | tests/lib/App/AppStore/Fetcher/AppFetcherTest.php | 79 |
3 files changed, 108 insertions, 3 deletions
diff --git a/config/config.sample.php b/config/config.sample.php index 845db00ac12..be79b22063d 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -973,6 +973,12 @@ $CONFIG = [ 'appstoreurl' => 'https://apps.nextcloud.com/api/v1', /** + * Filters allowed installable apps from the appstore. + * Empty array will prevent all apps from the store to be found. + */ +'appsallowlist' => [], + +/** * Use the ``apps_paths`` parameter to set the location of the Apps directory, * which should be scanned for available apps, and where user-specific apps * should be installed from the Apps store. The ``path`` defines the absolute diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php index 1605e5bd230..2216999e12f 100644 --- a/lib/private/App/AppStore/Fetcher/AppFetcher.php +++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php @@ -35,6 +35,7 @@ use OC\Files\AppData\Factory; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Http\Client\IClientService; use OCP\IConfig; +use OCP\Support\Subscription\IRegistry; use Psr\Log\LoggerInterface; class AppFetcher extends Fetcher { @@ -42,6 +43,9 @@ class AppFetcher extends Fetcher { /** @var CompareVersion */ private $compareVersion; + /** @var IRegistry */ + private $registry; + /** @var bool */ private $ignoreMaxVersion; @@ -50,7 +54,8 @@ class AppFetcher extends Fetcher { ITimeFactory $timeFactory, IConfig $config, CompareVersion $compareVersion, - LoggerInterface $logger) { + LoggerInterface $logger, + IRegistry $registry) { parent::__construct( $appDataFactory, $clientService, @@ -59,9 +64,11 @@ class AppFetcher extends Fetcher { $logger ); + $this->compareVersion = $compareVersion; + $this->registry = $registry; + $this->fileName = 'apps.json'; $this->endpointName = 'apps.json'; - $this->compareVersion = $compareVersion; $this->ignoreMaxVersion = true; } @@ -172,4 +179,19 @@ class AppFetcher extends Fetcher { $this->fileName = $fileName; $this->ignoreMaxVersion = $ignoreMaxVersion; } + + + public function get($allowUnstable = false) { + $apps = parent::get($allowUnstable); + $whitelist = $this->config->getSystemValue('appsallowlist'); + + // If the admin specified a whitelist, filter apps from the appstore + if (is_array($whitelist) && $this->registry->delegateHasValidSubscription()) { + return array_filter($apps, function ($app) use ($whitelist) { + return in_array($app['id'], $whitelist); + }); + } + + return $apps; + } } diff --git a/tests/lib/App/AppStore/Fetcher/AppFetcherTest.php b/tests/lib/App/AppStore/Fetcher/AppFetcherTest.php index 840d47ed802..44869d353a4 100644 --- a/tests/lib/App/AppStore/Fetcher/AppFetcherTest.php +++ b/tests/lib/App/AppStore/Fetcher/AppFetcherTest.php @@ -34,6 +34,7 @@ use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use OCP\Http\Client\IResponse; use OCP\IConfig; +use OCP\Support\Subscription\IRegistry; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -50,6 +51,8 @@ class AppFetcherTest extends TestCase { protected $compareVersion; /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $logger; + /** @var IRegistry */ + protected $registry; /** @var AppFetcher */ protected $fetcher; /** @var string */ @@ -1849,6 +1852,7 @@ EJL3BaQAQaASSsvFrcozYxrQG4VzEg== $this->config = $this->createMock(IConfig::class); $this->compareVersion = new CompareVersion(); $this->logger = $this->createMock(LoggerInterface::class); + $this->registry = $this->createMock(IRegistry::class); $this->fetcher = new AppFetcher( $factory, @@ -1856,7 +1860,8 @@ EJL3BaQAQaASSsvFrcozYxrQG4VzEg== $this->timeFactory, $this->config, $this->compareVersion, - $this->logger + $this->logger, + $this->registry ); } @@ -2061,4 +2066,76 @@ EJL3BaQAQaASSsvFrcozYxrQG4VzEg== $this->fetcher->setVersion('11.0.0.2', 'future-apps.json', false); $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); } + + public function testGetWhitelist() { + $this->config->method('getSystemValue') + ->willReturnCallback(function ($key, $default) { + if ($key === 'appstoreenabled') { + return true; + } elseif ($key === 'version') { + return '11.0.0.2'; + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { + return 'https://custom.appsstore.endpoint/api/v1'; + } elseif ($key === 'appsallowlist') { + return ['contacts']; + } else { + return $default; + } + }); + + $file = $this->createMock(ISimpleFile::class); + $folder = $this->createMock(ISimpleFolder::class); + $folder + ->expects($this->at(0)) + ->method('getFile') + ->with('apps.json') + ->willThrowException(new NotFoundException()); + $folder + ->expects($this->at(1)) + ->method('newFile') + ->with('apps.json') + ->willReturn($file); + $this->appData + ->expects($this->once()) + ->method('getFolder') + ->with('/') + ->willReturn($folder); + $client = $this->createMock(IClient::class); + $this->clientService + ->expects($this->once()) + ->method('newClient') + ->willReturn($client); + $response = $this->createMock(IResponse::class); + $client + ->method('get') + ->with('https://custom.appsstore.endpoint/api/v1/apps.json') + ->willReturn($response); + $response + ->expects($this->once()) + ->method('getBody') + ->willReturn(self::$responseJson); + $response->method('getHeader') + ->with($this->equalTo('ETag')) + ->willReturn('"myETag"'); + $this->timeFactory + ->expects($this->once()) + ->method('getTime') + ->willReturn(1234); + + $this->registry + ->expects($this->once()) + ->method('delegateHasValidSubscription') + ->willReturn(true); + + $file + ->expects($this->once()) + ->method('putContent'); + $file + ->method('getContent') + ->willReturn(json_encode(self::$expectedResponse)); + + $apps = array_values($this->fetcher->get()); + $this->assertEquals(count($apps), 1); + $this->assertEquals($apps[0]['id'], 'contacts'); + } } |