Allow to force enable apps via CLI

Co-authored-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Joas Schilling 2019-09-05 12:55:24 +02:00 committed by Christoph Wurst
parent 642606754b
commit 3eee359d7f
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
8 changed files with 83 additions and 42 deletions

View File

@ -549,13 +549,7 @@ class AppSettingsController extends Controller {
public function force(string $appId): JSONResponse {
$appId = OC_App::cleanAppId($appId);
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
if (!in_array($appId, $ignoreMaxApps, true)) {
$ignoreMaxApps[] = $appId;
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
}
$this->appManager->ignoreNextcloudRequirementForApp($appId);
return new JSONResponse();
}

View File

@ -73,15 +73,22 @@ class Enable extends Command implements CompletionAwareInterface {
'g',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'enable the app only for a list of groups'
)
->addOption(
'force',
'f',
InputOption::VALUE_NONE,
'enable the app regardless of the Nextcloud version requirement'
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$appIds = $input->getArgument('app-id');
$groups = $this->resolveGroupIds($input->getOption('groups'));
$forceEnable = (bool) $input->getOption('force');
foreach ($appIds as $appId) {
$this->enableApp($appId, $groups, $output);
$this->enableApp($appId, $groups, $forceEnable, $output);
}
return $this->exitCode;
@ -90,9 +97,10 @@ class Enable extends Command implements CompletionAwareInterface {
/**
* @param string $appId
* @param array $groupIds
* @param bool $forceEnable
* @param OutputInterface $output
*/
private function enableApp(string $appId, array $groupIds, OutputInterface $output): void {
private function enableApp(string $appId, array $groupIds, bool $forceEnable, OutputInterface $output): void {
$groupNames = array_map(function (IGroup $group) {
return $group->getDisplayName();
}, $groupIds);
@ -106,13 +114,13 @@ class Enable extends Command implements CompletionAwareInterface {
$installer->downloadApp($appId);
}
$installer->installApp($appId);
$installer->installApp($appId, $forceEnable);
if ($groupIds === []) {
$this->appManager->enableApp($appId);
$this->appManager->enableApp($appId, $forceEnable);
$output->writeln($appId . ' enabled');
} else {
$this->appManager->enableAppForGroups($appId, $groupIds);
$this->appManager->enableAppForGroups($appId, $groupIds, $forceEnable);
$output->writeln($appId . ' enabled for groups: ' . implode(', ', $groupNames));
}
} catch (AppPathNotFoundException $e) {

View File

@ -42,6 +42,7 @@ use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\App\ManagerEvent;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\ILogger;
@ -66,6 +67,9 @@ class AppManager implements IAppManager {
/** @var IUserSession */
private $userSession;
/** @var IConfig */
private $config;
/** @var AppConfig */
private $appConfig;
@ -101,18 +105,21 @@ class AppManager implements IAppManager {
/**
* @param IUserSession $userSession
* @param IConfig $config
* @param AppConfig $appConfig
* @param IGroupManager $groupManager
* @param ICacheFactory $memCacheFactory
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(IUserSession $userSession,
IConfig $config,
AppConfig $appConfig,
IGroupManager $groupManager,
ICacheFactory $memCacheFactory,
EventDispatcherInterface $dispatcher,
ILogger $logger) {
$this->userSession = $userSession;
$this->config = $config;
$this->appConfig = $appConfig;
$this->groupManager = $groupManager;
$this->memCacheFactory = $memCacheFactory;
@ -296,16 +303,29 @@ class AppManager implements IAppManager {
return isset($installedApps[$appId]);
}
public function ignoreNextcloudRequirementForApp(string $appId): void {
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
if (!in_array($appId, $ignoreMaxApps, true)) {
$ignoreMaxApps[] = $appId;
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
}
}
/**
* Enable an app for every user
*
* @param string $appId
* @param bool $forceEnable
* @throws AppPathNotFoundException
*/
public function enableApp($appId) {
public function enableApp(string $appId, bool $forceEnable = false): void {
// Check if app exists
$this->getAppPath($appId);
if ($forceEnable) {
$this->ignoreNextcloudRequirementForApp($appId);
}
$this->installedAppsCache[$appId] = 'yes';
$this->appConfig->setValue($appId, 'enabled', 'yes');
$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent(
@ -334,10 +354,11 @@ class AppManager implements IAppManager {
*
* @param string $appId
* @param \OCP\IGroup[] $groups
* @param bool $forceEnable
* @throws \InvalidArgumentException if app can't be enabled for groups
* @throws AppPathNotFoundException
*/
public function enableAppForGroups($appId, $groups) {
public function enableAppForGroups(string $appId, array $groups, bool $forceEnable = false): void {
// Check if app exists
$this->getAppPath($appId);
@ -346,6 +367,10 @@ class AppManager implements IAppManager {
throw new \InvalidArgumentException("$appId can't be enabled for groups.");
}
if ($forceEnable) {
$this->ignoreNextcloudRequirementForApp($appId);
}
$groupIds = array_map(function ($group) {
/** @var \OCP\IGroup $group */
return ($group instanceof IGroup)

View File

@ -94,10 +94,11 @@ class Installer {
* Installs an app that is located in one of the app folders already
*
* @param string $appId App to install
* @param bool $forceEnable
* @throws \Exception
* @return string app ID
*/
public function installApp($appId) {
public function installApp(string $appId, bool $forceEnable = false): string {
$app = \OC_App::findAppInDirectories($appId);
if($app === false) {
throw new \Exception('App not found in any app directory');
@ -117,7 +118,7 @@ class Installer {
}
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
$ignoreMax = in_array($appId, $ignoreMaxApps);
$ignoreMax = $forceEnable || in_array($appId, $ignoreMaxApps, true);
$version = implode('.', \OCP\Util::getVersion());
if (!\OC_App::isAppCompatible($version, $info, $ignoreMax)) {

View File

@ -798,6 +798,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(AppManager::class, function (Server $c) {
return new \OC\App\AppManager(
$c->getUserSession(),
$c->getConfig(),
$c->query(\OC\AppConfig::class),
$c->getGroupManager(),
$c->getMemCacheFactory(),

View File

@ -86,10 +86,11 @@ interface IAppManager {
* Enable an app for every user
*
* @param string $appId
* @param bool $forceEnable
* @throws AppPathNotFoundException
* @since 8.0.0
*/
public function enableApp($appId);
public function enableApp(string $appId, bool $forceEnable = false): void;
/**
* Whether a list of types contains a protected app type
@ -105,10 +106,11 @@ interface IAppManager {
*
* @param string $appId
* @param \OCP\IGroup[] $groups
* @param bool $forceEnable
* @throws \Exception
* @since 8.0.0
*/
public function enableAppForGroups($appId, $groups);
public function enableAppForGroups(string $appId, array $groups, bool $forceEnable = false): void;
/**
* Disable an app for every user

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
@ -11,20 +11,17 @@ namespace Test\App;
use OC\App\AppManager;
use OC\AppConfig;
use OC\Group\Group;
use OC\User\User;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\IAppConfig;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase;
@ -35,7 +32,7 @@ use Test\TestCase;
*/
class AppManagerTest extends TestCase {
/**
* @return AppConfig|\PHPUnit_Framework_MockObject_MockObject
* @return AppConfig|MockObject
*/
protected function getAppConfig() {
$appConfig = array();
@ -73,25 +70,28 @@ class AppManagerTest extends TestCase {
return $config;
}
/** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
/** @var IUserSession|MockObject */
protected $userSession;
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
/** @var IConfig|MockObject */
private $config;
/** @var IGroupManager|MockObject */
protected $groupManager;
/** @var AppConfig|\PHPUnit_Framework_MockObject_MockObject */
/** @var AppConfig|MockObject */
protected $appConfig;
/** @var ICache|\PHPUnit_Framework_MockObject_MockObject */
/** @var ICache|MockObject */
protected $cache;
/** @var ICacheFactory|\PHPUnit_Framework_MockObject_MockObject */
/** @var ICacheFactory|MockObject */
protected $cacheFactory;
/** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */
/** @var EventDispatcherInterface|MockObject */
protected $eventDispatcher;
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
/** @var ILogger|MockObject */
protected $logger;
/** @var IAppManager */
@ -102,6 +102,7 @@ class AppManagerTest extends TestCase {
$this->userSession = $this->createMock(IUserSession::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->config = $this->createMock(IConfig::class);
$this->appConfig = $this->getAppConfig();
$this->cacheFactory = $this->createMock(ICacheFactory::class);
$this->cache = $this->createMock(ICache::class);
@ -111,7 +112,15 @@ class AppManagerTest extends TestCase {
->method('createDistributed')
->with('settings')
->willReturn($this->cache);
$this->manager = new AppManager($this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger);
$this->manager = new AppManager(
$this->userSession,
$this->config,
$this->appConfig,
$this->groupManager,
$this->cacheFactory,
$this->eventDispatcher,
$this->logger
);
}
protected function expectClearCache() {
@ -161,10 +170,10 @@ class AppManagerTest extends TestCase {
$groups = [$group1, $group2];
$this->expectClearCache();
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */
/** @var AppManager|MockObject $manager */
$manager = $this->getMockBuilder(AppManager::class)
->setConstructorArgs([
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
])
->setMethods([
'getAppPath',
@ -208,10 +217,10 @@ class AppManagerTest extends TestCase {
$groups = [$group1, $group2];
$this->expectClearCache();
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */
/** @var AppManager|MockObject $manager */
$manager = $this->getMockBuilder(AppManager::class)
->setConstructorArgs([
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
])
->setMethods([
'getAppPath',
@ -262,10 +271,10 @@ class AppManagerTest extends TestCase {
$groups = [$group1, $group2];
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */
/** @var AppManager|MockObject $manager */
$manager = $this->getMockBuilder(AppManager::class)
->setConstructorArgs([
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger
])
->setMethods([
'getAppPath',
@ -426,9 +435,9 @@ class AppManagerTest extends TestCase {
}
public function testGetAppsNeedingUpgrade() {
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */
/** @var AppManager|MockObject $manager */
$manager = $this->getMockBuilder(AppManager::class)
->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger])
->setConstructorArgs([$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger])
->setMethods(['getAppInfo'])
->getMock();
@ -476,9 +485,9 @@ class AppManagerTest extends TestCase {
}
public function testGetIncompatibleApps() {
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */
/** @var AppManager|MockObject $manager */
$manager = $this->getMockBuilder(AppManager::class)
->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger])
->setConstructorArgs([$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger])
->setMethods(['getAppInfo'])
->getMock();

View File

@ -549,6 +549,7 @@ class AppTest extends \Test\TestCase {
$this->overwriteService('AppConfig', $appConfig);
$this->overwriteService('AppManager', new \OC\App\AppManager(
\OC::$server->getUserSession(),
\OC::$server->getConfig(),
$appConfig,
\OC::$server->getGroupManager(),
\OC::$server->getMemCacheFactory(),