From 46045ecc528566edcbe302339ce37819e5320e86 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 22 Jan 2016 14:52:20 +0100 Subject: [PATCH] [Share 2.0] Add update share --- apps/files_sharing/api/ocssharewrapper.php | 3 +- apps/files_sharing/api/share20ocs.php | 66 +++++++++++++++++ lib/private/share20/defaultshareprovider.php | 63 +++++++++++++++++ lib/private/share20/manager.php | 74 ++++++++++++++++++-- 4 files changed, 201 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/api/ocssharewrapper.php b/apps/files_sharing/api/ocssharewrapper.php index cc52d47861..9f63e864ce 100644 --- a/apps/files_sharing/api/ocssharewrapper.php +++ b/apps/files_sharing/api/ocssharewrapper.php @@ -50,7 +50,8 @@ class OCSShareWrapper { } public function updateShare($params) { - return \OCA\Files_Sharing\API\Local::updateShare($params); + $id = $params['id']; + return $this->getShare20OCS()->updateShare($id); } public function deleteShare($params) { diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php index c2ff94db79..c5e7dcff82 100644 --- a/apps/files_sharing/api/share20ocs.php +++ b/apps/files_sharing/api/share20ocs.php @@ -425,6 +425,72 @@ class Share20OCS { return new \OC_OCS_Result($formatted); } + /** + * @param int $id + * @return \OC_OCS_Result + */ + public function updateShare($id) { + // Try both our default and our federated provider + $share = null; + + try { + $share = $this->shareManager->getShareById('ocinternal:' . $id); + } catch (\OC\Share20\Exception\ShareNotFound $e) { + //Ignore for now + //return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.'); + } + + // Could not find the share as internal share... maybe it is a federated share + if ($share === null) { + return \OCA\Files_Sharing\API\Local::updateShare(['id' => $id]); + } + + if (!$this->canAccessShare($share)) { + return new \OC_OCS_Result(null, 404, "wrong share Id, share doesn't exist."); + } + + $permissions = $this->request->getParam('permissions', null); + $password = $this->request->getParam('password', null); + $publicUpload = $this->request->getParam('publicUpload', null); + $expireDate = $this->request->getParam('expireDate', null); + + if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { + return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); + } + + if ($expireDate !== null) { + try { + $expireDate = $this->parseDate($expireDate); + } catch (\Exception $e) { + return new \OC_OCS_Result(null, 400, $e->getMessage()); + } + $share->setExpirationDate($expireDate); + } + + if ($permissions !== null) { + $permissions = (int)$permissions; + $share->setPermissions($permissions); + } + + if ($password !== null) { + $share->setPassword($password); + } + + if ($publicUpload === 'true') { + $share->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); + } else if ($publicUpload === 'false') { + $share->setPermissions(\OCP\Constants::PERMISSION_READ); + } + + try { + $share = $this->shareManager->updateShare($share); + } catch (\Exception $e) { + return new \OC_OCS_Result(null, 400, $e->getMessage()); + } + + return new \OC_OCS_Result($this->formatShare($share)); + } + /** * @param IShare $share * @return bool diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php index 3d5462792c..3703447b00 100644 --- a/lib/private/share20/defaultshareprovider.php +++ b/lib/private/share20/defaultshareprovider.php @@ -183,6 +183,69 @@ class DefaultShareProvider implements IShareProvider { * @return IShare The share object */ public function update(IShare $share) { + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + /* + * We allow updating the recipient on user shares. + */ + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) + ->set('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID())) + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID())) + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID())) + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) + ->set('item_source', $qb->createNamedParameter($share->getPath()->getId())) + ->set('file_source', $qb->createNamedParameter($share->getPath()->getId())) + ->execute(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID())) + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID())) + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) + ->set('item_source', $qb->createNamedParameter($share->getPath()->getId())) + ->set('file_source', $qb->createNamedParameter($share->getPath()->getId())) + ->execute(); + + /* + * Update all user defined group shares + */ + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share') + ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID())) + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID())) + ->set('item_source', $qb->createNamedParameter($share->getPath()->getId())) + ->set('file_source', $qb->createNamedParameter($share->getPath()->getId())) + ->execute(); + + /* + * Now update the permissions for all children that have not set it to 0 + */ + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share') + ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) + ->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0))) + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) + ->execute(); + + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + $qb = $this->dbConn->getQueryBuilder(); + $qb->update('share') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) + ->set('share_with', $qb->createNamedParameter($share->getPassword())) + ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID())) + ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID())) + ->set('permissions', $qb->createNamedParameter($share->getPermissions())) + ->set('item_source', $qb->createNamedParameter($share->getPath()->getId())) + ->set('file_source', $qb->createNamedParameter($share->getPath()->getId())) + ->set('token', $qb->createNamedParameter($share->getToken())) + ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime')) + ->execute(); + } + + return $this->getShareById($share->getId()); } /** diff --git a/lib/private/share20/manager.php b/lib/private/share20/manager.php index ea6463c745..249103018b 100644 --- a/lib/private/share20/manager.php +++ b/lib/private/share20/manager.php @@ -170,7 +170,7 @@ class Manager { throw new \InvalidArgumentException('unkown share type'); } - // Verify the initiator of the share is et + // Verify the initiator of the share is set if ($share->getSharedBy() === null) { throw new \InvalidArgumentException('SharedBy should be set'); } @@ -184,6 +184,7 @@ class Manager { if ($share->getPath() === null) { throw new \InvalidArgumentException('Path should be set'); } + // And it should be a file or a folder if (!($share->getPath() instanceof \OCP\Files\File) && !($share->getPath() instanceof \OCP\Files\Folder)) { @@ -289,6 +290,11 @@ class Manager { $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER); $existingShares = $provider->getSharesByPath($share->getPath()); foreach($existingShares as $existingShare) { + // Ignore if it is the same share + if ($existingShare->getFullId() === $share->getFullId()) { + continue; + } + // Identical share already existst if ($existingShare->getSharedWith() === $share->getSharedWith()) { throw new \Exception('Path already shared with this user'); @@ -325,6 +331,10 @@ class Manager { $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP); $existingShares = $provider->getSharesByPath($share->getPath()); foreach($existingShares as $existingShare) { + if ($existingShare->getFullId() === $share->getFullId()) { + continue; + } + if ($existingShare->getSharedWith() === $share->getSharedWith()) { throw new \Exception('Path already shared with this group'); } @@ -447,6 +457,11 @@ class Manager { // On creation of a share the owner is always the owner of the path $share->setShareOwner($share->getPath()->getOwner()); + // Cannot share with the owner + if ($share->getSharedWith() === $share->getShareOwner()) { + throw new \InvalidArgumentException('Can\'t share with the share owner'); + } + // Generate the target $target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getPath()->getName(); $target = \OC\Files\Filesystem::normalizePath($target); @@ -513,10 +528,61 @@ class Manager { /** * Update a share * - * @param Share $share - * @return Share The share object + * @param IShare $share + * @return IShare The share object */ - public function updateShare(Share $share) { + public function updateShare(IShare $share) { + if (!$this->canShare($share)) { + throw new \Exception('The Share API is disabled'); + } + + $originalShare = $this->getShareById($share->getFullId()); + + // We can't change the share type! + if ($share->getShareType() !== $originalShare->getShareType()) { + //Throw exception + } + + // We can only change the recipient on user shares + if ($share->getSharedWith() !== $originalShare->getSharedWith() && + $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) { + // Throw exception + } + + // Cannot share with the owner + if ($share->getSharedWith() === $share->getShareOwner()) { + throw new \InvalidArgumentException('Can\'t share with the share owner'); + } + + $this->generalCreateChecks($share); + + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + $this->userCreateChecks($share); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $this->groupCreateChecks($share); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + $this->linkCreateChecks($share); + + // Password updated. + if ($share->getPassword() !== $originalShare->getPassword()) { + //Verify the password + $this->verifyPassword($share->getPassword()); + + // If a password is set. Hash it! + if ($share->getPassword() !== null) { + $share->setPassword($this->hasher->hash($share->getPassword())); + } + } + + //Verify the expiration date + $share->setExpirationDate($this->validateExpiredate($share->getExpirationDate())); + } + + $this->pathCreateChecks($share->getPath()); + + // Now update the share! + $provider = $this->factory->getProviderForType($share->getShareType()); + return $provider->update($share); } /**