diff options
author | Côme Chilliet <91878298+come-nc@users.noreply.github.com> | 2025-06-05 17:55:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-05 17:55:08 +0200 |
commit | 5488f7e8b1e2676352edfcd0cf445144b8134db2 (patch) | |
tree | cce766251620203c8a5063e85ef0e5acafcd6688 | |
parent | 4b50105fb4fe0175454ce01309075f7de71be96d (diff) | |
parent | c85f7eacb88727c8e550fa38ff52d5ad992d1a77 (diff) | |
download | nextcloud-server-5488f7e8b1e2676352edfcd0cf445144b8134db2.tar.gz nextcloud-server-5488f7e8b1e2676352edfcd0cf445144b8134db2.zip |
Merge pull request #53352 from nextcloud/fix/install-app-before-enable
fix: Do not enable applications which are not installed yet
-rw-r--r-- | apps/provisioning_api/lib/Controller/AppsController.php | 16 | ||||
-rw-r--r-- | apps/provisioning_api/tests/Controller/AppsControllerTest.php | 11 | ||||
-rwxr-xr-x | build/integration/run.sh | 2 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | lib/private/App/AppManager.php | 9 | ||||
-rw-r--r-- | lib/private/App/AppStore/AppNotFoundException.php | 13 | ||||
-rw-r--r-- | lib/private/Installer.php | 6 |
8 files changed, 55 insertions, 4 deletions
diff --git a/apps/provisioning_api/lib/Controller/AppsController.php b/apps/provisioning_api/lib/Controller/AppsController.php index 4d32584591b..3f6cff7442a 100644 --- a/apps/provisioning_api/lib/Controller/AppsController.php +++ b/apps/provisioning_api/lib/Controller/AppsController.php @@ -8,6 +8,8 @@ declare(strict_types=1); */ namespace OCA\Provisioning_API\Controller; +use OC\App\AppStore\AppNotFoundException; +use OC\Installer; use OC_App; use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; @@ -16,6 +18,7 @@ use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCSController; +use OCP\IAppConfig; use OCP\IRequest; class AppsController extends OCSController { @@ -23,6 +26,8 @@ class AppsController extends OCSController { string $appName, IRequest $request, private IAppManager $appManager, + private Installer $installer, + private IAppConfig $appConfig, ) { parent::__construct($appName, $request); } @@ -108,10 +113,19 @@ class AppsController extends OCSController { public function enable(string $app): DataResponse { try { $app = $this->verifyAppId($app); + + if (!$this->installer->isDownloaded($app)) { + $this->installer->downloadApp($app); + } + + if ($this->appConfig->getValueString($app, 'installed_version', '') === '') { + $this->installer->installApp($app); + } + $this->appManager->enableApp($app); } catch (\InvalidArgumentException $e) { throw new OCSException($e->getMessage(), OCSController::RESPOND_UNAUTHORISED); - } catch (AppPathNotFoundException $e) { + } catch (AppPathNotFoundException|AppNotFoundException $e) { throw new OCSException('The request app was not found', OCSController::RESPOND_NOT_FOUND); } return new DataResponse(); diff --git a/apps/provisioning_api/tests/Controller/AppsControllerTest.php b/apps/provisioning_api/tests/Controller/AppsControllerTest.php index f56be7c4c36..f95daeae7d3 100644 --- a/apps/provisioning_api/tests/Controller/AppsControllerTest.php +++ b/apps/provisioning_api/tests/Controller/AppsControllerTest.php @@ -7,14 +7,17 @@ */ namespace OCA\Provisioning_API\Tests\Controller; +use OC\Installer; use OCA\Provisioning_API\Controller\AppsController; use OCA\Provisioning_API\Tests\TestCase; use OCP\App\IAppManager; use OCP\AppFramework\OCS\OCSException; +use OCP\IAppConfig; use OCP\IGroupManager; use OCP\IRequest; use OCP\IUserSession; use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; /** * Class AppsTest @@ -25,6 +28,8 @@ use OCP\Server; */ class AppsControllerTest extends TestCase { private IAppManager $appManager; + private IAppConfig&MockObject $appConfig; + private Installer&MockObject $installer; private AppsController $api; private IUserSession $userSession; @@ -34,13 +39,17 @@ class AppsControllerTest extends TestCase { $this->appManager = Server::get(IAppManager::class); $this->groupManager = Server::get(IGroupManager::class); $this->userSession = Server::get(IUserSession::class); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->installer = $this->createMock(Installer::class); $request = $this->createMock(IRequest::class); $this->api = new AppsController( 'provisioning_api', $request, - $this->appManager + $this->appManager, + $this->installer, + $this->appConfig, ); } diff --git a/build/integration/run.sh b/build/integration/run.sh index cbd3cceb3d1..30dd0646b10 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -18,6 +18,8 @@ HIDE_OC_LOGS=$2 INSTALLED=$($OCC status | grep installed: | cut -d " " -f 5) if [ "$INSTALLED" == "true" ]; then + # Disable appstore to avoid spamming from CI + $OCC config:system:set appstoreenabled --value=false --type=boolean # Disable bruteforce protection because the integration tests do trigger them $OCC config:system:set auth.bruteforce.protection.enabled --value false --type bool # Disable rate limit protection because the integration tests do trigger them diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 41bf5d54a33..36f64d970c3 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1049,6 +1049,7 @@ return array( 'OC\\AppScriptDependency' => $baseDir . '/lib/private/AppScriptDependency.php', 'OC\\AppScriptSort' => $baseDir . '/lib/private/AppScriptSort.php', 'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\AppNotFoundException' => $baseDir . '/lib/private/App/AppStore/AppNotFoundException.php', 'OC\\App\\AppStore\\Bundles\\Bundle' => $baseDir . '/lib/private/App/AppStore/Bundles/Bundle.php', 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => $baseDir . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', 'OC\\App\\AppStore\\Bundles\\EducationBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/EducationBundle.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 6fbcd9b9cfa..327366ca889 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1090,6 +1090,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\AppScriptDependency' => __DIR__ . '/../../..' . '/lib/private/AppScriptDependency.php', 'OC\\AppScriptSort' => __DIR__ . '/../../..' . '/lib/private/AppScriptSort.php', 'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\AppNotFoundException' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/AppNotFoundException.php', 'OC\\App\\AppStore\\Bundles\\Bundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/Bundle.php', 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', 'OC\\App\\AppStore\\Bundles\\EducationBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/EducationBundle.php', diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 413dc6ccd46..18f29114d0e 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -545,11 +545,16 @@ class AppManager implements IAppManager { * @param string $appId * @param bool $forceEnable * @throws AppPathNotFoundException + * @throws \InvalidArgumentException if the application is not installed yet */ public function enableApp(string $appId, bool $forceEnable = false): void { // Check if app exists $this->getAppPath($appId); + if ($this->config->getAppValue($appId, 'installed_version', '') === '') { + throw new \InvalidArgumentException("$appId is not installed, cannot be enabled."); + } + if ($forceEnable) { $this->overwriteNextcloudRequirement($appId); } @@ -596,6 +601,10 @@ class AppManager implements IAppManager { throw new \InvalidArgumentException("$appId can't be enabled for groups."); } + if ($this->config->getAppValue($appId, 'installed_version', '') === '') { + throw new \InvalidArgumentException("$appId is not installed, cannot be enabled."); + } + if ($forceEnable) { $this->overwriteNextcloudRequirement($appId); } diff --git a/lib/private/App/AppStore/AppNotFoundException.php b/lib/private/App/AppStore/AppNotFoundException.php new file mode 100644 index 00000000000..79ceebb4423 --- /dev/null +++ b/lib/private/App/AppStore/AppNotFoundException.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\App\AppStore; + +class AppNotFoundException extends \Exception { +} diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 60896ec429d..3bbef3252f4 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace OC; use Doctrine\DBAL\Exception\TableExistsException; +use OC\App\AppStore\AppNotFoundException; use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; use OC\AppFramework\Bootstrap\Coordinator; @@ -174,6 +175,7 @@ class Installer { * @param string $appId * @param bool [$allowUnstable] * + * @throws AppNotFoundException If the app is not found on the appstore * @throws \Exception If the installation was not successful */ public function downloadApp(string $appId, bool $allowUnstable = false): void { @@ -356,9 +358,9 @@ class Installer { } } - throw new \Exception( + throw new AppNotFoundException( sprintf( - 'Could not download app %s', + 'Could not download app %s, it was not found on the appstore', $appId ) ); |