Browse Source

Merge pull request #48855 from nextcloud/fix/app-store-remove-force-enable

fix(apps-store): Remove apps from force-enabled state when uninstalled
pull/49354/head
Ferdinand Thiessen 1 year ago
committed by GitHub
parent
commit
e5932c063d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      apps/settings/lib/Controller/AppSettingsController.php
  2. 7
      apps/settings/tests/Controller/AppSettingsControllerTest.php
  3. 11
      build/psalm-baseline.xml
  4. 34
      lib/private/App/AppManager.php
  5. 8
      lib/public/App/IAppManager.php

8
apps/settings/lib/Controller/AppSettingsController.php

@ -6,6 +6,7 @@
*/ */
namespace OCA\Settings\Controller; namespace OCA\Settings\Controller;
use OC\App\AppManager;
use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppDiscoverFetcher; use OC\App\AppStore\Fetcher\AppDiscoverFetcher;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
@ -15,7 +16,6 @@ use OC\App\DependencyAnalyzer;
use OC\App\Platform; use OC\App\Platform;
use OC\Installer; use OC\Installer;
use OCP\App\AppPathNotFoundException; use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
@ -62,7 +62,7 @@ class AppSettingsController extends Controller {
private IL10N $l10n, private IL10N $l10n,
private IConfig $config, private IConfig $config,
private INavigationManager $navigationManager, private INavigationManager $navigationManager,
private IAppManager $appManager,
private AppManager $appManager,
private CategoryFetcher $categoryFetcher, private CategoryFetcher $categoryFetcher,
private AppFetcher $appFetcher, private AppFetcher $appFetcher,
private IFactory $l10nFactory, private IFactory $l10nFactory,
@ -592,6 +592,8 @@ class AppSettingsController extends Controller {
$appId = $this->appManager->cleanAppId($appId); $appId = $this->appManager->cleanAppId($appId);
$result = $this->installer->removeApp($appId); $result = $this->installer->removeApp($appId);
if ($result !== false) { if ($result !== false) {
// If this app was force enabled, remove the force-enabled-state
$this->appManager->removeOverwriteNextcloudRequirement($appId);
$this->appManager->clearAppsCache(); $this->appManager->clearAppsCache();
return new JSONResponse(['data' => ['appid' => $appId]]); return new JSONResponse(['data' => ['appid' => $appId]]);
} }
@ -631,7 +633,7 @@ class AppSettingsController extends Controller {
public function force(string $appId): JSONResponse { public function force(string $appId): JSONResponse {
$appId = $this->appManager->cleanAppId($appId); $appId = $this->appManager->cleanAppId($appId);
$this->appManager->ignoreNextcloudRequirementForApp($appId);
$this->appManager->overwriteNextcloudRequirement($appId);
return new JSONResponse(); return new JSONResponse();
} }
} }

7
apps/settings/tests/Controller/AppSettingsControllerTest.php

@ -6,13 +6,13 @@
*/ */
namespace OCA\Settings\Tests\Controller; namespace OCA\Settings\Tests\Controller;
use OC\App\AppManager;
use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppDiscoverFetcher; use OC\App\AppStore\Fetcher\AppDiscoverFetcher;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\Installer; use OC\Installer;
use OCA\Settings\Controller\AppSettingsController; use OCA\Settings\Controller\AppSettingsController;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
@ -47,8 +47,7 @@ class AppSettingsControllerTest extends TestCase {
private $config; private $config;
/** @var INavigationManager|MockObject */ /** @var INavigationManager|MockObject */
private $navigationManager; private $navigationManager;
/** @var IAppManager|MockObject */
private $appManager;
private AppManager&MockObject $appManager;
/** @var CategoryFetcher|MockObject */ /** @var CategoryFetcher|MockObject */
private $categoryFetcher; private $categoryFetcher;
/** @var AppFetcher|MockObject */ /** @var AppFetcher|MockObject */
@ -83,7 +82,7 @@ class AppSettingsControllerTest extends TestCase {
->willReturnArgument(0); ->willReturnArgument(0);
$this->config = $this->createMock(IConfig::class); $this->config = $this->createMock(IConfig::class);
$this->navigationManager = $this->createMock(INavigationManager::class); $this->navigationManager = $this->createMock(INavigationManager::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->appManager = $this->createMock(AppManager::class);
$this->categoryFetcher = $this->createMock(CategoryFetcher::class); $this->categoryFetcher = $this->createMock(CategoryFetcher::class);
$this->appFetcher = $this->createMock(AppFetcher::class); $this->appFetcher = $this->createMock(AppFetcher::class);
$this->l10nFactory = $this->createMock(IFactory::class); $this->l10nFactory = $this->createMock(IFactory::class);

11
build/psalm-baseline.xml

@ -1025,11 +1025,6 @@
<code><![CDATA[getSettingsManager]]></code> <code><![CDATA[getSettingsManager]]></code>
</UndefinedInterfaceMethod> </UndefinedInterfaceMethod>
</file> </file>
<file src="apps/settings/lib/Controller/AppSettingsController.php">
<UndefinedInterfaceMethod>
<code><![CDATA[ignoreNextcloudRequirementForApp]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="apps/settings/lib/Hooks.php"> <file src="apps/settings/lib/Hooks.php">
<InvalidArrayOffset> <InvalidArrayOffset>
<code><![CDATA[[$user->getEMailAddress() => $user->getDisplayName()]]]></code> <code><![CDATA[[$user->getEMailAddress() => $user->getDisplayName()]]]></code>
@ -1337,12 +1332,6 @@
<code><![CDATA[!is_array($userIds)]]></code> <code><![CDATA[!is_array($userIds)]]></code>
</TypeDoesNotContainType> </TypeDoesNotContainType>
</file> </file>
<file src="lib/private/App/AppManager.php">
<LessSpecificImplementedReturnType>
<code><![CDATA[array]]></code>
<code><![CDATA[array]]></code>
</LessSpecificImplementedReturnType>
</file>
<file src="lib/private/App/AppStore/Fetcher/Fetcher.php"> <file src="lib/private/App/AppStore/Fetcher/Fetcher.php">
<TooManyArguments> <TooManyArguments>
<code><![CDATA[fetch]]></code> <code><![CDATA[fetch]]></code>

34
lib/private/App/AppManager.php

@ -200,10 +200,6 @@ class AppManager implements IAppManager {
return array_keys($appsForUser); return array_keys($appsForUser);
} }
/**
* @param IGroup $group
* @return array
*/
public function getEnabledAppsForGroup(IGroup $group): array { public function getEnabledAppsForGroup(IGroup $group): array {
$apps = $this->getInstalledAppsValues(); $apps = $this->getInstalledAppsValues();
$appsForGroups = array_filter($apps, function ($enabled) use ($group) { $appsForGroups = array_filter($apps, function ($enabled) use ($group) {
@ -304,10 +300,6 @@ class AppManager implements IAppManager {
return $this->autoDisabledApps; return $this->autoDisabledApps;
} }
/**
* @param string $appId
* @return array
*/
public function getAppRestriction(string $appId): array { public function getAppRestriction(string $appId): array {
$values = $this->getInstalledAppsValues(); $values = $this->getInstalledAppsValues();
@ -321,7 +313,6 @@ class AppManager implements IAppManager {
return json_decode($values[$appId], true); return json_decode($values[$appId], true);
} }
/** /**
* Check if an app is enabled for user * Check if an app is enabled for user
* *
@ -410,12 +401,25 @@ class AppManager implements IAppManager {
return isset($installedApps[$appId]); return isset($installedApps[$appId]);
} }
public function ignoreNextcloudRequirementForApp(string $appId): void {
/**
* Overwrite the `max-version` requirement for this app.
*/
public function overwriteNextcloudRequirement(string $appId): void {
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); $ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
if (!in_array($appId, $ignoreMaxApps, true)) { if (!in_array($appId, $ignoreMaxApps, true)) {
$ignoreMaxApps[] = $appId; $ignoreMaxApps[] = $appId;
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
} }
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
}
/**
* Remove the `max-version` overwrite for this app.
* This means this app now again can not be enabled if the `max-version` is smaller than the current Nextcloud version.
*/
public function removeOverwriteNextcloudRequirement(string $appId): void {
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []);
$ignoreMaxApps = array_filter($ignoreMaxApps, fn (string $id) => $id !== $appId);
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps);
} }
public function loadApp(string $app): void { public function loadApp(string $app): void {
@ -573,7 +577,7 @@ class AppManager implements IAppManager {
$this->getAppPath($appId); $this->getAppPath($appId);
if ($forceEnable) { if ($forceEnable) {
$this->ignoreNextcloudRequirementForApp($appId);
$this->overwriteNextcloudRequirement($appId);
} }
$this->installedAppsCache[$appId] = 'yes'; $this->installedAppsCache[$appId] = 'yes';
@ -619,7 +623,7 @@ class AppManager implements IAppManager {
} }
if ($forceEnable) { if ($forceEnable) {
$this->ignoreNextcloudRequirementForApp($appId);
$this->overwriteNextcloudRequirement($appId);
} }
/** @var string[] $groupIds */ /** @var string[] $groupIds */
@ -646,7 +650,7 @@ class AppManager implements IAppManager {
* @param bool $automaticDisabled * @param bool $automaticDisabled
* @throws \Exception if app can't be disabled * @throws \Exception if app can't be disabled
*/ */
public function disableApp($appId, $automaticDisabled = false) {
public function disableApp($appId, $automaticDisabled = false): void {
if ($this->isAlwaysEnabled($appId)) { if ($this->isAlwaysEnabled($appId)) {
throw new \Exception("$appId can't be disabled."); throw new \Exception("$appId can't be disabled.");
} }
@ -706,7 +710,7 @@ class AppManager implements IAppManager {
/** /**
* Clear the cached list of apps when enabling/disabling an app * Clear the cached list of apps when enabling/disabling an app
*/ */
public function clearAppsCache() {
public function clearAppsCache(): void {
$this->appInfos = []; $this->appInfos = [];
} }

8
lib/public/App/IAppManager.php

@ -144,7 +144,7 @@ interface IAppManager {
* @param bool $automaticDisabled * @param bool $automaticDisabled
* @since 8.0.0 * @since 8.0.0
*/ */
public function disableApp($appId, $automaticDisabled = false);
public function disableApp($appId, $automaticDisabled = false): void;
/** /**
* Get the directory for the given app. * Get the directory for the given app.
@ -185,7 +185,7 @@ interface IAppManager {
* Clear the cached list of apps when enabling/disabling an app * Clear the cached list of apps when enabling/disabling an app
* @since 8.1.0 * @since 8.1.0
*/ */
public function clearAppsCache();
public function clearAppsCache(): void;
/** /**
* @param string $appId * @param string $appId
@ -201,7 +201,7 @@ interface IAppManager {
* @return bool * @return bool
* *
* This function walks through the Nextcloud directory and loads all apps * This function walks through the Nextcloud directory and loads all apps
* it can find. A directory contains an app if the file /appinfo/info.xml
* it can find. A directory contains an app if the file `/appinfo/info.xml`
* exists. * exists.
* *
* if $types is set to non-empty array, only apps of those types will be loaded * if $types is set to non-empty array, only apps of those types will be loaded
@ -271,7 +271,7 @@ interface IAppManager {
/** /**
* Set the global default apps with fallbacks * Set the global default apps with fallbacks
* *
* @param string[] $appId
* @param string[] $defaultApps
* @throws \InvalidArgumentException If any of the apps is not installed * @throws \InvalidArgumentException If any of the apps is not installed
* @since 28.0.0 * @since 28.0.0
* @deprecated 31.0.0 * @deprecated 31.0.0

Loading…
Cancel
Save