diff options
author | Bjoern Schiessle <bjoern@schiessle.org> | 2018-06-13 14:19:59 +0200 |
---|---|---|
committer | Bjoern Schiessle <bjoern@schiessle.org> | 2018-07-11 10:11:44 +0200 |
commit | b23032e4c569f7ba54197171cbb02ed8119b6811 (patch) | |
tree | 882cc64ab6398f33962428d79aa270055a20f6e0 /apps/files_sharing | |
parent | c8631d607ef827f0eb29312faf7b2b808e1a8e7d (diff) | |
download | nextcloud-server-b23032e4c569f7ba54197171cbb02ed8119b6811.tar.gz nextcloud-server-b23032e4c569f7ba54197171cbb02ed8119b6811.zip |
implement federated group shares
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
Diffstat (limited to 'apps/files_sharing')
-rw-r--r-- | apps/files_sharing/appinfo/database.xml | 11 | ||||
-rw-r--r-- | apps/files_sharing/appinfo/info.xml | 2 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareAPIController.php | 93 | ||||
-rw-r--r-- | apps/files_sharing/lib/External/Manager.php | 31 |
4 files changed, 88 insertions, 49 deletions
diff --git a/apps/files_sharing/appinfo/database.xml b/apps/files_sharing/appinfo/database.xml index a70be408da4..c3cfb9e1c88 100644 --- a/apps/files_sharing/appinfo/database.xml +++ b/apps/files_sharing/appinfo/database.xml @@ -16,6 +16,17 @@ <length>4</length> </field> <field> + <name>parent</name> + <type>integer</type> + <default>-1</default> + <length>4</length> + </field> + <field> + <name>share_type</name> + <type>integer</type> + <length>4</length> + </field> + <field> <name>remote</name> <type>text</type> <notnull>true</notnull> diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index 94a31bea63c..f2725880df0 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -9,7 +9,7 @@ Turning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation. </description> - <version>1.6.1</version> + <version>1.6.2</version> <licence>agpl</licence> <author>Michael Gapczynski</author> <author>Bjoern Schiessle</author> diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 67ff9eae6d3..59b763ecf81 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -48,6 +48,7 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\Files\IRootFolder; use OCP\Lock\LockedException; +use OCP\Share; use OCP\Share\IManager; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\Exceptions\GenericShareException; @@ -181,15 +182,15 @@ class ShareAPIController extends OCSController { $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); } - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + if ($share->getShareType() === Share::SHARE_TYPE_USER) { $sharedWith = $this->userManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) { $group = $this->groupManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) { $result['share_with'] = $share->getPassword(); $result['share_with_displayname'] = $share->getPassword(); @@ -197,16 +198,16 @@ class ShareAPIController extends OCSController { $result['token'] = $share->getToken(); $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() || Share::SHARE_TYPE_REMOTE_GROUP) { $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD'); $result['token'] = $share->getToken(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) { + } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) { $result['share_with'] = $share->getSharedWith(); $result['password'] = $share->getPassword(); $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL'); $result['token'] = $share->getToken(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) { + } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) { // getSharedWith() returns either "name (type, owner)" or // "name (type, owner) [id]", depending on the Circles app version. $hasCircleId = (substr($share->getSharedWith(), -1) === ']'); @@ -301,7 +302,7 @@ class ShareAPIController extends OCSController { throw new OCSNotFoundException($this->l->t('Could not delete share')); } - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && + if ($share->getShareType() === Share::SHARE_TYPE_GROUP && $share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) { $this->shareManager->deleteFromSelf($share, $this->currentUser); @@ -388,14 +389,14 @@ class ShareAPIController extends OCSController { $permissions &= ~($permissions & ~$path->getPermissions()); } - if ($shareType === \OCP\Share::SHARE_TYPE_USER) { + if ($shareType === Share::SHARE_TYPE_USER) { // Valid user is required to share if ($shareWith === null || !$this->userManager->userExists($shareWith)) { throw new OCSNotFoundException($this->l->t('Please specify a valid user')); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); - } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { + } else if ($shareType === Share::SHARE_TYPE_GROUP) { if (!$this->shareManager->allowGroupSharing()) { throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator')); } @@ -406,7 +407,7 @@ class ShareAPIController extends OCSController { } $share->setSharedWith($shareWith); $share->setPermissions($permissions); - } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) { + } else if ($shareType === Share::SHARE_TYPE_LINK) { //Can we even share links? if (!$this->shareManager->shareApiAllowLinks()) { throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator')); @@ -416,7 +417,7 @@ class ShareAPIController extends OCSController { * For now we only allow 1 link share. * Return the existing link share if this is a duplicate */ - $existingShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0); + $existingShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, false, 1, 0); if (!empty($existingShares)) { return new DataResponse($this->formatShare($existingShares[0])); } @@ -457,21 +458,28 @@ class ShareAPIController extends OCSController { } } - } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + } else if ($shareType === Share::SHARE_TYPE_REMOTE) { if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); - } else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) { + } else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) { + if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) { + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); + } + + $share->setSharedWith($shareWith); + $share->setPermissions($permissions); + } else if ($shareType === Share::SHARE_TYPE_EMAIL) { if ($share->getNodeType() === 'file') { $share->setPermissions(Constants::PERMISSION_READ); } else { $share->setPermissions($permissions); } $share->setSharedWith($shareWith); - } else if ($shareType === \OCP\Share::SHARE_TYPE_CIRCLE) { + } else if ($shareType === Share::SHARE_TYPE_CIRCLE) { if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) { throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled')); } @@ -512,9 +520,9 @@ class ShareAPIController extends OCSController { */ private function getSharedWithMe($node = null, bool $includeTags): DataResponse { - $userShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); - $groupShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); - $circleShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_CIRCLE, $node, -1, 0); + $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0); + $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0); + $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0); $shares = array_merge($userShares, $groupShares, $circleShares); @@ -554,14 +562,14 @@ class ShareAPIController extends OCSController { /** @var \OCP\Share\IShare[] $shares */ $shares = []; foreach ($nodes as $node) { - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0)); - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0)); - if($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) { - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0)); + if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0)); } if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); } } @@ -635,16 +643,16 @@ class ShareAPIController extends OCSController { } // Get all shares - $userShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); - $groupShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); - $linkShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); - if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) { - $mailShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0); + $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); + $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); + $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { + $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0); } else { $mailShares = []; } - if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) { - $circleShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0); + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) { + $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0); } else { $circleShares = []; } @@ -652,7 +660,12 @@ class ShareAPIController extends OCSController { $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares); if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { - $federatedShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); + $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); + $shares = array_merge($shares, $federatedShares); + } + + if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) { + $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0); $shares = array_merge($shares, $federatedShares); } @@ -711,7 +724,7 @@ class ShareAPIController extends OCSController { /* * expirationdate, password and publicUpload only make sense for link shares */ - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + if ($share->getShareType() === Share::SHARE_TYPE_LINK) { $newPermissions = null; if ($publicUpload === 'true') { @@ -783,7 +796,7 @@ class ShareAPIController extends OCSController { $share->setPermissions($permissions); } - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) { + if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) { if ($password === '') { $share->setPassword(null); } else if ($password !== null) { @@ -806,8 +819,8 @@ class ShareAPIController extends OCSController { if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) { /* Check if this is an incomming share */ - $incomingShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); - $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); + $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); + $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); /** @var \OCP\Share\IShare[] $incomingShares */ if (!empty($incomingShares)) { @@ -846,13 +859,13 @@ class ShareAPIController extends OCSController { } // If the share is shared with you (or a group you are a member of) - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && + if ($share->getShareType() === Share::SHARE_TYPE_USER && $share->getSharedWith() === $this->currentUser ) { return true; } - if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) { $sharedWith = $this->groupManager->get($share->getSharedWith()); $user = $this->userManager->get($this->currentUser); if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) { @@ -860,7 +873,7 @@ class ShareAPIController extends OCSController { } } - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) { + if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) { // TODO: have a sanity check like above? return true; } @@ -915,7 +928,7 @@ class ShareAPIController extends OCSController { try { - if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) { + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) { $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser); return $share; } @@ -924,7 +937,7 @@ class ShareAPIController extends OCSController { } try { - if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) { + if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser); return $share; } diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php index 02783560afe..4875e7e26ce 100644 --- a/apps/files_sharing/lib/External/Manager.php +++ b/apps/files_sharing/lib/External/Manager.php @@ -126,12 +126,15 @@ class Manager { * @param string $password * @param string $name * @param string $owner + * @param int $shareType * @param boolean $accepted * @param string $user * @param int $remoteId + * @param int $parent * @return Mount|null + * @throws \Doctrine\DBAL\DBALException */ - public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) { + public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted=false, $user = null, $remoteId = -1, $parent = -1) { $user = $user ? $user : $this->uid; $accepted = $accepted ? 1 : 0; @@ -156,6 +159,7 @@ class Manager { 'mountpoint_hash' => $hash, 'accepted' => $accepted, 'remote_id' => $remoteId, + 'share_type' => $shareType, ]; $i = 1; @@ -174,10 +178,10 @@ class Manager { $query = $this->connection->prepare(' INSERT INTO `*PREFIX*share_external` - (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`, `parent`, `share_type`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '); - $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId)); + $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType)); $options = array( 'remote' => $remote, @@ -223,13 +227,17 @@ class Manager { $mountPoint = Filesystem::normalizePath($mountPoint); $hash = md5($mountPoint); - $acceptShare = $this->connection->prepare(' + if($share['share_type'] === \OCP\Share::SHARE_TYPE_USER) { + $acceptShare = $this->connection->prepare(' UPDATE `*PREFIX*share_external` SET `accepted` = ?, `mountpoint` = ?, `mountpoint_hash` = ? WHERE `id` = ? AND `user` = ?'); - $updated = $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid)); + $updated = $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid)); + } else { + // TODO group share, add additional row for the user who accepted it + } if ($updated === true) { $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept'); \OC_Hook::emit(Share::class, 'federated_share_added', ['server' => $share['remote']]); @@ -537,10 +545,17 @@ class Manager { * @return array list of open server-to-server shares */ private function getShares($accepted) { + $user = $this->userManager->get($this->uid); + $groups = $this->groupManager->getUserGroups($user); + $userGroups = []; + foreach ($groups as $group) { + $userGroups[] = $group->getGID(); + } + $query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted` FROM `*PREFIX*share_external` - WHERE `user` = ?'; - $parameters = [$this->uid]; + WHERE `user` = ? OR `user` IN (?)'; + $parameters = [$this->uid, implode(',',$userGroups)]; if (!is_null($accepted)) { $query .= ' AND `accepted` = ?'; $parameters[] = (int) $accepted; |