diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index adf3f766202e1..6a5e34f055a8e 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -999,6 +999,10 @@ MountConfigListView.prototype = _.extend({ } else { newElement = $(''); } + if (placeholder.tooltip) { + newElement.attr('title', placeholder.tooltip); + newElement.tooltip(); + } highlightInput(newElement); $td.append(newElement); return newElement; @@ -1213,8 +1217,6 @@ MountConfigListView.prototype = _.extend({ if (typeof message === 'string') { $statusSpan.attr('title', message); $statusSpan.tooltip(); - } else { - $statusSpan.tooltip('destroy'); } }, diff --git a/apps/files_external/lib/Controller/UserGlobalStoragesController.php b/apps/files_external/lib/Controller/UserGlobalStoragesController.php index 22c9c867855c8..b7ee0e9e429f5 100644 --- a/apps/files_external/lib/Controller/UserGlobalStoragesController.php +++ b/apps/files_external/lib/Controller/UserGlobalStoragesController.php @@ -27,6 +27,7 @@ use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Auth\IUserProvided; +use OCA\Files_External\Lib\DefinitionParameter; use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; use OCP\ILogger; use \OCP\IRequest; @@ -122,7 +123,7 @@ public function show($id, $testOnly = true) { } catch (NotFoundException $e) { return new DataResponse( [ - 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id)) + 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', [$id]), ], Http::STATUS_NOT_FOUND ); @@ -157,12 +158,12 @@ public function update( $storage = $this->service->getStorage($id); $authMechanism = $storage->getAuthMechanism(); if ($authMechanism instanceof IUserProvided) { - $authMechanism->saveBackendOptions($this->userSession->getUser(), $id, $backendOptions); + $authMechanism->saveBackendOptions($this->userSession->getUser(), $id, $backendOptions, $storage); $authMechanism->manipulateStorageConfig($storage, $this->userSession->getUser()); } else { return new DataResponse( [ - 'message' => (string)$this->l10n->t('Storage with ID "%d" is not user editable', array($id)) + 'message' => (string)$this->l10n->t('Storage with ID "%d" is not user editable', [$id]), ], Http::STATUS_FORBIDDEN ); @@ -170,7 +171,7 @@ public function update( } catch (NotFoundException $e) { return new DataResponse( [ - 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', array($id)) + 'message' => (string)$this->l10n->t('Storage with ID "%d" not found', [$id]), ], Http::STATUS_NOT_FOUND ); @@ -192,7 +193,17 @@ public function update( * @param StorageConfig $storage */ protected function sanitizeStorage(StorageConfig $storage) { - $storage->setBackendOptions([]); + $preserveBackendOptionKeys = array_filter($storage->getAuthMechanism()->getParameters(), function (DefinitionParameter $parameter) { + return $parameter->isFlagSet(DefinitionParameter::FLAG_PRESERVE_SANITIZE); + }); + $preserveBackendOptionKeys = array_map(function (DefinitionParameter $parameter) { + return $parameter->getName(); + }, $preserveBackendOptionKeys); + $preserveBackendOptions = array_filter($storage->getBackendOptions(), function (string $key) use ($preserveBackendOptionKeys) { + return in_array($key, $preserveBackendOptionKeys); + }, ARRAY_FILTER_USE_KEY); + + $storage->setBackendOptions($preserveBackendOptions); $storage->setMountOptions([]); if ($storage->getAuthMechanism() instanceof IUserProvided) { diff --git a/apps/files_external/lib/Lib/Auth/IUserProvided.php b/apps/files_external/lib/Lib/Auth/IUserProvided.php index ed4abaf657379..d4a236f955f71 100644 --- a/apps/files_external/lib/Lib/Auth/IUserProvided.php +++ b/apps/files_external/lib/Lib/Auth/IUserProvided.php @@ -22,6 +22,7 @@ namespace OCA\Files_External\Lib\Auth; +use OCA\Files_External\Lib\StorageConfig; use OCP\IUser; /** @@ -32,6 +33,7 @@ interface IUserProvided { * @param IUser $user the user for which to save the user provided options * @param int $mountId the mount id to save the options for * @param array $options the user provided options + * @param StorageConfig $storage */ - public function saveBackendOptions(IUser $user, $mountId, array $options); + public function saveBackendOptions(IUser $user, $mountId, array $options, StorageConfig $storage); } diff --git a/apps/files_external/lib/Lib/Auth/Password/UserProvided.php b/apps/files_external/lib/Lib/Auth/Password/UserProvided.php index 6bac2bd9c18f7..1f99d0ac0e8a4 100644 --- a/apps/files_external/lib/Lib/Auth/Password/UserProvided.php +++ b/apps/files_external/lib/Lib/Auth/Password/UserProvided.php @@ -51,6 +51,10 @@ public function __construct(IL10N $l, ICredentialsManager $credentialsManager) { ->setScheme(self::SCHEME_PASSWORD) ->setText($l->t('User entered, store in database')) ->addParameters([ + (new DefinitionParameter('key', $l->t('Credential Identifier'))) + ->setTooltip($l->t('Identifier used to reuse credentials between storage, leave empty to use per-storage credentials')) + ->setFlag(DefinitionParameter::FLAG_PRESERVE_SANITIZE) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), (new DefinitionParameter('user', $l->t('Username'))) ->setFlag(DefinitionParameter::FLAG_USER_PROVIDED), (new DefinitionParameter('password', $l->t('Password'))) @@ -59,12 +63,16 @@ public function __construct(IL10N $l, ICredentialsManager $credentialsManager) { ]); } - private function getCredentialsIdentifier($storageId) { - return self::CREDENTIALS_IDENTIFIER_PREFIX . $storageId; + private function getCredentialsIdentifier(?string $key, $storageId) { + if ($key) { + return self::CREDENTIALS_IDENTIFIER_PREFIX . $key; + } else { + return self::CREDENTIALS_IDENTIFIER_PREFIX . $storageId; + } } - public function saveBackendOptions(IUser $user, $id, array $options) { - $this->credentialsManager->store($user->getUID(), $this->getCredentialsIdentifier($id), [ + public function saveBackendOptions(IUser $user, $id, array $options, StorageConfig $storage) { + $this->credentialsManager->store($user->getUID(), $this->getCredentialsIdentifier($storage->getBackendOption('key'), $id), [ 'user' => $options['user'], // explicitly copy the fields we want instead of just passing the entire $options array 'password' => $options['password'] // this way we prevent users from being able to modify any other field ]); @@ -75,7 +83,7 @@ public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = n throw new InsufficientDataForMeaningfulAnswerException('No credentials saved'); } $uid = $user->getUID(); - $credentials = $this->credentialsManager->retrieve($uid, $this->getCredentialsIdentifier($storage->getId())); + $credentials = $this->credentialsManager->retrieve($uid, $this->getCredentialsIdentifier($storage->getBackendOption('key'), $storage->getId())); if (!isset($credentials)) { throw new InsufficientDataForMeaningfulAnswerException('No credentials saved'); diff --git a/apps/files_external/lib/Lib/DefinitionParameter.php b/apps/files_external/lib/Lib/DefinitionParameter.php index c1108fccce791..4b50dee914e56 100644 --- a/apps/files_external/lib/Lib/DefinitionParameter.php +++ b/apps/files_external/lib/Lib/DefinitionParameter.php @@ -38,6 +38,7 @@ class DefinitionParameter implements \JsonSerializable { const FLAG_NONE = 0; const FLAG_OPTIONAL = 1; const FLAG_USER_PROVIDED = 2; + const FLAG_PRESERVE_SANITIZE = 4; /** @var string name of parameter */ private $name; @@ -45,6 +46,9 @@ class DefinitionParameter implements \JsonSerializable { /** @var string human-readable parameter text */ private $text; + /** @var string human-readable parameter tool tip */ + private $tooltip; + /** @var int value type, see self::VALUE_* constants */ private $type = self::VALUE_TEXT; @@ -94,6 +98,26 @@ public function setType($type) { return $this; } + /** + * Set the tooltip for the parameter + * + * @param string $tooltip + * @return DefinitionParameter + */ + public function setTooltip(string $tooltip): DefinitionParameter { + $this->tooltip = $tooltip; + return $this; + } + + /** + * Get the tooltip for the value + * + * @return string + */ + public function getTooltip(): ?string { + return $this->tooltip; + } + /** * @return string */ @@ -152,7 +176,8 @@ public function jsonSerialize() { return [ 'value' => $this->getText(), 'flags' => $this->getFlags(), - 'type' => $this->getType() + 'type' => $this->getType(), + 'tooltip' => $this->getTooltip(), ]; }