Merge pull request #18441 from owncloud/ext-backends.advanced
Migrate advanced external storage backends to new registration API [part 3]
This commit is contained in:
commit
0dc7181335
31 changed files with 720 additions and 744 deletions
|
@ -37,11 +37,9 @@ OC::$CLASSPATH['OC\Files\Storage\OwnCloud'] = 'files_external/lib/owncloud.php';
|
|||
OC::$CLASSPATH['OC\Files\Storage\Google'] = 'files_external/lib/google.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\Swift'] = 'files_external/lib/swift.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\SMB'] = 'files_external/lib/smb.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\SMB_OC'] = 'files_external/lib/smb_oc.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\AmazonS3'] = 'files_external/lib/amazons3.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\Dropbox'] = 'files_external/lib/dropbox.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\SFTP'] = 'files_external/lib/sftp.php';
|
||||
OC::$CLASSPATH['OC\Files\Storage\SFTP_Key'] = 'files_external/lib/sftp_key.php';
|
||||
OC::$CLASSPATH['OC_Mount_Config'] = 'files_external/lib/config.php';
|
||||
OC::$CLASSPATH['OCA\Files\External\Api'] = 'files_external/lib/api.php';
|
||||
|
||||
|
@ -68,51 +66,6 @@ if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == '
|
|||
|
||||
// connecting hooks
|
||||
OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook');
|
||||
OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\SMB_OC', 'login');
|
||||
|
||||
OC_Mount_Config::registerBackend('\OC\Files\Storage\Swift', [
|
||||
'backend' => (string)$l->t('OpenStack Object Storage'),
|
||||
'priority' => 100,
|
||||
'configuration' => [
|
||||
'user' => (string)$l->t('Username'),
|
||||
'bucket' => (string)$l->t('Bucket'),
|
||||
'region' => '&'.$l->t('Region (optional for OpenStack Object Storage)'),
|
||||
'key' => '&*'.$l->t('API Key (required for Rackspace Cloud Files)'),
|
||||
'tenant' => '&'.$l->t('Tenantname (required for OpenStack Object Storage)'),
|
||||
'password' => '&*'.$l->t('Password (required for OpenStack Object Storage)'),
|
||||
'service_name' => '&'.$l->t('Service Name (required for OpenStack Object Storage)'),
|
||||
'url' => '&'.$l->t('URL of identity endpoint (required for OpenStack Object Storage)'),
|
||||
'timeout' => '&'.$l->t('Timeout of HTTP requests in seconds'),
|
||||
],
|
||||
'has_dependencies' => true,
|
||||
]);
|
||||
|
||||
|
||||
if (!OC_Util::runningOnWindows()) {
|
||||
OC_Mount_Config::registerBackend('\OC\Files\Storage\SMB_OC', [
|
||||
'backend' => (string)$l->t('SMB / CIFS using OC login'),
|
||||
'priority' => 90,
|
||||
'configuration' => [
|
||||
'host' => (string)$l->t('Host'),
|
||||
'username_as_share' => '!'.$l->t('Username as share'),
|
||||
'share' => '&'.$l->t('Share'),
|
||||
'root' => '&'.$l->t('Remote subfolder'),
|
||||
],
|
||||
'has_dependencies' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
OC_Mount_Config::registerBackend('\OC\Files\Storage\SFTP_Key', [
|
||||
'backend' => (string)$l->t('SFTP with secret key login'),
|
||||
'priority' => 100,
|
||||
'configuration' => array(
|
||||
'host' => (string)$l->t('Host'),
|
||||
'user' => (string)$l->t('Username'),
|
||||
'public_key' => (string)$l->t('Public key'),
|
||||
'private_key' => '#private_key',
|
||||
'root' => '&'.$l->t('Remote subfolder')),
|
||||
'custom' => 'sftp_key',
|
||||
]
|
||||
);
|
||||
$mountProvider = $appContainer->query('OCA\Files_External\Config\ConfigAdapter');
|
||||
\OC::$server->getMountProviderCollection()->registerProvider($mountProvider);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
namespace OCA\Files_External\AppInfo;
|
||||
|
||||
use \OCA\Files_External\Controller\AjaxController;
|
||||
use \OCP\AppFramework\App;
|
||||
use \OCP\IContainer;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
|
@ -36,18 +35,6 @@ class Application extends App {
|
|||
public function __construct(array $urlParams=array()) {
|
||||
parent::__construct('files_external', $urlParams);
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
||||
/**
|
||||
* Controllers
|
||||
*/
|
||||
$container->registerService('AjaxController', function (IContainer $c) {
|
||||
return new AjaxController(
|
||||
$c->query('AppName'),
|
||||
$c->query('Request')
|
||||
);
|
||||
});
|
||||
|
||||
$this->loadBackends();
|
||||
$this->loadAuthMechanisms();
|
||||
|
||||
|
@ -73,11 +60,14 @@ class Application extends App {
|
|||
$container->query('OCA\Files_External\Lib\Backend\AmazonS3'),
|
||||
$container->query('OCA\Files_External\Lib\Backend\Dropbox'),
|
||||
$container->query('OCA\Files_External\Lib\Backend\Google'),
|
||||
$container->query('OCA\Files_External\Lib\Backend\Swift'),
|
||||
$container->query('OCA\Files_External\Lib\Backend\SFTP_Key'),
|
||||
]);
|
||||
|
||||
if (!\OC_Util::runningOnWindows()) {
|
||||
$service->registerBackends([
|
||||
$container->query('OCA\Files_External\Lib\Backend\SMB'),
|
||||
$container->query('OCA\Files_External\Lib\Backend\SMB_OC'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +96,13 @@ class Application extends App {
|
|||
// AuthMechanism::SCHEME_OAUTH2 mechanisms
|
||||
$container->query('OCA\Files_External\Lib\Auth\OAuth2\OAuth2'),
|
||||
|
||||
// AuthMechanism::SCHEME_PUBLICKEY mechanisms
|
||||
$container->query('OCA\Files_External\Lib\Auth\PublicKey\RSA'),
|
||||
|
||||
// AuthMechanism::SCHEME_OPENSTACK mechanisms
|
||||
$container->query('OCA\Files_External\Lib\Auth\OpenStack\OpenStack'),
|
||||
$container->query('OCA\Files_External\Lib\Auth\OpenStack\Rackspace'),
|
||||
|
||||
// Specialized mechanisms
|
||||
$container->query('OCA\Files_External\Lib\Auth\AmazonS3\AccessKey'),
|
||||
]);
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace OCA\Files_External\AppInfo;
|
|||
'routes' => array(
|
||||
array(
|
||||
'name' => 'Ajax#getSshKeys',
|
||||
'url' => '/ajax/sftp_key.php',
|
||||
'url' => '/ajax/public_key.php',
|
||||
'verb' => 'POST',
|
||||
'requirements' => array()
|
||||
)
|
||||
|
|
|
@ -25,19 +25,19 @@ namespace OCA\Files_External\Controller;
|
|||
use OCP\AppFramework\Controller;
|
||||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use OCA\Files_External\Lib\Auth\PublicKey\RSA;
|
||||
|
||||
class AjaxController extends Controller {
|
||||
public function __construct($appName, IRequest $request) {
|
||||
/** @var RSA */
|
||||
private $rsaMechanism;
|
||||
|
||||
public function __construct($appName, IRequest $request, RSA $rsaMechanism) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->rsaMechanism = $rsaMechanism;
|
||||
}
|
||||
|
||||
private function generateSshKeys() {
|
||||
$rsa = new RSA();
|
||||
$rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_OPENSSH);
|
||||
$rsa->setPassword(\OC::$server->getConfig()->getSystemValue('secret', ''));
|
||||
|
||||
$key = $rsa->createKey();
|
||||
$key = $this->rsaMechanism->createKey();
|
||||
// Replace the placeholder label with a more meaningful one
|
||||
$key['publicKey'] = str_replace('phpseclib-generated-key', gethostname(), $key['publickey']);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ use \OCP\AppFramework\Http;
|
|||
use \OCA\Files_external\Service\GlobalStoragesService;
|
||||
use \OCA\Files_external\NotFoundException;
|
||||
use \OCA\Files_external\Lib\StorageConfig;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
|
||||
/**
|
||||
* Global storages controller
|
||||
|
@ -97,7 +98,7 @@ class GlobalStoragesController extends StoragesController {
|
|||
return $newStorage;
|
||||
}
|
||||
|
||||
$response = $this->validate($newStorage);
|
||||
$response = $this->validate($newStorage, BackendService::PERMISSION_CREATE);
|
||||
if (!empty($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -153,7 +154,7 @@ class GlobalStoragesController extends StoragesController {
|
|||
}
|
||||
$storage->setId($id);
|
||||
|
||||
$response = $this->validate($storage);
|
||||
$response = $this->validate($storage, BackendService::PERMISSION_MODIFY);
|
||||
if (!empty($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -178,4 +179,14 @@ class GlobalStoragesController extends StoragesController {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user type for this controller, used in validation
|
||||
*
|
||||
* @return string BackendService::USER_* constants
|
||||
*/
|
||||
protected function getUserType() {
|
||||
return BackendService::USER_ADMIN;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ use \OCA\Files_External\Lib\Backend\Backend;
|
|||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use \OCP\Files\StorageNotAvailableException;
|
||||
use \OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
|
||||
/**
|
||||
* Base class for storages controllers
|
||||
|
@ -124,10 +125,11 @@ abstract class StoragesController extends Controller {
|
|||
* Validate storage config
|
||||
*
|
||||
* @param StorageConfig $storage storage config
|
||||
* @param int $permissionCheck permission to check
|
||||
*
|
||||
* @return DataResponse|null returns response in case of validation error
|
||||
*/
|
||||
protected function validate(StorageConfig $storage) {
|
||||
protected function validate(StorageConfig $storage, $permissionCheck = BackendService::PERMISSION_CREATE) {
|
||||
$mountPoint = $storage->getMountPoint();
|
||||
if ($mountPoint === '' || $mountPoint === '/') {
|
||||
return new DataResponse(
|
||||
|
@ -157,12 +159,36 @@ abstract class StoragesController extends Controller {
|
|||
return new DataResponse(
|
||||
array(
|
||||
'message' => (string)$this->l10n->t('Invalid storage backend "%s"', [
|
||||
$storage->getBackend()->getIdentifier()
|
||||
$backend->getIdentifier()
|
||||
])
|
||||
),
|
||||
Http::STATUS_UNPROCESSABLE_ENTITY
|
||||
);
|
||||
}
|
||||
|
||||
if (!$backend->isPermitted($this->getUserType(), $permissionCheck)) {
|
||||
// not permitted to use backend
|
||||
return new DataResponse(
|
||||
array(
|
||||
'message' => (string)$this->l10n->t('Not permitted to use backend "%s"', [
|
||||
$backend->getIdentifier()
|
||||
])
|
||||
),
|
||||
Http::STATUS_UNPROCESSABLE_ENTITY
|
||||
);
|
||||
}
|
||||
if (!$authMechanism->isPermitted($this->getUserType(), $permissionCheck)) {
|
||||
// not permitted to use auth mechanism
|
||||
return new DataResponse(
|
||||
array(
|
||||
'message' => (string)$this->l10n->t('Not permitted to use authentication mechanism "%s"', [
|
||||
$authMechanism->getIdentifier()
|
||||
])
|
||||
),
|
||||
Http::STATUS_UNPROCESSABLE_ENTITY
|
||||
);
|
||||
}
|
||||
|
||||
if (!$backend->validateStorage($storage)) {
|
||||
// unsatisfied parameters
|
||||
return new DataResponse(
|
||||
|
@ -185,6 +211,13 @@ abstract class StoragesController extends Controller {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user type for this controller, used in validation
|
||||
*
|
||||
* @return string BackendService::USER_* constants
|
||||
*/
|
||||
abstract protected function getUserType();
|
||||
|
||||
/**
|
||||
* Check whether the given storage is available / valid.
|
||||
*
|
||||
|
|
|
@ -61,38 +61,6 @@ class UserStoragesController extends StoragesController {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate storage config
|
||||
*
|
||||
* @param StorageConfig $storage storage config
|
||||
*
|
||||
* @return DataResponse|null returns response in case of validation error
|
||||
*/
|
||||
protected function validate(StorageConfig $storage) {
|
||||
$result = parent::validate($storage);
|
||||
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Verify that the mount point applies for the current user
|
||||
// Prevent non-admin users from mounting local storage and other disabled backends
|
||||
/** @var Backend */
|
||||
$backend = $storage->getBackend();
|
||||
if (!$backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL)) {
|
||||
return new DataResponse(
|
||||
array(
|
||||
'message' => (string)$this->l10n->t('Admin-only storage backend "%s"', [
|
||||
$storage->getBackend()->getIdentifier()
|
||||
])
|
||||
),
|
||||
Http::STATUS_UNPROCESSABLE_ENTITY
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return storage
|
||||
*
|
||||
|
@ -135,7 +103,7 @@ class UserStoragesController extends StoragesController {
|
|||
return $newStorage;
|
||||
}
|
||||
|
||||
$response = $this->validate($newStorage);
|
||||
$response = $this->validate($newStorage, BackendService::PERMISSION_CREATE);
|
||||
if (!empty($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -183,7 +151,7 @@ class UserStoragesController extends StoragesController {
|
|||
}
|
||||
$storage->setId($id);
|
||||
|
||||
$response = $this->validate($storage);
|
||||
$response = $this->validate($storage, BackendService::PERMISSION_MODIFY);
|
||||
if (!empty($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
@ -218,4 +186,14 @@ class UserStoragesController extends StoragesController {
|
|||
public function destroy($id) {
|
||||
return parent::destroy($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user type for this controller, used in validation
|
||||
*
|
||||
* @return string BackendService::USER_* constants
|
||||
*/
|
||||
protected function getUserType() {
|
||||
return BackendService::USER_PERSONAL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
46
apps/files_external/js/public_key.js
Normal file
46
apps/files_external/js/public_key.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme) {
|
||||
if (scheme === 'publickey') {
|
||||
var config = $tr.find('.configuration');
|
||||
if ($(config).find('[name="public_key_generate"]').length === 0) {
|
||||
setupTableRow($tr, config);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#externalStorage').on('click', '[name="public_key_generate"]', function(event) {
|
||||
event.preventDefault();
|
||||
var tr = $(this).parent().parent();
|
||||
generateKeys(tr);
|
||||
});
|
||||
|
||||
function setupTableRow(tr, config) {
|
||||
$(config).append($(document.createElement('input'))
|
||||
.addClass('button auth-param')
|
||||
.attr('type', 'button')
|
||||
.attr('value', t('files_external', 'Generate keys'))
|
||||
.attr('name', 'public_key_generate')
|
||||
);
|
||||
// If there's no private key, build one
|
||||
if (0 === $(config).find('[data-parameter="private_key"]').val().length) {
|
||||
generateKeys(tr);
|
||||
}
|
||||
}
|
||||
|
||||
function generateKeys(tr) {
|
||||
var config = $(tr).find('.configuration');
|
||||
|
||||
$.post(OC.filePath('files_external', 'ajax', 'public_key.php'), {}, function(result) {
|
||||
if (result && result.status === 'success') {
|
||||
$(config).find('[data-parameter="public_key"]').val(result.data.public_key);
|
||||
$(config).find('[data-parameter="private_key"]').val(result.data.private_key);
|
||||
OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() {
|
||||
// Nothing to do
|
||||
});
|
||||
} else {
|
||||
OC.dialogs.alert(result.data.message, t('files_external', 'Error generating key pair') );
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$('#externalStorage tbody tr.\\\\OC\\\\Files\\\\Storage\\\\SFTP_Key').each(function() {
|
||||
var tr = $(this);
|
||||
var config = $(tr).find('.configuration');
|
||||
if ($(config).find('.sftp_key').length === 0) {
|
||||
setupTableRow(tr, config);
|
||||
}
|
||||
});
|
||||
|
||||
// We can't catch the DOM elements being added, but we can pick up when
|
||||
// they receive focus
|
||||
$('#externalStorage').on('focus', 'tbody tr.\\\\OC\\\\Files\\\\Storage\\\\SFTP_Key', function() {
|
||||
var tr = $(this);
|
||||
var config = $(tr).find('.configuration');
|
||||
|
||||
if ($(config).find('.sftp_key').length === 0) {
|
||||
setupTableRow(tr, config);
|
||||
}
|
||||
});
|
||||
|
||||
$('#externalStorage').on('click', '.sftp_key', function(event) {
|
||||
event.preventDefault();
|
||||
var tr = $(this).parent().parent();
|
||||
generateKeys(tr);
|
||||
});
|
||||
|
||||
function setupTableRow(tr, config) {
|
||||
$(config).append($(document.createElement('input')).addClass('button sftp_key')
|
||||
.attr('type', 'button')
|
||||
.attr('value', t('files_external', 'Generate keys')));
|
||||
// If there's no private key, build one
|
||||
if (0 === $(config).find('[data-parameter="private_key"]').val().length) {
|
||||
generateKeys(tr);
|
||||
}
|
||||
}
|
||||
|
||||
function generateKeys(tr) {
|
||||
var config = $(tr).find('.configuration');
|
||||
|
||||
$.post(OC.filePath('files_external', 'ajax', 'sftp_key.php'), {}, function(result) {
|
||||
if (result && result.status === 'success') {
|
||||
$(config).find('[data-parameter="public_key"]').val(result.data.public_key);
|
||||
$(config).find('[data-parameter="private_key"]').val(result.data.private_key);
|
||||
OCA.External.mountConfig.saveStorageConfig(tr, function() {
|
||||
// Nothing to do
|
||||
});
|
||||
} else {
|
||||
OC.dialogs.alert(result.data.message, t('files_external', 'Error generating key pair') );
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
|
@ -22,7 +22,7 @@
|
|||
namespace OCA\Files_External\Lib\Auth;
|
||||
|
||||
use \OCA\Files_External\Lib\StorageConfig;
|
||||
use \OCA\Files_External\Lib\VisibilityTrait;
|
||||
use \OCA\Files_External\Lib\PermissionsTrait;
|
||||
use \OCA\Files_External\Lib\IdentifierTrait;
|
||||
use \OCA\Files_External\Lib\FrontendDefinitionTrait;
|
||||
use \OCA\Files_External\Lib\StorageModifierTrait;
|
||||
|
@ -40,7 +40,7 @@ use \OCA\Files_External\Lib\StorageModifierTrait;
|
|||
* scheme, which are provided from the authentication mechanism.
|
||||
*
|
||||
* This class uses the following traits:
|
||||
* - VisibilityTrait
|
||||
* - PermissionsTrait
|
||||
* Restrict usage to admin-only/none
|
||||
* - FrontendDefinitionTrait
|
||||
* Specify configuration parameters and other definitions
|
||||
|
@ -58,7 +58,7 @@ class AuthMechanism implements \JsonSerializable {
|
|||
const SCHEME_PUBLICKEY = 'publickey';
|
||||
const SCHEME_OPENSTACK = 'openstack';
|
||||
|
||||
use VisibilityTrait;
|
||||
use PermissionsTrait;
|
||||
use FrontendDefinitionTrait;
|
||||
use StorageModifierTrait;
|
||||
use IdentifierTrait;
|
||||
|
|
48
apps/files_external/lib/auth/openstack/openstack.php
Normal file
48
apps/files_external/lib/auth/openstack/openstack.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?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\Auth\OpenStack;
|
||||
|
||||
use \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
|
||||
/**
|
||||
* OpenStack Keystone authentication
|
||||
*/
|
||||
class OpenStack extends AuthMechanism {
|
||||
|
||||
public function __construct(IL10N $l) {
|
||||
$this
|
||||
->setIdentifier('openstack::openstack')
|
||||
->setScheme(self::SCHEME_OPENSTACK)
|
||||
->setText($l->t('OpenStack'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('user', $l->t('Username'))),
|
||||
(new DefinitionParameter('password', $l->t('Password')))
|
||||
->setType(DefinitionParameter::VALUE_PASSWORD),
|
||||
(new DefinitionParameter('tenant', $l->t('Tenant name'))),
|
||||
(new DefinitionParameter('url', $l->t('Identity endpoint URL'))),
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
}
|
46
apps/files_external/lib/auth/openstack/rackspace.php
Normal file
46
apps/files_external/lib/auth/openstack/rackspace.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?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\Auth\OpenStack;
|
||||
|
||||
use \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
|
||||
/**
|
||||
* Rackspace authentication
|
||||
*/
|
||||
class Rackspace extends AuthMechanism {
|
||||
|
||||
public function __construct(IL10N $l) {
|
||||
$this
|
||||
->setIdentifier('openstack::rackspace')
|
||||
->setScheme(self::SCHEME_OPENSTACK)
|
||||
->setText($l->t('Rackspace'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('user', $l->t('Username'))),
|
||||
(new DefinitionParameter('key', $l->t('API key')))
|
||||
->setType(DefinitionParameter::VALUE_PASSWORD),
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
}
|
80
apps/files_external/lib/auth/publickey/rsa.php
Normal file
80
apps/files_external/lib/auth/publickey/rsa.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?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\Auth\PublicKey;
|
||||
|
||||
use \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use \OCA\Files_External\Lib\StorageConfig;
|
||||
use \OCP\IConfig;
|
||||
use \phpseclib\Crypt\RSA as RSACrypt;
|
||||
|
||||
/**
|
||||
* RSA public key authentication
|
||||
*/
|
||||
class RSA extends AuthMechanism {
|
||||
|
||||
const CREATE_KEY_BITS = 1024;
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
public function __construct(IL10N $l, IConfig $config) {
|
||||
$this->config = $config;
|
||||
|
||||
$this
|
||||
->setIdentifier('publickey::rsa')
|
||||
->setScheme(self::SCHEME_PUBLICKEY)
|
||||
->setText($l->t('RSA public key'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('user', $l->t('Username'))),
|
||||
(new DefinitionParameter('public_key', $l->t('Public key'))),
|
||||
(new DefinitionParameter('private_key', 'private_key'))
|
||||
->setType(DefinitionParameter::VALUE_HIDDEN),
|
||||
])
|
||||
->setCustomJs('public_key')
|
||||
;
|
||||
}
|
||||
|
||||
public function manipulateStorageConfig(StorageConfig &$storage) {
|
||||
$auth = new RSACrypt();
|
||||
$auth->setPassword($this->config->getSystemValue('secret', ''));
|
||||
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
|
||||
throw new \RuntimeException('unable to load private key');
|
||||
}
|
||||
$storage->setBackendOption('public_key_auth', $auth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a keypair
|
||||
*
|
||||
* @return array ['privatekey' => $privateKey, 'publickey' => $publicKey]
|
||||
*/
|
||||
public function createKey() {
|
||||
$rsa = new RSACrypt();
|
||||
$rsa->setPublicKeyFormat(RSACrypt::PUBLIC_FORMAT_OPENSSH);
|
||||
$rsa->setPassword($this->config->getSystemValue('secret', ''));
|
||||
|
||||
return $rsa->createKey(self::CREATE_KEY_BITS);
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
namespace OCA\Files_External\Lib\Backend;
|
||||
|
||||
use \OCA\Files_External\Lib\StorageConfig;
|
||||
use \OCA\Files_External\Lib\VisibilityTrait;
|
||||
use \OCA\Files_External\Lib\PermissionsTrait;
|
||||
use \OCA\Files_External\Lib\FrontendDefinitionTrait;
|
||||
use \OCA\Files_External\Lib\PriorityTrait;
|
||||
use \OCA\Files_External\Lib\DependencyTrait;
|
||||
|
@ -43,7 +43,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
|||
* scheme, which are provided from the authentication mechanism.
|
||||
*
|
||||
* This class uses the following traits:
|
||||
* - VisibilityTrait
|
||||
* - PermissionsTrait
|
||||
* Restrict usage to admin-only/none
|
||||
* - FrontendDefinitionTrait
|
||||
* Specify configuration parameters and other definitions
|
||||
|
@ -56,7 +56,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
|||
*/
|
||||
class Backend implements \JsonSerializable {
|
||||
|
||||
use VisibilityTrait;
|
||||
use PermissionsTrait;
|
||||
use FrontendDefinitionTrait;
|
||||
use PriorityTrait;
|
||||
use DependencyTrait;
|
||||
|
|
|
@ -39,7 +39,7 @@ class Local extends Backend {
|
|||
->addParameters([
|
||||
(new DefinitionParameter('datadir', $l->t('Location'))),
|
||||
])
|
||||
->setAllowedVisibility(BackendService::VISIBILITY_ADMIN)
|
||||
->setAllowedPermissions(BackendService::USER_PERSONAL, BackendService::PERMISSION_NONE)
|
||||
->setPriority(BackendService::PRIORITY_DEFAULT + 50)
|
||||
->addAuthScheme(AuthMechanism::SCHEME_NULL)
|
||||
->setLegacyAuthMechanism($legacyAuth)
|
||||
|
|
|
@ -43,6 +43,7 @@ class SFTP extends Backend {
|
|||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
])
|
||||
->addAuthScheme(AuthMechanism::SCHEME_PASSWORD)
|
||||
->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY)
|
||||
->setLegacyAuthMechanism($legacyAuth)
|
||||
;
|
||||
}
|
||||
|
|
50
apps/files_external/lib/backend/sftp_key.php
Normal file
50
apps/files_external/lib/backend/sftp_key.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?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 \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\Backend\Backend;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
use \OCA\Files_External\Lib\Auth\PublicKey\RSA;
|
||||
|
||||
class SFTP_Key extends Backend {
|
||||
|
||||
public function __construct(IL10N $l, RSA $legacyAuth) {
|
||||
$this
|
||||
->setIdentifier('\OC\Files\Storage\SFTP_Key')
|
||||
->setStorageClass('\OC\Files\Storage\SFTP')
|
||||
->setText($l->t('SFTP with secret key login [DEPRECATED]'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('host', $l->t('Host'))),
|
||||
(new DefinitionParameter('root', $l->t('Remote subfolder')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
])
|
||||
->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
|
||||
->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE)
|
||||
->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY)
|
||||
->setLegacyAuthMechanism($legacyAuth)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
69
apps/files_external/lib/backend/smb_oc.php
Normal file
69
apps/files_external/lib/backend/smb_oc.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?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 \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\Backend\Backend;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
use \OCA\Files_External\Lib\Auth\Password\SessionCredentials;
|
||||
use \OCA\Files_External\Lib\StorageConfig;
|
||||
|
||||
/**
|
||||
* Deprecated SMB_OC class - use SMB with the password::sessioncredentials auth mechanism
|
||||
*/
|
||||
class SMB_OC extends Backend {
|
||||
|
||||
public function __construct(IL10N $l, SessionCredentials $legacyAuth) {
|
||||
$this
|
||||
->setIdentifier('\OC\Files\Storage\SMB_OC')
|
||||
->setStorageClass('\OC\Files\Storage\SMB')
|
||||
->setText($l->t('SMB / CIFS using OC login [DEPRECATED]'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('host', $l->t('Host'))),
|
||||
(new DefinitionParameter('username_as_share', $l->t('Username as share')))
|
||||
->setType(DefinitionParameter::VALUE_BOOLEAN),
|
||||
(new DefinitionParameter('share', $l->t('Share')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
(new DefinitionParameter('root', $l->t('Remote subfolder')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
])
|
||||
->setDependencyCheck('\OC\Files\Storage\SMB::checkDependencies')
|
||||
->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
|
||||
->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE)
|
||||
->setPriority(BackendService::PRIORITY_DEFAULT - 10)
|
||||
->addAuthScheme(AuthMechanism::SCHEME_PASSWORD)
|
||||
->setLegacyAuthMechanism($legacyAuth)
|
||||
;
|
||||
}
|
||||
|
||||
public function manipulateStorageConfig(StorageConfig &$storage) {
|
||||
$username_as_share = ($storage->getBackendOption('username_as_share') === true);
|
||||
|
||||
if ($username_as_share) {
|
||||
$share = '/' . $storage->getBackendOption('user');
|
||||
$storage->setBackendOption('share', $share);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
60
apps/files_external/lib/backend/swift.php
Normal file
60
apps/files_external/lib/backend/swift.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?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 \OCP\IL10N;
|
||||
use \OCA\Files_External\Lib\Backend\Backend;
|
||||
use \OCA\Files_External\Lib\DefinitionParameter;
|
||||
use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
use \OCA\Files_External\Lib\Auth\OpenStack\OpenStack;
|
||||
use \OCA\Files_External\Lib\Auth\OpenStack\Rackspace;
|
||||
|
||||
class Swift extends Backend {
|
||||
|
||||
public function __construct(IL10N $l, OpenStack $openstackAuth, Rackspace $rackspaceAuth) {
|
||||
$this
|
||||
->setIdentifier('swift')
|
||||
->addIdentifierAlias('\OC\Files\Storage\Swift') // legacy compat
|
||||
->setStorageClass('\OC\Files\Storage\Swift')
|
||||
->setText($l->t('OpenStack Object Storage'))
|
||||
->addParameters([
|
||||
(new DefinitionParameter('service_name', $l->t('Service name')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
(new DefinitionParameter('region', $l->t('Region')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
(new DefinitionParameter('bucket', $l->t('Bucket'))),
|
||||
(new DefinitionParameter('timeout', $l->t('Request timeout (seconds)')))
|
||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||
])
|
||||
->setDependencyCheck('\OC\Files\Storage\Swift::checkDependencies')
|
||||
->addAuthScheme(AuthMechanism::SCHEME_OPENSTACK)
|
||||
->setLegacyAuthMechanismCallback(function(array $params) use ($openstackAuth, $rackspaceAuth) {
|
||||
if (isset($params['options']['key']) && $params['options']['key']) {
|
||||
return $rackspaceAuth;
|
||||
}
|
||||
return $openstackAuth;
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
}
|
164
apps/files_external/lib/permissionstrait.php
Normal file
164
apps/files_external/lib/permissionstrait.php
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?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 backend and auth mechanism permissions
|
||||
*
|
||||
* For user type constants, see BackendService::USER_*
|
||||
* For permission constants, see BackendService::PERMISSION_*
|
||||
*/
|
||||
trait PermissionsTrait {
|
||||
|
||||
/** @var array [user type => permissions] */
|
||||
protected $permissions = [
|
||||
BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT,
|
||||
BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT,
|
||||
];
|
||||
|
||||
/** @var array [user type => allowed permissions] */
|
||||
protected $allowedPermissions = [
|
||||
BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT,
|
||||
BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @return int
|
||||
*/
|
||||
public function getPermissions($userType) {
|
||||
if (isset($this->permissions[$userType])) {
|
||||
return $this->permissions[$userType];
|
||||
}
|
||||
return BackendService::PERMISSION_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user type has permission
|
||||
*
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return bool
|
||||
*/
|
||||
public function isPermitted($userType, $permission) {
|
||||
if ($this->getPermissions($userType) & $permission) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permissions
|
||||
* @return self
|
||||
*/
|
||||
public function setPermissions($userType, $permissions) {
|
||||
$this->permissions[$userType] = $permissions;
|
||||
$this->allowedPermissions[$userType] =
|
||||
$this->getAllowedPermissions($userType) | $permissions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return self
|
||||
*/
|
||||
public function addPermission($userType, $permission) {
|
||||
return $this->setPermissions($userType,
|
||||
$this->getPermissions($userType) | $permission
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return self
|
||||
*/
|
||||
public function removePermission($userType, $permission) {
|
||||
return $this->setPermissions($userType,
|
||||
$this->getPermissions($userType) & ~$permission
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @return int
|
||||
*/
|
||||
public function getAllowedPermissions($userType) {
|
||||
if (isset($this->allowedPermissions[$userType])) {
|
||||
return $this->allowedPermissions[$userType];
|
||||
}
|
||||
return BackendService::PERMISSION_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user type has an allowed permission
|
||||
*
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedPermitted($userType, $permission) {
|
||||
if ($this->getAllowedPermissions($userType) & $permission) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permissions
|
||||
* @return self
|
||||
*/
|
||||
public function setAllowedPermissions($userType, $permissions) {
|
||||
$this->allowedPermissions[$userType] = $permissions;
|
||||
$this->permissions[$userType] =
|
||||
$this->getPermissions($userType) & $permissions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return self
|
||||
*/
|
||||
public function addAllowedPermission($userType, $permission) {
|
||||
return $this->setAllowedPermissions($userType,
|
||||
$this->getAllowedPermissions($userType) | $permission
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userType
|
||||
* @param int $permission
|
||||
* @return self
|
||||
*/
|
||||
public function removeAllowedPermission($userType, $permission) {
|
||||
return $this->setAllowedPermissions($userType,
|
||||
$this->getAllowedPermissions($userType) & ~$permission
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -40,10 +40,11 @@ use phpseclib\Net\SFTP\Stream;
|
|||
class SFTP extends \OC\Files\Storage\Common {
|
||||
private $host;
|
||||
private $user;
|
||||
private $password;
|
||||
private $root;
|
||||
private $port = 22;
|
||||
|
||||
private $auth;
|
||||
|
||||
/**
|
||||
* @var SFTP
|
||||
*/
|
||||
|
@ -73,8 +74,15 @@ class SFTP extends \OC\Files\Storage\Common {
|
|||
}
|
||||
|
||||
$this->user = $params['user'];
|
||||
$this->password
|
||||
= isset($params['password']) ? $params['password'] : '';
|
||||
|
||||
if (isset($params['public_key_auth'])) {
|
||||
$this->auth = $params['public_key_auth'];
|
||||
} elseif (isset($params['password'])) {
|
||||
$this->auth = $params['password'];
|
||||
} else {
|
||||
throw new \UnexpectedValueException('no authentication parameters specified');
|
||||
}
|
||||
|
||||
$this->root
|
||||
= isset($params['root']) ? $this->cleanPath($params['root']) : '/';
|
||||
|
||||
|
@ -112,7 +120,7 @@ class SFTP extends \OC\Files\Storage\Common {
|
|||
$this->writeHostKeys($hostKeys);
|
||||
}
|
||||
|
||||
if (!$this->client->login($this->user, $this->password)) {
|
||||
if (!$this->client->login($this->user, $this->auth)) {
|
||||
throw new \Exception('Login failed');
|
||||
}
|
||||
return $this->client;
|
||||
|
@ -125,7 +133,6 @@ class SFTP extends \OC\Files\Storage\Common {
|
|||
if (
|
||||
!isset($this->host)
|
||||
|| !isset($this->user)
|
||||
|| !isset($this->password)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Ross Nicoll <jrn@jrn.me.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 OC\Files\Storage;
|
||||
|
||||
use phpseclib\Crypt\RSA;
|
||||
|
||||
class SFTP_Key extends \OC\Files\Storage\SFTP {
|
||||
private $publicKey;
|
||||
private $privateKey;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($params) {
|
||||
parent::__construct($params);
|
||||
$this->publicKey = $params['public_key'];
|
||||
$this->privateKey = $params['private_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection.
|
||||
*
|
||||
* @return \phpseclib\Net\SFTP connected client instance
|
||||
* @throws \Exception when the connection failed
|
||||
*/
|
||||
public function getConnection() {
|
||||
if (!is_null($this->client)) {
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
$hostKeys = $this->readHostKeys();
|
||||
$this->client = new \phpseclib\Net\SFTP($this->getHost());
|
||||
|
||||
// The SSH Host Key MUST be verified before login().
|
||||
$currentHostKey = $this->client->getServerPublicHostKey();
|
||||
if (array_key_exists($this->getHost(), $hostKeys)) {
|
||||
if ($hostKeys[$this->getHost()] !== $currentHostKey) {
|
||||
throw new \Exception('Host public key does not match known key');
|
||||
}
|
||||
} else {
|
||||
$hostKeys[$this->getHost()] = $currentHostKey;
|
||||
$this->writeHostKeys($hostKeys);
|
||||
}
|
||||
|
||||
$key = $this->getPrivateKey();
|
||||
if (is_null($key)) {
|
||||
throw new \Exception('Secret key could not be loaded');
|
||||
}
|
||||
if (!$this->client->login($this->getUser(), $key)) {
|
||||
throw new \Exception('Login failed');
|
||||
}
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the private key to be used for authentication to the remote server.
|
||||
*
|
||||
* @return RSA instance or null in case of a failure to load the key.
|
||||
*/
|
||||
private function getPrivateKey() {
|
||||
$key = new RSA();
|
||||
$key->setPassword(\OC::$server->getConfig()->getSystemValue('secret', ''));
|
||||
if (!$key->loadKey($this->privateKey)) {
|
||||
// Should this exception rather than return null?
|
||||
return null;
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the provided host name/address is invalid (cannot be resolved
|
||||
* and is not an IPv4 address).
|
||||
*
|
||||
* @return true; never returns in case of a problem, this return value is used just to
|
||||
* make unit tests happy.
|
||||
*/
|
||||
public function assertHostAddressValid($hostname) {
|
||||
// TODO: Should handle IPv6 addresses too
|
||||
if (!preg_match('/^\d+\.\d+\.\d+\.\d+$/', $hostname) && gethostbyname($hostname) === $hostname) {
|
||||
// Hostname is not an IPv4 address and cannot be resolved via DNS
|
||||
throw new \InvalidArgumentException('Cannot resolve hostname.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the provided port number is invalid (cannot be resolved
|
||||
* and is not an IPv4 address).
|
||||
*
|
||||
* @return true; never returns in case of a problem, this return value is used just to
|
||||
* make unit tests happy.
|
||||
*/
|
||||
public function assertPortNumberValid($port) {
|
||||
if (!preg_match('/^\d+$/', $port)) {
|
||||
throw new \InvalidArgumentException('Port number must be a number.');
|
||||
}
|
||||
if ($port < 0 || $port > 65535) {
|
||||
throw new \InvalidArgumentException('Port number must be between 0 and 65535 inclusive.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces anything that's not an alphanumeric character or "." in a hostname
|
||||
* with "_", to make it safe for use as part of a file name.
|
||||
*/
|
||||
protected function sanitizeHostName($name) {
|
||||
return preg_replace('/[^\d\w\._]/', '_', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces anything that's not an alphanumeric character or "_" in a username
|
||||
* with "_", to make it safe for use as part of a file name.
|
||||
*/
|
||||
protected function sanitizeUserName($name) {
|
||||
return preg_replace('/[^\d\w_]/', '_', $name);
|
||||
}
|
||||
|
||||
public function test() {
|
||||
|
||||
// FIXME: Use as expression in empty once PHP 5.4 support is dropped
|
||||
$host = $this->getHost();
|
||||
if (empty($host)) {
|
||||
\OC::$server->getLogger()->warning('Hostname has not been specified');
|
||||
return false;
|
||||
}
|
||||
// FIXME: Use as expression in empty once PHP 5.4 support is dropped
|
||||
$user = $this->getUser();
|
||||
if (empty($user)) {
|
||||
\OC::$server->getLogger()->warning('Username has not been specified');
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->privateKey)) {
|
||||
\OC::$server->getLogger()->warning('Private key was missing from the request');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check the host
|
||||
$hostParts = explode(':', $this->getHost());
|
||||
try {
|
||||
if (count($hostParts) == 1) {
|
||||
$hostname = $hostParts[0];
|
||||
$this->assertHostAddressValid($hostname);
|
||||
} else if (count($hostParts) == 2) {
|
||||
$hostname = $hostParts[0];
|
||||
$this->assertHostAddressValid($hostname);
|
||||
$this->assertPortNumberValid($hostParts[1]);
|
||||
} else {
|
||||
throw new \Exception('Host connection string is invalid.');
|
||||
}
|
||||
} catch(\Exception $e) {
|
||||
\OC::$server->getLogger()->warning($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the key
|
||||
$key = $this->getPrivateKey();
|
||||
if (is_null($key)) {
|
||||
\OC::$server->getLogger()->warning('Secret key could not be loaded');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->getConnection()->nlist() === false) {
|
||||
return false;
|
||||
}
|
||||
} catch(\Exception $e) {
|
||||
// We should be throwing a more specific error, so we're not just catching
|
||||
// Exception here
|
||||
\OC::$server->getLogger()->warning($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the key somewhere it can easily be extracted later
|
||||
if (\OC::$server->getUserSession()->getUser()) {
|
||||
$view = new \OC\Files\View('/'.\OC::$server->getUserSession()->getUser()->getUId().'/files_external/sftp_keys');
|
||||
if (!$view->is_dir('')) {
|
||||
if (!$view->mkdir('')) {
|
||||
\OC::$server->getLogger()->warning('Could not create secret key directory.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$key_filename = $this->sanitizeUserName($this->getUser()).'@'.$this->sanitizeHostName($hostname).'.pub';
|
||||
$key_file = $view->fopen($key_filename, "w");
|
||||
if ($key_file) {
|
||||
fwrite($key_file, $this->publicKey);
|
||||
fclose($key_file);
|
||||
} else {
|
||||
\OC::$server->getLogger()->warning('Could not write secret key file.');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
* @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 OC\Files\Storage;
|
||||
|
||||
|
||||
use Icewind\SMB\Exception\AccessDeniedException;
|
||||
use Icewind\SMB\Exception\Exception;
|
||||
use Icewind\SMB\Server;
|
||||
|
||||
class SMB_OC extends SMB {
|
||||
private $username_as_share;
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($params) {
|
||||
if (isset($params['host'])) {
|
||||
$host = $params['host'];
|
||||
$this->username_as_share = ($params['username_as_share'] === true);
|
||||
|
||||
// dummy credentials, unused, to satisfy constructor
|
||||
$user = 'foo';
|
||||
$password = 'bar';
|
||||
if (\OC::$server->getSession()->exists('smb-credentials')) {
|
||||
$params_auth = json_decode(\OC::$server->getCrypto()->decrypt(\OC::$server->getSession()->get('smb-credentials')), true);
|
||||
$user = \OC::$server->getSession()->get('loginname');
|
||||
$password = $params_auth['password'];
|
||||
} else {
|
||||
// assume we are testing from the admin section
|
||||
}
|
||||
|
||||
$root = isset($params['root']) ? $params['root'] : '/';
|
||||
$share = '';
|
||||
|
||||
if ($this->username_as_share) {
|
||||
$share = '/' . $user;
|
||||
} elseif (isset($params['share'])) {
|
||||
$share = $params['share'];
|
||||
} else {
|
||||
throw new \Exception();
|
||||
}
|
||||
parent::__construct(array(
|
||||
"user" => $user,
|
||||
"password" => $password,
|
||||
"host" => $host,
|
||||
"share" => $share,
|
||||
"root" => $root
|
||||
));
|
||||
} else {
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Intercepts the user credentials on login and stores them
|
||||
* encrypted inside the session if SMB_OC storage is enabled.
|
||||
* @param array $params
|
||||
*/
|
||||
public static function login($params) {
|
||||
$mountpoints = \OC_Mount_Config::getAbsoluteMountPoints($params['uid']);
|
||||
$mountpointClasses = array();
|
||||
foreach($mountpoints as $mountpoint) {
|
||||
$mountpointClasses[$mountpoint['class']] = true;
|
||||
}
|
||||
if(isset($mountpointClasses['\OC\Files\Storage\SMB_OC'])) {
|
||||
\OC::$server->getSession()->set('smb-credentials', \OC::$server->getCrypto()->encrypt(json_encode($params)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSharable($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isPersonal
|
||||
* @return bool
|
||||
*/
|
||||
public function test($isPersonal = true) {
|
||||
if ($isPersonal) {
|
||||
if ($this->stat('')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
$server = new Server($this->server->getHost(), '', '');
|
||||
|
||||
try {
|
||||
$server->listShares();
|
||||
return true;
|
||||
} catch (AccessDeniedException $e) {
|
||||
// expected due to anonymous login
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
<?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
|
||||
*
|
||||
* The standard visibility defines which users/groups can use or see the
|
||||
* object. The allowed visibility defines the maximum visibility allowed to be
|
||||
* set on the object. The standard visibility is often set dynamically by
|
||||
* stored configuration parameters that can be modified by the administrator,
|
||||
* while the allowed visibility is set directly by the object and cannot be
|
||||
* modified by the administrator.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -34,8 +34,12 @@ $userStoragesService = $appContainer->query('OCA\Files_external\Service\UserStor
|
|||
OCP\Util::addScript('files_external', 'settings');
|
||||
OCP\Util::addStyle('files_external', 'settings');
|
||||
|
||||
$backends = $backendService->getBackendsVisibleFor(BackendService::VISIBILITY_PERSONAL);
|
||||
$authMechanisms = $backendService->getAuthMechanismsVisibleFor(BackendService::VISIBILITY_PERSONAL);
|
||||
$backends = array_filter($backendService->getAvailableBackends(), function($backend) {
|
||||
return $backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE);
|
||||
});
|
||||
$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) {
|
||||
return $authMechanism->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE);
|
||||
});
|
||||
foreach ($backends as $backend) {
|
||||
if ($backend->getCustomJs()) {
|
||||
\OCP\Util::addScript('files_external', $backend->getCustomJs());
|
||||
|
|
|
@ -31,13 +31,17 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
|
|||
*/
|
||||
class BackendService {
|
||||
|
||||
/** Visibility constants for VisibilityTrait */
|
||||
const VISIBILITY_NONE = 0;
|
||||
const VISIBILITY_PERSONAL = 1;
|
||||
const VISIBILITY_ADMIN = 2;
|
||||
//const VISIBILITY_ALIENS = 4;
|
||||
/** Permission constants for PermissionsTrait */
|
||||
const PERMISSION_NONE = 0;
|
||||
const PERMISSION_MOUNT = 1;
|
||||
const PERMISSION_CREATE = 2;
|
||||
const PERMISSION_MODIFY = 4;
|
||||
|
||||
const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
|
||||
const PERMISSION_DEFAULT = 7; // MOUNT | CREATE | MODIFY
|
||||
|
||||
/** User contants */
|
||||
const USER_ADMIN = 'admin';
|
||||
const USER_PERSONAL = 'personal';
|
||||
|
||||
/** Priority constants for PriorityTrait */
|
||||
const PRIORITY_DEFAULT = 100;
|
||||
|
@ -81,7 +85,7 @@ class BackendService {
|
|||
*/
|
||||
public function registerBackend(Backend $backend) {
|
||||
if (!$this->isAllowedUserBackend($backend)) {
|
||||
$backend->removeVisibility(BackendService::VISIBILITY_PERSONAL);
|
||||
$backend->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT);
|
||||
}
|
||||
foreach ($backend->getIdentifierAliases() as $alias) {
|
||||
$this->backends[$alias] = $backend;
|
||||
|
@ -103,7 +107,7 @@ class BackendService {
|
|||
*/
|
||||
public function registerAuthMechanism(AuthMechanism $authMech) {
|
||||
if (!$this->isAllowedAuthMechanism($authMech)) {
|
||||
$authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL);
|
||||
$authMech->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT);
|
||||
}
|
||||
foreach ($authMech->getIdentifierAliases() as $alias) {
|
||||
$this->authMechanisms[$alias] = $authMech;
|
||||
|
@ -144,30 +148,6 @@ class BackendService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get backends visible for $visibleFor
|
||||
*
|
||||
* @param int $visibleFor
|
||||
* @return Backend[]
|
||||
*/
|
||||
public function getBackendsVisibleFor($visibleFor) {
|
||||
return array_filter($this->getAvailableBackends(), function($backend) use ($visibleFor) {
|
||||
return $backend->isVisibleFor($visibleFor);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get backends allowed to be visible for $visibleFor
|
||||
*
|
||||
* @param int $visibleFor
|
||||
* @return Backend[]
|
||||
*/
|
||||
public function getBackendsAllowedVisibleFor($visibleFor) {
|
||||
return array_filter($this->getAvailableBackends(), function($backend) use ($visibleFor) {
|
||||
return $backend->isAllowedVisibleFor($visibleFor);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @return Backend|null
|
||||
|
@ -205,31 +185,6 @@ class BackendService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication mechanisms visible for $visibleFor
|
||||
*
|
||||
* @param int $visibleFor
|
||||
* @return AuthMechanism[]
|
||||
*/
|
||||
public function getAuthMechanismsVisibleFor($visibleFor) {
|
||||
return array_filter($this->getAuthMechanisms(), function($authMechanism) use ($visibleFor) {
|
||||
return $authMechanism->isVisibleFor($visibleFor);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication mechanisms allowed to be visible for $visibleFor
|
||||
*
|
||||
* @param int $visibleFor
|
||||
* @return AuthMechanism[]
|
||||
*/
|
||||
public function getAuthMechanismsAllowedVisibleFor($visibleFor) {
|
||||
return array_filter($this->getAuthMechanisms(), function($authMechanism) use ($visibleFor) {
|
||||
return $authMechanism->isAllowedVisibleFor($visibleFor);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @return AuthMechanism|null
|
||||
|
|
|
@ -41,8 +41,12 @@ OCP\Util::addStyle('files_external', 'settings');
|
|||
\OC_Util::addVendorScript('select2/select2');
|
||||
\OC_Util::addVendorStyle('select2/select2');
|
||||
|
||||
$backends = $backendService->getBackendsVisibleFor(BackendService::VISIBILITY_ADMIN);
|
||||
$authMechanisms = $backendService->getAuthMechanismsVisibleFor(BackendService::VISIBILITY_ADMIN);
|
||||
$backends = array_filter($backendService->getAvailableBackends(), function($backend) {
|
||||
return $backend->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE);
|
||||
});
|
||||
$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) {
|
||||
return $authMechanism->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE);
|
||||
});
|
||||
foreach ($backends as $backend) {
|
||||
if ($backend->getCustomJs()) {
|
||||
\OCP\Util::addScript('files_external', $backend->getCustomJs());
|
||||
|
@ -54,13 +58,19 @@ foreach ($authMechanisms as $authMechanism) {
|
|||
}
|
||||
}
|
||||
|
||||
$userBackends = array_filter($backendService->getAvailableBackends(), function($backend) {
|
||||
return $backend->isAllowedPermitted(
|
||||
BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT
|
||||
);
|
||||
});
|
||||
|
||||
$tmpl = new OCP\Template('files_external', 'settings');
|
||||
$tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
|
||||
$tmpl->assign('isAdminPage', true);
|
||||
$tmpl->assign('storages', $globalStoragesService->getAllStorages());
|
||||
$tmpl->assign('backends', $backends);
|
||||
$tmpl->assign('authMechanisms', $authMechanisms);
|
||||
$tmpl->assign('userBackends', $backendService->getBackendsAllowedVisibleFor(BackendService::VISIBILITY_PERSONAL));
|
||||
$tmpl->assign('userBackends', $userBackends);
|
||||
$tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends()));
|
||||
$tmpl->assign('allowUserMounting', $backendService->isUserMountingAllowed());
|
||||
return $tmpl->fetchPage();
|
||||
|
|
|
@ -197,7 +197,7 @@
|
|||
<p id="userMountingBackends"<?php if ($_['allowUserMounting'] != 'yes'): ?> class="hidden"<?php endif; ?>>
|
||||
<?php p($l->t('Allow users to mount the following external storage')); ?><br />
|
||||
<?php $i = 0; foreach ($_['userBackends'] as $backend): ?>
|
||||
<input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL)) print_unescaped(' checked="checked"'); ?> />
|
||||
<input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT)) print_unescaped(' checked="checked"'); ?> />
|
||||
<label for="allowUserMountingBackends<?php p($i); ?>"><?php p($backend->getText()); ?></label> <br />
|
||||
<?php $i++; ?>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -75,10 +75,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
|
|||
$authMech = $this->getAuthMechMock();
|
||||
$authMech->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$authMech->method('isPermitted')
|
||||
->willReturn(true);
|
||||
$backend = $this->getBackendMock();
|
||||
$backend->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$backend->method('isVisibleFor')
|
||||
$backend->method('isPermitted')
|
||||
->willReturn(true);
|
||||
|
||||
$storageConfig = new StorageConfig(1);
|
||||
|
@ -114,10 +116,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
|
|||
$authMech = $this->getAuthMechMock();
|
||||
$authMech->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$authMech->method('isPermitted')
|
||||
->willReturn(true);
|
||||
$backend = $this->getBackendMock();
|
||||
$backend->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$backend->method('isVisibleFor')
|
||||
$backend->method('isPermitted')
|
||||
->willReturn(true);
|
||||
|
||||
$storageConfig = new StorageConfig(1);
|
||||
|
@ -245,10 +249,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
|
|||
$authMech = $this->getAuthMechMock();
|
||||
$authMech->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$authMech->method('isPermitted')
|
||||
->willReturn(true);
|
||||
$backend = $this->getBackendMock();
|
||||
$backend->method('validateStorage')
|
||||
->willReturn(true);
|
||||
$backend->method('isVisibleFor')
|
||||
$backend->method('isPermitted')
|
||||
->willReturn(true);
|
||||
|
||||
$storageConfig = new StorageConfig(255);
|
||||
|
@ -332,12 +338,14 @@ abstract class StoragesControllerTest extends \Test\TestCase {
|
|||
$backend = $this->getBackendMock();
|
||||
$backend->method('validateStorage')
|
||||
->willReturn($backendValidate);
|
||||
$backend->method('isVisibleFor')
|
||||
$backend->method('isPermitted')
|
||||
->willReturn(true);
|
||||
|
||||
$authMech = $this->getAuthMechMock();
|
||||
$authMech->method('validateStorage')
|
||||
->will($this->returnValue($authMechValidate));
|
||||
$authMech->method('isPermitted')
|
||||
->willReturn(true);
|
||||
|
||||
$storageConfig = new StorageConfig();
|
||||
$storageConfig->setMountPoint('mount');
|
||||
|
|
|
@ -49,15 +49,21 @@ class UserStoragesControllerTest extends StoragesControllerTest {
|
|||
}
|
||||
|
||||
public function testAddOrUpdateStorageDisallowedBackend() {
|
||||
$backend = $this->getBackendMock();
|
||||
$backend->method('isVisibleFor')
|
||||
->with(BackendService::VISIBILITY_PERSONAL)
|
||||
$backend1 = $this->getBackendMock();
|
||||
$backend1->expects($this->once())
|
||||
->method('isPermitted')
|
||||
->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
|
||||
->willReturn(false);
|
||||
$backend2 = $this->getBackendMock();
|
||||
$backend2->expects($this->once())
|
||||
->method('isPermitted')
|
||||
->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_MODIFY)
|
||||
->willReturn(false);
|
||||
$authMech = $this->getAuthMechMock();
|
||||
|
||||
$storageConfig = new StorageConfig(1);
|
||||
$storageConfig->setMountPoint('mount');
|
||||
$storageConfig->setBackend($backend);
|
||||
$storageConfig->setBackend($backend1);
|
||||
$storageConfig->setAuthMechanism($authMech);
|
||||
$storageConfig->setBackendOptions([]);
|
||||
|
||||
|
@ -82,6 +88,8 @@ class UserStoragesControllerTest extends StoragesControllerTest {
|
|||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus());
|
||||
|
||||
$storageConfig->setBackend($backend2);
|
||||
|
||||
$response = $this->controller->update(
|
||||
1,
|
||||
'mount',
|
||||
|
|
|
@ -83,11 +83,11 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
|
||||
$backendAllowed = $this->getBackendMock('\User\Mount\Allowed');
|
||||
$backendAllowed->expects($this->never())
|
||||
->method('removeVisibility');
|
||||
->method('removePermission');
|
||||
$backendNotAllowed = $this->getBackendMock('\User\Mount\NotAllowed');
|
||||
$backendNotAllowed->expects($this->once())
|
||||
->method('removeVisibility')
|
||||
->with(BackendService::VISIBILITY_PERSONAL);
|
||||
->method('removePermission')
|
||||
->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE | BackendService::PERMISSION_MOUNT);
|
||||
|
||||
$backendAlias = $this->getMockBuilder('\OCA\Files_External\Lib\Backend\Backend')
|
||||
->disableOriginalConstructor()
|
||||
|
@ -126,27 +126,5 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
$this->assertArrayNotHasKey('identifier:\Backend\NotAvailable', $availableBackends);
|
||||
}
|
||||
|
||||
public function testGetUserBackends() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
|
||||
$backendAllowed = $this->getBackendMock('\User\Mount\Allowed');
|
||||
$backendAllowed->expects($this->once())
|
||||
->method('isVisibleFor')
|
||||
->with(BackendService::VISIBILITY_PERSONAL)
|
||||
->will($this->returnValue(true));
|
||||
$backendNotAllowed = $this->getBackendMock('\User\Mount\NotAllowed');
|
||||
$backendNotAllowed->expects($this->once())
|
||||
->method('isVisibleFor')
|
||||
->with(BackendService::VISIBILITY_PERSONAL)
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$service->registerBackend($backendAllowed);
|
||||
$service->registerBackend($backendNotAllowed);
|
||||
|
||||
$userBackends = $service->getBackendsVisibleFor(BackendService::VISIBILITY_PERSONAL);
|
||||
$this->assertArrayHasKey('identifier:\User\Mount\Allowed', $userBackends);
|
||||
$this->assertArrayNotHasKey('identifier:\User\Mount\NotAllowed', $userBackends);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue