From 47cd9760350baaf24bdf92c7a77129e59ec2f8f3 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sun, 23 Apr 2017 22:10:17 +0200 Subject: [PATCH] Add app bundles Signed-off-by: Lukas Reschke --- lib/composer/composer/autoload_classmap.php | 6 ++ lib/composer/composer/autoload_static.php | 6 ++ lib/private/App/AppStore/Bundles/Bundle.php | 66 ++++++++++++++++ .../App/AppStore/Bundles/BundleFetcher.php | 79 +++++++++++++++++++ .../App/AppStore/Bundles/CoreBundle.php | 49 ++++++++++++ .../App/AppStore/Bundles/EnterpriseBundle.php | 54 +++++++++++++ .../App/AppStore/Bundles/GroupwareBundle.php | 50 ++++++++++++ lib/private/Installer.php | 33 +++++++- lib/private/Repair.php | 7 ++ lib/private/Repair/NC12/InstallCoreBundle.php | 78 ++++++++++++++++++ lib/private/Server.php | 8 +- lib/private/Setup.php | 20 ++++- lib/private/Updater.php | 7 +- lib/private/legacy/app.php | 6 +- settings/Controller/AppSettingsController.php | 27 ++++++- settings/ajax/enableapp.php | 17 ++-- settings/ajax/updateapp.php | 3 +- settings/js/apps.js | 36 ++++++++- version.php | 2 +- 19 files changed, 533 insertions(+), 21 deletions(-) create mode 100644 lib/private/App/AppStore/Bundles/Bundle.php create mode 100644 lib/private/App/AppStore/Bundles/BundleFetcher.php create mode 100644 lib/private/App/AppStore/Bundles/CoreBundle.php create mode 100644 lib/private/App/AppStore/Bundles/EnterpriseBundle.php create mode 100644 lib/private/App/AppStore/Bundles/GroupwareBundle.php create mode 100644 lib/private/Repair/NC12/InstallCoreBundle.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 9dea4d10fb..9a26c9c91e 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -318,6 +318,11 @@ return array( 'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php', 'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.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\\CoreBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/CoreBundle.php', + 'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php', + 'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/Fetcher.php', @@ -727,6 +732,7 @@ return array( 'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\MoveAvatars' => $baseDir . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => $baseDir . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', + 'OC\\Repair\\NC12\\InstallCoreBundle' => $baseDir . '/lib/private/Repair/NC12/InstallCoreBundle.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => $baseDir . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\RemoveRootShares' => $baseDir . '/lib/private/Repair/RemoveRootShares.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 11d949de34..8160c65c03 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -348,6 +348,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php', 'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.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\\CoreBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/CoreBundle.php', + 'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php', + 'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/Fetcher.php', @@ -757,6 +762,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\MoveAvatars' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', + 'OC\\Repair\\NC12\\InstallCoreBundle' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/InstallCoreBundle.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\RemoveRootShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveRootShares.php', diff --git a/lib/private/App/AppStore/Bundles/Bundle.php b/lib/private/App/AppStore/Bundles/Bundle.php new file mode 100644 index 0000000000..596f02d51e --- /dev/null +++ b/lib/private/App/AppStore/Bundles/Bundle.php @@ -0,0 +1,66 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\App\AppStore\Bundles; + +use OCP\IL10N; + +abstract class Bundle { + /** @var IL10N */ + protected $l10n; + + /** + * @param IL10N $l10n + */ + public function __construct(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * Get the identifier of the bundle + * + * @return string + */ + public final function getIdentifier() { + return substr(strrchr(get_class($this), '\\'), 1); + } + + /** + * Get the name of the bundle + * + * @return string + */ + public abstract function getName(); + + /** + * Get the description of the bundle + * + * @return string + */ + public abstract function getDescription(); + + /** + * Get the list of app identifiers in the bundle + * + * @return array + */ + public abstract function getAppIdentifiers(); +} diff --git a/lib/private/App/AppStore/Bundles/BundleFetcher.php b/lib/private/App/AppStore/Bundles/BundleFetcher.php new file mode 100644 index 0000000000..3203b1cc5f --- /dev/null +++ b/lib/private/App/AppStore/Bundles/BundleFetcher.php @@ -0,0 +1,79 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\App\AppStore\Bundles; + +use OCP\IL10N; + +class BundleFetcher { + /** @var IL10N */ + private $l10n; + + /** + * @param IL10N $l10n + */ + public function __construct(IL10N $l10n) { + $this->l10n = $l10n; + } + + /** + * @return Bundle[] + */ + public function getBundles() { + return [ + new EnterpriseBundle($this->l10n), + new GroupwareBundle($this->l10n), + ]; + } + + /** + * Bundles that should be installed by default after installation + * + * @return Bundle[] + */ + public function getDefaultInstallationBundle() { + return [ + new CoreBundle($this->l10n), + ]; + } + + /** + * Get the bundle with the specified identifier + * + * @param string $identifier + * @return Bundle + * @throws \BadMethodCallException If the bundle does not exist + */ + public function getBundleByIdentifier($identifier) { + /** @var Bundle[] $bundles */ + $bundles = array_merge( + $this->getBundles(), + $this->getDefaultInstallationBundle() + ); + foreach($bundles as $bundle) { + if($bundle->getIdentifier() === $identifier) { + return $bundle; + } + } + + throw new \BadMethodCallException('Bundle with specified identifier does not exist'); + } +} diff --git a/lib/private/App/AppStore/Bundles/CoreBundle.php b/lib/private/App/AppStore/Bundles/CoreBundle.php new file mode 100644 index 0000000000..b400d0d0f6 --- /dev/null +++ b/lib/private/App/AppStore/Bundles/CoreBundle.php @@ -0,0 +1,49 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\App\AppStore\Bundles; + +class CoreBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Core bundle'); + } + + /** + * {@inheritDoc} + */ + public function getDescription() { + return (string)$this->l10n->t('Default apps required by Nextcloud'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'bruteforcesettings', + ]; + } + +} diff --git a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php new file mode 100644 index 0000000000..ed7c118078 --- /dev/null +++ b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php @@ -0,0 +1,54 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\App\AppStore\Bundles; + +class EnterpriseBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Enterprise bundle'); + } + + /** + * {@inheritDoc} + */ + public function getDescription() { + return (string)$this->l10n->t('Apps for the Enterprise.'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'admin_audit', + 'user_ldap', + 'files_retention', + 'files_automatedtagging', + 'user_saml', + 'files_accesscontrol', + ]; + } + +} diff --git a/lib/private/App/AppStore/Bundles/GroupwareBundle.php b/lib/private/App/AppStore/Bundles/GroupwareBundle.php new file mode 100644 index 0000000000..b05a54accf --- /dev/null +++ b/lib/private/App/AppStore/Bundles/GroupwareBundle.php @@ -0,0 +1,50 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\App\AppStore\Bundles; + +class GroupwareBundle extends Bundle { + + /** + * {@inheritDoc} + */ + public function getName() { + return (string)$this->l10n->t('Groupware bundle'); + } + + /** + * {@inheritDoc} + */ + public function getDescription() { + return (string)$this->l10n->t('Apps for groupware functionalities.'); + } + + /** + * {@inheritDoc} + */ + public function getAppIdentifiers() { + return [ + 'calendar', + 'contacts', + ]; + } + +} diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 0d6030d574..8702f264e5 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -42,6 +42,8 @@ namespace OC; use Doctrine\DBAL\Exception\TableExistsException; +use OC\App\AppManager; +use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\CodeChecker\CodeChecker; use OC\App\CodeChecker\EmptyCheck; @@ -50,7 +52,9 @@ use OC\Archive\TAR; use OC_App; use OC_DB; use OC_Helper; +use OCP\App\IAppManager; use OCP\Http\Client\IClientService; +use OCP\IConfig; use OCP\ILogger; use OCP\ITempManager; use phpseclib\File\X509; @@ -67,21 +71,26 @@ class Installer { private $tempManager; /** @var ILogger */ private $logger; + /** @var IConfig */ + private $config; /** * @param AppFetcher $appFetcher * @param IClientService $clientService * @param ITempManager $tempManager * @param ILogger $logger + * @param IConfig $config */ public function __construct(AppFetcher $appFetcher, IClientService $clientService, ITempManager $tempManager, - ILogger $logger) { + ILogger $logger, + IConfig $config) { $this->appFetcher = $appFetcher; $this->clientService = $clientService; $this->tempManager = $tempManager; $this->logger = $logger; + $this->config = $config; } /** @@ -109,6 +118,7 @@ class Installer { } } + \OC_App::registerAutoloading($appId, $basedir); \OC_App::setupBackgroundJobs($info['background-jobs']); //run appinfo/install.php @@ -419,6 +429,27 @@ class Installer { } + /** + * Installs the app within the bundle and marks the bundle as installed + * + * @param Bundle $bundle + * @throws \Exception If app could not get installed + */ + public function installAppBundle(Bundle $bundle) { + $appIds = $bundle->getAppIdentifiers(); + foreach($appIds as $appId) { + if(!$this->isDownloaded($appId)) { + $this->downloadApp($appId); + } + $this->installApp($appId); + $app = new OC_App(); + $app->enable($appId); + } + $bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true); + $bundles[] = $bundle->getIdentifier(); + $this->config->setAppValue('core', 'installed.bundles', json_encode($bundles)); + } + /** * Installs shipped apps * diff --git a/lib/private/Repair.php b/lib/private/Repair.php index e808774ec9..65e0342905 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -30,12 +30,14 @@ namespace OC; +use OC\App\AppStore\Bundles\BundleFetcher; use OC\Repair\CleanTags; use OC\Repair\Collation; use OC\Repair\MoveUpdaterStepFile; use OC\Repair\NC11\CleanPreviews; use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC11\MoveAvatars; +use OC\Repair\NC12\InstallCoreBundle; use OC\Repair\NC12\UpdateLanguageCodes; use OC\Repair\OldGroupMembershipShares; use OC\Repair\RemoveRootShares; @@ -136,6 +138,11 @@ class Repair implements IOutput{ ), new FixMountStorages(\OC::$server->getDatabaseConnection()), new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), + new InstallCoreBundle( + \OC::$server->query(BundleFetcher::class), + \OC::$server->getConfig(), + \OC::$server->query(Installer::class) + ) ]; } diff --git a/lib/private/Repair/NC12/InstallCoreBundle.php b/lib/private/Repair/NC12/InstallCoreBundle.php new file mode 100644 index 0000000000..4028b0c875 --- /dev/null +++ b/lib/private/Repair/NC12/InstallCoreBundle.php @@ -0,0 +1,78 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Repair\NC12; + +use OC\App\AppStore\Bundles\BundleFetcher; +use OC\Installer; +use OCP\IConfig; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class InstallCoreBundle implements IRepairStep { + /** @var BundleFetcher */ + private $bundleFetcher; + /** @var IConfig */ + private $config; + /** @var Installer */ + private $installer; + + /** + * @param BundleFetcher $bundleFetcher + * @param IConfig $config + * @param Installer $installer + */ + public function __construct(BundleFetcher $bundleFetcher, + IConfig $config, + Installer $installer) { + $this->bundleFetcher = $bundleFetcher; + $this->config = $config; + $this->installer = $installer; + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'Install new core bundle components'; + } + + /** + * {@inheritdoc} + */ + public function run(IOutput $output) { + $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0'); + + if (version_compare($versionFromBeforeUpdate, '12.0.0.14', '>')) { + return; + } + + $defaultBundle = $this->bundleFetcher->getDefaultInstallationBundle(); + foreach($defaultBundle as $bundle) { + try { + $this->installer->installAppBundle($bundle); + $output->info('Successfully installed core app bundle.'); + } catch (\Exception $e) { + $output->warning('Could not install core app bundle:' . $e->getMessage()); + } + } + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 7724feb551..b05e05660b 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -43,6 +43,7 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; use OC\App\AppManager; +use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\AppFramework\Http\Request; @@ -816,7 +817,12 @@ class Server extends ServerContainer implements IServerContainer { ); }); $this->registerAlias('MimeTypeLoader', \OCP\Files\IMimeTypeLoader::class); - + $this->registerService(BundleFetcher::class, function () { + return new BundleFetcher($this->getL10N('lib')); + }); + $this->registerService(AppFetcher::class, function() { + return $this->getAppFetcher(); + }); $this->registerService(\OCP\Notification\IManager::class, function (Server $c) { return new Manager( $c->query(IValidator::class) diff --git a/lib/private/Setup.php b/lib/private/Setup.php index e2806efad4..b1cf289d9a 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -41,6 +41,7 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; use Exception; +use OC\App\AppStore\Bundles\BundleFetcher; use OCP\Defaults; use OCP\IL10N; use OCP\ILogger; @@ -63,11 +64,12 @@ class Setup { /** * @param SystemConfig $config * @param IniGetWrapper $iniWrapper + * @param IL10N $l10n * @param Defaults $defaults * @param ILogger $logger * @param ISecureRandom $random */ - function __construct(SystemConfig $config, + public function __construct(SystemConfig $config, IniGetWrapper $iniWrapper, IL10N $l10n, Defaults $defaults, @@ -364,8 +366,22 @@ class Setup { $group =\OC::$server->getGroupManager()->createGroup('admin'); $group->addUser($user); - //guess what this does + // Install shipped apps and specified app bundles Installer::installShippedApps(); + $installer = new Installer( + \OC::$server->getAppFetcher(), + \OC::$server->getHTTPClientService(), + \OC::$server->getTempManager(), + \OC::$server->getLogger(), + \OC::$server->getConfig() + ); + $bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib')); + $defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle(); + foreach($defaultInstallationBundles as $bundle) { + try { + $installer->installAppBundle($bundle); + } catch (Exception $e) {} + } // create empty file in data dir, so we can later find // out that this is indeed an ownCloud data directory diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 4427e4c48d..c080ee0eb4 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -243,11 +243,11 @@ class Updater extends BasicEmitter { } // update all shipped apps - $disabledApps = $this->checkAppsRequirements(); + $this->checkAppsRequirements(); $this->doAppUpgrade(); // upgrade appstore apps - $this->upgradeAppStoreApps($disabledApps); + $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps()); // install new shipped apps on upgrade OC_App::loadApps('authentication'); @@ -441,7 +441,8 @@ class Updater extends BasicEmitter { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - $this->log + $this->log, + \OC::$server->getConfig() ); if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) { $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]); diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index 3800b8b770..111da7d0d4 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -365,7 +365,8 @@ class OC_App { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getConfig() ); $isDownloaded = $installer->isDownloaded($appId); @@ -427,7 +428,8 @@ class OC_App { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getConfig() ); return $installer->removeApp($app); } diff --git a/settings/Controller/AppSettingsController.php b/settings/Controller/AppSettingsController.php index 7be6c2bf56..0d204bd47a 100644 --- a/settings/Controller/AppSettingsController.php +++ b/settings/Controller/AppSettingsController.php @@ -27,6 +27,7 @@ namespace OC\Settings\Controller; +use OC\App\AppStore\Bundles\BundleFetcher; use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Version\VersionParser; @@ -50,6 +51,7 @@ class AppSettingsController extends Controller { const CAT_ENABLED = 0; const CAT_DISABLED = 1; const CAT_ALL_INSTALLED = 2; + const CAT_APP_BUNDLES = 3; /** @var \OCP\IL10N */ private $l10n; @@ -65,6 +67,8 @@ class AppSettingsController extends Controller { private $appFetcher; /** @var IFactory */ private $l10nFactory; + /** @var BundleFetcher */ + private $bundleFetcher; /** * @param string $appName @@ -76,6 +80,7 @@ class AppSettingsController extends Controller { * @param CategoryFetcher $categoryFetcher * @param AppFetcher $appFetcher * @param IFactory $l10nFactory + * @param BundleFetcher $bundleFetcher */ public function __construct($appName, IRequest $request, @@ -85,7 +90,8 @@ class AppSettingsController extends Controller { IAppManager $appManager, CategoryFetcher $categoryFetcher, AppFetcher $appFetcher, - IFactory $l10nFactory) { + IFactory $l10nFactory, + BundleFetcher $bundleFetcher) { parent::__construct($appName, $request); $this->l10n = $l10n; $this->config = $config; @@ -94,6 +100,7 @@ class AppSettingsController extends Controller { $this->categoryFetcher = $categoryFetcher; $this->appFetcher = $appFetcher; $this->l10nFactory = $l10nFactory; + $this->bundleFetcher = $bundleFetcher; } /** @@ -131,6 +138,7 @@ class AppSettingsController extends Controller { $formattedCategories = [ ['id' => self::CAT_ALL_INSTALLED, 'ident' => 'installed', 'displayName' => (string)$this->l10n->t('Your apps')], ['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled apps')], + ['id' => self::CAT_APP_BUNDLES, 'ident' => 'app-bundles', 'displayName' => (string)$this->l10n->t('App bundles')], ['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Disabled apps')], ]; $categories = $this->categoryFetcher->get(); @@ -334,6 +342,23 @@ class AppSettingsController extends Controller { return ($a < $b) ? -1 : 1; }); break; + case 'app-bundles': + $bundles = $this->bundleFetcher->getBundles(); + $apps = []; + foreach($bundles as $bundle) { + $apps[] = [ + 'id' => $bundle->getIdentifier(), + 'author' => 'Nextcloud', + 'name' => $bundle->getName() . ' (' . $bundle->getDescription() .')', + 'description' => '', + 'internal' => true, + 'active' => false, + 'removable' => false, + 'groups' => [], + 'apps' => $bundle->getAppIdentifiers(), + ]; + } + break; default: $apps = $this->getAppsForCategory($category); diff --git a/settings/ajax/enableapp.php b/settings/ajax/enableapp.php index b6d62671a6..4c4fa0be66 100644 --- a/settings/ajax/enableapp.php +++ b/settings/ajax/enableapp.php @@ -36,13 +36,20 @@ if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay } $groups = isset($_POST['groups']) ? (array)$_POST['groups'] : null; +$appIds = isset($_POST['appIds']) ? (array)$_POST['appIds'] : []; try { - $app = new OC_App(); - $appId = (string)$_POST['appid']; - $appId = OC_App::cleanAppId($appId); - $app->enable($appId, $groups); - OC_JSON::success(['data' => ['update_required' => \OC_App::shouldUpgrade($appId)]]); + $updateRequired = false; + foreach($appIds as $appId) { + $app = new OC_App(); + $appId = OC_App::cleanAppId($appId); + $app->enable($appId, $groups); + if(\OC_App::shouldUpgrade($appId)) { + $updateRequired = true; + } + } + + OC_JSON::success(['data' => ['update_required' => $updateRequired]]); } catch (Exception $e) { \OCP\Util::writeLog('core', $e->getMessage(), \OCP\Util::ERROR); OC_JSON::error(array("data" => array("message" => $e->getMessage()) )); diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php index 3020f82857..bcf8e14914 100644 --- a/settings/ajax/updateapp.php +++ b/settings/ajax/updateapp.php @@ -44,7 +44,8 @@ try { \OC::$server->getAppFetcher(), \OC::$server->getHTTPClientService(), \OC::$server->getTempManager(), - \OC::$server->getLogger() + \OC::$server->getLogger(), + \OC::$server->getConfig() ); $result = $installer->updateAppstoreApp($appId); $config->setSystemValue('maintenance', false); diff --git a/settings/js/apps.js b/settings/js/apps.js index 3326886951..cda0b5112e 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -29,6 +29,7 @@ OC.Settings.Apps = OC.Settings.Apps || { State: { currentCategory: null, + currentCategoryElements: null, apps: null, $updateNotification: null, availableUpdates: 0 @@ -90,14 +91,15 @@ OC.Settings.Apps = OC.Settings.Apps || { }), { type:'GET', success: function (apps) { + OC.Settings.Apps.State.currentCategoryElements = apps.apps; var appListWithIndex = _.indexBy(apps.apps, 'id'); OC.Settings.Apps.State.apps = appListWithIndex; var appList = _.map(appListWithIndex, function(app) { // default values for missing fields return _.extend({level: 0}, app); }); - var source - if (categoryId === 'enabled' || categoryId === 'disabled' || categoryId === 'installed') { + var source; + if (categoryId === 'enabled' || categoryId === 'disabled' || categoryId === 'installed' || categoryId === 'app-bundles') { source = $("#app-template-installed").html(); $('#apps-list').addClass('installed'); } else { @@ -303,6 +305,20 @@ OC.Settings.Apps = OC.Settings.Apps || { return $.get(OC.generateUrl('apps/files')); }, + enableAppBundle:function(bundleId, active, element, groups) { + if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { + OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.enableAppBundle, this, bundleId, active, element, groups)); + return; + } + + var bundles = OC.Settings.Apps.State.currentCategoryElements; + bundles.forEach(function(bundle) { + if(bundle['id'] === bundleId) { + OC.Settings.Apps.enableApp(bundle['apps'], active, element, groups); + } + }); + }, + enableApp:function(appId, active, element, groups) { if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.enableApp, this, appId, active, element, groups)); @@ -342,7 +358,14 @@ OC.Settings.Apps = OC.Settings.Apps || { // TODO: display message to admin to not refresh the page! // TODO: lock UI to prevent further operations element.val(t('settings','Enabling app …')); - $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appId, groups: groups},function(result) { + + var appIdArray = []; + if( typeof appId === 'string' ) { + appIdArray = [appId]; + } else { + appIdArray = appId; + } + $.post(OC.filePath('settings','ajax','enableapp.php'),{appIds: appIdArray, groups: groups},function(result) { if(!result || result.status !== 'success') { if (result.data && result.data.message) { OC.Settings.Apps.showErrorMessage(appId, result.data.message); @@ -777,7 +800,12 @@ OC.Settings.Apps = OC.Settings.Apps || { var element = $(this); var active = $(this).data('active'); - OC.Settings.Apps.enableApp(appId, active, element); + var category = $('#app-navigation').attr('data-category'); + if(category === 'app-bundles') { + OC.Settings.Apps.enableAppBundle(appId, active, element); + } else { + OC.Settings.Apps.enableApp(appId, active, element); + } }); $(document).on('click', '#apps-list input.uninstall', function () { diff --git a/version.php b/version.php index 0d1d327cb7..011c693d7b 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(12, 0, 0, 14); +$OC_Version = array(12, 0, 0, 15); // The human readable string $OC_VersionString = '12.0 alpha';