From 64bd769ebfb067ac371fb701117d941bae480b44 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 23 Oct 2024 12:55:28 +0200 Subject: [PATCH] fix(apps-store): Remove apps from force-enabled state when uninstalled If an app is force-enabled and then uninstalled the force-enabled state was kept. This is now removed, so when the app should be re-installed the compatibility should be reevaluated. Signed-off-by: Ferdinand Thiessen --- .../lib/Controller/AppSettingsController.php | 16 ++++++---- build/psalm-baseline.xml | 1 + lib/private/App/AppManager.php | 30 +++++++++++-------- lib/public/App/IAppManager.php | 8 ++--- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php index 7affb0d5069c0..fadac07afb049 100644 --- a/apps/settings/lib/Controller/AppSettingsController.php +++ b/apps/settings/lib/Controller/AppSettingsController.php @@ -6,6 +6,7 @@ */ namespace OCA\Settings\Controller; +use OC\App\AppManager; use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Fetcher\AppDiscoverFetcher; use OC\App\AppStore\Fetcher\AppFetcher; @@ -15,7 +16,6 @@ use OC\App\Platform; use OC\Installer; use OCP\App\AppPathNotFoundException; -use OCP\App\IAppManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; @@ -62,7 +62,7 @@ public function __construct( private IL10N $l10n, private IConfig $config, private INavigationManager $navigationManager, - private IAppManager $appManager, + private AppManager $appManager, private CategoryFetcher $categoryFetcher, private AppFetcher $appFetcher, private IFactory $l10nFactory, @@ -592,7 +592,10 @@ public function uninstallApp(string $appId): JSONResponse { $appId = $this->appManager->cleanAppId($appId); $result = $this->installer->removeApp($appId); if ($result !== false) { - $this->appManager->clearAppsCache(); + $appManager = $this->appManager; + // If this app was force enabled, remove the force-enabled-state + $appManager->removeOverwriteNextcloudRequirement($appId); + $appManager->clearAppsCache(); return new JSONResponse(['data' => ['appid' => $appId]]); } return new JSONResponse(['data' => ['message' => $this->l10n->t('Could not remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); @@ -630,8 +633,11 @@ private function sortApps($a, $b) { } public function force(string $appId): JSONResponse { - $appId = $this->appManager->cleanAppId($appId); - $this->appManager->ignoreNextcloudRequirementForApp($appId); + /** @var \OC\App\AppManager $appManager */ + $appManager = $this->appManager; + + $appId = $appManager->cleanAppId($appId); + $appManager->overwriteNextcloudRequirement($appId); return new JSONResponse(); } } diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 824431c46a522..06f99aaa0218a 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1029,6 +1029,7 @@ + diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 2b6d2a2700bc4..b2836bd504297 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -200,10 +200,6 @@ public function getEnabledAppsForUser(IUser $user) { return array_keys($appsForUser); } - /** - * @param IGroup $group - * @return array - */ public function getEnabledAppsForGroup(IGroup $group): array { $apps = $this->getInstalledAppsValues(); $appsForGroups = array_filter($apps, function ($enabled) use ($group) { @@ -304,10 +300,6 @@ public function getAutoDisabledApps(): array { return $this->autoDisabledApps; } - /** - * @param string $appId - * @return array - */ public function getAppRestriction(string $appId): array { $values = $this->getInstalledAppsValues(); @@ -321,7 +313,6 @@ public function getAppRestriction(string $appId): array { return json_decode($values[$appId], true); } - /** * Check if an app is enabled for user * @@ -410,12 +401,25 @@ public function isInstalled($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', []); if (!in_array($appId, $ignoreMaxApps, true)) { $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 { @@ -646,7 +650,7 @@ public function enableAppForGroups(string $appId, array $groups, bool $forceEnab * @param bool $automaticDisabled * @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)) { throw new \Exception("$appId can't be disabled."); } @@ -706,7 +710,7 @@ public function getAppWebPath(string $appId): string { /** * Clear the cached list of apps when enabling/disabling an app */ - public function clearAppsCache() { + public function clearAppsCache(): void { $this->appInfos = []; } diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 0af7cdfc49530..110bcacf396be 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -144,7 +144,7 @@ public function enableAppForGroups(string $appId, array $groups, bool $forceEnab * @param bool $automaticDisabled * @since 8.0.0 */ - public function disableApp($appId, $automaticDisabled = false); + public function disableApp($appId, $automaticDisabled = false): void; /** * Get the directory for the given app. @@ -185,7 +185,7 @@ public function getInstalledApps(); * Clear the cached list of apps when enabling/disabling an app * @since 8.1.0 */ - public function clearAppsCache(); + public function clearAppsCache(): void; /** * @param string $appId @@ -201,7 +201,7 @@ public function isShipped($appId); * @return bool * * 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. * * if $types is set to non-empty array, only apps of those types will be loaded @@ -271,7 +271,7 @@ public function getDefaultApps(): array; /** * Set the global default apps with fallbacks * - * @param string[] $appId + * @param string[] $defaultApps * @throws \InvalidArgumentException If any of the apps is not installed * @since 28.0.0 * @deprecated 31.0.0