aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/Service/BackendService.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/lib/Service/BackendService.php')
-rw-r--r--apps/files_external/lib/Service/BackendService.php161
1 files changed, 110 insertions, 51 deletions
diff --git a/apps/files_external/lib/Service/BackendService.php b/apps/files_external/lib/Service/BackendService.php
index 49af01f5bf9..3a688ee66e6 100644
--- a/apps/files_external/lib/Service/BackendService.php
+++ b/apps/files_external/lib/Service/BackendService.php
@@ -1,34 +1,23 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- *
- * @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/>
- *
+ * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OCA\Files_External\Service;
-use \OCP\IConfig;
-
-use \OCA\Files_External\Lib\Backend\Backend;
-use \OCA\Files_External\Lib\Auth\AuthMechanism;
-use \OCA\Files_External\Lib\Config\IBackendProvider;
-use \OCA\Files_External\Lib\Config\IAuthMechanismProvider;
+use OCA\Files_External\Config\IConfigHandler;
+use OCA\Files_External\ConfigLexicon;
+use OCA\Files_External\Lib\Auth\AuthMechanism;
+use OCA\Files_External\Lib\Backend\Backend;
+use OCA\Files_External\Lib\Config\IAuthMechanismProvider;
+use OCA\Files_External\Lib\Config\IBackendProvider;
+use OCA\Files_External\Lib\MissingDependency;
+use OCP\EventDispatcher\GenericEvent;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IAppConfig;
+use OCP\Server;
/**
* Service class to manage backend definitions
@@ -36,18 +25,15 @@ use \OCA\Files_External\Lib\Config\IAuthMechanismProvider;
class BackendService {
/** Visibility constants for VisibilityTrait */
- const VISIBILITY_NONE = 0;
- const VISIBILITY_PERSONAL = 1;
- const VISIBILITY_ADMIN = 2;
+ public const VISIBILITY_NONE = 0;
+ public const VISIBILITY_PERSONAL = 1;
+ public const VISIBILITY_ADMIN = 2;
//const VISIBILITY_ALIENS = 4;
- const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
+ public const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
/** Priority constants for PriorityTrait */
- const PRIORITY_DEFAULT = 100;
-
- /** @var IConfig */
- protected $config;
+ public const PRIORITY_DEFAULT = 100;
/** @var bool */
private $userMountingAllowed = true;
@@ -67,21 +53,17 @@ class BackendService {
/** @var IAuthMechanismProvider[] */
private $authMechanismProviders = [];
- /**
- * @param IConfig $config
- */
+ /** @var callable[] */
+ private $configHandlerLoaders = [];
+
+ private $configHandlers = [];
+
public function __construct(
- IConfig $config
+ protected IAppConfig $appConfig,
) {
- $this->config = $config;
-
// Load config values
- if ($this->config->getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') {
- $this->userMountingAllowed = false;
- }
- $this->userMountingBackends = explode(',',
- $this->config->getAppValue('files_external', 'user_mounting_backends', '')
- );
+ $this->userMountingAllowed = $appConfig->getValueBool('files_external', ConfigLexicon::ALLOW_USER_MOUNTING);
+ $this->userMountingBackends = explode(',', $appConfig->getValueString('files_external', ConfigLexicon::USER_MOUNTING_BACKENDS));
// if no backend is in the list an empty string is in the array and user mounting is disabled
if ($this->userMountingBackends === ['']) {
@@ -99,7 +81,19 @@ class BackendService {
$this->backendProviders[] = $provider;
}
+ private function callForRegistrations() {
+ static $eventSent = false;
+ if (!$eventSent) {
+ Server::get(IEventDispatcher::class)->dispatch(
+ 'OCA\\Files_External::loadAdditionalBackends',
+ new GenericEvent()
+ );
+ $eventSent = true;
+ }
+ }
+
private function loadBackendProviders() {
+ $this->callForRegistrations();
foreach ($this->backendProviders as $provider) {
$this->registerBackends($provider->getBackends());
}
@@ -117,6 +111,7 @@ class BackendService {
}
private function loadAuthMechanismProviders() {
+ $this->callForRegistrations();
foreach ($this->authMechanismProviders as $provider) {
$this->registerAuthMechanisms($provider->getAuthMechanisms());
}
@@ -193,8 +188,9 @@ class BackendService {
* @return Backend[]
*/
public function getAvailableBackends() {
- return array_filter($this->getBackends(), function($backend) {
- return !($backend->checkDependencies());
+ return array_filter($this->getBackends(), function ($backend) {
+ $missing = array_filter($backend->checkDependencies(), fn (MissingDependency $dependency) => !$dependency->isOptional());
+ return count($missing) === 0;
});
}
@@ -232,7 +228,7 @@ class BackendService {
* @return AuthMechanism[]
*/
public function getAuthMechanismsByScheme(array $schemes) {
- return array_filter($this->getAuthMechanisms(), function($authMech) use ($schemes) {
+ return array_filter($this->getAuthMechanisms(), function ($authMech) use ($schemes) {
return in_array($authMech->getScheme(), $schemes, true);
});
}
@@ -263,8 +259,8 @@ class BackendService {
* @return bool
*/
protected function isAllowedUserBackend(Backend $backend) {
- if ($this->userMountingAllowed &&
- array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends)
+ if ($this->userMountingAllowed
+ && array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends)
) {
return true;
}
@@ -280,4 +276,67 @@ class BackendService {
protected function isAllowedAuthMechanism(AuthMechanism $authMechanism) {
return true; // not implemented
}
+
+ /**
+ * registers a configuration handler
+ *
+ * The function of the provided $placeholder is mostly to act a sorting
+ * criteria, so longer placeholders are replaced first. This avoids
+ * "$user" overwriting parts of "$userMail" and "$userLang", for example.
+ * The provided value should not contain the $ prefix, only a-z0-9 are
+ * allowed. Upper case letters are lower cased, the replacement is case-
+ * insensitive.
+ *
+ * The configHandlerLoader should just instantiate the handler on demand.
+ * For now all handlers are instantiated when a mount is loaded, independent
+ * of whether the placeholder is present or not. This may change in future.
+ *
+ * @since 16.0.0
+ */
+ public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) {
+ $placeholder = trim(strtolower($placeholder));
+ if (!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) {
+ throw new \RuntimeException(sprintf(
+ 'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder
+ ));
+ }
+ if ($placeholder === '') {
+ throw new \RuntimeException('Invalid empty placeholder');
+ }
+ if (isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
+ throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder));
+ }
+ $this->configHandlerLoaders[$placeholder] = $configHandlerLoader;
+ }
+
+ protected function loadConfigHandlers():void {
+ $this->callForRegistrations();
+ $newLoaded = false;
+ foreach ($this->configHandlerLoaders as $placeholder => $loader) {
+ $handler = $loader();
+ if (!$handler instanceof IConfigHandler) {
+ throw new \RuntimeException(sprintf(
+ 'Handler for %s is not an instance of IConfigHandler', $placeholder
+ ));
+ }
+ $this->configHandlers[$placeholder] = $handler;
+ $newLoaded = true;
+ }
+ $this->configHandlerLoaders = [];
+ if ($newLoaded) {
+ // ensure those with longest placeholders come first,
+ // to avoid substring matches
+ uksort($this->configHandlers, function ($phA, $phB) {
+ return strlen($phB) <=> strlen($phA);
+ });
+ }
+ }
+
+ /**
+ * @since 16.0.0
+ */
+ public function getConfigHandlers() {
+ $this->loadConfigHandlers();
+ return $this->configHandlers;
+ }
}