diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index 05ad282d3d11..a8859cdcbf22 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -24,6 +24,10 @@ Turning the feature off removes shared files and folders on the server for all s
Files_Sharing
+
+ OCA\Files_Sharing\Panels\Admin\SettingsPanel
+
+
OCA\Files_Sharing\DeleteOrphanedSharesJobOCA\Files_Sharing\ExpireSharesJob
diff --git a/apps/files_sharing/js/settings.js b/apps/files_sharing/js/settings.js
new file mode 100644
index 000000000000..6b16576366bc
--- /dev/null
+++ b/apps/files_sharing/js/settings.js
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+$(document).ready(function() {
+ var $blacklistedGroups = $('#files_sharing input[name="blacklisted_receiver_groups"]');
+ OC.Settings.setupGroupsSelect($blacklistedGroups);
+ $blacklistedGroups.change(function(ev) {
+ var groups = ev.val || [];
+ groups = JSON.stringify(groups);
+ OC.AppConfig.setValue('files_sharing', $(this).attr('name'), groups);
+ });
+});
\ No newline at end of file
diff --git a/apps/files_sharing/lib/API/OCSShareWrapper.php b/apps/files_sharing/lib/API/OCSShareWrapper.php
index bf3307b45c00..ecaca2183af9 100644
--- a/apps/files_sharing/lib/API/OCSShareWrapper.php
+++ b/apps/files_sharing/lib/API/OCSShareWrapper.php
@@ -22,6 +22,7 @@
use OCA\Files_Sharing\AppInfo\Application;
use OCA\Files_Sharing\Service\NotificationPublisher;
+use OCA\Files_Sharing\SharingBlacklist;
class OCSShareWrapper {
@@ -47,7 +48,8 @@ private function getShare20OCS() {
\OC::$server->getL10N('files_sharing'),
\OC::$server->getConfig(),
$this->application->getContainer()->query(NotificationPublisher::class),
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ $this->application->getContainer()->query(SharingBlacklist::class)
);
}
diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php
index 6b753fa35748..f3939766a4b2 100644
--- a/apps/files_sharing/lib/API/Share20OCS.php
+++ b/apps/files_sharing/lib/API/Share20OCS.php
@@ -39,6 +39,7 @@
use OCP\Share\IShare;
use OCA\Files_Sharing\Service\NotificationPublisher;
use OCA\Files_Sharing\Helper;
+use OCA\Files_Sharing\SharingBlacklist;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
@@ -71,6 +72,8 @@ class Share20OCS {
private $notificationPublisher;
/** @var EventDispatcher */
private $eventDispatcher;
+ /** @var SharingBlacklist */
+ private $sharingBlacklist;
/**
* @var string
@@ -102,7 +105,8 @@ public function __construct(
IL10N $l10n,
IConfig $config,
NotificationPublisher $notificationPublisher,
- EventDispatcher $eventDispatcher
+ EventDispatcher $eventDispatcher,
+ SharingBlacklist $sharingBlacklist
) {
$this->shareManager = $shareManager;
$this->userManager = $userManager;
@@ -115,6 +119,7 @@ public function __construct(
$this->config = $config;
$this->notificationPublisher = $notificationPublisher;
$this->eventDispatcher = $eventDispatcher;
+ $this->sharingBlacklist = $sharingBlacklist;
$this->additionalInfoField = $this->config->getAppValue('core', 'user_additional_info_field', '');
}
@@ -402,6 +407,9 @@ public function createShare() {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC\OCS\Result(null, 404, $this->l->t('Please specify a valid group'));
}
+ if ($this->sharingBlacklist->isGroupBlacklisted($this->groupManager->get($shareWith))) {
+ return new \OC\OCS\Result(null, 403, $this->l->t('The group is blacklisted for sharing'));
+ }
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
if ($autoAccept) {
diff --git a/apps/files_sharing/lib/Controller/ShareesController.php b/apps/files_sharing/lib/Controller/ShareesController.php
index 580e4e5f97ff..459659b58427 100644
--- a/apps/files_sharing/lib/Controller/ShareesController.php
+++ b/apps/files_sharing/lib/Controller/ShareesController.php
@@ -40,6 +40,7 @@
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share;
+use OCA\Files_Sharing\SharingBlacklist;
class ShareesController extends OCSController {
@@ -107,6 +108,9 @@ class ShareesController extends OCSController {
*/
protected $additionalInfoField;
+ /** @var SharingBlacklist */
+ protected $sharingBlacklist;
+
/**
* @param IGroupManager $groupManager
* @param IUserManager $userManager
@@ -127,7 +131,8 @@ public function __construct($appName,
IUserSession $userSession,
IURLGenerator $urlGenerator,
ILogger $logger,
- \OCP\Share\IManager $shareManager) {
+ \OCP\Share\IManager $shareManager,
+ SharingBlacklist $sharingBlacklist) {
parent::__construct($appName, $request);
$this->groupManager = $groupManager;
@@ -139,6 +144,7 @@ public function __construct($appName,
$this->request = $request;
$this->logger = $logger;
$this->shareManager = $shareManager;
+ $this->sharingBlacklist = $sharingBlacklist;
$this->additionalInfoField = $this->config->getAppValue('core', 'user_additional_info_field', '');
}
@@ -284,7 +290,7 @@ protected function getGroups($search) {
foreach ($groups as $group) {
// FIXME: use a more efficient approach
$gid = $group->getGID();
- if (!\in_array($gid, $groupIds)) {
+ if (!\in_array($gid, $groupIds) || $this->sharingBlacklist->isGroupBlacklisted($group)) {
continue;
}
if (\strtolower($gid) === $lowerSearch || \strtolower($group->getDisplayName()) === $lowerSearch) {
@@ -310,7 +316,8 @@ protected function getGroups($search) {
// On page one we try if the search result has a direct hit on the
// user id and if so, we add that to the exact match list
$group = $this->groupManager->get($search);
- if ($group instanceof IGroup && (!$this->shareWithMembershipGroupOnly || \in_array($group->getGID(), $userGroups))) {
+ if ($group instanceof IGroup && !$this->sharingBlacklist->isGroupBlacklisted($group) &&
+ (!$this->shareWithMembershipGroupOnly || \in_array($group->getGID(), $userGroups))) {
\array_push($this->result['exact']['groups'], [
'label' => $group->getDisplayName(),
'value' => [
diff --git a/apps/files_sharing/lib/Panels/Admin/SettingsPanel.php b/apps/files_sharing/lib/Panels/Admin/SettingsPanel.php
new file mode 100644
index 000000000000..1bb328d65dea
--- /dev/null
+++ b/apps/files_sharing/lib/Panels/Admin/SettingsPanel.php
@@ -0,0 +1,47 @@
+
+ *
+ * @copyright Copyright (c) 2018, 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 OCA\Files_Sharing\Panels\Admin;
+use OCP\Settings\ISettings;
+use OCP\Template;
+use OCA\Files_Sharing\SharingBlacklist;
+
+class SettingsPanel implements ISettings {
+ /** @var SharingBlacklist */
+ private $sharingBlacklist;
+
+ public function __construct(SharingBlacklist $sharingBlacklist) {
+ $this->sharingBlacklist = $sharingBlacklist;
+ }
+
+ public function getPanel() {
+ $tmpl = new Template('files_sharing', 'settings');
+ $tmpl->assign('blacklistedReceivers', \implode('|', $this->sharingBlacklist->getBlacklistedReceiverGroups()));
+ return $tmpl;
+ }
+
+ public function getPriority() {
+ return 0;
+ }
+
+ public function getSectionID() {
+ return 'sharing';
+ }
+}
diff --git a/apps/files_sharing/lib/SharingBlacklist.php b/apps/files_sharing/lib/SharingBlacklist.php
new file mode 100644
index 000000000000..07ad8b485beb
--- /dev/null
+++ b/apps/files_sharing/lib/SharingBlacklist.php
@@ -0,0 +1,107 @@
+
+ *
+ * @copyright Copyright (c) 2018, 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 OCA\Files_Sharing;
+
+use OCP\IConfig;
+use OCP\IGroup;
+
+/**
+ * Class to handle a blacklist for sharing. The main functionality is to check if a particular group
+ * has been blacklisted for sharing, which means that noone should share with that group.
+ *
+ * Note that this class will only handle the configuration and perform the checks against the configuration
+ * This class won't prevent the sharing action by itself.
+ */
+class SharingBlacklist {
+ /** @var IConfig */
+ private $config;
+
+ private $blacklistCache = null;
+
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * Check if the target group is blacklisted
+ * @param IGroup $group the group to check
+ * @return bool true if the group is blacklisted, false otherwise
+ */
+ public function isGroupBlacklisted(IGroup $group) {
+ $this->initCache();
+
+ $groupId = $group->getGID();
+
+ if (isset($this->blacklistCache['receivers']['ids'][$groupId])) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Clear the internal cache of this class. Use this function if any of the keys used by this class is changed
+ * outside of this class, such as a direct change of the 'blacklisted_group_displaynames' in the appconfig table
+ * Note that this is an object-based cache. It won't persist for multiple HTTP requests
+ */
+ public function clearCache() {
+ $this->blacklistCache = null;
+ }
+
+ /**
+ * Set the list of groups to be blacklisted by id.
+ * @param string[] $ids a list with the ids of the groups to be blacklisted
+ */
+ public function setBlacklistedReceiverGroups(array $ids) {
+ $this->config->setAppValue('files_sharing', 'blacklisted_receiver_groups', \json_encode($ids));
+ $this->blacklistCache = null; // clear the cache
+ }
+
+ /**
+ * Get the list of blacklisted group ids
+ * Note that this might contain wrong information
+ * @return string[] the list of group ids
+ */
+ public function getBlacklistedReceiverGroups() {
+ return \json_decode($this->config->getAppValue('files_sharing', 'blacklisted_receiver_groups', '[]'), true);
+ }
+
+ private function initCache() {
+ if ($this->blacklistCache === null) {
+ $this->blacklistCache = [
+ 'receivers' => [
+ 'ids' => $this->fetchBlacklistedReceiverGroupIds(),
+ ],
+ ];
+ }
+ }
+
+ private function fetchBlacklistedReceiverGroupIds() {
+ $configuredBlacklist = $this->config->getAppValue('files_sharing', 'blacklisted_receiver_groups', '[]');
+ $decodedGroups = \json_decode($configuredBlacklist, true);
+ // expected a plain array here
+ $groupSet = [];
+ foreach ($decodedGroups as $group) {
+ $groupSet[$group] = true;
+ }
+ return $groupSet;
+ }
+}
diff --git a/apps/files_sharing/templates/settings.php b/apps/files_sharing/templates/settings.php
new file mode 100644
index 000000000000..20aeb328d79f
--- /dev/null
+++ b/apps/files_sharing/templates/settings.php
@@ -0,0 +1,32 @@
+
+ *
+ * @copyright Copyright (c) 2018, 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
+ *
+ */
+script('files_sharing', 'settings');
+?>
+
+
+
t('Files Sharing')); ?>
+
+
t('Exclude groups from receiving shares.')); ?>
+
+
+ t('These groups will not receive shares. Members of the group can still send and receive shares outside of the group.')); ?>
+
+
\ No newline at end of file
diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/API/Share20OCSTest.php
index 355020818425..6bb73ebdb409 100644
--- a/apps/files_sharing/tests/API/Share20OCSTest.php
+++ b/apps/files_sharing/tests/API/Share20OCSTest.php
@@ -27,6 +27,7 @@
use OC\OCS\Result;
use OCA\Files_Sharing\API\Share20OCS;
use OCA\Files_Sharing\Service\NotificationPublisher;
+use OCA\Files_Sharing\SharingBlacklist;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IConfig;
@@ -35,6 +36,7 @@
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
+use OCP\IGroup;
use OCP\IUserManager;
use OCP\Lock\LockedException;
use OCP\Share;
@@ -84,6 +86,8 @@ class Share20OCSTest extends TestCase {
private $notificationPublisher;
private $eventDispatcher;
+ /** @var SharingBlacklist */
+ private $sharingBlacklist;
protected function setUp() {
$this->shareManager = $this->getMockBuilder('OCP\Share\IManager')
@@ -118,6 +122,7 @@ protected function setUp() {
$this->notificationPublisher = $this->createMock(NotificationPublisher::class);
$this->eventDispatcher = $this->createMock(EventDispatcher::class);
+ $this->sharingBlacklist = $this->createMock(SharingBlacklist::class);
$this->ocs = new Share20OCS(
$this->shareManager,
@@ -130,7 +135,8 @@ protected function setUp() {
$this->l,
$this->config,
$this->notificationPublisher,
- $this->eventDispatcher
+ $this->eventDispatcher,
+ $this->sharingBlacklist
);
}
@@ -151,7 +157,8 @@ private function mockFormatShare() {
$this->l,
$this->config,
$this->notificationPublisher,
- $this->eventDispatcher
+ $this->eventDispatcher,
+ $this->sharingBlacklist,
])->setMethods(['formatShare'])
->getMock();
}
@@ -160,6 +167,20 @@ private function newShare() {
return \OC::$server->getShareManager()->newShare();
}
+ private function getGroupMock(array $attrs) {
+ $groupMock = $this->getMockBuilder(IGroup::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ if (isset($attrs['guid'])) {
+ $groupMock->method('getGID')->willReturn($attrs['guid']);
+ }
+ if (isset($attrs['displayname'])) {
+ $groupMock->method('getDisplayName')->willReturn($attrs['displayname']);
+ }
+ return $groupMock;
+ }
+
public function testDeleteShareShareNotFound() {
$this->shareManager
->expects($this->exactly(2))
@@ -461,7 +482,8 @@ public function testGetShare(\OCP\Share\IShare $share, array $result) {
$this->l,
$this->config,
$this->notificationPublisher,
- $this->eventDispatcher
+ $this->eventDispatcher,
+ $this->sharingBlacklist,
])->setMethods(['canAccessShare'])
->getMock();
@@ -895,6 +917,54 @@ public function testCreateShareGroupNoValidShareWith() {
$this->assertEquals($expected->getData(), $result->getData());
}
+ public function testCreateShareGroupBlacklisted() {
+ $share = $this->newShare();
+ $this->shareManager->method('newShare')->willReturn($share);
+
+ $this->request->method('getParam')
+ ->will($this->returnValueMap([
+ ['path', null, 'valid-path'],
+ ['permissions', null, \OCP\Constants::PERMISSION_ALL],
+ ['shareType', '-1', Share::SHARE_TYPE_GROUP],
+ ['shareWith', null, 'validGroup'],
+ ]));
+
+ $userFolder = $this->createMock('\OCP\Files\Folder');
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->with('currentUser')
+ ->willReturn($userFolder);
+
+ $path = $this->createMock('\OCP\Files\Folder');
+ $storage = $this->createMock('OCP\Files\Storage');
+ $storage->method('instanceOfStorage')
+ ->with('OCA\Files_Sharing\External\Storage')
+ ->willReturn(false);
+ $path->method('getStorage')->willReturn($storage);
+ $userFolder->expects($this->once())
+ ->method('get')
+ ->with('valid-path')
+ ->willReturn($path);
+
+ $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
+ $this->groupManager->method('get')
+ ->with('validGroup')
+ ->willReturn($this->getGroupMock(['guid' => 'gegege1', 'displayname' => 'validGroup']));
+
+ $this->shareManager->expects($this->once())
+ ->method('allowGroupSharing')
+ ->willReturn(true);
+
+ $this->sharingBlacklist->method('isGroupBlacklisted')->willReturn(true);
+
+ $expected = new \OC\OCS\Result(null, 403, 'The group is blacklisted for sharing');
+
+ $result = $this->ocs->createShare();
+
+ $this->assertEquals($expected->getMeta(), $result->getMeta());
+ $this->assertEquals($expected->getData(), $result->getData());
+ }
+
public function testCreateShareGroup() {
$share = $this->newShare();
$this->shareManager->method('newShare')->willReturn($share);
@@ -928,6 +998,9 @@ public function testCreateShareGroup() {
->willReturn($path);
$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
+ $this->groupManager->method('get')
+ ->with('validGroup')
+ ->willReturn($this->getGroupMock(['guid' => 'gegege1', 'displayname' => 'validGroup']));
$this->shareManager->expects($this->once())
->method('allowGroupSharing')
@@ -950,6 +1023,8 @@ public function testCreateShareGroup() {
}))
->will($this->returnArgument(0));
+ $this->sharingBlacklist->method('isGroupBlacklisted')->willReturn(false);
+
$expected = new \OC\OCS\Result();
$result = $ocs->createShare();
@@ -2704,7 +2779,8 @@ public function getOcsDisabledAPI() {
$this->l,
$this->config,
$this->notificationPublisher,
- $this->eventDispatcher
+ $this->eventDispatcher,
+ $this->sharingBlacklist
);
}
@@ -2796,7 +2872,8 @@ public function testGetShareAdditionalInfo($configValue, $expectedInfo) {
$this->l,
$config,
$this->notificationPublisher,
- $this->eventDispatcher
+ $this->eventDispatcher,
+ $this->sharingBlacklist
);
list($file, ) = $this->getMockFileFolder();
diff --git a/apps/files_sharing/tests/API/ShareesTest.php b/apps/files_sharing/tests/API/ShareesTest.php
index 043e2c68fabd..a08b0daf72db 100644
--- a/apps/files_sharing/tests/API/ShareesTest.php
+++ b/apps/files_sharing/tests/API/ShareesTest.php
@@ -27,6 +27,7 @@
namespace OCA\Files_Sharing\Tests\API;
use OCA\Files_Sharing\Controller\ShareesController;
+use OCA\Files_Sharing\SharingBlacklist;
use OCA\Files_Sharing\Tests\TestCase;
use OCP\AppFramework\Http;
use OCP\Contacts\IManager;
@@ -73,6 +74,9 @@ class ShareesTest extends TestCase {
/** @var \OCP\Share\IManager|\PHPUnit_Framework_MockObject_MockObject */
protected $shareManager;
+ /** @var SharingBlacklist|\PHPUnit_Framework_MockObject_MockObject */
+ protected $sharingBlacklist;
+
protected function setUp() {
parent::setUp();
@@ -104,6 +108,10 @@ protected function setUp() {
->disableOriginalConstructor()
->getMock();
+ $this->sharingBlacklist = $this->getMockBuilder(SharingBlacklist::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
$this->sharees = new ShareesController(
'files_sharing',
$this->request,
@@ -114,7 +122,8 @@ protected function setUp() {
$this->session,
$this->getMockBuilder(IURLGenerator::class)->disableOriginalConstructor()->getMock(),
$this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(),
- $this->shareManager
+ $this->shareManager,
+ $this->sharingBlacklist
);
}
@@ -534,7 +543,8 @@ public function testGetUsers(
$this->session,
$this->getMockBuilder(IURLGenerator::class)->disableOriginalConstructor()->getMock(),
$this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(),
- $this->shareManager
+ $this->shareManager,
+ $this->sharingBlacklist
);
$this->invokePrivate($this->sharees, 'limit', [2]);
$this->invokePrivate($this->sharees, 'offset', [0]);
@@ -594,8 +604,8 @@ public function testGetUsers(
public function dataGetGroups() {
return [
- ['test', false, true, [], [], [], [], true, false],
- ['test', false, false, [], [], [], [], true, false],
+ ['test', false, true, [], [], [], [], true],
+ ['test', false, false, [], [], [], [], true],
// group without display name
[
'test', false, true,
@@ -604,7 +614,6 @@ public function dataGetGroups() {
[],
[['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
true,
- false,
],
// group with display name, search by id
[
@@ -614,7 +623,6 @@ public function dataGetGroups() {
[],
[['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
true,
- false,
],
// group with display name, search by display name
[
@@ -624,7 +632,6 @@ public function dataGetGroups() {
[],
[['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
true,
- false,
],
// group with display name, search by display name, exact expected
[
@@ -634,7 +641,6 @@ public function dataGetGroups() {
[['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
[],
true,
- false,
],
[
'test', false, false,
@@ -643,7 +649,6 @@ public function dataGetGroups() {
[],
[],
true,
- false,
],
[
'test', false, true,
@@ -655,7 +660,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
false,
- false,
],
[
'test', false, false,
@@ -667,7 +671,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[],
true,
- false,
],
[
'test', false, true,
@@ -682,7 +685,6 @@ public function dataGetGroups() {
['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
],
false,
- null,
],
[
'test', false, false,
@@ -694,7 +696,6 @@ public function dataGetGroups() {
[],
[],
true,
- null,
],
[
'test', false, true,
@@ -703,15 +704,12 @@ public function dataGetGroups() {
$this->getGroupMock('test1'),
],
[],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
+ [],
[
['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
],
false,
- $this->getGroupMock('test'),
],
[
'test', false, false,
@@ -720,15 +718,12 @@ public function dataGetGroups() {
$this->getGroupMock('test1'),
],
[],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
+ [],
[],
true,
- $this->getGroupMock('test'),
],
- ['test', true, true, [], [], [], [], true, false],
- ['test', true, false, [], [], [], [], true, false],
+ ['test', true, true, [], [], [], [], true],
+ ['test', true, false, [], [], [], [], true],
[
'test', true, true,
[
@@ -739,7 +734,6 @@ public function dataGetGroups() {
[],
[['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
false,
- false,
],
[
'test', true, false,
@@ -751,7 +745,6 @@ public function dataGetGroups() {
[],
[],
true,
- false,
],
[
'test', true, true,
@@ -763,7 +756,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[],
false,
- false,
],
[
'test', true, false,
@@ -775,7 +767,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[],
true,
- false,
],
[
'test', true, true,
@@ -787,7 +778,6 @@ public function dataGetGroups() {
[],
[['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
false,
- false,
],
[
'test', true, false,
@@ -799,7 +789,6 @@ public function dataGetGroups() {
[],
[],
true,
- false,
],
[
'test', true, true,
@@ -811,7 +800,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
false,
- false,
],
[
'test', true, false,
@@ -823,7 +811,6 @@ public function dataGetGroups() {
[['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
[],
true,
- false,
],
[
'test', true, true,
@@ -838,7 +825,6 @@ public function dataGetGroups() {
['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
],
false,
- null,
],
[
'test', true, false,
@@ -850,7 +836,6 @@ public function dataGetGroups() {
[],
[],
true,
- null,
],
[
'test', true, true,
@@ -859,15 +844,12 @@ public function dataGetGroups() {
$this->getGroupMock('test1'),
],
[$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
+ [],
[
['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
],
false,
- $this->getGroupMock('test'),
],
[
'test', true, false,
@@ -876,12 +858,9 @@ public function dataGetGroups() {
$this->getGroupMock('test1'),
],
[$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
+ [],
[],
true,
- $this->getGroupMock('test'),
],
// group enumeration restricted to group memberships
[
@@ -900,14 +879,13 @@ public function dataGetGroups() {
['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
],
true,
- false,
true
],
[
// exact match
'test0', false, true,
// group results
- [],
+ [$this->getGroupMock('test0')],
// user group memberships
[$this->getGroupMock('test')],
// exact expected
@@ -917,10 +895,62 @@ public function dataGetGroups() {
// non-exact expected
[],
true,
- // exact match to test for
- $this->getGroupMock('test0'),
true
],
+ [
+ // check with group blacklist (not exact match)
+ 'test', false, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ],
+ false,
+ false,
+ ['test1']
+ ],
+ [
+ // check with group blacklist (exact match)
+ 'test', false, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ false,
+ ['test']
+ ],
+ [
+ // check with group blacklist (both exact and not)
+ 'test', false, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ],
+ false,
+ false,
+ ['test', 'test1']
+ ],
];
}
@@ -935,7 +965,8 @@ public function dataGetGroups() {
* @param array $exactExpected
* @param array $expected
* @param bool $reachedEnd
- * @param mixed $singleGroup false when testing a search or group mock when testing direct match
+ * @param bool $shareeEnumerationGroupMembers
+ * @param array $blacklistedGroupNames list with the names of the blacklisted groups
*/
public function testGetGroups(
$searchTerm,
@@ -946,8 +977,8 @@ public function testGetGroups(
$exactExpected,
$expected,
$reachedEnd,
- $singleGroup,
- $shareeEnumerationGroupMembers = false
+ $shareeEnumerationGroupMembers = false,
+ $blacklistedGroupNames = []
) {
$this->invokePrivate($this->sharees, 'limit', [2]);
$this->invokePrivate($this->sharees, 'offset', [0]);
@@ -960,12 +991,12 @@ public function testGetGroups(
->with($searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
->willReturn($groupResponse);
- if ($singleGroup !== false) {
- $this->groupManager->expects($this->once())
- ->method('get')
- ->with($searchTerm)
- ->willReturn($singleGroup);
- }
+ $getGroupValueMap = \array_map(function ($group) {
+ return [$group->getGID(), $group];
+ }, $groupResponse);
+
+ $this->groupManager->method('get')
+ ->will($this->returnValueMap($getGroupValueMap));
if ($shareWithMembershipGroupOnly || $shareeEnumerationGroupMembers) {
$user = $this->getUserMock('admin', 'Administrator');
@@ -980,6 +1011,13 @@ public function testGetGroups(
->willReturn($userGroupsResponse);
}
+ // don't care about the particular implementation of the method
+ // just mark the group as blacklisted based on the displayname
+ $this->sharingBlacklist->method('isGroupBlacklisted')
+ ->will($this->returnCallback(function (IGroup $group) use ($blacklistedGroupNames) {
+ return \in_array($group->getDisplayName(), $blacklistedGroupNames, true);
+ }));
+
$this->invokePrivate($this->sharees, 'getGroups', [$searchTerm]);
$result = $this->invokePrivate($this->sharees, 'result');
@@ -1484,7 +1522,8 @@ public function testSearchInvalid($message, $search = '', $itemType = null, $pag
$this->session,
$this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
- $this->shareManager
+ $this->shareManager,
+ $this->sharingBlacklist
])
->setMethods(['searchSharees', 'isRemoteSharingAllowed'])
->getMock();
@@ -1633,7 +1672,8 @@ public function testSearchSharees($searchTerm, $itemType, array $shareTypes, $pa
$this->session,
$this->getMockBuilder(IURLGenerator::class)->disableOriginalConstructor()->getMock(),
$this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(),
- $this->shareManager
+ $this->shareManager,
+ $this->sharingBlacklist
])
->setMethods(['getShareesForShareIds', 'getUsers', 'getGroups', 'getRemote'])
->getMock();
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index cd0d986debcf..527b80690d01 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -33,6 +33,7 @@
use OCP\IRequest;
use OCP\Share;
use OCA\Files_Sharing\Service\NotificationPublisher;
+use OCA\Files_Sharing\SharingBlacklist;
/**
* Class ApiTest
@@ -125,7 +126,8 @@ private function createOCS($request, $userId) {
$l,
\OC::$server->getConfig(),
\OC::$server->getAppContainer('files_sharing')->query(NotificationPublisher::class),
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ \OC::$server->getAppContainer('files_sharing')->query(SharingBlacklist::class)
);
}
diff --git a/apps/files_sharing/tests/Panels/Admin/SettingsPanelTest.php b/apps/files_sharing/tests/Panels/Admin/SettingsPanelTest.php
new file mode 100644
index 000000000000..0f0838457277
--- /dev/null
+++ b/apps/files_sharing/tests/Panels/Admin/SettingsPanelTest.php
@@ -0,0 +1,89 @@
+
+ *
+ * @copyright Copyright (c) 2018, 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 OCA\Files_Sharing\Tests\Panels\Admin;
+
+use OCP\GroupInterface;
+use OCA\Files_Sharing\SharingBlacklist;
+use OCA\Files_Sharing\Panels\Admin\SettingsPanel;
+
+class SettingsPanelTest extends \Test\TestCase {
+ /** @var SharingBlacklist | \PHPUnit_Framework_MockObject_MockObject */
+ private $sharingBlacklist;
+
+ /** @var SettingsPanel | \PHPUnit_Framework_MockObject_MockObject */
+ private $settingsPanel;
+
+ protected function setUp() {
+ $this->sharingBlacklist = $this->getMockBuilder(SharingBlacklist::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->settingsPanel = new SettingsPanel($this->sharingBlacklist);
+ }
+
+ public function testGetSectionID() {
+ $this->assertEquals('sharing', $this->settingsPanel->getSectionID());
+ }
+
+ public function testGetPriority() {
+ $this->assertEquals(0, $this->settingsPanel->getPriority());
+ }
+
+ public function testGetPanel() {
+ $this->sharingBlacklist->method('getBlacklistedReceiverGroups')->willReturn([]);
+
+ $page = $this->settingsPanel->getPanel()->fetchPage();
+ $doc = new \DOMDocument();
+ $doc->loadHTML($page);
+ $xpath = new \DOMXPath($doc);
+
+ $inputNodes = $xpath->query('//input[@name="blacklisted_receiver_groups"]');
+ $this->assertEquals(1, $inputNodes->length); // only 1 element should be found
+ $inputNode = $inputNodes->item(0);
+ $this->assertSame('', $inputNode->attributes->getNamedItem('value')->value);
+ }
+
+ public function getPanelWithBlacklistProvider() {
+ return [
+ [['group1']],
+ [['group1', 'group2']],
+ [['group1', 'group2', 'group3']],
+ [['1234mkdds_lklk', '12345678-1234-1234-123456789abcdf']],
+ ];
+ }
+
+ /**
+ * @dataProvider getPanelWithBlacklistProvider
+ */
+ public function testGetPanelWithBlacklist($ids) {
+ $this->sharingBlacklist->method('getBlacklistedReceiverGroups')->willReturn($ids);
+
+ $page = $this->settingsPanel->getPanel()->fetchPage();
+ $doc = new \DOMDocument();
+ $doc->loadHTML($page);
+ $xpath = new \DOMXPath($doc);
+
+ $inputNodes = $xpath->query('//input[@name="blacklisted_receiver_groups"]');
+ $this->assertEquals(1, $inputNodes->length); // only 1 element should be found
+ $inputNode = $inputNodes->item(0);
+ $this->assertSame(\implode("|", $ids), $inputNode->attributes->getNamedItem('value')->value);
+ }
+}
diff --git a/apps/files_sharing/tests/SharingBlacklistTest.php b/apps/files_sharing/tests/SharingBlacklistTest.php
new file mode 100644
index 000000000000..55a68d34f86b
--- /dev/null
+++ b/apps/files_sharing/tests/SharingBlacklistTest.php
@@ -0,0 +1,120 @@
+
+ *
+ * @copyright Copyright (c) 2018, 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 OCA\Files_Sharing\Tests;
+
+use OCP\IConfig;
+use OCP\IGroup;
+use OCP\GroupInterface;
+use OCA\Files_Sharing\SharingBlacklist;
+
+class SharingBlacklistTest extends \Test\TestCase {
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+
+ /** @var SharingBlacklist | \PHPUnit_Framework_MockObject_MockObject */
+ private $sharingBlacklist;
+
+ public function setUp() {
+ $this->config = $this->getMockBuilder(IConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->sharingBlacklist = new SharingBlacklist($this->config);
+ }
+
+ public function setGetBlacklistedReceiverGroupsProvider() {
+ return [
+ [[]],
+ [["group1"]],
+ [["group1", "group2", "$group3"]],
+ ];
+ }
+
+ /**
+ * @dataProvider setGetBlacklistedReceiverGroupsProvider
+ */
+ public function testSetGetBlacklistedReceiverGroups($ids) {
+ $keyValues = [];
+ $this->config->method('setAppValue')
+ ->will($this->returnCallback(function ($app, $key, $value) use (&$keyValues) {
+ $keyValues[$key] = $value;
+ }));
+
+ $this->config->method('getAppValue')
+ ->will($this->returnCallback(function ($app, $key, $default) use (&$keyValues) {
+ return (isset($keyValues[$key])) ? $keyValues[$key] : $default;
+ }));
+
+ $this->sharingBlacklist->setBlacklistedReceiverGroups($ids);
+ $this->assertEquals($ids, $this->sharingBlacklist->getBlacklistedReceiverGroups());
+ }
+
+ private function getGroupMock($id, $displayname) {
+ $groupMock = $this->getMockBuilder(IGroup::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $groupBackendMock = $this->getMockBuilder(GroupInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $groupMock->method('getBackend')->willReturn($groupBackendMock);
+ $groupMock->method('getGID')->willReturn($id);
+ $groupMock->method('getDisplayName')->willReturn($displayname);
+ return $groupMock;
+ }
+
+ public function isGroupBlacklistedProvider() {
+ $groupMock1 = $this->getGroupMock('Mygroup', 'my group');
+ return [
+ [$groupMock1, '["Mygroup"]'],
+ [$groupMock1, '["Mygroup", "my_other_group"]'],
+ [$groupMock1, '["one group", "Mygroup"]'],
+ ];
+ }
+
+ /**
+ * @dataProvider isGroupBlacklistedProvider
+ */
+ public function testIsGroupBlacklisted($group, $configValue) {
+ $this->config->method('getAppValue')->willReturn($configValue);
+
+ $this->assertTrue($this->sharingBlacklist->isGroupBlacklisted($group));
+ }
+
+ public function isGroupBlacklistedNotBlacklistedProvider() {
+ $groupMock1 = $this->getGroupMock('Mygroup', 'my group');
+ return [
+ [$groupMock1, '[]'],
+ [$groupMock1, '["my group"]'],
+ [$groupMock1, '["Mygroup2", "my group"]'],
+ ];
+ }
+
+ /**
+ * @dataProvider isGroupBlacklistedNotBlacklistedProvider
+ */
+ public function testIsGroupBlacklistedNotBlacklisted($group, $configValue) {
+ $this->config->method('getAppValue')->willReturn($configValue);
+
+ $this->assertFalse($this->sharingBlacklist->isGroupBlacklisted($group));
+ }
+}