diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 72db1aa3e4c5..273914dbc487 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -496,7 +496,7 @@ MountOptionsDropdown.prototype = { } var $el = $(template({ - mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)') + mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)'), })); this.$el = $el; @@ -654,7 +654,6 @@ MountConfigListView.prototype = _.extend({ * @param {int} [options.userListLimit] page size in applicable users dropdown */ initialize: function($el, options) { - var self = this; this.$el = $el; this._isPersonal = ($el.data('admin') !== true); if (this._isPersonal) { @@ -668,6 +667,7 @@ MountConfigListView.prototype = _.extend({ } this._encryptionEnabled = options.encryptionEnabled; + this._allowUserMountSharing = options.allowUserMountSharing; // read the backend config that was carefully crammed // into the data-configurations attribute of the select @@ -1272,12 +1272,15 @@ MountConfigListView.prototype = _.extend({ var visibleOptions = [ 'previews', 'filesystem_check_changes', - 'enable_sharing', 'encoding_compatibility' ]; if (this._encryptionEnabled) { visibleOptions.push('encrypt'); } + if (!this._isPersonal || this._allowUserMountSharing) { + visibleOptions.push('enable_sharing'); + } + dropDown.show($toggle, storage.mountOptions || [], visibleOptions); $('body').on('mouseup.mountOptionsDropdown', function(event) { var $target = $(event.target); @@ -1308,7 +1311,8 @@ $(document).ready(function() { var enabled = $('#files_external').attr('data-encryption-enabled'); var encryptionEnabled = (enabled ==='true')? true: false; var mountConfigListView = new MountConfigListView($('#externalStorage'), { - encryptionEnabled: encryptionEnabled + encryptionEnabled: encryptionEnabled, + allowUserMountSharing: (parseInt($('#allowUserMountSharing').val(), 10) === 1) }); mountConfigListView.loadStorages(); @@ -1328,6 +1332,13 @@ $(document).ready(function() { OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}}); }); + var $allowUserMountSharing = $('#allowUserMountSharing'); + $allowUserMountSharing.bind('change', function() { + OC.msg.startSaving('#userMountSharingMsg'); + OC.AppConfig.setValue('core', 'allow_user_mount_sharing', this.checked ? 'yes' : 'no'); + OC.msg.finishedSaving('#userMountSharingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}}); + }); + $('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() { OC.msg.startSaving('#userMountingMsg'); diff --git a/apps/files_external/lib/Panels/Admin.php b/apps/files_external/lib/Panels/Admin.php index 07f4ce662aa4..9d53be3a48e4 100644 --- a/apps/files_external/lib/Panels/Admin.php +++ b/apps/files_external/lib/Panels/Admin.php @@ -67,6 +67,8 @@ public function getPanel() { $tmpl->assign('authMechanisms', $this->backendService->getAuthMechanisms()); $tmpl->assign('dependencies', \OC_Mount_Config::dependencyMessage($this->backendService->getBackends())); $tmpl->assign('allowUserMounting', $this->backendService->isUserMountingAllowed()); + $tmpl->assign('allowUserMountSharing', $this->config->getAppValue('core', 'allow_user_mount_sharing', 'yes') === 'yes'); + return $tmpl; } diff --git a/apps/files_external/lib/Panels/Personal.php b/apps/files_external/lib/Panels/Personal.php index 06225b2ae6f4..1b8a4cfb1ce3 100644 --- a/apps/files_external/lib/Panels/Personal.php +++ b/apps/files_external/lib/Panels/Personal.php @@ -68,6 +68,7 @@ public function getPanel() { $tmpl->assign('backends', $this->backendService->getAvailableBackends()); $tmpl->assign('authMechanisms', $this->backendService->getAuthMechanisms()); $tmpl->assign('allowUserMounting', $enabled); + $tmpl->assign('allowUserMountSharing', $this->config->getAppValue('core', 'allow_user_mount_sharing', 'yes') === 'yes'); return $tmpl; } diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 422daacab9c0..4fb57ab52249 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -152,7 +152,14 @@ +
+ /> +

+ + diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js index 36ac2b1315df..86ccfcdd27df 100644 --- a/apps/files_external/tests/js/settingsSpec.js +++ b/apps/files_external/tests/js/settingsSpec.js @@ -336,7 +336,7 @@ describe('OCA.External.Settings tests', function() { expect($td.find('.dropdown').length).toEqual(0); }); - it('doesnt show the encryption option when encryption is disabled', function () { + it('does not show the encryption option when encryption is disabled', function () { view._encryptionEnabled = false; $td.find('img').click(); @@ -375,6 +375,41 @@ describe('OCA.External.Settings tests', function() { encoding_compatibility: false }); }); + + it('does not show the sharing option when sharing is disabled for user shares', function () { + var testCases = [ + { + personal: false, + sharingAllowed: false, + expectedVisible: true + }, + { + personal: true, + sharingAllowed: false, + expectedVisible: false + }, + { + personal: true, + sharingAllowed: true, + expectedVisible: true + }, + ]; + + _.each(testCases, function(testCase) { + view._isPersonal = testCase.personal; + view._allowUserMountSharing = testCase.sharingAllowed; + + $td.find('img').click(); + + expect($td.find('.dropdown [name=enable_sharing]:visible').length) + .toEqual(testCase.expectedVisible ? 1 : 0); + + $('body').mouseup(); + + expect($td.find('.dropdown').length).toEqual(0); + }); + + }); }); }); describe('applicable user list', function() { diff --git a/lib/private/Files/External/ConfigAdapter.php b/lib/private/Files/External/ConfigAdapter.php index ba247a55a011..d2edde346015 100644 --- a/lib/private/Files/External/ConfigAdapter.php +++ b/lib/private/Files/External/ConfigAdapter.php @@ -35,12 +35,16 @@ use OCP\Files\External\IStorageConfig; use OC\Files\Storage\FailedStorage; use OCP\Files\StorageNotAvailableException; +use OCP\IConfig; /** * Make the old files_external config work with the new public mount config api */ class ConfigAdapter implements IMountProvider { + /** @var IConfig */ + private $config; + /** @var IUserStoragesService */ private $userStoragesService; @@ -52,9 +56,11 @@ class ConfigAdapter implements IMountProvider { * @param IUserGlobalStoragesService $userGlobalStoragesService */ public function __construct( + IConfig $config, IUserStoragesService $userStoragesService, IUserGlobalStoragesService $userGlobalStoragesService ) { + $this->config = $config; $this->userStoragesService = $userStoragesService; $this->userGlobalStoragesService = $userGlobalStoragesService; } @@ -146,6 +152,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) { $mounts[$storage->getMountPoint()] = $mount; } + $allowUserMountSharing = $this->config->getAppValue('core', 'allow_user_mount_sharing', 'yes') === 'yes'; foreach ($this->userStoragesService->getStorages() as $storage) { try { $this->prepareStorageConfig($storage, $user); @@ -155,6 +162,11 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) { $impl = new FailedStorage(['exception' => $e]); } + $mountOptions = $storage->getMountOptions(); + if (!$allowUserMountSharing) { + $mountOptions['enable_sharing'] = false; + } + $mount = new PersonalMount( $this->userStoragesService, $storage->getId(), @@ -162,7 +174,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) { '/' . $user->getUID() . '/files' . $storage->getMountPoint(), null, $loader, - $storage->getMountOptions() + $mountOptions ); $mounts[$storage->getMountPoint()] = $mount; } diff --git a/lib/private/Files/Storage/Temporary.php b/lib/private/Files/Storage/Temporary.php index 185a1032acd9..1e85ffc73e9a 100644 --- a/lib/private/Files/Storage/Temporary.php +++ b/lib/private/Files/Storage/Temporary.php @@ -44,4 +44,8 @@ public function __destruct() { public function getDataDir() { return $this->datadir; } + + public function getAvailability() { + return ['available' => true, 'last_checked' => 0]; + } } diff --git a/lib/private/Server.php b/lib/private/Server.php index 44de9ebae00a..7cc052fdbed9 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -556,6 +556,7 @@ public function __construct($webRoot, \OC\Config $config) { // external storage if ($config->getAppValue('core', 'enable_external_storage', 'no') === 'yes') { $manager->registerProvider(new \OC\Files\External\ConfigAdapter( + $c->query('AllConfig'), $c->query('UserStoragesService'), $c->query('UserGlobalStoragesService') )); diff --git a/tests/lib/Files/External/ConfigAdapterTest.php b/tests/lib/Files/External/ConfigAdapterTest.php new file mode 100644 index 000000000000..37577410d6fe --- /dev/null +++ b/tests/lib/Files/External/ConfigAdapterTest.php @@ -0,0 +1,193 @@ + + * + * @copyright Copyright (c) 2017, ownCloud GmbH. + * @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 + * + */ +namespace Test\Files\External; + +use OCP\Files\External\Service\IUserStoragesService; +use OCP\Files\External\Service\IUserGlobalStoragesService; +use OCP\IUser; +use OC\Files\External\ConfigAdapter; +use OCP\IConfig; +use OC\Files\External\Service\UserStoragesService; +use OC\Files\External\Service\UserGlobalStoragesService; +use OCP\Files\External\IStorageConfig; +use OCP\Files\External\Auth\AuthMechanism; +use OCP\Files\External\Backend\Backend; +use OC\Files\External\PersonalMount; +use OC\Files\Mount\MountPoint; +use OC\Files\Storage\StorageFactory; + +class ConfigAdapterTest extends \Test\TestCase { + + /** @var \OCP\IConfig */ + private $config; + + /** @var IUserStoragesService */ + private $userStoragesService; + + /** @var IUserGlobalStoragesService */ + private $userGlobalStoragesService; + + /** @var IUser **/ + private $user; + + protected function setUp() { + $this->config = $this->createMock(IConfig::class); + $this->userStoragesService = $this->createMock(UserStoragesService::class); + $this->userGlobalStoragesService = $this->createMock(UserGlobalStoragesService::class); + $this->user = $this->createMock(IUser::class); + $this->user->expects($this->any()) + ->method('getUID') + ->willReturn('user1'); + } + + private function createStorageConfig($mountPoint, $mountOptions) { + $auth = $this->createMock(AuthMechanism::class); + $backend = $this->createMock(Backend::class); + $config = $this->createMock(IStorageConfig::class); + + $config->expects($this->any()) + ->method('getBackendOptions') + ->willReturn([]); + $config->expects($this->any()) + ->method('getBackendOption') + ->willReturn(null); + $config->expects($this->any()) + ->method('getAuthMechanism') + ->willReturn($auth); + $config->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $config->expects($this->any()) + ->method('getMountPoint') + ->willReturn($mountPoint); + $config->expects($this->any()) + ->method('getMountOptions') + ->willReturn($mountOptions); + + $auth->expects($this->once()) + ->method('manipulateStorageConfig') + ->with($config, $this->user); + $backend->expects($this->once()) + ->method('manipulateStorageConfig') + ->with($config, $this->user); + + $backend->expects($this->once()) + ->method('getStorageClass') + ->willReturn('\OC\Files\Storage\Temporary'); + + $backend->expects($this->once()) + ->method('wrapStorage') + ->will($this->returnArgument(0)); + $auth->expects($this->once()) + ->method('wrapStorage') + ->will($this->returnArgument(0)); + + return $config; + } + + private function getMountsForUser($globalStorages, $personalStorages) { + $storageFactory = $this->createMock(StorageFactory::class); + $storageFactory->expects($this->any()) + ->method('wrap') + ->will($this->returnArgument(1)); + + $this->userStoragesService->expects($this->at(0)) + ->method('setUser') + ->with($this->user); + $this->userGlobalStoragesService->expects($this->at(0)) + ->method('setUser') + ->with($this->user); + + $this->userGlobalStoragesService->expects($this->at(1)) + ->method('getUniqueStorages') + ->willReturn($globalStorages); + $this->userStoragesService->expects($this->at(1)) + ->method('getStorages') + ->willReturn($personalStorages); + + $this->userStoragesService->expects($this->at(2)) + ->method('resetUser'); + $this->userGlobalStoragesService->expects($this->at(2)) + ->method('resetUser'); + + $configAdapter = new ConfigAdapter( + $this->config, + $this->userStoragesService, + $this->userGlobalStoragesService + ); + + return $configAdapter->getMountsForUser($this->user, $storageFactory); + } + + public function testGetPersonalMounts() { + $storage1 = $this->createStorageConfig('/mount1', ['test_value' => true]); + $storage2 = $this->createStorageConfig('/globalmount1', ['test_value2' => 'abc']); + + $result = $this->getMountsForUser([$storage2], [$storage1]); + + $this->assertCount(2, $result); + + $mount = $result['/mount1']; + $this->assertInstanceOf(PersonalMount::class, $mount); + $this->assertEquals('/user1/files/mount1/', $mount->getMountPoint()); + $options = $mount->getOptions(); + $this->assertTrue($options['test_value']); + + $mount = $result['/globalmount1']; + $this->assertEquals('/user1/files/globalmount1/', $mount->getMountPoint()); + $options = $mount->getOptions(); + $this->assertEquals('abc', $options['test_value2']); + } + + public function sharingOptionProvider() { + return [ + [true, true], + [false, false], + ]; + } + + /** + * @dataProvider sharingOptionProvider + */ + public function testGetPersonalMountSharingOption($isSharingAllowed, $expectedValue) { + $this->config->expects($this->any()) + ->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'allow_user_mount_sharing', 'yes', $isSharingAllowed ? 'yes' : 'no'] + ])); + + $storage1 = $this->createStorageConfig('/mount1', ['enable_sharing' => true]); + $storage2 = $this->createStorageConfig('/globalmount1', ['enable_sharing' => true]); + + $result = $this->getMountsForUser([$storage2], [$storage1]); + + $this->assertCount(2, $result); + + $mount = $result['/mount1']; + $options = $mount->getOptions(); + $this->assertEquals($expectedValue, $options['enable_sharing']); + + $mount = $result['/globalmount1']; + $options = $mount->getOptions(); + $this->assertTrue($options['enable_sharing']); + } +} +