summaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib
diff options
context:
space:
mode:
authorRobin McCorkell <rmccorkell@owncloud.com>2015-08-11 18:45:07 +0100
committerRobin McCorkell <rmccorkell@owncloud.com>2015-08-19 10:05:11 +0100
commit37beb58c6f395523d8e2934870c5f52a8c6f6df0 (patch)
treeb14325a790ddaf7236c3f8c1939ce9ef10df58bb /apps/files_external/lib
parent74237a9c44192fb98944ea7f3c14fa6f22c0814b (diff)
downloadnextcloud-server-37beb58c6f395523d8e2934870c5f52a8c6f6df0.tar.gz
nextcloud-server-37beb58c6f395523d8e2934870c5f52a8c6f6df0.zip
Introduce BackendService for managing external storage backends
Backends are registered to the BackendService through new data structures: Backends are concrete classes, deriving from \OCA\Files_External\Lib\Backend\Backend. During construction, the various configuration parameters of the Backend can be set, in a design similar to Symfony Console. DefinitionParameter stores a parameter configuration for an external storage: name of parameter, human-readable name, type of parameter (text, password, hidden, checkbox), flags (optional or not). Storages in the StoragesController now get their parameters validated server-side (fixes a TODO).
Diffstat (limited to 'apps/files_external/lib')
-rw-r--r--apps/files_external/lib/backend/backend.php94
-rw-r--r--apps/files_external/lib/config.php255
-rw-r--r--apps/files_external/lib/config/configadapter.php14
-rw-r--r--apps/files_external/lib/definitionparameter.php179
-rw-r--r--apps/files_external/lib/dependencytrait.php86
-rw-r--r--apps/files_external/lib/frontenddefinitiontrait.php147
-rw-r--r--apps/files_external/lib/missingdependency.php64
-rw-r--r--apps/files_external/lib/personalmount.php45
-rw-r--r--apps/files_external/lib/prioritytrait.php60
-rw-r--r--apps/files_external/lib/storageconfig.php45
-rw-r--r--apps/files_external/lib/storagemodifiertrait.php51
-rw-r--r--apps/files_external/lib/visibilitytrait.php129
12 files changed, 958 insertions, 211 deletions
diff --git a/apps/files_external/lib/backend/backend.php b/apps/files_external/lib/backend/backend.php
new file mode 100644
index 00000000000..e7cd27a1d6c
--- /dev/null
+++ b/apps/files_external/lib/backend/backend.php
@@ -0,0 +1,94 @@
+<?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\Backend;
+
+use \OCA\Files_External\Lib\StorageConfig;
+use \OCA\Files_External\Lib\VisibilityTrait;
+use \OCA\Files_External\Lib\FrontendDefinitionTrait;
+use \OCA\Files_External\Lib\PriorityTrait;
+use \OCA\Files_External\Lib\DependencyTrait;
+use \OCA\Files_External\Lib\StorageModifierTrait;
+
+/**
+ * Storage backend
+ */
+class Backend implements \JsonSerializable {
+
+ use VisibilityTrait;
+ use FrontendDefinitionTrait;
+ use PriorityTrait;
+ use DependencyTrait;
+ use StorageModifierTrait;
+
+ /** @var string storage class */
+ private $storageClass;
+
+ /**
+ * @return string
+ */
+ public function getClass() {
+ // return storage class for legacy compat
+ return $this->getStorageClass();
+ }
+
+ /**
+ * @return string
+ */
+ public function getStorageClass() {
+ return $this->storageClass;
+ }
+
+ /**
+ * @param string $class
+ * @return self
+ */
+ public function setStorageClass($class) {
+ $this->storageClass = $class;
+ return $this;
+ }
+
+ /**
+ * Serialize into JSON for client-side JS
+ *
+ * @return array
+ */
+ public function jsonSerialize() {
+ $data = $this->jsonSerializeDefinition();
+
+ $data['backend'] = $data['name']; // legacy compat
+ $data['priority'] = $this->getPriority();
+
+ return $data;
+ }
+
+ /**
+ * Check if parameters are satisfied in a StorageConfig
+ *
+ * @param StorageConfig $storage
+ * @return bool
+ */
+ public function validateStorage(StorageConfig $storage) {
+ return $this->validateStorageDefinition($storage);
+ }
+
+}
+
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
index 8fcf39cc767..11dec94621a 100644
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
@@ -32,6 +32,9 @@
*/
use phpseclib\Crypt\AES;
+use \OCP\AppFramework\IAppContainer;
+use \OCA\Files_External\Lib\BackendConfig;
+use \OCA\Files_External\Service\BackendService;
/**
* Class to configure mount.json globally and for users
@@ -51,71 +54,19 @@ class OC_Mount_Config {
// whether to skip backend test (for unit tests, as this static class is not mockable)
public static $skipTest = false;
- private static $backends = array();
+ /** @var IAppContainer */
+ private static $appContainer;
/**
- * @param string $class
- * @param array $definition
- * @return bool
- */
- public static function registerBackend($class, $definition) {
- if (!isset($definition['backend'])) {
- return false;
- }
-
- OC_Mount_Config::$backends[$class] = $definition;
- return true;
- }
-
- /**
- * Setup backends
+ * Teach OC_Mount_Config about the AppFramework
*
- * @return array of previously registered backends
+ * @param IAppContainer $appContainer
*/
- public static function setUp($backends = array()) {
- $backup = self::$backends;
- self::$backends = $backends;
-
- return $backup;
- }
-
- /**
- * Get details on each of the external storage backends, used for the mount config UI
- * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded
- * If the configuration parameter should be secret, add a '*' to the beginning of the value
- * If the configuration parameter is a boolean, add a '!' to the beginning of the value
- * If the configuration parameter is optional, add a '&' to the beginning of the value
- * If the configuration parameter is hidden, add a '#' to the beginning of the value
- *
- * @return array
- */
- public static function getBackends() {
- $sortFunc = function ($a, $b) {
- return strcasecmp($a['backend'], $b['backend']);
- };
-
- $backEnds = array();
-
- foreach (OC_Mount_Config::$backends as $class => $backend) {
- if (isset($backend['has_dependencies']) and $backend['has_dependencies'] === true) {
- if (!method_exists($class, 'checkDependencies')) {
- \OCP\Util::writeLog('files_external',
- "Backend class $class has dependencies but doesn't provide method checkDependencies()",
- \OCP\Util::DEBUG);
- continue;
- } elseif ($class::checkDependencies() !== true) {
- continue;
- }
- }
- $backEnds[$class] = $backend;
- }
-
- uasort($backEnds, $sortFunc);
-
- return $backEnds;
+ public static function initApp(IAppContainer $appContainer) {
+ self::$appContainer = $appContainer;
}
- /**
+ /*
* Hook that mounts the given user's visible mount points
*
* @param array $data
@@ -151,14 +102,14 @@ class OC_Mount_Config {
/**
* Returns the mount points for the given user.
* The mount point is relative to the data directory.
+ * TODO: Move me into StoragesService
*
* @param string $user user
* @return array of mount point string as key, mountpoint config as value
*/
public static function getAbsoluteMountPoints($user) {
$mountPoints = array();
-
- $backends = self::getBackends();
+ $backendService = self::$appContainer->query('OCA\Files_External\Service\BackendService');
// Load system mount points
$mountConfig = self::readData();
@@ -166,18 +117,20 @@ class OC_Mount_Config {
// Global mount points (is this redundant?)
if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) {
foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) {
+ $backend = $backendService->getBackend($options['class']);
$options['personal'] = false;
$options['options'] = self::decryptPasswords($options['options']);
if (!isset($options['priority'])) {
- $options['priority'] = $backends[$options['class']]['priority'];
+ $options['priority'] = $backend->getPriority();
}
+
// Override if priority greater
if ((!isset($mountPoints[$mountPoint]))
|| ($options['priority'] >= $mountPoints[$mountPoint]['priority'])
) {
$options['priority_type'] = self::MOUNT_TYPE_GLOBAL;
- $options['backend'] = $backends[$options['class']]['backend'];
+ $options['backend'] = $backend->getText();
$mountPoints[$mountPoint] = $options;
}
}
@@ -190,10 +143,11 @@ class OC_Mount_Config {
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
+ $backend = $backendService->getBackend($options['class']);
$options['personal'] = false;
$options['options'] = self::decryptPasswords($options['options']);
if (!isset($options['priority'])) {
- $options['priority'] = $backends[$options['class']]['priority'];
+ $options['priority'] = $backend->getPriority();
}
// Override if priority greater
@@ -201,7 +155,7 @@ class OC_Mount_Config {
|| ($options['priority'] >= $mountPoints[$mountPoint]['priority'])
) {
$options['priority_type'] = self::MOUNT_TYPE_GLOBAL;
- $options['backend'] = $backends[$options['class']]['backend'];
+ $options['backend'] = $backend->getText();
$mountPoints[$mountPoint] = $options;
}
}
@@ -215,10 +169,11 @@ class OC_Mount_Config {
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
+ $backend = $backendService->getBackend($options['class']);
$options['personal'] = false;
$options['options'] = self::decryptPasswords($options['options']);
if (!isset($options['priority'])) {
- $options['priority'] = $backends[$options['class']]['priority'];
+ $options['priority'] = $backend->getPriority();
}
// Override if priority greater or if priority type different
@@ -227,7 +182,7 @@ class OC_Mount_Config {
|| ($mountPoints[$mountPoint]['priority_type'] !== self::MOUNT_TYPE_GROUP)
) {
$options['priority_type'] = self::MOUNT_TYPE_GROUP;
- $options['backend'] = $backends[$options['class']]['backend'];
+ $options['backend'] = $backend->getText();
$mountPoints[$mountPoint] = $options;
}
}
@@ -243,10 +198,11 @@ class OC_Mount_Config {
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
+ $backend = $backendService->getBackend($options['class']);
$options['personal'] = false;
$options['options'] = self::decryptPasswords($options['options']);
if (!isset($options['priority'])) {
- $options['priority'] = $backends[$options['class']]['priority'];
+ $options['priority'] = $backend->getPriority();
}
// Override if priority greater or if priority type different
@@ -255,7 +211,7 @@ class OC_Mount_Config {
|| ($mountPoints[$mountPoint]['priority_type'] !== self::MOUNT_TYPE_USER)
) {
$options['priority_type'] = self::MOUNT_TYPE_USER;
- $options['backend'] = $backends[$options['class']]['backend'];
+ $options['backend'] = $backend->getText();
$mountPoints[$mountPoint] = $options;
}
}
@@ -263,19 +219,18 @@ class OC_Mount_Config {
}
}
- $personalBackends = self::getPersonalBackends();
-
// Load personal mount points
$mountConfig = self::readData($user);
if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) {
foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) {
- if (isset($personalBackends[$options['class']])) {
+ $backend = $backendService->getBackend($options['class']);
+ if ($backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL)) {
$options['personal'] = true;
$options['options'] = self::decryptPasswords($options['options']);
// Always override previous config
$options['priority_type'] = self::MOUNT_TYPE_PERSONAL;
- $options['backend'] = $backends[$options['class']]['backend'];
+ $options['backend'] = $backend->getText();
$mountPoints[$mountPoint] = $options;
}
}
@@ -304,43 +259,6 @@ class OC_Mount_Config {
return $input;
}
-
- /**
- * Get details on each of the external storage backends, used for the mount config UI
- * Some backends are not available as a personal backend, f.e. Local and such that have
- * been disabled by the admin.
- *
- * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded
- * If the configuration parameter should be secret, add a '*' to the beginning of the value
- * If the configuration parameter is a boolean, add a '!' to the beginning of the value
- * If the configuration parameter is optional, add a '&' to the beginning of the value
- * If the configuration parameter is hidden, add a '#' to the beginning of the value
- *
- * @return array
- */
- public static function getPersonalBackends() {
-
- // Check whether the user has permissions to add personal storage backends
- // return an empty array if this is not the case
- if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') {
- return array();
- }
-
- $backEnds = self::getBackends();
-
- // Remove local storage and other disabled storages
- unset($backEnds['\OC\Files\Storage\Local']);
-
- $allowedBackEnds = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', ''));
- foreach ($backEnds as $backend => $null) {
- if (!in_array($backend, $allowedBackEnds)) {
- unset($backEnds[$backend]);
- }
- }
-
- return $backEnds;
- }
-
/**
* Get the system mount points
* The returned array is not in the same format as getUserMountPoints()
@@ -349,7 +267,7 @@ class OC_Mount_Config {
*/
public static function getSystemMountPoints() {
$mountPoints = self::readData();
- $backends = self::getBackends();
+ $backendService = self::$appContainer->query('\OCA\Files_External\Service\BackendService');
$system = array();
if (isset($mountPoints[self::MOUNT_TYPE_GROUP])) {
foreach ($mountPoints[self::MOUNT_TYPE_GROUP] as $group => $mounts) {
@@ -358,9 +276,10 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\' . substr($mount['class'], 15);
}
+ $backend = $backendService->getBackend($mount['class']);
$mount['options'] = self::decryptPasswords($mount['options']);
if (!isset($mount['priority'])) {
- $mount['priority'] = $backends[$mount['class']]['priority'];
+ $mount['priority'] = $backend->getPriority();
}
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
@@ -368,7 +287,7 @@ class OC_Mount_Config {
$config = array(
'class' => $mount['class'],
'mountpoint' => $mountPoint,
- 'backend' => $backends[$mount['class']]['backend'],
+ 'backend' => $backend->getText(),
'priority' => $mount['priority'],
'options' => $mount['options'],
'applicable' => array('groups' => array($group), 'users' => array())
@@ -401,16 +320,17 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\' . substr($mount['class'], 15);
}
+ $backend = $backendService->getBackend($mount['class']);
$mount['options'] = self::decryptPasswords($mount['options']);
if (!isset($mount['priority'])) {
- $mount['priority'] = $backends[$mount['class']]['priority'];
+ $mount['priority'] = $backend->getPriority();
}
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
$config = array(
'class' => $mount['class'],
'mountpoint' => $mountPoint,
- 'backend' => $backends[$mount['class']]['backend'],
+ 'backend' => $backend->getText(),
'priority' => $mount['priority'],
'options' => $mount['options'],
'applicable' => array('groups' => array(), 'users' => array($user))
@@ -447,7 +367,7 @@ class OC_Mount_Config {
*/
public static function getPersonalMountPoints() {
$mountPoints = self::readData(OCP\User::getUser());
- $backEnds = self::getBackends();
+ $backendService = self::$appContainer->query('\OCA\Files_External\Service\BackendService');
$uid = OCP\User::getUser();
$personal = array();
if (isset($mountPoints[self::MOUNT_TYPE_USER][$uid])) {
@@ -456,12 +376,13 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\' . substr($mount['class'], 15);
}
+ $backend = $backendService->getBackend($mount['class']);
$mount['options'] = self::decryptPasswords($mount['options']);
$config = array(
'class' => $mount['class'],
// Remove '/uid/files/' from mount point
'mountpoint' => substr($mountPoint, strlen($uid) + 8),
- 'backend' => $backEnds[$mount['class']]['backend'],
+ 'backend' => $backend->getText(),
'options' => $mount['options']
);
if (isset($mount['id'])) {
@@ -535,7 +456,7 @@ class OC_Mount_Config {
$applicable,
$isPersonal = false,
$priority = null) {
- $backends = self::getBackends();
+ $backendService = self::$appContainer->query('\OCA\Files_External\Service\BackendService');
$mountPoint = OC\Files\Filesystem::normalizePath($mountPoint);
$relMountPoint = $mountPoint;
if ($mountPoint === '' || $mountPoint === '/') {
@@ -543,15 +464,15 @@ class OC_Mount_Config {
return false;
}
- if (!isset($backends[$class])) {
+ $backend = $backendService->getBackend($class);
+ if (!isset($backend)) {
// invalid backend
return false;
}
if ($isPersonal) {
// Verify that the mount point applies for the current user
// Prevent non-admin users from mounting local storage and other disabled backends
- $allowed_backends = self::getPersonalBackends();
- if ($applicable != OCP\User::getUser() || !isset($allowed_backends[$class])) {
+ if ($applicable != OCP\User::getUser() || !$backend->isVisibleFor(BackendConfig::VISIBILITY_PERSONAL)) {
return false;
}
$mountPoint = '/' . $applicable . '/files/' . ltrim($mountPoint, '/');
@@ -578,13 +499,8 @@ class OC_Mount_Config {
// Set default priority if none set
if (!isset($mountPoints[$mountType][$applicable][$mountPoint]['priority'])) {
- if (isset($backends[$class]['priority'])) {
- $mountPoints[$mountType][$applicable][$mountPoint]['priority']
- = $backends[$class]['priority'];
- } else {
- $mountPoints[$mountType][$applicable][$mountPoint]['priority']
- = 100;
- }
+ $mountPoints[$mountType][$applicable][$mountPoint]['priority']
+ = $backend->getPriority();
}
self::writeData($isPersonal ? OCP\User::getUser() : null, $mountPoints);
@@ -721,74 +637,35 @@ class OC_Mount_Config {
}
/**
- * check dependencies
+ * Get backend dependency message
+ * TODO: move into AppFramework along with templates
+ *
+ * @param BackendConfig[] $backends
+ * @return string
*/
- public static function checkDependencies() {
- $dependencies = array();
- foreach (OC_Mount_Config::$backends as $class => $backend) {
- if (isset($backend['has_dependencies']) and $backend['has_dependencies'] === true) {
- $result = $class::checkDependencies();
- if ($result !== true) {
- if (!is_array($result)) {
- $result = array($result);
- }
- foreach ($result as $key => $value) {
- if (is_numeric($key)) {
- OC_Mount_Config::addDependency($dependencies, $value, $backend['backend']);
- } else {
- OC_Mount_Config::addDependency($dependencies, $key, $backend['backend'], $value);
- }
- }
- }
- }
- }
-
- if (count($dependencies) > 0) {
- return OC_Mount_Config::generateDependencyMessage($dependencies);
- }
- return '';
- }
-
- private static function addDependency(&$dependencies, $module, $backend, $message = null) {
- if (!isset($dependencies[$module])) {
- $dependencies[$module] = array();
- }
-
- if ($message === null) {
- $dependencies[$module][] = $backend;
- } else {
- $dependencies[$module][] = array('backend' => $backend, 'message' => $message);
- }
- }
-
- private static function generateDependencyMessage($dependencies) {
+ public static function dependencyMessage($backends) {
$l = new \OC_L10N('files_external');
- $dependencyMessage = '';
- foreach ($dependencies as $module => $backends) {
- $dependencyGroup = array();
- foreach ($backends as $backend) {
- if (is_array($backend)) {
- $dependencyMessage .= '<br />' . $l->t('<b>Note:</b> ') . $backend['message'];
+ $message = '';
+ $dependencyGroups = [];
+
+ foreach ($backends as $backend) {
+ foreach ($backend->checkDependencies() as $dependency) {
+ if ($message = $dependency->getMessage()) {
+ $message .= '<br />' . $l->t('<b>Note:</b> ') . $message;
} else {
- $dependencyGroup[] = $backend;
+ $dependencyGroups[$dependency->getDependency()][] = $backend;
}
}
+ }
- $dependencyGroupCount = count($dependencyGroup);
- if ($dependencyGroupCount > 0) {
- $backends = '';
- for ($i = 0; $i < $dependencyGroupCount; $i++) {
- if ($i > 0 && $i === $dependencyGroupCount - 1) {
- $backends .= ' ' . $l->t('and') . ' ';
- } elseif ($i > 0) {
- $backends .= ', ';
- }
- $backends .= '<i>' . $dependencyGroup[$i] . '</i>';
- }
- $dependencyMessage .= '<br />' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends);
- }
+ foreach ($dependencyGroups as $module => $dependants) {
+ $backends = implode(', ', array_map(function($backend) {
+ return '<i>' . $backend->getText() . '</i>';
+ }, $dependants));
+ $message .= '<br />' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends);
}
- return $dependencyMessage;
+
+ return $message;
}
/**
diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php
index b5c2ba4fc92..6956de1e748 100644
--- a/apps/files_external/lib/config/configadapter.php
+++ b/apps/files_external/lib/config/configadapter.php
@@ -24,14 +24,23 @@ namespace OCA\Files_External\Config;
use OC\Files\Mount\MountPoint;
use OCP\Files\Storage\IStorageFactory;
-use OCA\Files_External\PersonalMount;
+use OCA\Files_External\Lib\PersonalMount;
use OCP\Files\Config\IMountProvider;
use OCP\IUser;
+use OCA\Files_external\Service\UserStoragesService;
/**
* Make the old files_external config work with the new public mount config api
*/
class ConfigAdapter implements IMountProvider {
+
+ /**
+ * @param UserStoragesService $userStoragesService
+ */
+ public function __construct(UserStoragesService $userStoragesService) {
+ $this->userStoragesService = $userStoragesService;
+ }
+
/**
* Get all mountpoints applicable for the user
*
@@ -49,7 +58,8 @@ class ConfigAdapter implements IMountProvider {
}
$mountOptions = isset($options['mountOptions']) ? $options['mountOptions'] : [];
if (isset($options['personal']) && $options['personal']) {
- $mounts[] = new PersonalMount($options['class'], $mountPoint, $options['options'], $loader, $mountOptions);
+ $mount = new PersonalMount($this->userStoragesService, $options['id'], $options['class'], $mountPoint, $options['options'], $loader, $mountOptions);
+ $mounts[] = $mount;
} else {
$mounts[] = new MountPoint($options['class'], $mountPoint, $options['options'], $loader, $mountOptions);
}
diff --git a/apps/files_external/lib/definitionparameter.php b/apps/files_external/lib/definitionparameter.php
new file mode 100644
index 00000000000..4b560908b69
--- /dev/null
+++ b/apps/files_external/lib/definitionparameter.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @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;
+
+/**
+ * Parameter for an external storage definition
+ */
+class DefinitionParameter implements \JsonSerializable {
+
+ /** Value constants */
+ const VALUE_TEXT = 0;
+ const VALUE_BOOLEAN = 1;
+ const VALUE_PASSWORD = 2;
+ const VALUE_HIDDEN = 3;
+
+ /** Flag constants */
+ const FLAG_NONE = 0;
+ const FLAG_OPTIONAL = 1;
+
+ /** @var string name of parameter */
+ private $name;
+
+ /** @var string human-readable parameter text */
+ private $text;
+
+ /** @var int value type, see self::VALUE_* constants */
+ private $type = self::VALUE_TEXT;
+
+ /** @var int flags, see self::FLAG_* constants */
+ private $flags = self::FLAG_NONE;
+
+ /**
+ * @param string $name
+ * @param string $text
+ */
+ public function __construct($name, $text) {
+ $this->name = $name;
+ $this->text = $text;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * @return string
+ */
+ public function getText() {
+ return $this->text;
+ }
+
+ /**
+ * Get value type
+ *
+ * @return int
+ */
+ public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * Set value type
+ *
+ * @param int $type
+ * @return self
+ */
+ public function setType($type) {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getFlags() {
+ return $this->flags;
+ }
+
+ /**
+ * @param int $flags
+ * @return self
+ */
+ public function setFlags($flags) {
+ $this->flags = $flags;
+ return $this;
+ }
+
+ /**
+ * @param int $flag
+ * @return self
+ */
+ public function setFlag($flag) {
+ $this->flags |= $flag;
+ return $this;
+ }
+
+ /**
+ * @param int $flag
+ * @return bool
+ */
+ public function isFlagSet($flag) {
+ return (bool) $this->flags & $flag;
+ }
+
+ /**
+ * Serialize into JSON for client-side JS
+ *
+ * @return string
+ */
+ public function jsonSerialize() {
+ $prefix = '';
+ switch ($this->getType()) {
+ case self::VALUE_BOOLEAN:
+ $prefix = '!';
+ break;
+ case self::VALUE_PASSWORD:
+ $prefix = '*';
+ break;
+ case self::VALUE_HIDDEN:
+ $prefix = '#';
+ break;
+ }
+
+ switch ($this->getFlags()) {
+ case self::FLAG_OPTIONAL:
+ $prefix = '&' . $prefix;
+ break;
+ }
+
+ return $prefix . $this->getText();
+ }
+
+ /**
+ * Validate a parameter value against this
+ *
+ * @param mixed $value Value to check
+ * @return bool success
+ */
+ public function validateValue($value) {
+ if ($this->getFlags() & self::FLAG_OPTIONAL) {
+ return true;
+ }
+ switch ($this->getType()) {
+ case self::VALUE_BOOLEAN:
+ if (!is_bool($value)) {
+ return false;
+ }
+ break;
+ default:
+ if (empty($value)) {
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+}
diff --git a/apps/files_external/lib/dependencytrait.php b/apps/files_external/lib/dependencytrait.php
new file mode 100644
index 00000000000..116421eab14
--- /dev/null
+++ b/apps/files_external/lib/dependencytrait.php
@@ -0,0 +1,86 @@
+<?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 \OCA\Files_External\Lib\MissingDependency;
+
+/**
+ * Trait for objects that have dependencies for use
+ */
+trait DependencyTrait {
+
+ /** @var callable|null dependency check */
+ private $dependencyCheck = null;
+
+ /**
+ * @return bool
+ */
+ public function hasDependencies() {
+ return !is_null($this->dependencyCheck);
+ }
+
+ /**
+ * @param callable $dependencyCheck
+ * @return self
+ */
+ public function setDependencyCheck(callable $dependencyCheck) {
+ $this->dependencyCheck = $dependencyCheck;
+ return $this;
+ }
+
+ /**
+ * Check if object is valid for use
+ *
+ * @return MissingDependency[] Unsatisfied dependencies
+ */
+ public function checkDependencies() {
+ $ret = [];
+
+ if ($this->hasDependencies()) {
+ $result = call_user_func($this->dependencyCheck);
+ if ($result !== true) {
+ if (!is_array($result)) {
+ $result = [$result];
+ }
+ foreach ($result as $key => $value) {
+ if (!($value instanceof MissingDependency)) {
+ $module = null;
+ $message = null;
+ if (is_numeric($key)) {
+ $module = $value;
+ } else {
+ $module = $key;
+ $message = $value;
+ }
+ $value = new MissingDependency($module, $this);
+ $value->setMessage($message);
+ }
+ $ret[] = $value;
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+}
+
diff --git a/apps/files_external/lib/frontenddefinitiontrait.php b/apps/files_external/lib/frontenddefinitiontrait.php
new file mode 100644
index 00000000000..4b826372d2f
--- /dev/null
+++ b/apps/files_external/lib/frontenddefinitiontrait.php
@@ -0,0 +1,147 @@
+<?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 \OCA\Files_External\Lib\DefinitionParameter;
+use \OCA\Files_External\Lib\StorageConfig;
+
+/**
+ * Trait for objects that have a frontend representation
+ */
+trait FrontendDefinitionTrait {
+
+ /** @var string human-readable mechanism name */
+ private $text;
+
+ /** @var DefinitionParameter[] parameters for mechanism */
+ private $parameters = [];
+
+ /** @var string|null custom JS */
+ private $customJs = null;
+
+ /**
+ * @return string
+ */
+ public function getText() {
+ return $this->text;
+ }
+
+ /**
+ * @param string $text
+ * @return self
+ */
+ public function setText($text) {
+ $this->text = $text;
+ return $this;
+ }
+
+ /**
+ * @param FrontendDefinitionTrait $a
+ * @param FrontendDefinitionTrait $b
+ * @return int
+ */
+ public static function lexicalCompare(FrontendDefinitionTrait $a, FrontendDefinitionTrait $b) {
+ return strcmp($a->getText(), $b->getText());
+ }
+
+ /**
+ * @return DefinitionParameter[]
+ */
+ public function getParameters() {
+ return $this->parameters;
+ }
+
+ /**
+ * @param DefinitionParameter[] $parameters
+ * @return self
+ */
+ public function addParameters(array $parameters) {
+ foreach ($parameters as $parameter) {
+ $this->addParameter($parameter);
+ }
+ return $this;
+ }
+
+ /**
+ * @param DefinitionParameter $parameter
+ * @return self
+ */
+ public function addParameter(DefinitionParameter $parameter) {
+ $this->parameters[$parameter->getName()] = $parameter;
+ return $this;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getCustomJs() {
+ return $this->customJs;
+ }
+
+ /**
+ * @param string $custom
+ * @return self
+ */
+ public function setCustomJs($custom) {
+ $this->customJs = $custom;
+ return $this;
+ }
+
+ /**
+ * Serialize into JSON for client-side JS
+ *
+ * @return array
+ */
+ public function jsonSerializeDefinition() {
+ $configuration = [];
+ foreach ($this->getParameters() as $parameter) {
+ $configuration[$parameter->getName()] = $parameter;
+ }
+
+ $data = [
+ 'name' => $this->getText(),
+ 'configuration' => $configuration,
+ ];
+ if (isset($this->customJs)) {
+ $data['custom'] = $this->getCustomJs();
+ }
+ return $data;
+ }
+
+ /**
+ * Check if parameters are satisfied in a StorageConfig
+ *
+ * @param StorageConfig $storage
+ * @return bool
+ */
+ public function validateStorageDefinition(StorageConfig $storage) {
+ $options = $storage->getBackendOptions();
+ foreach ($this->getParameters() as $name => $parameter) {
+ $value = isset($options[$name]) ? $options[$name] : null;
+ if (!$parameter->validateValue($value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/apps/files_external/lib/missingdependency.php b/apps/files_external/lib/missingdependency.php
new file mode 100644
index 00000000000..9b25aeacc9b
--- /dev/null
+++ b/apps/files_external/lib/missingdependency.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @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;
+
+/**
+ * External storage backend dependency
+ */
+class MissingDependency {
+
+ /** @var string */
+ private $dependency;
+
+ /** @var string|null Custom message */
+ private $message = null;
+
+ /**
+ * @param string $dependency
+ */
+ public function __construct($dependency) {
+ $this->dependency = $dependency;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDependency() {
+ return $this->dependency;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getMessage() {
+ return $this->message;
+ }
+
+ /**
+ * @param string $message
+ * @return self
+ */
+ public function setMessage($message) {
+ $this->message = $message;
+ return $this;
+ }
+}
diff --git a/apps/files_external/lib/personalmount.php b/apps/files_external/lib/personalmount.php
index bbffc958641..d177f1a1ad0 100644
--- a/apps/files_external/lib/personalmount.php
+++ b/apps/files_external/lib/personalmount.php
@@ -20,15 +20,45 @@
*
*/
-namespace OCA\Files_External;
+namespace OCA\Files_External\Lib;
use OC\Files\Mount\MountPoint;
use OC\Files\Mount\MoveableMount;
+use OCA\Files_External\Service\UserStoragesService;
/**
* Person mount points can be moved by the user
*/
class PersonalMount extends MountPoint implements MoveableMount {
+ /** @var UserStoragesService */
+ protected $storagesService;
+
+ /** @var int */
+ protected $storageId;
+
+ /**
+ * @param UserStoragesService $storagesService
+ * @param int $storageId
+ * @param string|\OC\Files\Storage\Storage $storage
+ * @param string $mountpoint
+ * @param array $arguments (optional) configuration for the storage backend
+ * @param \OCP\Files\Storage\IStorageFactory $loader
+ * @param array $mountOptions mount specific options
+ */
+ public function __construct(
+ UserStoragesService $storagesService,
+ $storageId,
+ $storage,
+ $mountpoint,
+ $arguments = null,
+ $loader = null,
+ $mountOptions = null
+ ) {
+ parent::__construct($storage, $mountpoint, $arguments, $loader, $mountOptions);
+ $this->storagesService = $storagesService;
+ $this->storageId = $storageId;
+ }
+
/**
* Move the mount point to $target
*
@@ -36,9 +66,13 @@ class PersonalMount extends MountPoint implements MoveableMount {
* @return bool
*/
public function moveMount($target) {
- $result = \OC_Mount_Config::movePersonalMountPoint($this->getMountPoint(), $target, \OC_Mount_Config::MOUNT_TYPE_USER);
+ $storage = $this->storagesService->getStorage($this->storageId);
+ // remove "/$user/files" prefix
+ $targetParts = explode('/', trim($target, '/'), 3);
+ $storage->setMountPoint($targetParts[2]);
+ $this->storagesService->updateStorage($storage);
$this->setMountPoint($target);
- return $result;
+ return true;
}
/**
@@ -47,8 +81,7 @@ class PersonalMount extends MountPoint implements MoveableMount {
* @return bool
*/
public function removeMount() {
- $user = \OCP\User::getUser();
- $relativeMountPoint = substr($this->getMountPoint(), strlen('/' . $user . '/files/'));
- return \OC_Mount_Config::removeMountPoint($relativeMountPoint, \OC_Mount_Config::MOUNT_TYPE_USER, $user , true);
+ $this->storagesService->removeStorage($this->storageId);
+ return true;
}
}
diff --git a/apps/files_external/lib/prioritytrait.php b/apps/files_external/lib/prioritytrait.php
new file mode 100644
index 00000000000..22f9fe275d8
--- /dev/null
+++ b/apps/files_external/lib/prioritytrait.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @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 \OCA\Files_External\Service\BackendService;
+
+/**
+ * Trait to implement priority mechanics for a configuration class
+ */
+trait PriorityTrait {
+
+ /** @var int initial priority */
+ protected $priority = BackendService::PRIORITY_DEFAULT;
+
+ /**
+ * @return int
+ */
+ public function getPriority() {
+ return $this->priority;
+ }
+
+ /**
+ * @param int $priority
+ * @return self
+ */
+ public function setPriority($priority) {
+ $this->priority = $priority;
+ return $this;
+ }
+
+ /**
+ * @param PriorityTrait $a
+ * @param PriorityTrait $b
+ * @return int
+ */
+ public static function priorityCompare(PriorityTrait $a, PriorityTrait $b) {
+ return ($a->getPriority() - $b->getPriority());
+ }
+
+}
+
diff --git a/apps/files_external/lib/storageconfig.php b/apps/files_external/lib/storageconfig.php
index 92c27701d80..cf8271ff4eb 100644
--- a/apps/files_external/lib/storageconfig.php
+++ b/apps/files_external/lib/storageconfig.php
@@ -21,6 +21,8 @@
namespace OCA\Files_external\Lib;
+use \OCA\Files_External\Lib\Backend\Backend;
+
/**
* External storage configuration
*/
@@ -34,11 +36,11 @@ class StorageConfig implements \JsonSerializable {
private $id;
/**
- * Backend class name
+ * Backend
*
- * @var string
+ * @var Backend
*/
- private $backendClass;
+ private $backend;
/**
* Backend options
@@ -138,21 +140,17 @@ class StorageConfig implements \JsonSerializable {
}
/**
- * Returns the external storage backend class name
- *
- * @return string external storage backend class name
+ * @return Backend
*/
- public function getBackendClass() {
- return $this->backendClass;
+ public function getBackend() {
+ return $this->backend;
}
/**
- * Sets the external storage backend class name
- *
- * @param string external storage backend class name
+ * @param Backend
*/
- public function setBackendClass($backendClass) {
- $this->backendClass = $backendClass;
+ public function setBackend(Backend $backend) {
+ $this->backend= $backend;
}
/**
@@ -174,6 +172,25 @@ class StorageConfig implements \JsonSerializable {
}
/**
+ * @param string $key
+ * @return mixed
+ */
+ public function getBackendOption($key) {
+ if (isset($this->backendOptions[$key])) {
+ return $this->backendOptions[$key];
+ }
+ return null;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ */
+ public function setBackendOption($key, $value) {
+ $this->backendOptions[$key] = $value;
+ }
+
+ /**
* Returns the mount priority
*
* @return int priority
@@ -283,7 +300,7 @@ class StorageConfig implements \JsonSerializable {
$result['id'] = $this->id;
}
$result['mountPoint'] = $this->mountPoint;
- $result['backendClass'] = $this->backendClass;
+ $result['backendClass'] = $this->backend->getClass();
$result['backendOptions'] = $this->backendOptions;
if (!is_null($this->priority)) {
$result['priority'] = $this->priority;
diff --git a/apps/files_external/lib/storagemodifiertrait.php b/apps/files_external/lib/storagemodifiertrait.php
new file mode 100644
index 00000000000..f78116103db
--- /dev/null
+++ b/apps/files_external/lib/storagemodifiertrait.php
@@ -0,0 +1,51 @@
+<?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\Storage;
+use \OCA\Files_External\Lib\StorageConfig;
+
+/**
+ * Trait for objects that can modify StorageConfigs and wrap Storages
+ */
+trait StorageModifierTrait {
+
+ /**
+ * Modify a StorageConfig parameters
+ *
+ * @param StorageConfig $storage
+ */
+ public function manipulateStorageConfig(StorageConfig &$storage) {
+ }
+
+ /**
+ * Wrap a Storage if necessary
+ *
+ * @param Storage $storage
+ * @return Storage
+ */
+ public function wrapStorage(Storage $storage) {
+ return $storage;
+ }
+
+}
+
diff --git a/apps/files_external/lib/visibilitytrait.php b/apps/files_external/lib/visibilitytrait.php
new file mode 100644
index 00000000000..06c95dd70c9
--- /dev/null
+++ b/apps/files_external/lib/visibilitytrait.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @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 \OCA\Files_External\Service\BackendService;
+
+/**
+ * Trait to implement visibility mechanics for a configuration class
+ */
+trait VisibilityTrait {
+
+ /** @var int visibility */
+ protected $visibility = BackendService::VISIBILITY_DEFAULT;
+
+ /** @var int allowed visibilities */
+ protected $allowedVisibility = BackendService::VISIBILITY_DEFAULT;
+
+ /**
+ * @return int
+ */
+ public function getVisibility() {
+ return $this->visibility;
+ }
+
+ /**
+ * Check if the backend is visible for a user type
+ *
+ * @param int $visibility
+ * @return bool
+ */
+ public function isVisibleFor($visibility) {
+ if ($this->visibility & $visibility) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function setVisibility($visibility) {
+ $this->visibility = $visibility;
+ $this->allowedVisibility |= $visibility;
+ return $this;
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function addVisibility($visibility) {
+ return $this->setVisibility($this->visibility | $visibility);
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function removeVisibility($visibility) {
+ return $this->setVisibility($this->visibility & ~$visibility);
+ }
+
+ /**
+ * @return int
+ */
+ public function getAllowedVisibility() {
+ return $this->allowedVisibility;
+ }
+
+ /**
+ * Check if the backend is allowed to be visible for a user type
+ *
+ * @param int $allowedVisibility
+ * @return bool
+ */
+ public function isAllowedVisibleFor($allowedVisibility) {
+ if ($this->allowedVisibility & $allowedVisibility) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function setAllowedVisibility($allowedVisibility) {
+ $this->allowedVisibility = $allowedVisibility;
+ $this->visibility &= $allowedVisibility;
+ return $this;
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function addAllowedVisibility($allowedVisibility) {
+ return $this->setAllowedVisibility($this->allowedVisibility | $allowedVisibility);
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function removeAllowedVisibility($allowedVisibility) {
+ return $this->setAllowedVisibility($this->allowedVisibility & ~$allowedVisibility);
+ }
+
+}