[Share 2.0] Share Object creation is a fragile thing

* We can't assume that the file still exists
* We can't assume that the user/group still exists

Basically we do not always nicely cleanup shares.
This commit is contained in:
Roeland Jago Douma 2016-01-15 21:15:25 +01:00
parent b877b0508b
commit 0939520e1a
2 changed files with 84 additions and 13 deletions

View file

@ -20,8 +20,11 @@
*/
namespace OC\Share20;
use OC\Share20\Exception\InvalidShare;
use OC\Share20\Exception\ShareNotFound;
use OC\Share20\Exception\BackendError;
use OCP\Files\NotFoundException;
use OCP\IGroup;
use OCP\IUser;
use OCP\IGroupManager;
use OCP\IUserManager;
@ -95,10 +98,14 @@ class DefaultShareProvider implements IShareProvider {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
//Set the UID of the user we share with
$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID()));
/** @var IUser $sharedWith */
$sharedWith = $share->getSharedWith();
$qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getUID()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
//Set the GID of the group we share with
$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getGID()));
/** @var IGroup $sharedWith */
$sharedWith = $share->getSharedWith();
$qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getGID()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
//Set the token of the share
$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
@ -152,7 +159,7 @@ class DefaultShareProvider implements IShareProvider {
// Now fetch the inserted share and create a complete share object
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('*PREFIX*share')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
$cursor = $qb->execute();
@ -335,6 +342,7 @@ class DefaultShareProvider implements IShareProvider {
*
* @param mixed[] $data
* @return Share
* @throws InvalidShare
*/
private function createShare($data) {
$share = new Share();
@ -346,31 +354,45 @@ class DefaultShareProvider implements IShareProvider {
->setMailSend((bool)$data['mail_send']);
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
$share->setSharedWith($this->userManager->get($data['share_with']));
$sharedWith = $this->userManager->get($data['share_with']);
if ($sharedWith === null) {
throw new InvalidShare();
}
$share->setSharedWith($sharedWith);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$share->setSharedWith($this->groupManager->get($data['share_with']));
$sharedWith = $this->groupManager->get($data['share_with']);
if ($sharedWith === null) {
throw new InvalidShare();
}
$share->setSharedWith($sharedWith);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
$share->setPassword($data['share_with']);
$share->setToken($data['token']);
} else {
$share->setSharedWith($data['share_with']);
}
if ($data['uid_initiator'] === null) {
//OLD SHARE
$share->setSharedBy($this->userManager->get($data['uid_owner']));
$folder = $this->rootFolder->getUserFolder($share->getSharedBy()->getUID());
$path = $folder->getById((int)$data['file_source'])[0];
$sharedBy = $this->userManager->get($data['uid_owner']);
if ($sharedBy === null) {
throw new InvalidShare();
}
$share->setSharedBy($sharedBy);
$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
$owner = $path->getOwner();
$share->setShareOwner($owner);
} else {
//New share!
$share->setSharedBy($this->userManager->get($data['uid_initiator']));
$share->setShareOwner($this->userManager->get($data['uid_owner']));
$sharedBy = $this->userManager->get($data['uid_initiator']);
$shareOwner = $this->userManager->get($data['uid_owner']);
if ($sharedBy === null || $shareOwner === null) {
throw new InvalidShare();
}
$share->setSharedBy($sharedBy);
$share->setShareOwner($shareOwner);
}
$path = $this->rootFolder->getUserFolder($share->getShareOwner()->getUID())->getById((int)$data['file_source'])[0];
$path = $this->getNode($share->getShareOwner(), (int)$data['file_source']);
$share->setPath($path);
if ($data['expiration'] !== null) {
@ -383,4 +405,28 @@ class DefaultShareProvider implements IShareProvider {
return $share;
}
/**
* Get the node with file $id for $user
*
* @param IUser $user
* @param int $id
* @return \OCP\Files\File|\OCP\Files\Folder
* @throws InvalidShare
*/
private function getNode(IUser $user, $id) {
try {
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
} catch (NotFoundException $e) {
throw new InvalidShare();
}
$nodes = $userFolder->getById($id);
if (empty($nodes)) {
throw new InvalidShare();
}
return $nodes[0];
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* @author Roeland Jago Douma <rullzer@owncloud.com>
*
* @copyright Copyright (c) 2016, 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 InvalidShare extends \Exception {
}