diff options
-rw-r--r-- | apps/files_external/controller/storagescontroller.php | 38 | ||||
-rw-r--r-- | apps/files_external/js/settings.js | 8 | ||||
-rw-r--r-- | apps/files_external/lib/config.php | 3 | ||||
-rw-r--r-- | apps/files_external/lib/config/configadapter.php | 29 | ||||
-rw-r--r-- | apps/files_external/lib/failedstorage.php | 200 | ||||
-rw-r--r-- | apps/files_external/lib/insufficientdataformeaningfulanswerexception.php | 30 | ||||
-rw-r--r-- | apps/files_external/lib/storagemodifiertrait.php | 6 | ||||
-rw-r--r-- | settings/css/settings.css | 12 |
8 files changed, 298 insertions, 28 deletions
diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php index f1d1625bdc6..3d91af8bd8f 100644 --- a/apps/files_external/controller/storagescontroller.php +++ b/apps/files_external/controller/storagescontroller.php @@ -34,6 +34,8 @@ use \OCA\Files_external\NotFoundException; use \OCA\Files_external\Lib\StorageConfig; use \OCA\Files_External\Lib\Backend\Backend; use \OCA\Files_External\Lib\Auth\AuthMechanism; +use \OCP\Files\StorageNotAvailableException; +use \OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; /** * Base class for storages controllers @@ -182,21 +184,27 @@ abstract class StoragesController extends Controller { * @param StorageConfig $storage storage configuration */ protected function updateStorageStatus(StorageConfig &$storage) { - /** @var AuthMechanism */ - $authMechanism = $storage->getAuthMechanism(); - $authMechanism->manipulateStorageConfig($storage); - /** @var Backend */ - $backend = $storage->getBackend(); - $backend->manipulateStorageConfig($storage); - - // update status (can be time-consuming) - $storage->setStatus( - \OC_Mount_Config::getBackendStatus( - $storage->getBackend()->getStorageClass(), - $storage->getBackendOptions(), - false - ) - ); + try { + /** @var AuthMechanism */ + $authMechanism = $storage->getAuthMechanism(); + $authMechanism->manipulateStorageConfig($storage); + /** @var Backend */ + $backend = $storage->getBackend(); + $backend->manipulateStorageConfig($storage); + + // update status (can be time-consuming) + $storage->setStatus( + \OC_Mount_Config::getBackendStatus( + $backend->getStorageClass(), + $storage->getBackendOptions(), + false + ) + ); + } catch (InsufficientDataForMeaningfulAnswerException $e) { + $storage->setStatus(\OC_Mount_Config::STATUS_INDETERMINATE); + } catch (StorageNotAvailableException $e) { + $storage->setStatus(\OC_Mount_Config::STATUS_ERROR); + } } /** diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 7288f90fa77..c15f36d8bd7 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -191,7 +191,8 @@ var StorageConfig = function(id) { StorageConfig.Status = { IN_PROGRESS: -1, SUCCESS: 0, - ERROR: 1 + ERROR: 1, + INDETERMINATE: 2 }; /** * @memberof OCA.External.Settings @@ -946,7 +947,7 @@ MountConfigListView.prototype = { */ updateStatus: function($tr, status) { var $statusSpan = $tr.find('.status span'); - $statusSpan.removeClass('success error loading-small'); + $statusSpan.removeClass('loading-small success indeterminate error'); switch (status) { case StorageConfig.Status.IN_PROGRESS: $statusSpan.addClass('loading-small'); @@ -954,6 +955,9 @@ MountConfigListView.prototype = { case StorageConfig.Status.SUCCESS: $statusSpan.addClass('success'); break; + case StorageConfig.Status.INDETERMINATE: + $statusSpan.addClass('indeterminate'); + break; default: $statusSpan.addClass('error'); } diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 5c38a3ba0cb..91c33ef10a5 100644 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -52,6 +52,7 @@ class OC_Mount_Config { // getBackendStatus return types const STATUS_SUCCESS = 0; const STATUS_ERROR = 1; + const STATUS_INDETERMINATE = 2; // whether to skip backend test (for unit tests, as this static class is not mockable) public static $skipTest = false; @@ -218,7 +219,7 @@ class OC_Mount_Config { * @param string|array $input * @return string */ - private static function setUserVars($user, $input) { + public static function setUserVars($user, $input) { if (is_array($input)) { foreach ($input as &$value) { if (is_string($value)) { diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php index 9829629761c..a15d9e06a5f 100644 --- a/apps/files_external/lib/config/configadapter.php +++ b/apps/files_external/lib/config/configadapter.php @@ -32,6 +32,8 @@ use OCP\IUser; use OCA\Files_external\Service\UserStoragesService; use OCA\Files_External\Service\UserGlobalStoragesService; use OCA\Files_External\Lib\StorageConfig; +use OCP\Files\StorageNotAvailableException; +use OCA\Files_External\Lib\FailedStorage; /** * Make the old files_external config work with the new public mount config api @@ -60,8 +62,15 @@ class ConfigAdapter implements IMountProvider { * Process storage ready for mounting * * @param StorageConfig $storage + * @param IUser $user */ - private function prepareStorageConfig(StorageConfig &$storage) { + private function prepareStorageConfig(StorageConfig &$storage, IUser $user) { + foreach ($storage->getBackendOptions() as $option => $value) { + $storage->setBackendOption($option, \OC_Mount_Config::setUserVars( + $user->getUID(), $value + )); + } + $objectStore = $storage->getBackendOption('objectstore'); if ($objectStore) { $objectClass = $objectStore['class']; @@ -103,8 +112,13 @@ class ConfigAdapter implements IMountProvider { $this->userGlobalStoragesService->setUser($user); foreach ($this->userGlobalStoragesService->getAllStorages() as $storage) { - $this->prepareStorageConfig($storage); - $impl = $this->constructStorage($storage); + try { + $this->prepareStorageConfig($storage, $user); + $impl = $this->constructStorage($storage); + } catch (\Exception $e) { + // propagate exception into filesystem + $impl = new FailedStorage(['exception' => $e]); + } $mount = new MountPoint( $impl, @@ -117,8 +131,13 @@ class ConfigAdapter implements IMountProvider { } foreach ($this->userStoragesService->getAllStorages() as $storage) { - $this->prepareStorageConfig($storage); - $impl = $this->constructStorage($storage); + try { + $this->prepareStorageConfig($storage, $user); + $impl = $this->constructStorage($storage); + } catch (\Exception $e) { + // propagate exception into filesystem + $impl = new FailedStorage(['exception' => $e]); + } $mount = new PersonalMount( $this->userStoragesService, diff --git a/apps/files_external/lib/failedstorage.php b/apps/files_external/lib/failedstorage.php new file mode 100644 index 00000000000..6afa98052c2 --- /dev/null +++ b/apps/files_external/lib/failedstorage.php @@ -0,0 +1,200 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\Files_External\Lib; + +use \OCP\Lock\ILockingProvider; +use \OC\Files\Storage\Common; +use \OCP\Files\StorageNotAvailableException; + +/** + * Storage placeholder to represent a missing precondition, storage unavailable + */ +class FailedStorage extends Common { + + /** @var \Exception */ + protected $e; + + /** + * @param array $params ['exception' => \Exception] + */ + public function __construct($params) { + $this->e = $params['exception']; + } + + public function getId() { + // we can't return anything sane here + return 'failedstorage'; + } + + public function mkdir($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function rmdir($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function opendir($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function is_dir($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function is_file($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function stat($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function filetype($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function filesize($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function isCreatable($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function isReadable($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function isUpdatable($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function isDeletable($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function isSharable($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getPermissions($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function file_exists($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function filemtime($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function file_get_contents($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function file_put_contents($path, $data) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function unlink($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function rename($path1, $path2) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function copy($path1, $path2) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function fopen($path, $mode) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getMimeType($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function hash($type, $path, $raw = false) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function free_space($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function search($query) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function touch($path, $mtime = null) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getLocalFile($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getLocalFolder($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function hasUpdated($path, $time) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getETag($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function getDirectDownload($path) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function verifyPath($path, $fileName) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function acquireLock($path, $type, ILockingProvider $provider) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function releaseLock($path, $type, ILockingProvider $provider) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + + public function changeLock($path, $type, ILockingProvider $provider) { + throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e); + } + +} diff --git a/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php b/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php new file mode 100644 index 00000000000..dd4cd75df12 --- /dev/null +++ b/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php @@ -0,0 +1,30 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\Files_External\Lib; + +use \OCP\Files\StorageNotAvailableException; + +/** + * Authentication mechanism or backend has insufficient data + */ +class InsufficientDataForMeaningfulAnswerException extends StorageNotAvailableException { +} diff --git a/apps/files_external/lib/storagemodifiertrait.php b/apps/files_external/lib/storagemodifiertrait.php index a11d265e841..3af0bb234d9 100644 --- a/apps/files_external/lib/storagemodifiertrait.php +++ b/apps/files_external/lib/storagemodifiertrait.php @@ -23,6 +23,8 @@ namespace OCA\Files_External\Lib; use \OCP\Files\Storage; use \OCA\Files_External\Lib\StorageConfig; +use \OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; +use \OCP\Files\StorageNotAvailableException; /** * Trait for objects that can modify StorageConfigs and wrap Storages @@ -43,6 +45,8 @@ trait StorageModifierTrait { * Modify a StorageConfig parameters * * @param StorageConfig $storage + * @throws InsufficientDataForMeaningfulAnswerException + * @throws StorageNotAvailableException */ public function manipulateStorageConfig(StorageConfig &$storage) { } @@ -52,6 +56,8 @@ trait StorageModifierTrait { * * @param Storage $storage * @return Storage + * @throws InsufficientDataForMeaningfulAnswerException + * @throws StorageNotAvailableException */ public function wrapStorage(Storage $storage) { return $storage; diff --git a/settings/css/settings.css b/settings/css/settings.css index 7340f2b2a63..9bd342ca6f2 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -431,14 +431,16 @@ table.grid td.date{ } span.success { - background: #37ce02; - border-radius: 3px; + background: #37ce02; + border-radius: 3px; } - span.error { - background: #ce3702; + background: #ce3702; +} +span.indeterminate { + background: #e6db00; + border-radius: 40% 0; } - /* PASSWORD */ .strengthify-wrapper { |