diff options
-rw-r--r-- | apps/files_external/lib/config/configadapter.php | 8 | ||||
-rw-r--r-- | apps/files_external/lib/failedstorage.php | 3 | ||||
-rw-r--r-- | apps/files_trashbin/lib/trashbin.php | 2 | ||||
-rw-r--r-- | apps/updatenotification/appinfo/app.php | 8 | ||||
-rw-r--r-- | apps/updatenotification/appinfo/application.php | 12 | ||||
-rw-r--r-- | apps/updatenotification/appinfo/routes.php | 1 | ||||
-rw-r--r-- | apps/updatenotification/controller/admincontroller.php | 58 | ||||
-rw-r--r-- | apps/updatenotification/js/admin.js | 14 | ||||
-rw-r--r-- | apps/updatenotification/templates/admin.php | 42 | ||||
-rw-r--r-- | apps/updatenotification/tests/controller/AdminControllerTest.php | 98 | ||||
-rw-r--r-- | config/config.sample.php | 6 | ||||
-rw-r--r-- | lib/private/comments/comment.php | 2 | ||||
-rw-r--r-- | lib/private/files/storage/wrapper/availability.php | 17 | ||||
-rw-r--r-- | lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php | 5 |
14 files changed, 251 insertions, 25 deletions
diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php index 51c2debd726..d85e0f45631 100644 --- a/apps/files_external/lib/config/configadapter.php +++ b/apps/files_external/lib/config/configadapter.php @@ -23,6 +23,7 @@ namespace OCA\Files_External\Config; +use OC\Files\Storage\Wrapper\Availability; use OCA\Files_external\Migration\StorageMigrator; use OCP\Files\Storage; use OC\Files\Mount\MountPoint; @@ -34,6 +35,7 @@ use OCA\Files_external\Service\UserStoragesService; use OCA\Files_External\Service\UserGlobalStoragesService; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Lib\FailedStorage; +use OCP\Files\StorageNotAvailableException; /** * Make the old files_external config work with the new public mount config api @@ -132,8 +134,10 @@ class ConfigAdapter implements IMountProvider { try { $availability = $impl->getAvailability(); - if (!$availability['available']) { - $impl = new FailedStorage(['exception' => null]); + if (!$availability['available'] && !Availability::shouldRecheck($availability)) { + $impl = new FailedStorage([ + 'exception' => new StorageNotAvailableException('Storage with mount id ' . $storage->getId() . ' is not available') + ]); } } catch (\Exception $e) { // propagate exception into filesystem diff --git a/apps/files_external/lib/failedstorage.php b/apps/files_external/lib/failedstorage.php index 928d09e20f8..20cf43d74b2 100644 --- a/apps/files_external/lib/failedstorage.php +++ b/apps/files_external/lib/failedstorage.php @@ -39,6 +39,9 @@ class FailedStorage extends Common { */ public function __construct($params) { $this->e = $params['exception']; + if (!$this->e) { + throw new \InvalidArgumentException('Missing "exception" argument in FailedStorage constructor'); + } } public function getId() { diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index bcd73639d3c..46447908b90 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -204,7 +204,7 @@ class Trashbin { $ownerView = new View('/' . $owner); // file has been deleted in between - if (!$ownerView->file_exists('/files/' . $ownerPath)) { + if (is_null($ownerPath) || $ownerPath === '' || !$ownerView->file_exists('/files/' . $ownerPath)) { return true; } diff --git a/apps/updatenotification/appinfo/app.php b/apps/updatenotification/appinfo/app.php index 9148b6e6ef7..f257cba6974 100644 --- a/apps/updatenotification/appinfo/app.php +++ b/apps/updatenotification/appinfo/app.php @@ -31,9 +31,11 @@ if(\OC::$server->getConfig()->getSystemValue('updatechecker', true) === true) { $userObject = \OC::$server->getUserSession()->getUser(); if($userObject !== null) { - if(\OC::$server->getGroupManager()->isAdmin($userObject->getUID()) && $updateChecker->getUpdateState() !== []) { - \OCP\Util::addScript('updatenotification', 'notification'); - OC_Hook::connect('\OCP\Config', 'js', $updateChecker, 'getJavaScript'); + if(\OC::$server->getGroupManager()->isAdmin($userObject->getUID())) { + if($updateChecker->getUpdateState() !== []) { + \OCP\Util::addScript('updatenotification', 'notification'); + OC_Hook::connect('\OCP\Config', 'js', $updateChecker, 'getJavaScript'); + } \OC_App::registerAdmin('updatenotification', 'admin'); } } diff --git a/apps/updatenotification/appinfo/application.php b/apps/updatenotification/appinfo/application.php index ae3317c1b54..24c0a11af69 100644 --- a/apps/updatenotification/appinfo/application.php +++ b/apps/updatenotification/appinfo/application.php @@ -22,7 +22,9 @@ namespace OCA\UpdateNotification\AppInfo; use OC\AppFramework\Utility\TimeFactory; +use OC\Updater; use OCA\UpdateNotification\Controller\AdminController; +use OCA\UpdateNotification\UpdateChecker; use OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; @@ -32,13 +34,21 @@ class Application extends App { $container = $this->getContainer(); $container->registerService('AdminController', function(IAppContainer $c) { + $updater = new \OC\Updater( + \OC::$server->getHTTPHelper(), + \OC::$server->getConfig(), + \OC::$server->getIntegrityCodeChecker() + ); return new AdminController( $c->query('AppName'), $c->query('Request'), $c->getServer()->getJobList(), $c->getServer()->getSecureRandom(), $c->getServer()->getConfig(), - new TimeFactory() + new TimeFactory(), + $c->getServer()->getL10N($c->query('AppName')), + new UpdateChecker($updater), + $c->getServer()->getDateTimeFormatter() ); }); } diff --git a/apps/updatenotification/appinfo/routes.php b/apps/updatenotification/appinfo/routes.php index 2cf43c89769..9021d381b1b 100644 --- a/apps/updatenotification/appinfo/routes.php +++ b/apps/updatenotification/appinfo/routes.php @@ -24,4 +24,5 @@ namespace OCA\UpdateNotification\AppInfo; $application = new Application(); $application->registerRoutes($this, ['routes' => [ ['name' => 'Admin#createCredentials', 'url' => '/credentials', 'verb' => 'GET'], + ['name' => 'Admin#setChannel', 'url' => '/channel', 'verb' => 'POST'], ]]); diff --git a/apps/updatenotification/controller/admincontroller.php b/apps/updatenotification/controller/admincontroller.php index 505ea01edd9..cb0c6409d7e 100644 --- a/apps/updatenotification/controller/admincontroller.php +++ b/apps/updatenotification/controller/admincontroller.php @@ -21,12 +21,15 @@ namespace OCA\UpdateNotification\Controller; +use OCA\UpdateNotification\UpdateChecker; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\IConfig; +use OCP\IDateTimeFormatter; +use OCP\IL10N; use OCP\IRequest; use OCP\Security\ISecureRandom; @@ -39,6 +42,12 @@ class AdminController extends Controller { private $config; /** @var ITimeFactory */ private $timeFactory; + /** @var UpdateChecker */ + private $updateChecker; + /** @var IL10N */ + private $l10n; + /** @var IDateTimeFormatter */ + private $dateTimeFormatter; /** * @param string $appName @@ -47,25 +56,70 @@ class AdminController extends Controller { * @param ISecureRandom $secureRandom * @param IConfig $config * @param ITimeFactory $timeFactory + * @param IL10N $l10n + * @param UpdateChecker $updateChecker + * @param IDateTimeFormatter $dateTimeFormatter */ public function __construct($appName, IRequest $request, IJobList $jobList, ISecureRandom $secureRandom, IConfig $config, - ITimeFactory $timeFactory) { + ITimeFactory $timeFactory, + IL10N $l10n, + UpdateChecker $updateChecker, + IDateTimeFormatter $dateTimeFormatter) { parent::__construct($appName, $request); $this->jobList = $jobList; $this->secureRandom = $secureRandom; $this->config = $config; $this->timeFactory = $timeFactory; + $this->l10n = $l10n; + $this->updateChecker = $updateChecker; + $this->dateTimeFormatter = $dateTimeFormatter; } /** * @return TemplateResponse */ public function displayPanel() { - return new TemplateResponse($this->appName, 'admin', [], ''); + $lastUpdateCheck = $this->dateTimeFormatter->formatDateTime( + $this->config->getAppValue('core', 'lastupdatedat') + ); + + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + + $params = [ + 'isNewVersionAvailable' => ($this->updateChecker->getUpdateState() === []) ? false : true, + 'lastChecked' => $lastUpdateCheck, + 'currentChannel' => $currentChannel, + 'channels' => $channels, + ]; + + return new TemplateResponse($this->appName, 'admin', $params, ''); + } + + /** + * @UseSession + * + * @param string $channel + * @return DataResponse + */ + public function setChannel($channel) { + \OCP\Util::setChannel($channel); + $this->config->setAppValue('core', 'lastupdatedat', 0); + return new DataResponse(['status' => 'success', 'data' => ['message' => $this->l10n->t('Updated channel')]]); } /** diff --git a/apps/updatenotification/js/admin.js b/apps/updatenotification/js/admin.js index df021fe2e97..2fc8c9d99b1 100644 --- a/apps/updatenotification/js/admin.js +++ b/apps/updatenotification/js/admin.js @@ -15,7 +15,7 @@ */ var loginToken = ''; $(document).ready(function(){ - $('#oca_updatenotification').click(function() { + $('#oca_updatenotification_button').click(function() { // Load the new token $.ajax({ url: OC.generateUrl('/apps/updatenotification/credentials') @@ -39,4 +39,16 @@ $(document).ready(function(){ }); }); }); + $('#release-channel').change(function() { + var newChannel = $('#release-channel').find(":selected").val(); + $.post( + OC.generateUrl('/apps/updatenotification/channel'), + { + 'channel': newChannel + }, + function(data){ + OC.msg.finishedAction('#channel_save_msg', data); + } + ); + }); }); diff --git a/apps/updatenotification/templates/admin.php b/apps/updatenotification/templates/admin.php index 647c88dea17..c1adc8d0d3e 100644 --- a/apps/updatenotification/templates/admin.php +++ b/apps/updatenotification/templates/admin.php @@ -1,8 +1,42 @@ -<?php script('updatenotification', 'admin') ?> -<form id="oca_updatenotification" class="section"> +<?php + script('updatenotification', 'admin'); + + /** @var array $_ */ + /** @var bool $isNewVersionAvailable */ + $isNewVersionAvailable = $_['isNewVersionAvailable']; + /** @var string $newVersionString */ + $newVersionString = $_['newVersionString']; + /** @var string $lastCheckedDate */ + $lastCheckedDate = $_['lastChecked']; + /** @var array $channels */ + $channels = $_['channels']; + /** @var string $currentChannel */ + $currentChannel = $_['currentChannel']; +?> +<form id="oca_updatenotification_section" class="section"> <h2><?php p($l->t('Updater')); ?></h2> + + <?php if($isNewVersionAvailable === true): ?> + <strong><?php p($l->t('A new version is available: %s', [$newVersionString])); ?></strong> + <input type="button" id="oca_updatenotification_button" value="<?php p($l->t('Open updater')) ?>"> + <?php else: ?> + <strong><?php print_unescaped($l->t('Your version is up to date.')); ?></strong> + <span class="icon-info svg" title="<?php p($l->t('Checked on %s', [$lastCheckedDate])) ?>"></span> + <?php endif; ?> + <p> - <?php p($l->t('For security reasons the built-in ownCloud updater is using additional credentials. To visit the updater page please click the following button.')) ?> + <label for="release-channel"><?php p($l->t('Update channel:')) ?></label> + <select id="release-channel"> + <option value="<?php p($currentChannel); ?>"><?php p($currentChannel); ?></option> + <?php foreach ($channels as $channel => $channelTitle){ ?> + <option value="<?php p($channelTitle) ?>"> + <?php p($channelTitle) ?> + </option> + <?php } ?> + </select> + <span id="channel_save_msg"></span> + </p> + <p> + <em><?php p($l->t('You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel.')); ?></em> </p> - <input type="button" id="oca_updatenotification" value="<?php p($l->t('Open updater')) ?>"> </form> diff --git a/apps/updatenotification/tests/controller/AdminControllerTest.php b/apps/updatenotification/tests/controller/AdminControllerTest.php index 5a0f9d21469..50adcd2028b 100644 --- a/apps/updatenotification/tests/controller/AdminControllerTest.php +++ b/apps/updatenotification/tests/controller/AdminControllerTest.php @@ -22,11 +22,14 @@ namespace OCA\UpdateNotification\Tests\Controller; use OCA\UpdateNotification\Controller\AdminController; +use OCA\UpdateNotification\UpdateChecker; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\IConfig; +use OCP\IDateTimeFormatter; +use OCP\IL10N; use OCP\IRequest; use OCP\Security\ISecureRandom; use Test\TestCase; @@ -44,6 +47,12 @@ class AdminControllerTest extends TestCase { private $adminController; /** @var ITimeFactory */ private $timeFactory; + /** @var IL10N */ + private $l10n; + /** @var UpdateChecker */ + private $updateChecker; + /** @var IDateTimeFormatter */ + private $dateTimeFormatter; public function setUp() { parent::setUp(); @@ -53,6 +62,10 @@ class AdminControllerTest extends TestCase { $this->secureRandom = $this->getMock('\\OCP\\Security\\ISecureRandom'); $this->config = $this->getMock('\\OCP\\IConfig'); $this->timeFactory = $this->getMock('\\OCP\\AppFramework\\Utility\\ITimeFactory'); + $this->l10n = $this->getMock('\\OCP\\IL10N'); + $this->updateChecker = $this->getMockBuilder('\\OCA\\UpdateNotification\\UpdateChecker') + ->disableOriginalConstructor()->getMock(); + $this->dateTimeFormatter = $this->getMock('\\OCP\\IDateTimeFormatter'); $this->adminController = new AdminController( 'updatenotification', @@ -60,15 +73,94 @@ class AdminControllerTest extends TestCase { $this->jobList, $this->secureRandom, $this->config, - $this->timeFactory + $this->timeFactory, + $this->l10n, + $this->updateChecker, + $this->dateTimeFormatter ); } - public function testDisplayPanel() { - $expected = new TemplateResponse('updatenotification', 'admin', [], ''); + public function testDisplayPanelWithUpdate() { + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->willReturn('12345'); + $this->dateTimeFormatter + ->expects($this->once()) + ->method('formatDateTime') + ->with('12345') + ->willReturn('LastCheckedReturnValue'); + $this->updateChecker + ->expects($this->once()) + ->method('getUpdateState') + ->willReturn(['foo' => 'bar']); + + $params = [ + 'isNewVersionAvailable' => true, + 'lastChecked' => 'LastCheckedReturnValue', + 'currentChannel' => \OCP\Util::getChannel(), + 'channels' => $channels, + ]; + + $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); + $this->assertEquals($expected, $this->adminController->displayPanel()); + } + + public function testDisplayPanelWithoutUpdate() { + $channels = [ + 'daily', + 'beta', + 'stable', + 'production', + ]; + $currentChannel = \OCP\Util::getChannel(); + + // Remove the currently used channel from the channels list + if(($key = array_search($currentChannel, $channels)) !== false) { + unset($channels[$key]); + } + + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->willReturn('12345'); + $this->dateTimeFormatter + ->expects($this->once()) + ->method('formatDateTime') + ->with('12345') + ->willReturn('LastCheckedReturnValue'); + $this->updateChecker + ->expects($this->once()) + ->method('getUpdateState') + ->willReturn([]); + + $params = [ + 'isNewVersionAvailable' => false, + 'lastChecked' => 'LastCheckedReturnValue', + 'currentChannel' => \OCP\Util::getChannel(), + 'channels' => $channels, + ]; + + $expected = new TemplateResponse('updatenotification', 'admin', $params, ''); $this->assertEquals($expected, $this->adminController->displayPanel()); } + public function testCreateCredentials() { $this->jobList ->expects($this->once()) diff --git a/config/config.sample.php b/config/config.sample.php index 1a6c8b31280..4321e5bab83 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -414,6 +414,12 @@ $CONFIG = array( /** + * File versions + * + * These parameters control the Versions app. + */ + +/** * If the versions app is enabled (default), this setting defines the policy * for when versions will be permanently deleted. * The app allows for two settings, a minimum time for version retention, diff --git a/lib/private/comments/comment.php b/lib/private/comments/comment.php index 31848ed38b6..60663d61578 100644 --- a/lib/private/comments/comment.php +++ b/lib/private/comments/comment.php @@ -362,7 +362,7 @@ class Comment implements IComment { protected function fromArray($data) { foreach(array_keys($data) as $key) { // translate DB keys to internal setter names - $setter = 'set' . str_replace('_', '', ucwords($key,'_')); + $setter = 'set' . implode('', array_map('ucfirst', explode('_', $key))); $setter = str_replace('Timestamp', 'DateTime', $setter); if(method_exists($this, $setter)) { diff --git a/lib/private/files/storage/wrapper/availability.php b/lib/private/files/storage/wrapper/availability.php index 55ddb0d5e8f..0ed31ba854a 100644 --- a/lib/private/files/storage/wrapper/availability.php +++ b/lib/private/files/storage/wrapper/availability.php @@ -29,6 +29,16 @@ namespace OC\Files\Storage\Wrapper; class Availability extends Wrapper { const RECHECK_TTL_SEC = 600; // 10 minutes + public static function shouldRecheck($availability) { + if (!$availability['available']) { + // trigger a recheck if TTL reached + if ((time() - $availability['last_checked']) > self::RECHECK_TTL_SEC) { + return true; + } + } + return false; + } + /** * @return bool */ @@ -47,11 +57,8 @@ class Availability extends Wrapper { */ private function isAvailable() { $availability = $this->getAvailability(); - if (!$availability['available']) { - // trigger a recheck if TTL reached - if ((time() - $availability['last_checked']) > self::RECHECK_TTL_SEC) { - return $this->updateAvailability(); - } + if (self::shouldRecheck($availability)) { + return $this->updateAvailability(); } return $availability['available']; } diff --git a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php index fc261e4bc5a..766897e7517 100644 --- a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php +++ b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php @@ -35,8 +35,9 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator { $excludedFolders = [ rtrim($root . '/data', '/'), rtrim($root .'/themes', '/'), - rtrim($root.'/config', '/'), - rtrim($root.'/apps', '/'), + rtrim($root . '/config', '/'), + rtrim($root . '/apps', '/'), + rtrim($root . '/assets', '/'), ]; $customDataDir = \OC::$server->getConfig()->getSystemValue('datadirectory', ''); if($customDataDir !== '') { |