The new sharing code now handles deletion

OCS -> ShareManager -> DefaultShareProvider
This commit is contained in:
Roeland Jago Douma 2015-10-30 13:10:08 +01:00
parent 8b5179459a
commit 6624fa212a
12 changed files with 1471 additions and 108 deletions

View file

@ -22,8 +22,11 @@ namespace OCA\Files_Sharing\API;
class OCSShareWrapper { class OCSShareWrapper {
/**
* @return Share20OCS
*/
private function getShare20OCS() { private function getShare20OCS() {
return new share20OCS(new \OC\Share20\Manager( return new Share20OCS(new \OC\Share20\Manager(
\OC::$server->getUserSession()->getUser(), \OC::$server->getUserSession()->getUser(),
\OC::$server->getUserManager(), \OC::$server->getUserManager(),
\OC::$server->getGroupManager(), \OC::$server->getGroupManager(),
@ -31,7 +34,10 @@ class OCSShareWrapper {
\OC::$server->getAppConfig(), \OC::$server->getAppConfig(),
\OC::$server->getUserFolder(), \OC::$server->getUserFolder(),
new \OC\Share20\DefaultShareProvider( new \OC\Share20\DefaultShareProvider(
\OC::$server->getDatabaseConnection() \OC::$server->getDatabaseConnection(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getUserFolder()
) )
), ),
\OC::$server->getGroupManager(), \OC::$server->getGroupManager(),
@ -57,6 +63,7 @@ class OCSShareWrapper {
} }
public function deleteShare($params) { public function deleteShare($params) {
return \OCA\Files_Sharing\API\Local::deleteShare($params); $id = (int)$params['id'];
return $this->getShare20OCS()->deleteShare($id);
} }
} }

View file

@ -0,0 +1,73 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files_Sharing\API;
class Share20OCS {
/** @var OC\Share20\Manager */
private $shareManager;
/** @var OCP\IGroupManager */
private $groupManager;
/** @var OCP\IUserManager */
private $userManager;
/** @var OCP\IRequest */
private $request;
/** @var OCP\Files\Folder */
private $userFolder;
public function __construct(\OC\Share20\Manager $shareManager,
\OCP\IGroupManager $groupManager,
\OCP\IUserManager $userManager,
\OCP\IRequest $request,
\OCP\Files\Folder $userFolder) {
$this->shareManager = $shareManager;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->request = $request;
$this->userFolder = $userFolder;
}
/**
* Delete a share
*
* @param int $id
* @return \OC_OCS_Result
*/
public function deleteShare($id) {
try {
$share = $this->shareManager->getShareById($id);
} catch (\OC\Share20\Exception\ShareNotFound $e) {
return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
}
try {
$this->shareManager->deleteShare($share);
} catch (\OC\Share20\Exception\BackendError $e) {
return new \OC_OCS_Result(null, 404, 'could not delete share');
}
return new \OC_OCS_Result();
}
}

View file

@ -0,0 +1,113 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files_Sharing\Tests\API;
use OCA\Files_Sharing\API\Share20OCS;
class Share20OCSTest extends \Test\TestCase {
/** @var OC\Share20\Manager */
private $shareManager;
/** @var OCP\IGroupManager */
private $groupManager;
/** @var OCP\IUserManager */
private $userManager;
/** @var OCP\IRequest */
private $request;
/** @var OCP\Files\Folder */
private $userFolder;
/** @var OCS */
private $ocs;
protected function setUp() {
$this->shareManager = $this->getMockBuilder('OC\Share20\Manager')
->disableOriginalConstructor()
->getMock();
$this->groupManager = $this->getMockBuilder('OCP\IGroupManager')
->disableOriginalConstructor()
->getMock();
$this->userManager = $this->getMockBuilder('OCP\IUserManager')
->disableOriginalConstructor()
->getMock();
$this->request = $this->getMockBuilder('OCP\IRequest')
->disableOriginalConstructor()
->getMock();
$this->userFolder = $this->getMockBuilder('OCP\Files\Folder')
->disableOriginalConstructor()
->getMock();
$this->ocs = new Share20OCS($this->shareManager,
$this->groupManager,
$this->userManager,
$this->request,
$this->userFolder);
}
public function testDeleteShareShareNotFound() {
$this->shareManager
->expects($this->once())
->method('getShareById')
->with(42)
->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
$expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
public function testDeleteShareCouldNotDelete() {
$share = $this->getMock('OC\Share20\IShare');
$this->shareManager
->expects($this->once())
->method('getShareById')
->with(42)
->willReturn($share);
$this->shareManager
->expects($this->once())
->method('deleteShare')
->with($share)
->will($this->throwException(new \OC\Share20\Exception\BackendError()));
$expected = new \OC_OCS_Result(null, 404, 'could not delete share');
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
public function testDeleteShare() {
$share = $this->getMock('OC\Share20\IShare');
$this->shareManager
->expects($this->once())
->method('getShareById')
->with(42)
->willReturn($share);
$this->shareManager
->expects($this->once())
->method('deleteShare')
->with($share);
$expected = new \OC_OCS_Result();
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
}

View file

@ -0,0 +1,248 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Share20;
use OC\Share20\Exception\ShareNotFound;
use OC\Share20\Exception\BackendError;
use OCP\IUser;
class DefaultShareProvider implements IShareProvider {
/** @var \OCP\IDBConnection */
private $dbConn;
/** @var \OCP\IUserManager */
private $userManager;
/** @var \OCP\IGroupManager */
private $groupManager;
/** @var \OCP\Files\Folder */
private $userFolder;
public function __construct(\OCP\IDBConnection $connection,
\OCP\IUserManager $userManager,
\OCP\IGroupManager $groupManager,
\OCP\Files\Folder $userFolder) {
$this->dbConn = $connection;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->userFolder = $userFolder;
}
/**
* Share a path
*
* @param Share $share
* @return Share The share object
*/
public function create(Share $share) {
throw new \Exception();
}
/**
* Update a share
*
* @param Share $share
* @return Share The share object
*/
public function update(Share $share) {
throw new \Exception();
}
/**
* Get all childre of this share
*
* @param IShare $share
* @return IShare[]
*/
private function getChildren(IShare $share) {
$children = [];
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createParameter('parent')))
->setParameter(':parent', $share->getId());
$cursor = $qb->execute();
while($data = $cursor->fetch()) {
$children[] = $this->createShare($data);
}
$cursor->closeCursor();
return $children;
}
/**
* Delete all the children of this share
*
* @param IShare $share
*/
protected function deleteChildren(IShare $share) {
foreach($this->getChildren($share) as $child) {
$this->delete($child);
}
}
/**
* Delete a share
*
* @param Share $share
* @throws BackendError
*/
public function delete(IShare $share) {
$this->deleteChildren($share);
$qb = $this->dbConn->getQueryBuilder();
$qb->delete('share')
->where($qb->expr()->eq('id', $qb->createParameter('id')))
->setParameter(':id', $share->getId());
try {
$qb->execute();
} catch (\Exception $e) {
throw new BackendError();
}
}
/**
* Get all shares by the given user
*
* @param IUser $user
* @param int $shareType
* @param int $offset
* @param int $limit
* @return Share[]
*/
public function getShares(IUser $user, $shareType, $offset, $limit) {
throw new \Exception();
}
/**
* Get share by id
*
* @param int $id
* @return IShare
* @throws ShareNotFound
*/
public function getShareById($id) {
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createParameter('id')))
->setParameter(':id', $id);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ShareNotFound();
}
$share = $this->createShare($data);
return $share;
}
/**
* Get shares for a given path
*
* @param \OCP\Files\Node $path
* @param Share[]
*/
public function getSharesByPath(\OCP\IUser $user, \OCP\Files\Node $path) {
throw new \Exception();
}
/**
* Get shared with the given user
*
* @param IUser $user
* @param int $shareType
* @param Share
*/
public function getSharedWithMe(IUser $user, $shareType = null) {
throw new \Exception();
}
/**
* Get a share by token and if present verify the password
*
* @param string $token
* @param string $password
* @param Share
*/
public function getShareByToken($token, $password = null) {
throw new \Exception();
}
/**
* Create a share object from an database row
*
* @param mixed[] $data
* @return Share
*/
private function createShare($data) {
$share = new Share();
$share->setId((int)$data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions']);
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
$share->setSharedWith($this->userManager->get($data['share_with']));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$share->setSharedWith($this->groupManager->get($data['share_with']));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
/*
* TODO: Clean this up, this should be set as password not sharedWith
*/
$share->setSharedWith($data['share_with']);
$share->setToken($data['token']);
} else {
$share->setSharedWith($data['share_with']);
}
$share->setSharedBy($this->userManager->get($data['uid_owner']));
// TODO: getById can return an array. How to handle this properly??
$path = $this->userFolder->getById($data['file_source']);
$path = $path[0];
$share->setPath($path);
$owner = $path->getStorage()->getOwner('.');
if ($owner !== false) {
$share->setShareOwner($this->userManager->get($owner));
}
if ($data['expiration'] !== null) {
$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
$share->setExpirationDate($expiration);
}
return $share;
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Share20\Exception;
class BackendError extends \Exception {
}

View file

@ -0,0 +1,25 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Share20\Exception;
class ShareNotFound extends \Exception {
}

View file

@ -0,0 +1,149 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Share20;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\IUser;
use OCP\IGroup;
interface IShare {
/**
* Get the id of the share
*
* @return string
*/
public function getId();
/**
* Set the path of this share
*
* @param File|Folder $path
* @return Share The modified object
*/
public function setPath(Node $path);
/**
* Get the path of this share for the current user
*
* @return File|Folder
*/
public function getPath();
/**
* Set the shareType
*
* @param int $shareType
* @return Share The modified object
*/
public function setShareType($shareType);
/**
* Get the shareType
*
* @return int
*/
public function getShareType();
/**
* Set the receiver of this share
*
* @param IUser|IGroup|string
* @return Share The modified object
*/
public function setSharedWith($sharedWith);
/**
* Get the receiver of this share
*
* @return IUser|IGroup|string
*/
public function getSharedWith();
/**
* Set the permissions
*
* @param int $permissions
* @return Share The modified object
*/
public function setPermissions($permissions);
/**
* Get the share permissions
*
* @return int
*/
public function getPermissions();
/**
* Set the expiration date
*
* @param \DateTime $expireDate
* @return Share The modified object
*/
public function setExpirationDate(\DateTime $expireDate);
/**
* Get the share expiration date
*
* @return \DateTime
*/
public function getExpirationDate();
/**
* Get share sharer
*
* @return IUser|string
*/
public function getSharedBy();
/**
* Get the original share owner (who owns the path)
*
* @return IUser|string
*/
public function getShareOwner();
/**
* Set the password
*
* @param string $password
*
* @return Share The modified object
*/
public function setPassword($password);
/**
* Get the token
*
* @return string
*/
public function getToken();
/**
* Get the parent it
*
* @return int
*/
public function getParent();
}

View file

@ -20,6 +20,8 @@
*/ */
namespace OC\Share20; namespace OC\Share20;
use OC\Share20\Exception\ShareNotFound;
use OC\Share20\Exception\BackendError;
use OCP\IUser; use OCP\IUser;
interface IShareProvider { interface IShareProvider {
@ -44,8 +46,9 @@ interface IShareProvider {
* Delete a share * Delete a share
* *
* @param Share $share * @param Share $share
* @throws BackendError
*/ */
public function delete(Share $share); public function delete(IShare $share);
/** /**
* Get all shares by the given user * Get all shares by the given user
@ -62,7 +65,8 @@ interface IShareProvider {
* Get share by id * Get share by id
* *
* @param int $id * @param int $id
* @return Share * @return IShare
* @throws ShareNotFound
*/ */
public function getShareById($id); public function getShareById($id);

View file

@ -28,8 +28,7 @@ use OCP\IUser;
use OCP\ILogger; use OCP\ILogger;
use OCP\Files\Folder; use OCP\Files\Folder;
use OC\Share20\Exceptions\ShareNotFoundException; use OC\Share20\Exception\ShareNotFound;
use OC\Share20\Exception\PreconditionFailed;
/** /**
* This class is the communication hub for all sharing related operations. * This class is the communication hub for all sharing related operations.
@ -39,12 +38,7 @@ class Manager {
/** /**
* @var IShareProvider[] * @var IShareProvider[]
*/ */
private $shareProviders; private $defaultProvider;
/**
* @var string[]
*/
private $shareTypeToProviderId;
/** @var IUser */ /** @var IUser */
private $currentUser; private $currentUser;
@ -79,47 +73,7 @@ class Manager {
$this->userFolder = $userFolder; $this->userFolder = $userFolder;
// TEMP SOLUTION JUST TO GET STARTED // TEMP SOLUTION JUST TO GET STARTED
$this->shareProviders['ocdef'] = $defaultProvider; $this->defaultProvider = $defaultProvider;
$this->shareTypeToProviderId = [
\OCP\Share::SHARE_TYPE_USER => 'ocdef',
\OCP\Share::SHARE_TYPE_GROUP => 'ocdef',
\OCP\Share::SHARE_TYPE_LINK => 'ocdef',
];
// TODO: Get storage share provider from primary storage
}
/**
* Get a ShareProvider
*
* @param string $id
* @return IShareProvider
*/
private function getShareProvider($id) {
if (!isset($this->shareProviders[$id])) {
//Throw exception;
}
// Check if we have instanciated this provider yet
if (!($this->shareProviders[$id] instanceOf \OC\Share20\IShareProvider)) {
throw new \Exception();
}
return $this->shareProviders[$id];
}
/**
* Get shareProvider based on shareType
*
* @param int $shareType
* @return IShareProvider
*/
private function getShareProviderByType($shareType) {
if (!isset($this->shareTypeToProviderId[$shareType])) {
//Throw exception
}
return $this->getShareProvider($this->shareTypeToProviderId[$shareType]);
} }
/** /**
@ -146,9 +100,15 @@ class Manager {
* Delete a share * Delete a share
* *
* @param Share $share * @param Share $share
* @throws ShareNotFound
* @throws \OC\Share20\Exception\BackendError
*/ */
public function deleteShare(Share $share) { public function deleteShare(IShare $share) {
throw new \Exception(); if ($share->getId() === null) {
throw new ShareNotFound();
}
$this->defaultProvider->delete($share);
} }
/** /**
@ -168,10 +128,18 @@ class Manager {
* @param string $id * @param string $id
* @return Share * @return Share
* *
* @throws ShareNotFoundException * @throws ShareNotFound
*/ */
public function getShareById($id) { public function getShareById($id) {
throw new \Exception(); $share = $this->defaultProvider->getShareById($id);
if ($share->getSharedWith() !== $this->currentUser &&
$share->getSharedBy() !== $this->currentUser &&
$share->getShareOwner() !== $this->currentUser) {
throw new ShareNotFound();
}
return $share;
} }
/** /**

View file

@ -24,13 +24,10 @@ use OCP\Files\Node;
use OCP\IUser; use OCP\IUser;
use OCP\IGroup; use OCP\IGroup;
class Share { class Share implements IShare {
/** @var string */ /** @var string */
private $internalId; private $id;
/** @var string */
private $providerId;
/** @var Node */ /** @var Node */
private $path; private $path;
@ -39,7 +36,7 @@ class Share {
private $shareType; private $shareType;
/** @var IUser|IGroup|string */ /** @var IUser|IGroup|string */
private $shareWith; private $sharedWith;
/** @var IUser|string */ /** @var IUser|string */
private $sharedBy; private $sharedBy;
@ -56,57 +53,30 @@ class Share {
/** @var string */ /** @var string */
private $password; private $password;
/** @var string */
private $token;
/** @var int */
private $parent;
/** /**
* Set the id of the ShareProvider * Set the id of the share
* Should only be used by the share manager
* *
* @param string $providerId * @param int id
* @return Share The modified object * @return Share The modified object
*/ */
public function setProviderId($providerId) { public function setId($id) {
$this->providerId = $providerId; $this->id = $id;
return $this; return $this;
} }
/**
* Get the id of the ShareProvider
*
* @return string
*/
public function getProviderId() {
return $this->providerId;
}
/**
* Set the internal (to the provider) share id
* Should only be used by the share provider
*
* @param string $id
* @return Share The modified object
*/
public function setInternalId($id) {
$this->internalId = $id;
return $this;
}
/**
* Get the internal (to the provider) share id
* Should only be used by the share provider
*
* @return string
*/
public function getInternalId() {
return $this->internalId;
}
/** /**
* Get the id of the share * Get the id of the share
* *
* @return string * @return string
*/ */
public function getId() { public function getId() {
//TODO $id should be set as well as $providerId return $this->id;
return $this->providerId . ':' . $this->internalId;
} }
/** /**
@ -150,23 +120,23 @@ class Share {
} }
/** /**
* Set the shareWith * Set the receiver of this share
* *
* @param IUser|IGroup|string * @param IUser|IGroup|string
* @return Share The modified object * @return Share The modified object
*/ */
public function setShareWith($shareWith) { public function setSharedWith($sharedWith) {
$this->shareWith = $shareWith; $this->sharedWith = $sharedWith;
return $this; return $this;
} }
/** /**
* Get the shareWith * Get the receiver of this share
* *
* @return IUser|IGroup|string * @return IUser|IGroup|string
*/ */
public function getShareWith() { public function getSharedWith() {
return $this->shareWith; return $this->sharedWith;
} }
/** /**
@ -282,4 +252,44 @@ class Share {
public function getPassword($password) { public function getPassword($password) {
return $this->password; return $this->password;
} }
/**
* Set the token
*
* @param string $token
* @return Share The modified object
*/
public function setToken($token) {
$this->token = $token;
return $this;
}
/**
* Get the token
*
* @return string
*/
public function getToken() {
return $this->token;
}
/**
* Set the parent id of this share
*
* @param int $parent
* @return Share The modified object
*/
public function setParent($parent) {
$this->parent = $parent;
return $this;
}
/**
* Get the parent id of this share
*
* @return int
*/
public function getParent() {
return $this->parent;
}
} }

View file

@ -0,0 +1,543 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Test\Share20;
use OCP\IDBConnection;
use OCP\IUserManager;
use OCP\IGroupManager;
use OCP\Files\Folder;
use OC\Share20\DefaultShareProvider;
class DefaultShareProviderTest extends \Test\TestCase {
/** @var IDBConnection */
protected $dbConn;
/** @var IUserManager */
protected $userManager;
/** @var IGroupManager */
protected $groupManager;
/** @var Folder */
protected $userFolder;
/** @var DefaultShareProvider */
protected $provider;
public function setUp() {
$this->dbConn = \OC::$server->getDatabaseConnection();
$this->userManager = $this->getMock('OCP\IUserManager');
$this->groupManager = $this->getMock('OCP\IGroupManager');
$this->userFolder = $this->getMock('OCP\Files\Folder');
//Empty share table
$this->dbConn->getQueryBuilder()->delete('share')->execute();
$this->provider = new DefaultShareProvider(
$this->dbConn,
$this->userManager,
$this->groupManager,
$this->userFolder
);
}
public function tearDown() {
$this->dbConn->getQueryBuilder()->delete('share')->execute();
}
/**
* @expectedException OC\Share20\Exception\ShareNotFound
*/
public function testGetShareByIdNotExist() {
$this->provider->getShareById(1);
}
public function testGetShareByIdUserShare() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedWith = $this->getMock('OCP\IUser');
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedWith', $sharedWith],
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->assertEquals(1, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
$this->assertEquals($sharedWith, $share->getSharedWith());
$this->assertEquals($sharedBy, $share->getSharedBy());
$this->assertEquals($shareOwner, $share->getShareOwner());
$this->assertEquals($path, $share->getPath());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
$this->assertEquals(null, $share->getExpirationDate());
}
public function testGetShareByIdGroupShare() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_GROUP),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedWith = $this->getMock('OCP\IGroup');
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$this->groupManager
->expects($this->once())
->method('get')
->with('sharedWith')
->willReturn($sharedWith);
$share = $this->provider->getShareById(1);
$this->assertEquals(1, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
$this->assertEquals($sharedWith, $share->getSharedWith());
$this->assertEquals($sharedBy, $share->getSharedBy());
$this->assertEquals($shareOwner, $share->getShareOwner());
$this->assertEquals($path, $share->getPath());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
$this->assertEquals(null, $share->getExpirationDate());
}
public function testGetShareByIdLinkShare() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
'token' => $qb->expr()->literal('token'),
'expiration' => $qb->expr()->literal('2000-01-02 00:00:00'),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->assertEquals(1, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
$this->assertEquals('sharedWith', $share->getSharedWith());
$this->assertEquals($sharedBy, $share->getSharedBy());
$this->assertEquals($shareOwner, $share->getShareOwner());
$this->assertEquals($path, $share->getPath());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals('token', $share->getToken());
$this->assertEquals(\DateTime::createFromFormat('Y-m-d H:i:s', '2000-01-02 00:00:00'), $share->getExpirationDate());
}
public function testGetShareByIdRemoteShare() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_REMOTE),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->assertEquals(1, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_REMOTE, $share->getShareType());
$this->assertEquals('sharedWith', $share->getSharedWith());
$this->assertEquals($sharedBy, $share->getSharedBy());
$this->assertEquals($shareOwner, $share->getShareOwner());
$this->assertEquals($path, $share->getPath());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
$this->assertEquals(null, $share->getExpirationDate());
}
public function testDeleteSingleShare() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedWith = $this->getMock('OCP\IUser');
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedWith', $sharedWith],
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->provider->delete($share);
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share');
$cursor = $qb->execute();
$result = $cursor->fetchAll();
$cursor->closeCursor();
$this->assertEmpty($result);
}
public function testDeleteSingleShareKeepOther() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(2),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->once())
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->once())
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->once())
->method('getById')
->with(42)
->willReturn([$path]);
$sharedWith = $this->getMock('OCP\IUser');
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedWith', $sharedWith],
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->provider->delete($share);
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share');
$cursor = $qb->execute();
$result = $cursor->fetchAll();
$cursor->closeCursor();
$this->assertCount(1, $result);
}
public function testDeleteNestedShares() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(1),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith'),
'uid_owner' => $qb->expr()->literal('sharedBy'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
]);
$qb->execute();
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(2),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith2'),
'uid_owner' => $qb->expr()->literal('sharedBy2'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
'parent' => $qb->expr()->literal(1),
]);
$qb->execute();
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
->values([
'id' => $qb->expr()->literal(3),
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
'share_with' => $qb->expr()->literal('sharedWith2'),
'uid_owner' => $qb->expr()->literal('sharedBy2'),
'file_source' => $qb->expr()->literal(42),
'permissions' => $qb->expr()->literal(13),
'parent' => $qb->expr()->literal(2),
]);
$qb->execute();
$storage = $this->getMock('OC\Files\Storage\Storage');
$storage
->expects($this->exactly(3))
->method('getOwner')
->willReturn('shareOwner');
$path = $this->getMock('OCP\Files\Node');
$path
->expects($this->exactly(3))
->method('getStorage')
->wilLReturn($storage);
$this->userFolder
->expects($this->exactly(3))
->method('getById')
->with(42)
->willReturn([$path]);
$sharedWith = $this->getMock('OCP\IUser');
$sharedBy = $this->getMock('OCP\IUser');
$shareOwner = $this->getMock('OCP\IUser');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedWith', $sharedWith],
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$share = $this->provider->getShareById(1);
$this->provider->delete($share);
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share');
$cursor = $qb->execute();
$result = $cursor->fetchAll();
$cursor->closeCursor();
$this->assertEmpty($result);
}
/**
* @expectedException \OC\Share20\Exception\BackendError
*/
public function testDeleteFails() {
$share = $this->getMock('OC\Share20\IShare');
$expr = $this->getMock('OCP\DB\QueryBuilder\IExpressionBuilder');
$qb = $this->getMock('OCP\DB\QueryBuilder\IQueryBuilder');
$qb->expects($this->once())
->method('delete')
->will($this->returnSelf());
$qb->expects($this->once())
->method('expr')
->willReturn($expr);
$qb->expects($this->once())
->method('where')
->will($this->returnSelf());
$qb->expects($this->once())
->method('setParameter')
->will($this->returnSelf());
$qb->expects($this->once())
->method('execute')
->will($this->throwException(new \Exception));
$db = $this->getMock('OCP\IDBConnection');
$db->expects($this->once())
->method('getQueryBuilder')
->with()
->willReturn($qb);
$provider = $this->getMockBuilder('OC\Share20\DefaultShareProvider')
->setConstructorArgs([
$db,
$this->userManager,
$this->groupManager,
$this->userFolder,
]
)
->setMethods(['deleteChildren'])
->getMock();
$provider
->expects($this->once())
->method('deleteChildren')
->with($share);
$provider->delete($share);
}
}

View file

@ -0,0 +1,198 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Test\Share20;
use OC\Share20\Manager;
use OC\Share20\Exception;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IAppConfig;
use OCP\Files\Folder;
use OCP\Share20\IShareProvider;
class ManagerTest extends \Test\TestCase {
/** @var Manager */
protected $manager;
/** @var IUser */
protected $user;
/** @var IUserManager */
protected $userManager;
/** @var IGroupManager */
protected $groupManager;
/** @var ILogger */
protected $logger;
/** @var IAppConfig */
protected $appConfig;
/** @var Folder */
protected $userFolder;
/** @var IShareProvider */
protected $defaultProvider;
public function setUp() {
$this->user = $this->getMock('\OCP\IUser');
$this->userManager = $this->getMock('\OCP\IUserManager');
$this->groupManager = $this->getMock('\OCP\IGroupManager');
$this->logger = $this->getMock('\OCP\ILogger');
$this->appConfig = $this->getMock('\OCP\IAppConfig');
$this->userFolder = $this->getMock('\OCP\Files\Folder');
$this->defaultProvider = $this->getMock('\OC\Share20\IShareProvider');
$this->manager = new Manager(
$this->user,
$this->userManager,
$this->groupManager,
$this->logger,
$this->appConfig,
$this->userFolder,
$this->defaultProvider
);
}
/**
* @expectedException OC\Share20\Exception\ShareNotFound
*/
public function testDeleteNoShareId() {
$share = $this->getMock('\OC\Share20\IShare');
$share
->expects($this->once())
->method('getId')
->with()
->willReturn(null);
$this->manager->deleteShare($share);
}
public function testDelete() {
$share = $this->getMock('\OC\Share20\IShare');
$share
->expects($this->once())
->method('getId')
->with()
->willReturn(42);
$this->defaultProvider
->expects($this->once())
->method('delete')
->with($share);
$this->manager->deleteShare($share);
}
/**
* @expectedException OC\Share20\Exception\ShareNotFound
*/
public function testGetShareByIdNotFoundInBackend() {
$this->defaultProvider
->expects($this->once())
->method('getShareById')
->with(42)
->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
$this->manager->getShareById(42);
}
/**
* @expectedException OC\Share20\Exception\ShareNotFound
*/
public function testGetShareByIdNotAuthorized() {
$otherUser1 = $this->getMock('\OCP\IUser');
$otherUser2 = $this->getMock('\OCP\IUser');
$otherUser3 = $this->getMock('\OCP\IUser');
$share = $this->getMock('\OC\Share20\IShare');
$share
->expects($this->once())
->method('getSharedWith')
->with()
->willReturn($otherUser1);
$share
->expects($this->once())
->method('getSharedBy')
->with()
->willReturn($otherUser2);
$share
->expects($this->once())
->method('getShareOwner')
->with()
->willReturn($otherUser3);
$this->defaultProvider
->expects($this->once())
->method('getShareById')
->with(42)
->willReturn($share);
$this->manager->getShareById(42);
}
public function dataGetShareById() {
return [
['getSharedWith'],
['getSharedBy'],
['getShareOwner'],
];
}
/**
* @dataProvider dataGetShareById
*/
public function testGetShareById($currentUserIs) {
$otherUser1 = $this->getMock('\OCP\IUser');
$otherUser2 = $this->getMock('\OCP\IUser');
$otherUser3 = $this->getMock('\OCP\IUser');
$share = $this->getMock('\OC\Share20\IShare');
$share
->method('getSharedWith')
->with()
->willReturn($currentUserIs === 'getSharedWith' ? $this->user : $otherUser1);
$share
->method('getSharedBy')
->with()
->willReturn($currentUserIs === 'getSharedBy' ? $this->user : $otherUser2);
$share
->method('getShareOwner')
->with()
->willReturn($currentUserIs === 'getShareOwner' ? $this->user : $otherUser3);
$this->defaultProvider
->expects($this->once())
->method('getShareById')
->with(42)
->willReturn($share);
$this->assertEquals($share, $this->manager->getShareById(42));
}
}