3rd-party apps are disabled on upgrade - refs #14026

This commit is contained in:
Thomas Müller 2015-02-17 12:00:39 +01:00
parent e5c6af5102
commit bbf7f56f94
7 changed files with 87 additions and 85 deletions

View File

@ -36,9 +36,12 @@ if (OC::checkUpgrade(false)) {
$eventSource = \OC::$server->createEventSource(); $eventSource = \OC::$server->createEventSource();
$updater = new \OC\Updater( $updater = new \OC\Updater(
\OC::$server->getHTTPHelper(), \OC::$server->getHTTPHelper(),
\OC::$server->getAppConfig(), \OC::$server->getConfig(),
\OC_Log::$object \OC_Log::$object
); );
$incompatibleApps = [];
$disabledThirdPartyApps = [];
$updater->listen('\OC\Updater', 'maintenanceStart', function () use ($eventSource, $l) { $updater->listen('\OC\Updater', 'maintenanceStart', function () use ($eventSource, $l) {
$eventSource->send('success', (string)$l->t('Turned on maintenance mode')); $eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
}); });
@ -57,13 +60,11 @@ if (OC::checkUpgrade(false)) {
$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) { $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
$eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version))); $eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version)));
}); });
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use ($eventSource, $l) { $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
$list = array(); $incompatibleApps[]= $app;
foreach ($appList as $appId) { });
$info = OC_App::getAppInfo($appId); $updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use (&$disabledThirdPartyApps) {
$list[] = $info['name'] . ' (' . $info['id'] . ')'; $disabledThirdPartyApps[]= $app;
}
$eventSource->send('success', (string)$l->t('Disabled incompatible apps: %s', implode(', ', $list)));
}); });
$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) { $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) {
$eventSource->send('failure', $message); $eventSource->send('failure', $message);
@ -73,6 +74,15 @@ if (OC::checkUpgrade(false)) {
$updater->upgrade(); $updater->upgrade();
if (!empty($incompatibleApps)) {
$eventSource->send('notice',
(string)$l->t('Following incompatible apps have been disabled: %s', implode(', ', $incompatibleApps)));
}
if (!empty($disabledThirdPartyApps)) {
$eventSource->send('notice',
(string)$l->t('Following 3rd party apps have been disabled: %s', implode(', ', $disabledThirdPartyApps)));
}
$eventSource->send('done', ''); $eventSource->send('done', '');
$eventSource->close(); $eventSource->close();
} }

View File

@ -100,7 +100,8 @@ class Upgrade extends Command {
if(\OC::checkUpgrade(false)) { if(\OC::checkUpgrade(false)) {
$self = $this; $self = $this;
$updater = new Updater(\OC::$server->getHTTPHelper(), \OC::$server->getAppConfig()); $updater = new Updater(\OC::$server->getHTTPHelper(),
\OC::$server->getConfig());
$updater->setSimulateStepEnabled($simulateStepEnabled); $updater->setSimulateStepEnabled($simulateStepEnabled);
$updater->setUpdateStepEnabled($updateStepEnabled); $updater->setUpdateStepEnabled($updateStepEnabled);
@ -122,8 +123,11 @@ class Upgrade extends Command {
$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) { $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
$output->writeln('<info>Checked database schema update</info>'); $output->writeln('<info>Checked database schema update</info>');
}); });
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use($output) { $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) {
$output->writeln('<info>Disabled incompatible apps: ' . implode(', ', $appList) . '</info>'); $output->writeln('<info>Disabled incompatible app: ' . $app . '</info>');
});
$updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use($output) {
$output->writeln('<info>Disabled 3rd-party app: ' . $app . '</info>');
}); });
$updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) { $updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) {

View File

@ -38,6 +38,9 @@
updateEventSource.listen('success', function(message) { updateEventSource.listen('success', function(message) {
$('<span>').append(message).append('<br />').appendTo($el); $('<span>').append(message).append('<br />').appendTo($el);
}); });
updateEventSource.listen('notice', function(message) {
$('<span>').addClass('error').append(message).append('<br />').appendTo($el);
});
updateEventSource.listen('error', function(message) { updateEventSource.listen('error', function(message) {
$('<span>').addClass('error').append(message).append('<br />').appendTo($el); $('<span>').addClass('error').append(message).append('<br />').appendTo($el);
message = t('core', 'Please reload the page.'); message = t('core', 'Please reload the page.');

View File

@ -958,39 +958,6 @@ class OC_App {
return false; return false;
} }
/**
* check if the current enabled apps are compatible with the current
* ownCloud version. disable them if not.
* This is important if you upgrade ownCloud and have non ported 3rd
* party apps installed.
*
* @param array $apps optional app id list to check, uses all enabled apps
* when not specified
*
* @return array containing the list of ids of the disabled apps
*/
public static function checkAppsRequirements($apps = array()) {
$disabledApps = array();
if (empty($apps)) {
$apps = OC_App::getEnabledApps();
}
$version = OC_Util::getVersion();
foreach ($apps as $app) {
// check if the app is compatible with this version of ownCloud
$info = OC_App::getAppInfo($app);
if (!self::isAppCompatible($version, $info)) {
OC_Log::write('core',
'App "' . $info['name'] . '" (' . $app . ') can\'t be used because it is'
. ' not compatible with this version of ownCloud',
OC_Log::ERROR);
OC_App::disable($app);
OC_Hook::emit('update', 'success', 'Disabled ' . $info['name'] . ' app because it is not compatible');
$disabledApps[] = $app;
}
}
return $disabledApps;
}
/** /**
* Adjust the number of version parts of $version1 to match * Adjust the number of version parts of $version1 to match
* the number of version parts of $version2. * the number of version parts of $version2.

View File

@ -77,7 +77,8 @@ class OC_TemplateLayout extends OC_Template {
// Update notification // Update notification
if($this->config->getSystemValue('updatechecker', true) === true && if($this->config->getSystemValue('updatechecker', true) === true &&
OC_User::isAdminUser(OC_User::getUser())) { OC_User::isAdminUser(OC_User::getUser())) {
$updater = new \OC\Updater(\OC::$server->getHTTPHelper(), \OC::$server->getAppConfig()); $updater = new \OC\Updater(\OC::$server->getHTTPHelper(),
\OC::$server->getConfig());
$data = $updater->check(); $data = $updater->check();
if(isset($data['version']) && $data['version'] != '' and $data['version'] !== Array()) { if(isset($data['version']) && $data['version'] != '' and $data['version'] !== Array()) {

View File

@ -30,6 +30,9 @@
namespace OC; namespace OC;
use OC\Hooks\BasicEmitter; use OC\Hooks\BasicEmitter;
use OC_App;
use OC_Util;
use OCP\IConfig;
/** /**
* Class that handles autoupdating of ownCloud * Class that handles autoupdating of ownCloud
@ -42,29 +45,27 @@ use OC\Hooks\BasicEmitter;
*/ */
class Updater extends BasicEmitter { class Updater extends BasicEmitter {
/** /** @var \OC\Log $log */
* @var \OC\Log $log
*/
private $log; private $log;
/** /** @var \OC\HTTPHelper $helper */
* @var \OC\HTTPHelper $helper;
*/
private $httpHelper; private $httpHelper;
/** /** @var IConfig */
* @var \OCP\IAppConfig;
*/
private $config; private $config;
/** @var bool */
private $simulateStepEnabled; private $simulateStepEnabled;
/** @var bool */
private $updateStepEnabled; private $updateStepEnabled;
/** /**
* @param HTTPHelper $httpHelper
* @param IConfig $config
* @param \OC\Log $log * @param \OC\Log $log
*/ */
public function __construct($httpHelper, $config, $log = null) { public function __construct(HTTPHelper $httpHelper, IConfig $config, $log = null) {
$this->httpHelper = $httpHelper; $this->httpHelper = $httpHelper;
$this->log = $log; $this->log = $log;
$this->config = $config; $this->config = $config;
@ -102,23 +103,23 @@ class Updater extends BasicEmitter {
public function check($updaterUrl = null) { public function check($updaterUrl = null) {
// Look up the cache - it is invalidated all 30 minutes // Look up the cache - it is invalidated all 30 minutes
if (($this->config->getValue('core', 'lastupdatedat') + 1800) > time()) { if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
return json_decode($this->config->getValue('core', 'lastupdateResult'), true); return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true);
} }
if (is_null($updaterUrl)) { if (is_null($updaterUrl)) {
$updaterUrl = 'https://apps.owncloud.com/updater.php'; $updaterUrl = 'https://apps.owncloud.com/updater.php';
} }
$this->config->setValue('core', 'lastupdatedat', time()); $this->config->setAppValue('core', 'lastupdatedat', time());
if ($this->config->getValue('core', 'installedat', '') == '') { if ($this->config->getAppValue('core', 'installedat', '') == '') {
$this->config->setValue('core', 'installedat', microtime(true)); $this->config->setAppValue('core', 'installedat', microtime(true));
} }
$version = \OC_Util::getVersion(); $version = \OC_Util::getVersion();
$version['installed'] = $this->config->getValue('core', 'installedat'); $version['installed'] = $this->config->getAppValue('core', 'installedat');
$version['updated'] = $this->config->getValue('core', 'lastupdatedat'); $version['updated'] = $this->config->getAppValue('core', 'lastupdatedat');
$version['updatechannel'] = \OC_Util::getChannel(); $version['updatechannel'] = \OC_Util::getChannel();
$version['edition'] = \OC_Util::getEditionString(); $version['edition'] = \OC_Util::getEditionString();
$version['build'] = \OC_Util::getBuild(); $version['build'] = \OC_Util::getBuild();
@ -146,7 +147,7 @@ class Updater extends BasicEmitter {
} }
// Cache the result // Cache the result
$this->config->setValue('core', 'lastupdateResult', json_encode($data)); $this->config->setAppValue('core', 'lastupdateResult', json_encode($data));
return $tmp; return $tmp;
} }
@ -157,9 +158,9 @@ class Updater extends BasicEmitter {
* @return bool true if the operation succeeded, false otherwise * @return bool true if the operation succeeded, false otherwise
*/ */
public function upgrade() { public function upgrade() {
\OC_Config::setValue('maintenance', true); $this->config->setSystemValue('maintenance', true);
$installedVersion = \OC_Config::getValue('version', '0.0.0'); $installedVersion = $this->config->getSystemValue('version', '0.0.0');
$currentVersion = implode('.', \OC_Util::getVersion()); $currentVersion = implode('.', \OC_Util::getVersion());
if ($this->log) { if ($this->log) {
$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
@ -172,7 +173,7 @@ class Updater extends BasicEmitter {
$this->emit('\OC\Updater', 'failure', array($exception->getMessage())); $this->emit('\OC\Updater', 'failure', array($exception->getMessage()));
} }
\OC_Config::setValue('maintenance', false); $this->config->setSystemValue('maintenance', false);
$this->emit('\OC\Updater', 'maintenanceEnd'); $this->emit('\OC\Updater', 'maintenanceEnd');
} }
@ -220,10 +221,10 @@ class Updater extends BasicEmitter {
// create empty file in data dir, so we can later find // create empty file in data dir, so we can later find
// out that this is indeed an ownCloud data directory // out that this is indeed an ownCloud data directory
// (in case it didn't exist before) // (in case it didn't exist before)
file_put_contents(\OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', ''); file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
// pre-upgrade repairs // pre-upgrade repairs
$repair = new \OC\Repair(\OC\Repair::getBeforeUpgradeRepairSteps()); $repair = new Repair(Repair::getBeforeUpgradeRepairSteps());
$repair->run(); $repair->run();
// simulate DB upgrade // simulate DB upgrade
@ -238,22 +239,18 @@ class Updater extends BasicEmitter {
if ($this->updateStepEnabled) { if ($this->updateStepEnabled) {
$this->doCoreUpgrade(); $this->doCoreUpgrade();
$disabledApps = \OC_App::checkAppsRequirements(); $this->checkAppsRequirements();
if (!empty($disabledApps)) {
$this->emit('\OC\Updater', 'disabledApps', array($disabledApps));
}
$this->doAppUpgrade(); $this->doAppUpgrade();
// post-upgrade repairs // post-upgrade repairs
$repair = new \OC\Repair(\OC\Repair::getRepairSteps()); $repair = new Repair(Repair::getRepairSteps());
$repair->run(); $repair->run();
//Invalidate update feed //Invalidate update feed
$this->config->setValue('core', 'lastupdatedat', 0); $this->config->setAppValue('core', 'lastupdatedat', 0);
// only set the final version if everything went well // only set the final version if everything went well
\OC_Config::setValue('version', implode('.', \OC_Util::getVersion())); $this->config->setSystemValue('version', implode('.', \OC_Util::getVersion()));
} }
} }
@ -278,14 +275,11 @@ class Updater extends BasicEmitter {
$apps = \OC_App::getEnabledApps(); $apps = \OC_App::getEnabledApps();
foreach ($apps as $appId) { foreach ($apps as $appId) {
if ($version) { $info = \OC_App::getAppInfo($appId);
$info = \OC_App::getAppInfo($appId); $compatible = \OC_App::isAppCompatible($version, $info);
$compatible = \OC_App::isAppCompatible($version, $info); $isShipped = \OC_App::isShipped($appId);
} else {
$compatible = true;
}
if ($compatible && \OC_App::shouldUpgrade($appId)) { if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
/** /**
* FIXME: The preupdate check is performed before the database migration, otherwise database changes * FIXME: The preupdate check is performed before the database migration, otherwise database changes
* are not possible anymore within it. - Consider this when touching the code. * are not possible anymore within it. - Consider this when touching the code.
@ -356,5 +350,28 @@ class Updater extends BasicEmitter {
} }
} }
} }
/**
* check if the current enabled apps are compatible with the current
* ownCloud version. disable them if not.
* This is important if you upgrade ownCloud and have non ported 3rd
* party apps installed.
*/
private function checkAppsRequirements() {
$apps = OC_App::getEnabledApps();
$version = OC_Util::getVersion();
foreach ($apps as $app) {
// check if the app is compatible with this version of ownCloud
$info = OC_App::getAppInfo($app);
if(!OC_App::isAppCompatible($version, $info)) {
OC_App::disable($app);
$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
}
if (!OC_App::isShipped($app)) {
\OC_App::disable($app);
$this->emit('\OC\Updater', 'thirdPartyAppDisabled', array($app));
}
}
}
} }

View File

@ -88,7 +88,7 @@ class UpdaterTest extends \Test\TestCase {
protected function getUpdaterMock($content){ protected function getUpdaterMock($content){
// Invalidate cache // Invalidate cache
$mockedAppConfig = $this->getMockBuilder('\OC\AppConfig') $mockedConfig = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock() ->getMock()
; ;
@ -101,7 +101,7 @@ class UpdaterTest extends \Test\TestCase {
$mockedHTTPHelper->expects($this->once())->method('getUrlContent')->will($this->returnValue($content)); $mockedHTTPHelper->expects($this->once())->method('getUrlContent')->will($this->returnValue($content));
return new Updater($mockedHTTPHelper, $mockedAppConfig); return new Updater($mockedHTTPHelper, $mockedConfig);
} }
} }