Merge pull request #2834 from nextcloud/accesListToShareManager
Access list to share manager
This commit is contained in:
commit
10290eb006
|
@ -28,6 +28,7 @@ namespace OCA\FederatedFileSharing;
|
||||||
|
|
||||||
use OC\Share20\Share;
|
use OC\Share20\Share;
|
||||||
use OCP\Federation\ICloudIdManager;
|
use OCP\Federation\ICloudIdManager;
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
|
@ -974,4 +975,43 @@ class FederatedShareProvider implements IShareProvider {
|
||||||
$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
|
$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
|
||||||
return ($result === 'yes');
|
return ($result === 'yes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getAccessList($nodes, $currentAccess) {
|
||||||
|
$ids = [];
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$ids[] = $node->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb = $this->dbConnection->getQueryBuilder();
|
||||||
|
$qb->select('share_with', 'token', 'file_source')
|
||||||
|
->from('share')
|
||||||
|
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
|
||||||
|
->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
|
||||||
|
->andWhere($qb->expr()->orX(
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||||
|
));
|
||||||
|
$cursor = $qb->execute();
|
||||||
|
|
||||||
|
if ($currentAccess === false) {
|
||||||
|
$remote = $cursor->fetch() !== false;
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
return ['remote' => $remote];
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote = [];
|
||||||
|
while ($row = $cursor->fetch()) {
|
||||||
|
$remote[$row['share_with']] = [
|
||||||
|
'node_id' => $row['file_source'],
|
||||||
|
'token' => $row['token'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
return ['remote' => $remote];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
|
||||||
protected $addressHandler;
|
protected $addressHandler;
|
||||||
/** @var Notifications | \PHPUnit_Framework_MockObject_MockObject */
|
/** @var Notifications | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
protected $notifications;
|
protected $notifications;
|
||||||
/** @var TokenHandler */
|
/** @var TokenHandler|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
protected $tokenHandler;
|
protected $tokenHandler;
|
||||||
/** @var IL10N */
|
/** @var IL10N */
|
||||||
protected $l;
|
protected $l;
|
||||||
|
@ -788,4 +788,60 @@ class FederatedShareProviderTest extends \Test\TestCase {
|
||||||
$u1->delete();
|
$u1->delete();
|
||||||
$u2->delete();
|
$u2->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAccessList() {
|
||||||
|
$userManager = \OC::$server->getUserManager();
|
||||||
|
$rootFolder = \OC::$server->getRootFolder();
|
||||||
|
|
||||||
|
$u1 = $userManager->createUser('testFed', md5(time()));
|
||||||
|
|
||||||
|
$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
|
||||||
|
$file1 = $folder1->newFile('bar1');
|
||||||
|
|
||||||
|
$this->tokenHandler->expects($this->exactly(2))
|
||||||
|
->method('generateToken')
|
||||||
|
->willReturnOnConsecutiveCalls('token1', 'token2');
|
||||||
|
$this->notifications->expects($this->atLeastOnce())
|
||||||
|
->method('sendRemoteShare')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$result = $this->provider->getAccessList([$file1], true);
|
||||||
|
$this->assertEquals(['remote' => []], $result);
|
||||||
|
|
||||||
|
$result = $this->provider->getAccessList([$file1], false);
|
||||||
|
$this->assertEquals(['remote' => false], $result);
|
||||||
|
|
||||||
|
$share1 = $this->shareManager->newShare();
|
||||||
|
$share1->setSharedWith('user@server.com')
|
||||||
|
->setSharedBy($u1->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ)
|
||||||
|
->setNode($file1);
|
||||||
|
$this->provider->create($share1);
|
||||||
|
|
||||||
|
$share2 = $this->shareManager->newShare();
|
||||||
|
$share2->setSharedWith('foobar@localhost')
|
||||||
|
->setSharedBy($u1->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ)
|
||||||
|
->setNode($file1);
|
||||||
|
$this->provider->create($share2);
|
||||||
|
|
||||||
|
$result = $this->provider->getAccessList([$file1], true);
|
||||||
|
$this->assertEquals(['remote' => [
|
||||||
|
'user@server.com' => [
|
||||||
|
'token' => 'token1',
|
||||||
|
'node_id' => $file1->getId(),
|
||||||
|
],
|
||||||
|
'foobar@localhost' => [
|
||||||
|
'token' => 'token2',
|
||||||
|
'node_id' => $file1->getId(),
|
||||||
|
],
|
||||||
|
]], $result);
|
||||||
|
|
||||||
|
$result = $this->provider->getAccessList([$file1], false);
|
||||||
|
$this->assertEquals(['remote' => true], $result);
|
||||||
|
|
||||||
|
$u1->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -834,4 +834,31 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
return $shares;
|
return $shares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getAccessList($nodes, $currentAccess) {
|
||||||
|
$ids = [];
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$ids[] = $node->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb = $this->dbConnection->getQueryBuilder();
|
||||||
|
$qb->select('share_with')
|
||||||
|
->from('share')
|
||||||
|
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
|
||||||
|
->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
|
||||||
|
->andWhere($qb->expr()->orX(
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||||
|
))
|
||||||
|
->setMaxResults(1);
|
||||||
|
$cursor = $qb->execute();
|
||||||
|
|
||||||
|
$mail = $cursor->fetch() !== false;
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
return ['public' => $mail];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -664,4 +664,66 @@ class ShareByMailProviderTest extends TestCase {
|
||||||
$u2->delete();
|
$u2->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAccessList() {
|
||||||
|
$userManager = \OC::$server->getUserManager();
|
||||||
|
$rootFolder = \OC::$server->getRootFolder();
|
||||||
|
|
||||||
|
$provider = $this->getInstance(['sendMailNotification', 'createActivity']);
|
||||||
|
|
||||||
|
$u1 = $userManager->createUser('testFed', md5(time()));
|
||||||
|
$u2 = $userManager->createUser('testFed2', md5(time()));
|
||||||
|
|
||||||
|
$folder = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
|
||||||
|
|
||||||
|
$accessList = $provider->getAccessList([$folder], true);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertFalse($accessList['public']);
|
||||||
|
$accessList = $provider->getAccessList([$folder], false);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertFalse($accessList['public']);
|
||||||
|
|
||||||
|
$share1 = $this->shareManager->newShare();
|
||||||
|
$share1->setSharedWith('user@server.com')
|
||||||
|
->setSharedBy($u1->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ)
|
||||||
|
->setNode($folder);
|
||||||
|
$share1 = $provider->create($share1);
|
||||||
|
|
||||||
|
$share2 = $this->shareManager->newShare();
|
||||||
|
$share2->setSharedWith('user2@server.com')
|
||||||
|
->setSharedBy($u2->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ)
|
||||||
|
->setNode($folder);
|
||||||
|
$share2 = $provider->create($share2);
|
||||||
|
|
||||||
|
$accessList = $provider->getAccessList([$folder], true);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertTrue($accessList['public']);
|
||||||
|
$accessList = $provider->getAccessList([$folder], false);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertTrue($accessList['public']);
|
||||||
|
|
||||||
|
$provider->delete($share2);
|
||||||
|
|
||||||
|
$accessList = $provider->getAccessList([$folder], true);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertTrue($accessList['public']);
|
||||||
|
$accessList = $provider->getAccessList([$folder], false);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertTrue($accessList['public']);
|
||||||
|
|
||||||
|
$provider->delete($share1);
|
||||||
|
|
||||||
|
$accessList = $provider->getAccessList([$folder], true);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertFalse($accessList['public']);
|
||||||
|
$accessList = $provider->getAccessList([$folder], false);
|
||||||
|
$this->assertArrayHasKey('public', $accessList);
|
||||||
|
$this->assertFalse($accessList['public']);
|
||||||
|
|
||||||
|
$u1->delete();
|
||||||
|
$u2->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@ return array(
|
||||||
'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php',
|
'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php',
|
||||||
'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php',
|
'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php',
|
||||||
'OCP\\Share\\IShare' => $baseDir . '/lib/public/Share/IShare.php',
|
'OCP\\Share\\IShare' => $baseDir . '/lib/public/Share/IShare.php',
|
||||||
|
'OCP\\Share\\IShareHelper' => $baseDir . '/lib/public/Share/IShareHelper.php',
|
||||||
'OCP\\Share\\IShareProvider' => $baseDir . '/lib/public/Share/IShareProvider.php',
|
'OCP\\Share\\IShareProvider' => $baseDir . '/lib/public/Share/IShareProvider.php',
|
||||||
'OCP\\Share_Backend' => $baseDir . '/lib/public/Share_Backend.php',
|
'OCP\\Share_Backend' => $baseDir . '/lib/public/Share_Backend.php',
|
||||||
'OCP\\Share_Backend_Collection' => $baseDir . '/lib/public/Share_Backend_Collection.php',
|
'OCP\\Share_Backend_Collection' => $baseDir . '/lib/public/Share_Backend_Collection.php',
|
||||||
|
@ -804,6 +805,7 @@ return array(
|
||||||
'OC\\Share20\\Manager' => $baseDir . '/lib/private/Share20/Manager.php',
|
'OC\\Share20\\Manager' => $baseDir . '/lib/private/Share20/Manager.php',
|
||||||
'OC\\Share20\\ProviderFactory' => $baseDir . '/lib/private/Share20/ProviderFactory.php',
|
'OC\\Share20\\ProviderFactory' => $baseDir . '/lib/private/Share20/ProviderFactory.php',
|
||||||
'OC\\Share20\\Share' => $baseDir . '/lib/private/Share20/Share.php',
|
'OC\\Share20\\Share' => $baseDir . '/lib/private/Share20/Share.php',
|
||||||
|
'OC\\Share20\\ShareHelper' => $baseDir . '/lib/private/Share20/ShareHelper.php',
|
||||||
'OC\\Share\\Constants' => $baseDir . '/lib/private/Share/Constants.php',
|
'OC\\Share\\Constants' => $baseDir . '/lib/private/Share/Constants.php',
|
||||||
'OC\\Share\\Helper' => $baseDir . '/lib/private/Share/Helper.php',
|
'OC\\Share\\Helper' => $baseDir . '/lib/private/Share/Helper.php',
|
||||||
'OC\\Share\\MailNotifications' => $baseDir . '/lib/private/Share/MailNotifications.php',
|
'OC\\Share\\MailNotifications' => $baseDir . '/lib/private/Share/MailNotifications.php',
|
||||||
|
|
|
@ -282,6 +282,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
||||||
'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php',
|
'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php',
|
||||||
'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php',
|
'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php',
|
||||||
'OCP\\Share\\IShare' => __DIR__ . '/../../..' . '/lib/public/Share/IShare.php',
|
'OCP\\Share\\IShare' => __DIR__ . '/../../..' . '/lib/public/Share/IShare.php',
|
||||||
|
'OCP\\Share\\IShareHelper' => __DIR__ . '/../../..' . '/lib/public/Share/IShareHelper.php',
|
||||||
'OCP\\Share\\IShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProvider.php',
|
'OCP\\Share\\IShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProvider.php',
|
||||||
'OCP\\Share_Backend' => __DIR__ . '/../../..' . '/lib/public/Share_Backend.php',
|
'OCP\\Share_Backend' => __DIR__ . '/../../..' . '/lib/public/Share_Backend.php',
|
||||||
'OCP\\Share_Backend_Collection' => __DIR__ . '/../../..' . '/lib/public/Share_Backend_Collection.php',
|
'OCP\\Share_Backend_Collection' => __DIR__ . '/../../..' . '/lib/public/Share_Backend_Collection.php',
|
||||||
|
@ -834,6 +835,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
||||||
'OC\\Share20\\Manager' => __DIR__ . '/../../..' . '/lib/private/Share20/Manager.php',
|
'OC\\Share20\\Manager' => __DIR__ . '/../../..' . '/lib/private/Share20/Manager.php',
|
||||||
'OC\\Share20\\ProviderFactory' => __DIR__ . '/../../..' . '/lib/private/Share20/ProviderFactory.php',
|
'OC\\Share20\\ProviderFactory' => __DIR__ . '/../../..' . '/lib/private/Share20/ProviderFactory.php',
|
||||||
'OC\\Share20\\Share' => __DIR__ . '/../../..' . '/lib/private/Share20/Share.php',
|
'OC\\Share20\\Share' => __DIR__ . '/../../..' . '/lib/private/Share20/Share.php',
|
||||||
|
'OC\\Share20\\ShareHelper' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareHelper.php',
|
||||||
'OC\\Share\\Constants' => __DIR__ . '/../../..' . '/lib/private/Share/Constants.php',
|
'OC\\Share\\Constants' => __DIR__ . '/../../..' . '/lib/private/Share/Constants.php',
|
||||||
'OC\\Share\\Helper' => __DIR__ . '/../../..' . '/lib/private/Share/Helper.php',
|
'OC\\Share\\Helper' => __DIR__ . '/../../..' . '/lib/private/Share/Helper.php',
|
||||||
'OC\\Share\\MailNotifications' => __DIR__ . '/../../..' . '/lib/private/Share/MailNotifications.php',
|
'OC\\Share\\MailNotifications' => __DIR__ . '/../../..' . '/lib/private/Share/MailNotifications.php',
|
||||||
|
|
|
@ -25,12 +25,21 @@
|
||||||
namespace OC\Encryption;
|
namespace OC\Encryption;
|
||||||
|
|
||||||
use OC\Cache\CappedMemoryCache;
|
use OC\Cache\CappedMemoryCache;
|
||||||
|
use OCP\Files\IRootFolder;
|
||||||
|
use OCP\Files\NotFoundException;
|
||||||
|
use OCP\Share\IManager;
|
||||||
|
|
||||||
class File implements \OCP\Encryption\IFile {
|
class File implements \OCP\Encryption\IFile {
|
||||||
|
|
||||||
/** @var Util */
|
/** @var Util */
|
||||||
protected $util;
|
protected $util;
|
||||||
|
|
||||||
|
/** @var IRootFolder */
|
||||||
|
private $rootFolder;
|
||||||
|
|
||||||
|
/** @var IManager */
|
||||||
|
private $shareManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache results of already checked folders
|
* cache results of already checked folders
|
||||||
*
|
*
|
||||||
|
@ -38,9 +47,13 @@ class File implements \OCP\Encryption\IFile {
|
||||||
*/
|
*/
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
public function __construct(Util $util) {
|
public function __construct(Util $util,
|
||||||
|
IRootFolder $rootFolder,
|
||||||
|
IManager $shareManager) {
|
||||||
$this->util = $util;
|
$this->util = $util;
|
||||||
$this->cache = new CappedMemoryCache();
|
$this->cache = new CappedMemoryCache();
|
||||||
|
$this->rootFolder = $rootFolder;
|
||||||
|
$this->shareManager = $shareManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,26 +76,34 @@ class File implements \OCP\Encryption\IFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
$ownerPath = substr($ownerPath, strlen('/files'));
|
$ownerPath = substr($ownerPath, strlen('/files'));
|
||||||
|
$userFolder = $this->rootFolder->getUserFolder($owner);
|
||||||
|
try {
|
||||||
|
$file = $userFolder->get($ownerPath);
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
$file = null;
|
||||||
|
}
|
||||||
$ownerPath = $this->util->stripPartialFileExtension($ownerPath);
|
$ownerPath = $this->util->stripPartialFileExtension($ownerPath);
|
||||||
|
|
||||||
|
|
||||||
// first get the shares for the parent and cache the result so that we don't
|
// first get the shares for the parent and cache the result so that we don't
|
||||||
// need to check all parents for every file
|
// need to check all parents for every file
|
||||||
$parent = dirname($ownerPath);
|
$parent = dirname($ownerPath);
|
||||||
|
$parentNode = $userFolder->get($parent);
|
||||||
if (isset($this->cache[$parent])) {
|
if (isset($this->cache[$parent])) {
|
||||||
$resultForParents = $this->cache[$parent];
|
$resultForParents = $this->cache[$parent];
|
||||||
} else {
|
} else {
|
||||||
$resultForParents = \OCP\Share::getUsersSharingFile($parent, $owner);
|
$resultForParents = $this->shareManager->getAccessList($parentNode);
|
||||||
$this->cache[$parent] = $resultForParents;
|
$this->cache[$parent] = $resultForParents;
|
||||||
}
|
}
|
||||||
$userIds = \array_merge($userIds, $resultForParents['users']);
|
$userIds = array_merge($userIds, $resultForParents['users']);
|
||||||
$public = $resultForParents['public'] || $resultForParents['remote'];
|
$public = $resultForParents['public'] || $resultForParents['remote'];
|
||||||
|
|
||||||
|
|
||||||
// Find out who, if anyone, is sharing the file
|
// Find out who, if anyone, is sharing the file
|
||||||
$resultForFile = \OCP\Share::getUsersSharingFile($ownerPath, $owner, false, false, false);
|
if ($file !== null) {
|
||||||
$userIds = \array_merge($userIds, $resultForFile['users']);
|
$resultForFile = $this->shareManager->getAccessList($file, false);
|
||||||
$public = $resultForFile['public'] || $resultForFile['remote'] || $public;
|
$userIds = array_merge($userIds, $resultForFile['users']);
|
||||||
|
$public = $resultForFile['public'] || $resultForFile['remote'] || $public;
|
||||||
|
}
|
||||||
|
|
||||||
// check if it is a group mount
|
// check if it is a group mount
|
||||||
if (\OCP\App::isEnabled("files_external")) {
|
if (\OCP\App::isEnabled("files_external")) {
|
||||||
|
|
|
@ -93,6 +93,7 @@ use OC\Security\CredentialsManager;
|
||||||
use OC\Security\SecureRandom;
|
use OC\Security\SecureRandom;
|
||||||
use OC\Security\TrustedDomainHelper;
|
use OC\Security\TrustedDomainHelper;
|
||||||
use OC\Session\CryptoWrapper;
|
use OC\Session\CryptoWrapper;
|
||||||
|
use OC\Share20\ShareHelper;
|
||||||
use OC\Tagging\TagMapper;
|
use OC\Tagging\TagMapper;
|
||||||
use OCA\Theming\ThemingDefaults;
|
use OCA\Theming\ThemingDefaults;
|
||||||
use OCP\App\IAppManager;
|
use OCP\App\IAppManager;
|
||||||
|
@ -106,6 +107,7 @@ use OCP\IServerContainer;
|
||||||
use OCP\ITempManager;
|
use OCP\ITempManager;
|
||||||
use OCP\RichObjectStrings\IValidator;
|
use OCP\RichObjectStrings\IValidator;
|
||||||
use OCP\Security\IContentSecurityPolicyManager;
|
use OCP\Security\IContentSecurityPolicyManager;
|
||||||
|
use OCP\Share\IShareHelper;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
|
@ -173,7 +175,11 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
$c->getGroupManager(),
|
$c->getGroupManager(),
|
||||||
$c->getConfig()
|
$c->getConfig()
|
||||||
);
|
);
|
||||||
return new Encryption\File($util);
|
return new Encryption\File(
|
||||||
|
$util,
|
||||||
|
$c->getRootFolder(),
|
||||||
|
$c->getShareManager()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->registerService('EncryptionKeyStorage', function (Server $c) {
|
$this->registerService('EncryptionKeyStorage', function (Server $c) {
|
||||||
|
@ -988,6 +994,12 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
$this->registerService(\OCP\ISession::class, function(SimpleContainer $c) {
|
$this->registerService(\OCP\ISession::class, function(SimpleContainer $c) {
|
||||||
return $c->query(\OCP\IUserSession::class)->getSession();
|
return $c->query(\OCP\IUserSession::class)->getSession();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->registerService(IShareHelper::class, function(Server $c) {
|
||||||
|
return new ShareHelper(
|
||||||
|
$c->query(\OCP\Share\IManager::class)
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -362,7 +362,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
if ($data === false) {
|
if ($data === false) {
|
||||||
$qb = $this->dbConn->getQueryBuilder();
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
|
|
||||||
$type = $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder';
|
$type = $share->getNodeType();
|
||||||
|
|
||||||
//Insert new share
|
//Insert new share
|
||||||
$qb->insert('share')
|
$qb->insert('share')
|
||||||
|
@ -373,8 +373,8 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
|
'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
|
||||||
'parent' => $qb->createNamedParameter($share->getId()),
|
'parent' => $qb->createNamedParameter($share->getId()),
|
||||||
'item_type' => $qb->createNamedParameter($type),
|
'item_type' => $qb->createNamedParameter($type),
|
||||||
'item_source' => $qb->createNamedParameter($share->getNode()->getId()),
|
'item_source' => $qb->createNamedParameter($share->getNodeId()),
|
||||||
'file_source' => $qb->createNamedParameter($share->getNode()->getId()),
|
'file_source' => $qb->createNamedParameter($share->getNodeId()),
|
||||||
'file_target' => $qb->createNamedParameter($share->getTarget()),
|
'file_target' => $qb->createNamedParameter($share->getTarget()),
|
||||||
'permissions' => $qb->createNamedParameter(0),
|
'permissions' => $qb->createNamedParameter(0),
|
||||||
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
|
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
|
||||||
|
@ -1070,4 +1070,115 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getAccessList($nodes, $currentAccess) {
|
||||||
|
$ids = [];
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$ids[] = $node->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
|
|
||||||
|
$or = $qb->expr()->orX(
|
||||||
|
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
|
||||||
|
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)),
|
||||||
|
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($currentAccess) {
|
||||||
|
$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
|
||||||
|
->from('share')
|
||||||
|
->where(
|
||||||
|
$or
|
||||||
|
)
|
||||||
|
->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
|
||||||
|
->andWhere($qb->expr()->orX(
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
|
||||||
|
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||||
|
));
|
||||||
|
$cursor = $qb->execute();
|
||||||
|
|
||||||
|
$users = [];
|
||||||
|
$link = false;
|
||||||
|
while($row = $cursor->fetch()) {
|
||||||
|
$type = (int)$row['share_type'];
|
||||||
|
if ($type === \OCP\Share::SHARE_TYPE_USER) {
|
||||||
|
$uid = $row['share_with'];
|
||||||
|
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||||
|
$users[$uid][$row['id']] = $row;
|
||||||
|
} else if ($type === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||||
|
$gid = $row['share_with'];
|
||||||
|
$group = $this->groupManager->get($gid);
|
||||||
|
|
||||||
|
if ($gid === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userList = $group->getUsers();
|
||||||
|
foreach ($userList as $user) {
|
||||||
|
$uid = $user->getUID();
|
||||||
|
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||||
|
$users[$uid][$row['id']] = $row;
|
||||||
|
}
|
||||||
|
} else if ($type === \OCP\Share::SHARE_TYPE_LINK) {
|
||||||
|
$link = true;
|
||||||
|
} else if ($type === self::SHARE_TYPE_USERGROUP && $currentAccess === true) {
|
||||||
|
$uid = $row['share_with'];
|
||||||
|
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||||
|
$users[$uid][$row['id']] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
if ($currentAccess === true) {
|
||||||
|
$users = array_map([$this, 'filterSharesOfUser'], $users);
|
||||||
|
$users = array_filter($users);
|
||||||
|
} else {
|
||||||
|
$users = array_keys($users);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['users' => $users, 'public' => $link];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each user the path with the fewest slashes is returned
|
||||||
|
* @param array $shares
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function filterSharesOfUser(array $shares) {
|
||||||
|
// Group shares when the user has a share exception
|
||||||
|
foreach ($shares as $id => $share) {
|
||||||
|
$type = (int) $share['share_type'];
|
||||||
|
$permissions = (int) $share['permissions'];
|
||||||
|
|
||||||
|
if ($type === self::SHARE_TYPE_USERGROUP) {
|
||||||
|
unset($shares[$share['parent']]);
|
||||||
|
|
||||||
|
if ($permissions === 0) {
|
||||||
|
unset($shares[$id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$best = [];
|
||||||
|
$bestDepth = 0;
|
||||||
|
foreach ($shares as $id => $share) {
|
||||||
|
$depth = substr_count($share['file_target'], '/');
|
||||||
|
if (empty($best) || $depth < $bestDepth) {
|
||||||
|
$bestDepth = $depth;
|
||||||
|
$best = [
|
||||||
|
'node_id' => $share['file_source'],
|
||||||
|
'node_path' => $share['file_target'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $best;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
use OCP\Share\IManager;
|
use OCP\Share\IManager;
|
||||||
use OCP\Share\IProviderFactory;
|
use OCP\Share\IProviderFactory;
|
||||||
|
use OCP\Share\IShare;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||||
use OCP\Share\IShareProvider;
|
use OCP\Share\IShareProvider;
|
||||||
|
@ -1176,29 +1177,109 @@ class Manager implements IManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get access list to a path. This means
|
* Get access list to a path. This means
|
||||||
* all the users and groups that can access a given path.
|
* all the users that can access a given path.
|
||||||
*
|
*
|
||||||
* Consider:
|
* Consider:
|
||||||
* -root
|
* -root
|
||||||
* |-folder1
|
* |-folder1 (23)
|
||||||
* |-folder2
|
* |-folder2 (32)
|
||||||
* |-fileA
|
* |-fileA (42)
|
||||||
*
|
*
|
||||||
* fileA is shared with user1
|
* fileA is shared with user1 and user1@server1
|
||||||
* folder2 is shared with group2
|
* folder2 is shared with group2 (user4 is a member of group2)
|
||||||
* folder1 is shared with user2
|
* folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
|
||||||
*
|
*
|
||||||
* Then the access list will to '/folder1/folder2/fileA' is:
|
* Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
|
||||||
* [
|
* [
|
||||||
* 'users' => ['user1', 'user2'],
|
* users => [
|
||||||
* 'groups' => ['group2']
|
* 'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
|
||||||
|
* 'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
|
||||||
|
* 'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
|
||||||
|
* ],
|
||||||
|
* remote => [
|
||||||
|
* 'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
|
||||||
|
* 'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
|
||||||
|
* ],
|
||||||
|
* public => bool
|
||||||
|
* mail => bool
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
* This is required for encryption
|
* The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
|
||||||
|
* [
|
||||||
|
* users => ['user1', 'user2', 'user4'],
|
||||||
|
* remote => bool,
|
||||||
|
* public => bool
|
||||||
|
* mail => bool
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* This is required for encryption/activity
|
||||||
*
|
*
|
||||||
* @param \OCP\Files\Node $path
|
* @param \OCP\Files\Node $path
|
||||||
|
* @param bool $recursive Should we check all parent folders as well
|
||||||
|
* @param bool $currentAccess Should the user have currently access to the file
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getAccessList(\OCP\Files\Node $path) {
|
public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
|
||||||
|
$owner = $path->getOwner()->getUID();
|
||||||
|
|
||||||
|
if ($currentAccess) {
|
||||||
|
$al = ['users' => [], 'remote' => [], 'public' => false];
|
||||||
|
} else {
|
||||||
|
$al = ['users' => [], 'remote' => false, 'public' => false];
|
||||||
|
}
|
||||||
|
if (!$this->userManager->userExists($owner)) {
|
||||||
|
return $al;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get node for the owner
|
||||||
|
$userFolder = $this->rootFolder->getUserFolder($owner);
|
||||||
|
if (!$userFolder->isSubNode($path)) {
|
||||||
|
$path = $userFolder->getById($path->getId())[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$providers = $this->factory->getAllProviders();
|
||||||
|
|
||||||
|
/** @var Node[] $nodes */
|
||||||
|
$nodes = [];
|
||||||
|
|
||||||
|
|
||||||
|
if ($currentAccess) {
|
||||||
|
$ownerPath = $path->getPath();
|
||||||
|
list(, , , $ownerPath) = explode('/', $ownerPath, 4);
|
||||||
|
$al['users'][$owner] = [
|
||||||
|
'node_id' => $path->getId(),
|
||||||
|
'node_path' => '/' . $ownerPath,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$al['users'][] = $owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all the shares
|
||||||
|
while ($path->getPath() !== $userFolder->getPath()) {
|
||||||
|
$nodes[] = $path;
|
||||||
|
if (!$recursive) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$path = $path->getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($providers as $provider) {
|
||||||
|
$tmp = $provider->getAccessList($nodes, $currentAccess);
|
||||||
|
|
||||||
|
foreach ($tmp as $k => $v) {
|
||||||
|
if (isset($al[$k])) {
|
||||||
|
if (is_array($al[$k])) {
|
||||||
|
$al[$k] = array_merge($al[$k], $v);
|
||||||
|
} else {
|
||||||
|
$al[$k] = $al[$k] || $v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$al[$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $al;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace OC\Share20;
|
||||||
|
|
||||||
|
use OCP\Files\InvalidPathException;
|
||||||
|
use OCP\Files\Node;
|
||||||
|
use OCP\Files\NotFoundException;
|
||||||
|
use OCP\Files\NotPermittedException;
|
||||||
|
use OCP\Share\IManager;
|
||||||
|
use OCP\Share\IShareHelper;
|
||||||
|
|
||||||
|
class ShareHelper implements IShareHelper {
|
||||||
|
|
||||||
|
/** @var IManager */
|
||||||
|
private $shareManager;
|
||||||
|
|
||||||
|
public function __construct(IManager $shareManager) {
|
||||||
|
$this->shareManager = $shareManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node $node
|
||||||
|
* @return array [ users => [Mapping $uid => $pathForUser], remotes => [Mapping $cloudId => $pathToMountRoot]]
|
||||||
|
*/
|
||||||
|
public function getPathsForAccessList(Node $node) {
|
||||||
|
$result = [
|
||||||
|
'users' => [],
|
||||||
|
'remotes' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$accessList = $this->shareManager->getAccessList($node, true, true);
|
||||||
|
if (!empty($accessList['users'])) {
|
||||||
|
$result['users'] = $this->getPathsForUsers($node, $accessList['users']);
|
||||||
|
}
|
||||||
|
if (!empty($accessList['remote'])) {
|
||||||
|
$result['remotes'] = $this->getPathsForRemotes($node, $accessList['remote']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sample:
|
||||||
|
* $users = [
|
||||||
|
* 'test1' => ['node_id' => 16, 'node_path' => '/foo'],
|
||||||
|
* 'test2' => ['node_id' => 23, 'node_path' => '/bar'],
|
||||||
|
* 'test3' => ['node_id' => 42, 'node_path' => '/cat'],
|
||||||
|
* 'test4' => ['node_id' => 48, 'node_path' => '/dog'],
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* Node tree:
|
||||||
|
* - SixTeen is the parent of TwentyThree
|
||||||
|
* - TwentyThree is the parent of FortyTwo
|
||||||
|
* - FortyEight does not exist
|
||||||
|
*
|
||||||
|
* $return = [
|
||||||
|
* 'test1' => '/foo/TwentyThree/FortyTwo',
|
||||||
|
* 'test2' => '/bar/FortyTwo',
|
||||||
|
* 'test3' => '/cat',
|
||||||
|
* ],
|
||||||
|
*
|
||||||
|
* @param Node $node
|
||||||
|
* @param array[] $users
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getPathsForUsers(Node $node, array $users) {
|
||||||
|
/** @var array[] $byId */
|
||||||
|
$byId = [];
|
||||||
|
/** @var array[] $results */
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($users as $uid => $info) {
|
||||||
|
if (!isset($byId[$info['node_id']])) {
|
||||||
|
$byId[$info['node_id']] = [];
|
||||||
|
}
|
||||||
|
$byId[$info['node_id']][$uid] = $info['node_path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isset($byId[$node->getId()])) {
|
||||||
|
foreach ($byId[$node->getId()] as $uid => $path) {
|
||||||
|
$results[$uid] = $path;
|
||||||
|
}
|
||||||
|
unset($byId[$node->getId()]);
|
||||||
|
}
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
return $results;
|
||||||
|
} catch (InvalidPathException $e) {
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($byId)) {
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = $node;
|
||||||
|
$appendix = '/' . $node->getName();
|
||||||
|
while (!empty($byId)) {
|
||||||
|
try {
|
||||||
|
/** @var Node $item */
|
||||||
|
$item = $item->getParent();
|
||||||
|
|
||||||
|
if (!empty($byId[$item->getId()])) {
|
||||||
|
foreach ($byId[$item->getId()] as $uid => $path) {
|
||||||
|
$results[$uid] = $path . $appendix;
|
||||||
|
}
|
||||||
|
unset($byId[$item->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$appendix = '/' . $item->getName() . $appendix;
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
return $results;
|
||||||
|
} catch (InvalidPathException $e) {
|
||||||
|
return $results;
|
||||||
|
} catch (NotPermittedException $e) {
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sample:
|
||||||
|
* $remotes = [
|
||||||
|
* 'test1' => ['node_id' => 16, 'token' => 't1'],
|
||||||
|
* 'test2' => ['node_id' => 23, 'token' => 't2'],
|
||||||
|
* 'test3' => ['node_id' => 42, 'token' => 't3'],
|
||||||
|
* 'test4' => ['node_id' => 48, 'token' => 't4'],
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* Node tree:
|
||||||
|
* - SixTeen is the parent of TwentyThree
|
||||||
|
* - TwentyThree is the parent of FortyTwo
|
||||||
|
* - FortyEight does not exist
|
||||||
|
*
|
||||||
|
* $return = [
|
||||||
|
* 'test1' => ['token' => 't1', 'node_path' => '/SixTeen'],
|
||||||
|
* 'test2' => ['token' => 't2', 'node_path' => '/SixTeen/TwentyThree'],
|
||||||
|
* 'test3' => ['token' => 't3', 'node_path' => '/SixTeen/TwentyThree/FortyTwo'],
|
||||||
|
* ],
|
||||||
|
*
|
||||||
|
* @param Node $node
|
||||||
|
* @param array[] $remotes
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getPathsForRemotes(Node $node, array $remotes) {
|
||||||
|
/** @var array[] $byId */
|
||||||
|
$byId = [];
|
||||||
|
/** @var array[] $results */
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($remotes as $cloudId => $info) {
|
||||||
|
if (!isset($byId[$info['node_id']])) {
|
||||||
|
$byId[$info['node_id']] = [];
|
||||||
|
}
|
||||||
|
$byId[$info['node_id']][$cloudId] = $info['token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = $node;
|
||||||
|
while (!empty($byId)) {
|
||||||
|
try {
|
||||||
|
if (!empty($byId[$item->getId()])) {
|
||||||
|
$path = $this->getMountedPath($item);
|
||||||
|
foreach ($byId[$item->getId()] as $uid => $token) {
|
||||||
|
$results[$uid] = [
|
||||||
|
'node_path' => $path,
|
||||||
|
'token' => $token,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
unset($byId[$item->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Node $item */
|
||||||
|
$item = $item->getParent();
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
return $results;
|
||||||
|
} catch (InvalidPathException $e) {
|
||||||
|
return $results;
|
||||||
|
} catch (NotPermittedException $e) {
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node $node
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getMountedPath(Node $node) {
|
||||||
|
$path = $node->getPath();
|
||||||
|
$sections = explode('/', $path, 4);
|
||||||
|
return '/' . $sections[3];
|
||||||
|
}
|
||||||
|
}
|
|
@ -191,6 +191,53 @@ interface IManager {
|
||||||
*/
|
*/
|
||||||
public function userDeletedFromGroup($uid, $gid);
|
public function userDeletedFromGroup($uid, $gid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get access list to a path. This means
|
||||||
|
* all the users that can access a given path.
|
||||||
|
*
|
||||||
|
* Consider:
|
||||||
|
* -root
|
||||||
|
* |-folder1 (23)
|
||||||
|
* |-folder2 (32)
|
||||||
|
* |-fileA (42)
|
||||||
|
*
|
||||||
|
* fileA is shared with user1 and user1@server1
|
||||||
|
* folder2 is shared with group2 (user4 is a member of group2)
|
||||||
|
* folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
|
||||||
|
*
|
||||||
|
* Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
|
||||||
|
* [
|
||||||
|
* users => [
|
||||||
|
* 'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
|
||||||
|
* 'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
|
||||||
|
* 'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
|
||||||
|
* ],
|
||||||
|
* remote => [
|
||||||
|
* 'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
|
||||||
|
* 'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
|
||||||
|
* ],
|
||||||
|
* public => bool
|
||||||
|
* mail => bool
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
|
||||||
|
* [
|
||||||
|
* users => ['user1', 'user2', 'user4'],
|
||||||
|
* remote => bool,
|
||||||
|
* public => bool
|
||||||
|
* mail => bool
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* This is required for encryption/activity
|
||||||
|
*
|
||||||
|
* @param \OCP\Files\Node $path
|
||||||
|
* @param bool $recursive Should we check all parent folders as well
|
||||||
|
* @param bool $currentAccess Should the user have currently access to the file
|
||||||
|
* @return array
|
||||||
|
* @since 12
|
||||||
|
*/
|
||||||
|
public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new share object. This is to be passed to
|
* Instantiates a new share object. This is to be passed to
|
||||||
* createShare.
|
* createShare.
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace OCP\Share;
|
||||||
|
|
||||||
|
use OCP\Files\Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface IShareHelper
|
||||||
|
*
|
||||||
|
* @package OCP\Share
|
||||||
|
* @since 12
|
||||||
|
*/
|
||||||
|
interface IShareHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node $node
|
||||||
|
* @return array [ users => [Mapping $uid => $pathForUser], remotes => [Mapping $cloudId => $pathToMountRoot]]
|
||||||
|
* @since 12
|
||||||
|
*/
|
||||||
|
public function getPathsForAccessList(Node $node);
|
||||||
|
}
|
|
@ -190,4 +190,16 @@ interface IShareProvider {
|
||||||
* @since 9.1.0
|
* @since 9.1.0
|
||||||
*/
|
*/
|
||||||
public function userDeletedFromGroup($uid, $gid);
|
public function userDeletedFromGroup($uid, $gid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the access list to the array of provided nodes.
|
||||||
|
*
|
||||||
|
* @see IManager::getAccessList() for sample docs
|
||||||
|
*
|
||||||
|
* @param Node[] $nodes The list of nodes to get access for
|
||||||
|
* @param bool $currentAccess If current access is required (like for removed shares that might get revived later)
|
||||||
|
* @return array
|
||||||
|
* @since 12
|
||||||
|
*/
|
||||||
|
public function getAccessList($nodes, $currentAccess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1545,9 +1545,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
$this->assertEquals(1, $stmt);
|
$this->assertEquals(1, $stmt);
|
||||||
$id = $qb->getLastInsertId();
|
$id = $qb->getLastInsertId();
|
||||||
|
|
||||||
$user1 = $this->getMock('\OCP\IUser');
|
$user1 = $this->createMock(IUser::class);
|
||||||
$user1->method('getUID')->willReturn('user1');
|
$user1->method('getUID')->willReturn('user1');
|
||||||
$user2 = $this->getMock('\OCP\IUser');
|
$user2 = $this->createMock(IUser::class);
|
||||||
$user2->method('getUID')->willReturn('user2');
|
$user2->method('getUID')->willReturn('user2');
|
||||||
$this->userManager->method('get')->will($this->returnValueMap([
|
$this->userManager->method('get')->will($this->returnValueMap([
|
||||||
['user1', $user1],
|
['user1', $user1],
|
||||||
|
@ -1556,7 +1556,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->groupManager->method('get')->with('group')->willReturn(null);
|
$this->groupManager->method('get')->with('group')->willReturn(null);
|
||||||
|
|
||||||
$file = $this->getMock('\OCP\Files\File');
|
$file = $this->createMock(File::class);
|
||||||
$file->method('getId')->willReturn(1);
|
$file->method('getId')->willReturn(1);
|
||||||
|
|
||||||
$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
|
$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
|
||||||
|
@ -2434,4 +2434,185 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
$u3->delete();
|
$u3->delete();
|
||||||
$g1->delete();
|
$g1->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAccessListNoCurrentAccessRequired() {
|
||||||
|
$userManager = \OC::$server->getUserManager();
|
||||||
|
$groupManager = \OC::$server->getGroupManager();
|
||||||
|
$rootFolder = \OC::$server->getRootFolder();
|
||||||
|
|
||||||
|
$provider = new DefaultShareProvider(
|
||||||
|
$this->dbConn,
|
||||||
|
$userManager,
|
||||||
|
$groupManager,
|
||||||
|
$rootFolder
|
||||||
|
);
|
||||||
|
|
||||||
|
$u1 = $userManager->createUser('testShare1', 'test');
|
||||||
|
$u2 = $userManager->createUser('testShare2', 'test');
|
||||||
|
$u3 = $userManager->createUser('testShare3', 'test');
|
||||||
|
$u4 = $userManager->createUser('testShare4', 'test');
|
||||||
|
$u5 = $userManager->createUser('testShare5', 'test');
|
||||||
|
|
||||||
|
$g1 = $groupManager->createGroup('group1');
|
||||||
|
$g1->addUser($u3);
|
||||||
|
$g1->addUser($u4);
|
||||||
|
|
||||||
|
$u1Folder = $rootFolder->getUserFolder($u1->getUID());
|
||||||
|
$folder1 = $u1Folder->newFolder('foo');
|
||||||
|
$folder2 = $folder1->newFolder('baz');
|
||||||
|
$file1 = $folder2->newFile('bar');
|
||||||
|
|
||||||
|
$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
|
||||||
|
$this->assertCount(0, $result['users']);
|
||||||
|
$this->assertFalse($result['public']);
|
||||||
|
|
||||||
|
$shareManager = \OC::$server->getShareManager();
|
||||||
|
$share1 = $shareManager->newShare();
|
||||||
|
$share1->setNode($folder1)
|
||||||
|
->setSharedBy($u1->getUID())
|
||||||
|
->setSharedWith($u2->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_USER)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
||||||
|
$share1 = $this->provider->create($share1);
|
||||||
|
|
||||||
|
$share2 = $shareManager->newShare();
|
||||||
|
$share2->setNode($folder2)
|
||||||
|
->setSharedBy($u2->getUID())
|
||||||
|
->setSharedWith($g1->getGID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
||||||
|
$share2 = $this->provider->create($share2);
|
||||||
|
|
||||||
|
$shareManager->deleteFromSelf($share2, $u4->getUID());
|
||||||
|
|
||||||
|
$share3 = $shareManager->newShare();
|
||||||
|
$share3->setNode($file1)
|
||||||
|
->setSharedBy($u3->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ);
|
||||||
|
$share3 = $this->provider->create($share3);
|
||||||
|
|
||||||
|
$share4 = $shareManager->newShare();
|
||||||
|
$share4->setNode($file1)
|
||||||
|
->setSharedBy($u3->getUID())
|
||||||
|
->setSharedWith($u5->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_USER)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ);
|
||||||
|
$share4 = $this->provider->create($share4);
|
||||||
|
|
||||||
|
$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
|
||||||
|
|
||||||
|
$this->assertCount(4, $result['users']);
|
||||||
|
$this->assertContains('testShare2', $result['users']);
|
||||||
|
$this->assertContains('testShare3', $result['users']);
|
||||||
|
$this->assertContains('testShare4', $result['users']);
|
||||||
|
$this->assertContains('testShare5', $result['users']);
|
||||||
|
$this->assertTrue($result['public']);
|
||||||
|
|
||||||
|
$provider->delete($share1);
|
||||||
|
$provider->delete($share2);
|
||||||
|
$provider->delete($share3);
|
||||||
|
$provider->delete($share4);
|
||||||
|
|
||||||
|
$u1->delete();
|
||||||
|
$u2->delete();
|
||||||
|
$u3->delete();
|
||||||
|
$u4->delete();
|
||||||
|
$u5->delete();
|
||||||
|
$g1->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAccessListCurrentAccessRequired() {
|
||||||
|
$userManager = \OC::$server->getUserManager();
|
||||||
|
$groupManager = \OC::$server->getGroupManager();
|
||||||
|
$rootFolder = \OC::$server->getRootFolder();
|
||||||
|
|
||||||
|
$provider = new DefaultShareProvider(
|
||||||
|
$this->dbConn,
|
||||||
|
$userManager,
|
||||||
|
$groupManager,
|
||||||
|
$rootFolder
|
||||||
|
);
|
||||||
|
|
||||||
|
$u1 = $userManager->createUser('testShare1', 'test');
|
||||||
|
$u2 = $userManager->createUser('testShare2', 'test');
|
||||||
|
$u3 = $userManager->createUser('testShare3', 'test');
|
||||||
|
$u4 = $userManager->createUser('testShare4', 'test');
|
||||||
|
$u5 = $userManager->createUser('testShare5', 'test');
|
||||||
|
|
||||||
|
$g1 = $groupManager->createGroup('group1');
|
||||||
|
$g1->addUser($u3);
|
||||||
|
$g1->addUser($u4);
|
||||||
|
|
||||||
|
$u1Folder = $rootFolder->getUserFolder($u1->getUID());
|
||||||
|
$folder1 = $u1Folder->newFolder('foo');
|
||||||
|
$folder2 = $folder1->newFolder('baz');
|
||||||
|
$file1 = $folder2->newFile('bar');
|
||||||
|
|
||||||
|
$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
|
||||||
|
$this->assertCount(0, $result['users']);
|
||||||
|
$this->assertFalse($result['public']);
|
||||||
|
|
||||||
|
$shareManager = \OC::$server->getShareManager();
|
||||||
|
$share1 = $shareManager->newShare();
|
||||||
|
$share1->setNode($folder1)
|
||||||
|
->setSharedBy($u1->getUID())
|
||||||
|
->setSharedWith($u2->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_USER)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
||||||
|
$share1 = $this->provider->create($share1);
|
||||||
|
|
||||||
|
$share2 = $shareManager->newShare();
|
||||||
|
$share2->setNode($folder2)
|
||||||
|
->setSharedBy($u2->getUID())
|
||||||
|
->setSharedWith($g1->getGID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
||||||
|
$share2 = $this->provider->create($share2);
|
||||||
|
|
||||||
|
$shareManager->deleteFromSelf($share2, $u4->getUID());
|
||||||
|
|
||||||
|
$share3 = $shareManager->newShare();
|
||||||
|
$share3->setNode($file1)
|
||||||
|
->setSharedBy($u3->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ);
|
||||||
|
$share3 = $this->provider->create($share3);
|
||||||
|
|
||||||
|
$share4 = $shareManager->newShare();
|
||||||
|
$share4->setNode($file1)
|
||||||
|
->setSharedBy($u3->getUID())
|
||||||
|
->setSharedWith($u5->getUID())
|
||||||
|
->setShareOwner($u1->getUID())
|
||||||
|
->setShareType(\OCP\Share::SHARE_TYPE_USER)
|
||||||
|
->setPermissions(\OCP\Constants::PERMISSION_READ);
|
||||||
|
$share4 = $this->provider->create($share4);
|
||||||
|
|
||||||
|
$result = $provider->getAccessList([$folder1, $folder2, $file1], true);
|
||||||
|
|
||||||
|
$this->assertCount(3, $result['users']);
|
||||||
|
$this->assertArrayHasKey('testShare2', $result['users']);
|
||||||
|
$this->assertArrayHasKey('testShare3', $result['users']);
|
||||||
|
$this->assertArrayHasKey('testShare5', $result['users']);
|
||||||
|
$this->assertTrue($result['public']);
|
||||||
|
|
||||||
|
$provider->delete($share1);
|
||||||
|
$provider->delete($share2);
|
||||||
|
$provider->delete($share3);
|
||||||
|
$provider->delete($share4);
|
||||||
|
|
||||||
|
$u1->delete();
|
||||||
|
$u2->delete();
|
||||||
|
$u3->delete();
|
||||||
|
$u4->delete();
|
||||||
|
$u5->delete();
|
||||||
|
$g1->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1022,12 +1022,12 @@ class ManagerTest extends \Test\TestCase {
|
||||||
public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup() {
|
public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup() {
|
||||||
$share = $this->manager->newShare();
|
$share = $this->manager->newShare();
|
||||||
|
|
||||||
$sharedWith = $this->getMock('\OCP\IUser');
|
$sharedWith = $this->createMock(IUser::class);
|
||||||
$sharedWith->method('getUID')->willReturn('sharedWith');
|
$sharedWith->method('getUID')->willReturn('sharedWith');
|
||||||
|
|
||||||
$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
|
$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
|
||||||
|
|
||||||
$path = $this->getMock('\OCP\Files\Node');
|
$path = $this->createMock(Node::class);
|
||||||
|
|
||||||
$share->setSharedWith('sharedWith')
|
$share->setSharedWith('sharedWith')
|
||||||
->setNode($path)
|
->setNode($path)
|
||||||
|
@ -1136,7 +1136,7 @@ class ManagerTest extends \Test\TestCase {
|
||||||
public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() {
|
public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() {
|
||||||
$share = $this->manager->newShare();
|
$share = $this->manager->newShare();
|
||||||
|
|
||||||
$user = $this->getMock('\OCP\IUser');
|
$user = $this->createMock(IUser::class);
|
||||||
$share->setSharedBy('user')->setSharedWith('group');
|
$share->setSharedBy('user')->setSharedWith('group');
|
||||||
|
|
||||||
$this->groupManager->method('get')->with('group')->willReturn(null);
|
$this->groupManager->method('get')->with('group')->willReturn(null);
|
||||||
|
@ -2611,7 +2611,7 @@ class ManagerTest extends \Test\TestCase {
|
||||||
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
|
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
|
||||||
$share->setSharedWith('shareWith');
|
$share->setSharedWith('shareWith');
|
||||||
|
|
||||||
$recipient = $this->getMock('\OCP\IUser');
|
$recipient = $this->createMock(IUser::class);
|
||||||
|
|
||||||
$this->groupManager->method('get')->with('shareWith')->willReturn(null);
|
$this->groupManager->method('get')->with('shareWith')->willReturn(null);
|
||||||
$this->userManager->method('get')->with('recipient')->willReturn($recipient);
|
$this->userManager->method('get')->with('recipient')->willReturn($recipient);
|
||||||
|
@ -2639,7 +2639,6 @@ class ManagerTest extends \Test\TestCase {
|
||||||
$this->manager->moveShare($share, 'recipient');
|
$this->manager->moveShare($share, 'recipient');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider dataTestShareProviderExists
|
* @dataProvider dataTestShareProviderExists
|
||||||
*/
|
*/
|
||||||
|
@ -2737,6 +2736,119 @@ class ManagerTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->assertSame($expects, $result);
|
$this->assertSame($expects, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAccessList() {
|
||||||
|
$factory = new DummyFactory2($this->createMock(IServerContainer::class));
|
||||||
|
|
||||||
|
$manager = new Manager(
|
||||||
|
$this->logger,
|
||||||
|
$this->config,
|
||||||
|
$this->secureRandom,
|
||||||
|
$this->hasher,
|
||||||
|
$this->mountManager,
|
||||||
|
$this->groupManager,
|
||||||
|
$this->l,
|
||||||
|
$factory,
|
||||||
|
$this->userManager,
|
||||||
|
$this->rootFolder,
|
||||||
|
$this->eventDispatcher
|
||||||
|
);
|
||||||
|
|
||||||
|
$factory->setProvider($this->defaultProvider);
|
||||||
|
$extraProvider = $this->createMock(IShareProvider::class);
|
||||||
|
$factory->setSecondProvider($extraProvider);
|
||||||
|
|
||||||
|
$owner = $this->createMock(IUser::class);
|
||||||
|
$owner->expects($this->once())
|
||||||
|
->method('getUID')
|
||||||
|
->willReturn('owner');
|
||||||
|
|
||||||
|
$node = $this->createMock(Node::class);
|
||||||
|
$node->expects($this->once())
|
||||||
|
->method('getOwner')
|
||||||
|
->willReturn($owner);
|
||||||
|
$node->expects($this->once())
|
||||||
|
->method('getId')
|
||||||
|
->willReturn(42);
|
||||||
|
|
||||||
|
$userFolder = $this->createMock(Folder::class);
|
||||||
|
$file = $this->createMock(File::class);
|
||||||
|
$folder = $this->createMock(Folder::class);
|
||||||
|
|
||||||
|
$file->method('getParent')
|
||||||
|
->willReturn($folder);
|
||||||
|
$file->method('getPath')
|
||||||
|
->willReturn('/owner/files/folder/file');
|
||||||
|
$file->method('getId')
|
||||||
|
->willReturn(23);
|
||||||
|
$folder->method('getParent')
|
||||||
|
->willReturn($userFolder);
|
||||||
|
$folder->method('getPath')
|
||||||
|
->willReturn('/owner/files/folder');
|
||||||
|
$userFolder->method('getById')
|
||||||
|
->with($this->equalTo(42))
|
||||||
|
->willReturn([$file]);
|
||||||
|
$userFolder->method('getPath')
|
||||||
|
->willReturn('/owner/files');
|
||||||
|
|
||||||
|
$this->userManager->method('userExists')
|
||||||
|
->with($this->equalTo('owner'))
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$this->defaultProvider->method('getAccessList')
|
||||||
|
->with(
|
||||||
|
$this->equalTo([$file, $folder]),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
->willReturn([
|
||||||
|
'users' => [
|
||||||
|
'user1' => [],
|
||||||
|
'user2' => [],
|
||||||
|
'user3' => [],
|
||||||
|
],
|
||||||
|
'public' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$extraProvider->method('getAccessList')
|
||||||
|
->with(
|
||||||
|
$this->equalTo([$file, $folder]),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
->willReturn([
|
||||||
|
'users' => [
|
||||||
|
'user3' => [],
|
||||||
|
'user4' => [],
|
||||||
|
'user5' => [],
|
||||||
|
],
|
||||||
|
'remote' => [
|
||||||
|
'remote1',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->rootFolder->method('getUserFolder')
|
||||||
|
->with($this->equalTo('owner'))
|
||||||
|
->willReturn($userFolder);
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
'users' => [
|
||||||
|
'owner' => [
|
||||||
|
'node_id' => 23,
|
||||||
|
'node_path' => '/folder/file'
|
||||||
|
]
|
||||||
|
, 'user1' => [], 'user2' => [], 'user3' => [], 'user4' => [], 'user5' => []],
|
||||||
|
'remote' => [
|
||||||
|
'remote1',
|
||||||
|
],
|
||||||
|
'public' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $manager->getAccessList($node, true, true);
|
||||||
|
|
||||||
|
$this->assertSame($expected['public'], $result['public']);
|
||||||
|
$this->assertSame($expected['remote'], $result['remote']);
|
||||||
|
$this->assertSame(array_values($expected['users']), array_values($result['users']));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyFactory implements IProviderFactory {
|
class DummyFactory implements IProviderFactory {
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace Test\Share20;
|
||||||
|
|
||||||
|
use OC\Share20\ShareHelper;
|
||||||
|
use OCP\Files\Node;
|
||||||
|
use OCP\Files\NotFoundException;
|
||||||
|
use OCP\Share\IManager;
|
||||||
|
use Test\TestCase;
|
||||||
|
|
||||||
|
class ShareHelperTest extends TestCase {
|
||||||
|
|
||||||
|
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $manager;
|
||||||
|
|
||||||
|
/** @var ShareHelper */
|
||||||
|
private $helper;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->manager = $this->createMock(IManager::class);
|
||||||
|
|
||||||
|
$this->helper = new ShareHelper($this->manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataGetPathsForAccessList() {
|
||||||
|
return [
|
||||||
|
[[], [], false, [], [], false, [
|
||||||
|
'users' => [],
|
||||||
|
'remotes' => [],
|
||||||
|
]],
|
||||||
|
[['user1', 'user2'], ['user1' => 'foo', 'user2' => 'bar'], true, [], [], false, [
|
||||||
|
'users' => ['user1' => 'foo', 'user2' => 'bar'],
|
||||||
|
'remotes' => [],
|
||||||
|
]],
|
||||||
|
[[], [], false, ['remote1', 'remote2'], ['remote1' => 'qwe', 'remote2' => 'rtz'], true, [
|
||||||
|
'users' => [],
|
||||||
|
'remotes' => ['remote1' => 'qwe', 'remote2' => 'rtz'],
|
||||||
|
]],
|
||||||
|
[['user1', 'user2'], ['user1' => 'foo', 'user2' => 'bar'], true, ['remote1', 'remote2'], ['remote1' => 'qwe', 'remote2' => 'rtz'], true, [
|
||||||
|
'users' => ['user1' => 'foo', 'user2' => 'bar'],
|
||||||
|
'remotes' => ['remote1' => 'qwe', 'remote2' => 'rtz'],
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataGetPathsForAccessList
|
||||||
|
*/
|
||||||
|
public function testGetPathsForAccessList(array $userList, array $userMap, $resolveUsers, array $remoteList, array $remoteMap, $resolveRemotes, array $expected) {
|
||||||
|
$this->manager->expects($this->once())
|
||||||
|
->method('getAccessList')
|
||||||
|
->willReturn([
|
||||||
|
'users' => $userList,
|
||||||
|
'remote' => $remoteList,
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var Node|\PHPUnit_Framework_MockObject_MockObject $node */
|
||||||
|
$node = $this->createMock(Node::class);
|
||||||
|
/** @var ShareHelper|\PHPUnit_Framework_MockObject_MockObject $helper */
|
||||||
|
$helper = $this->getMockBuilder(ShareHelper::class)
|
||||||
|
->setConstructorArgs([$this->manager])
|
||||||
|
->setMethods(['getPathsForUsers', 'getPathsForRemotes'])
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$helper->expects($resolveUsers ? $this->once() : $this->never())
|
||||||
|
->method('getPathsForUsers')
|
||||||
|
->with($node, $userList)
|
||||||
|
->willReturn($userMap);
|
||||||
|
|
||||||
|
$helper->expects($resolveRemotes ? $this->once() : $this->never())
|
||||||
|
->method('getPathsForRemotes')
|
||||||
|
->with($node, $remoteList)
|
||||||
|
->willReturn($remoteMap);
|
||||||
|
|
||||||
|
$this->assertSame($expected, $helper->getPathsForAccessList($node));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataGetPathsForUsers() {
|
||||||
|
return [
|
||||||
|
[[], [23 => 'TwentyThree', 42 => 'FortyTwo'], []],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'test1' => ['node_id' => 16, 'node_path' => '/foo'],
|
||||||
|
'test2' => ['node_id' => 23, 'node_path' => '/bar'],
|
||||||
|
'test3' => ['node_id' => 42, 'node_path' => '/cat'],
|
||||||
|
'test4' => ['node_id' => 48, 'node_path' => '/dog'],
|
||||||
|
],
|
||||||
|
[16 => 'SixTeen', 23 => 'TwentyThree', 42 => 'FortyTwo'],
|
||||||
|
[
|
||||||
|
'test1' => '/foo/TwentyThree/FortyTwo',
|
||||||
|
'test2' => '/bar/FortyTwo',
|
||||||
|
'test3' => '/cat',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataGetPathsForUsers
|
||||||
|
*
|
||||||
|
* @param array $users
|
||||||
|
* @param array $nodes
|
||||||
|
* @param array $expected
|
||||||
|
*/
|
||||||
|
public function testGetPathsForUsers(array $users, array $nodes, array $expected) {
|
||||||
|
$lastNode = null;
|
||||||
|
foreach ($nodes as $nodeId => $nodeName) {
|
||||||
|
/** @var Node|\PHPUnit_Framework_MockObject_MockObject $node */
|
||||||
|
$node = $this->createMock(Node::class);
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getId')
|
||||||
|
->willReturn($nodeId);
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getName')
|
||||||
|
->willReturn($nodeName);
|
||||||
|
if ($lastNode === null) {
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getParent')
|
||||||
|
->willThrowException(new NotFoundException());
|
||||||
|
} else {
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getParent')
|
||||||
|
->willReturn($lastNode);
|
||||||
|
}
|
||||||
|
$lastNode = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals($expected, self::invokePrivate($this->helper, 'getPathsForUsers', [$lastNode, $users]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataGetPathsForRemotes() {
|
||||||
|
return [
|
||||||
|
[[], [23 => 'TwentyThree', 42 => 'FortyTwo'], []],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'test1' => ['node_id' => 16, 'token' => 't1'],
|
||||||
|
'test2' => ['node_id' => 23, 'token' => 't2'],
|
||||||
|
'test3' => ['node_id' => 42, 'token' => 't3'],
|
||||||
|
'test4' => ['node_id' => 48, 'token' => 't4'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16 => '/admin/files/SixTeen',
|
||||||
|
23 => '/admin/files/SixTeen/TwentyThree',
|
||||||
|
42 => '/admin/files/SixTeen/TwentyThree/FortyTwo',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'test1' => ['token' => 't1', 'node_path' => '/SixTeen'],
|
||||||
|
'test2' => ['token' => 't2', 'node_path' => '/SixTeen/TwentyThree'],
|
||||||
|
'test3' => ['token' => 't3', 'node_path' => '/SixTeen/TwentyThree/FortyTwo'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataGetPathsForRemotes
|
||||||
|
*
|
||||||
|
* @param array $remotes
|
||||||
|
* @param array $nodes
|
||||||
|
* @param array $expected
|
||||||
|
*/
|
||||||
|
public function testGetPathsForRemotes(array $remotes, array $nodes, array $expected) {
|
||||||
|
$lastNode = null;
|
||||||
|
foreach ($nodes as $nodeId => $nodePath) {
|
||||||
|
/** @var Node|\PHPUnit_Framework_MockObject_MockObject $node */
|
||||||
|
$node = $this->createMock(Node::class);
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getId')
|
||||||
|
->willReturn($nodeId);
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getPath')
|
||||||
|
->willReturn($nodePath);
|
||||||
|
if ($lastNode === null) {
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getParent')
|
||||||
|
->willThrowException(new NotFoundException());
|
||||||
|
} else {
|
||||||
|
$node->expects($this->any())
|
||||||
|
->method('getParent')
|
||||||
|
->willReturn($lastNode);
|
||||||
|
}
|
||||||
|
$lastNode = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals($expected, self::invokePrivate($this->helper, 'getPathsForRemotes', [$lastNode, $remotes]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataGetMountedPath() {
|
||||||
|
return [
|
||||||
|
['/admin/files/foobar', '/foobar'],
|
||||||
|
['/admin/files/foo/bar', '/foo/bar'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataGetMountedPath
|
||||||
|
* @param string $path
|
||||||
|
* @param string $expected
|
||||||
|
*/
|
||||||
|
public function testGetMountedPath($path, $expected) {
|
||||||
|
/** @var Node|\PHPUnit_Framework_MockObject_MockObject $node */
|
||||||
|
$node = $this->createMock(Node::class);
|
||||||
|
$node->expects($this->once())
|
||||||
|
->method('getPath')
|
||||||
|
->willReturn($path);
|
||||||
|
|
||||||
|
$this->assertSame($expected, self::invokePrivate($this->helper, 'getMountedPath', [$node]));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue