*/
namespace OC\Share20;
+use OCP\Files\File;
use OCP\Share\IShareProvider;
use OC\Share20\Exception\InvalidShare;
use OC\Share20\Exception\ProviderException;
}
}
+ /**
+ * @inheritdoc
+ */
+ public function move(\OCP\Share\IShare $share, IUser $recipient) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
+ // Just update the target
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->update('share')
+ ->set('file_target', $qb->createNamedParameter($share->getTarget()))
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
+ ->execute();
+
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+
+ // Check if there is a usergroup share
+ $qb = $this->dbConn->getQueryBuilder();
+ $stmt = $qb->select('id')
+ ->from('share')
+ ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient->getUID())))
+ ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
+ ->setMaxResults(1)
+ ->execute();
+
+ $data = $stmt->fetch();
+ $stmt->closeCursor();
+
+ if ($data === false) {
+ // No usergroup share yet. Create one.
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
+ 'share_with' => $qb->createNamedParameter($recipient->getUID()),
+ 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()->getUID()),
+ 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()->getUID()),
+ 'parent' => $qb->createNamedParameter($share->getId()),
+ 'item_type' => $qb->createNamedParameter($share->getNode() instanceof File ? 'file' : 'folder'),
+ 'item_source' => $qb->createNamedParameter($share->getNode()->getId()),
+ 'file_source' => $qb->createNamedParameter($share->getNode()->getId()),
+ 'file_target' => $qb->createNamedParameter($share->getTarget()),
+ 'permissions' => $qb->createNamedParameter($share->getPermissions()),
+ 'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
+ ])->execute();
+ } else {
+ // Already a usergroup share. Update it.
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->update('share')
+ ->set('file_target', $qb->createNamedParameter($share->getTarget()))
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
+ ->execute();
+ }
+ }
+
+ return $share;
+ }
+
/**
* Get all shares by the given user. Sharetype and path can be used to filter.
*
$provider->deleteFromSelf($share, $recipient);
}
+ /**
+ * @inheritdoc
+ */
+ public function moveShare(\OCP\Share\IShare $share, IUser $recipient) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
+ throw new \InvalidArgumentException('Can\'t change target of link share');
+ }
+
+ if (($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipient) ||
+ ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && !$share->getSharedWith()->inGroup($recipient))) {
+ throw new \InvalidArgumentException('Invalid recipient');
+ }
+
+ list($providerId, ) = $this->splitFullId($share->getId());
+ $provider = $this->factory->getProvider($providerId);
+
+ $provider->move($share, $recipient);
+ }
+
/**
* Get shares shared by (initiated) by the provided user.
*
* Create a Share
*
* @param IShare $share
- * @return Share The share object
+ * @return IShare The share object
* @since 9.0.0
*/
public function createShare(IShare $share);
/**
- * Update a share
+ * Update a share.
+ * The target of the share can't be changed this way: use moveShare
+ * The share can't be removed this way (permission 0): use deleteShare
*
* @param IShare $share
* @return IShare The share object
*/
public function deleteFromSelf(IShare $share, IUser $recipient);
+ /**
+ * Move the share as a recipient of the share.
+ * This is updating the share target. So where the recipient has the share mounted.
+ *
+ * @param IShare $share
+ * @param IUser $recipient
+ * @return IShare
+ * @throws \InvalidArgumentException If $share is a link share or the $recipient does not match
+ * @since 9.0.0
+ */
+ public function moveShare(IShare $share, IUser $recipient);
+
/**
* Get shares shared by (initiated) by the provided user.
*
* Get the share by token possible with password
*
* @param string $token
- * @return Share
+ * @return IShare
* @throws ShareNotFound
* @since 9.0.0
*/
*/
public function deleteFromSelf(\OCP\Share\IShare $share, IUser $recipient);
+ /**
+ * Move a share as a recipient.
+ * This is updating the share target. Thus the mount point of the recipient.
+ * This may require special handling. If a user moves a group share
+ * the target should only be changed for them.
+ *
+ * @param \OCP\Share\IShare $share
+ * @param IUser $recipient
+ * @return \OCP\Share\IShare
+ * @since 9.0.0
+ */
+ public function move(\OCP\Share\IShare $share, IUser $recipient);
+
/**
* Get all shares by the given user
*
$stmt->closeCursor();
+ }
+
+ public function testMoveUserShare() {
+ $id = $this->addShareToDB(\OCP\Share::SHARE_TYPE_USER, 'user0', 'user1', 'user1', 'file',
+ 42, 'mytaret', 31, null, null);
+
+ $user0 = $this->getMock('\OCP\IUser');
+ $user0->method('getUID')->willReturn('user0');
+ $user1 = $this->getMock('\OCP\IUser');
+ $user1->method('getUID')->willReturn('user1');
+
+ $this->userManager->method('get')->will($this->returnValueMap([
+ ['user0', $user0],
+ ['user1', $user1],
+ ]));
+
+ $file = $this->getMock('\OCP\Files\File');
+ $file->method('getId')->willReturn(42);
+
+ $this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
+ $this->rootFolder->method('getById')->willReturn([$file]);
+
+ $share = $this->provider->getShareById($id, null);
+
+ $share->setTarget('/newTarget');
+ $this->provider->move($share, $user0);
+
+ $share = $this->provider->getShareById($id, null);
+ $this->assertSame('/newTarget', $share->getTarget());
+ }
+
+ public function testMoveGroupShare() {
+ $id = $this->addShareToDB(\OCP\Share::SHARE_TYPE_GROUP, 'group0', 'user1', 'user1', 'file',
+ 42, 'mytaret', 31, null, null);
+
+ $user0 = $this->getMock('\OCP\IUser');
+ $user0->method('getUID')->willReturn('user0');
+ $user1 = $this->getMock('\OCP\IUser');
+ $user1->method('getUID')->willReturn('user1');
+
+ $group0 = $this->getMock('\OCP\IGroup');
+ $group0->method('getGID')->willReturn('group0');
+ $group0->method('inGroup')->with($user0)->willReturn(true);
+
+ $this->groupManager->method('get')->with('group0')->willReturn($group0);
+
+ $this->userManager->method('get')->will($this->returnValueMap([
+ ['user0', $user0],
+ ['user1', $user1],
+ ]));
+
+ $folder = $this->getMock('\OCP\Files\Folder');
+ $folder->method('getId')->willReturn(42);
+
+ $this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
+ $this->rootFolder->method('getById')->willReturn([$folder]);
+
+ $share = $this->provider->getShareById($id, $user0);
+
+ $share->setTarget('/newTarget');
+ $this->provider->move($share, $user0);
+
+ $share = $this->provider->getShareById($id, $user0);
+ $this->assertSame('/newTarget', $share->getTarget());
+
+ $share->setTarget('/ultraNewTarget');
+ $this->provider->move($share, $user0);
+ $share = $this->provider->getShareById($id, $user0);
+ $this->assertSame('/ultraNewTarget', $share->getTarget());
}
}
$manager->updateShare($share);
}
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Can't change target of link share
+ */
+ public function testMoveShareLink() {
+ $share = $this->manager->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_LINK);
+
+ $recipient = $this->getMock('\OCP\IUser');
+
+ $this->manager->moveShare($share, $recipient);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Invalid recipient
+ */
+ public function testMoveShareUserNotRecipient() {
+ $share = $this->manager->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_USER);
+
+ $sharedWith = $this->getMock('\OCP\IUser');
+ $share->setSharedWith($sharedWith);
+
+ $recipient = $this->getMock('\OCP\IUser');
+
+ $this->manager->moveShare($share, $recipient);
+ }
+
+ public function testMoveShareUser() {
+ $share = $this->manager->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_USER);
+
+ $recipient = $this->getMock('\OCP\IUser');
+ $share->setSharedWith($recipient);
+
+ $this->defaultProvider->method('move')->with($share, $recipient)->will($this->returnArgument(0));
+
+ $this->manager->moveShare($share, $recipient);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Invalid recipient
+ */
+ public function testMoveShareGroupNotRecipient() {
+ $share = $this->manager->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
+
+ $sharedWith = $this->getMock('\OCP\IGroup');
+ $share->setSharedWith($sharedWith);
+
+ $recipient = $this->getMock('\OCP\IUser');
+ $sharedWith->method('inGroup')->with($recipient)->willReturn(false);
+
+ $this->manager->moveShare($share, $recipient);
+ }
+
+ public function testMoveShareGroup() {
+ $share = $this->manager->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
+
+ $sharedWith = $this->getMock('\OCP\IGroup');
+ $share->setSharedWith($sharedWith);
+
+ $recipient = $this->getMock('\OCP\IUser');
+ $sharedWith->method('inGroup')->with($recipient)->willReturn(true);
+
+ $this->defaultProvider->method('move')->with($share, $recipient)->will($this->returnArgument(0));
+
+ $this->manager->moveShare($share, $recipient);
+ }
}
class DummyPassword {