diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2016-12-22 21:44:21 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2017-04-13 12:58:50 +0200 |
commit | 2cbac3357ba445a3a4cd073e119efb871ea0f719 (patch) | |
tree | 42f12e6334f0f14b8f122bf1355f325366123396 /lib | |
parent | 97f8ca6595caf051eae9c9261bdbd481c9dd4be1 (diff) | |
download | nextcloud-server-2cbac3357ba445a3a4cd073e119efb871ea0f719.tar.gz nextcloud-server-2cbac3357ba445a3a4cd073e119efb871ea0f719.zip |
Offload acceslist creation to providers
* This allows for effective queries.
* Introduce currentAccess parameter to speciy if the users needs to have
currently acces (deleted incomming group share). (For notifications)
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | lib/private/Share20/DefaultShareProvider.php | 76 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 57 | ||||
-rw-r--r-- | lib/public/Share/IShareProvider.php | 17 |
5 files changed, 111 insertions, 41 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index ab6a3781147..3cf8733e415 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -794,6 +794,7 @@ return array( 'OC\\Share20\\Manager' => $baseDir . '/lib/private/Share20/Manager.php', 'OC\\Share20\\ProviderFactory' => $baseDir . '/lib/private/Share20/ProviderFactory.php', 'OC\\Share20\\Share' => $baseDir . '/lib/private/Share20/Share.php', + 'OC\\Share20\\ShareHelper' => $baseDir . '/lib/private/Share20/ShareHelper.php', 'OC\\Share\\Constants' => $baseDir . '/lib/private/Share/Constants.php', 'OC\\Share\\Helper' => $baseDir . '/lib/private/Share/Helper.php', 'OC\\Share\\MailNotifications' => $baseDir . '/lib/private/Share/MailNotifications.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 1b2c9f84df8..4aecf62329d 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -824,6 +824,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Share20\\Manager' => __DIR__ . '/../../..' . '/lib/private/Share20/Manager.php', 'OC\\Share20\\ProviderFactory' => __DIR__ . '/../../..' . '/lib/private/Share20/ProviderFactory.php', 'OC\\Share20\\Share' => __DIR__ . '/../../..' . '/lib/private/Share20/Share.php', + 'OC\\Share20\\ShareHelper' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareHelper.php', 'OC\\Share\\Constants' => __DIR__ . '/../../..' . '/lib/private/Share/Constants.php', 'OC\\Share\\Helper' => __DIR__ . '/../../..' . '/lib/private/Share/Helper.php', 'OC\\Share\\MailNotifications' => __DIR__ . '/../../..' . '/lib/private/Share/MailNotifications.php', diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index feae147066d..93e8cfc9d77 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -362,7 +362,7 @@ class DefaultShareProvider implements IShareProvider { if ($data === false) { $qb = $this->dbConn->getQueryBuilder(); - $type = $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder'; + $type = $share->getNodeType(); //Insert new share $qb->insert('share') @@ -373,8 +373,8 @@ class DefaultShareProvider implements IShareProvider { 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()), 'parent' => $qb->createNamedParameter($share->getId()), 'item_type' => $qb->createNamedParameter($type), - 'item_source' => $qb->createNamedParameter($share->getNode()->getId()), - 'file_source' => $qb->createNamedParameter($share->getNode()->getId()), + 'item_source' => $qb->createNamedParameter($share->getNodeId()), + 'file_source' => $qb->createNamedParameter($share->getNodeId()), 'file_target' => $qb->createNamedParameter($share->getTarget()), 'permissions' => $qb->createNamedParameter(0), 'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()), @@ -1070,4 +1070,74 @@ class DefaultShareProvider implements IShareProvider { } } } + + /** + * @inheritdoc + */ + public function getAccessList($nodes, $currentAccess) { + $ids = []; + foreach ($nodes as $node) { + $ids[] = $node->getId(); + } + + $qb = $this->dbConn->getQueryBuilder(); + + $or = $qb->expr()->orX( + $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)), + $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP)), + $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK)) + ); + + if ($currentAccess) { + $or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))); + } + + $qb->select('share_type', 'share_with') + ->from('share') + ->where( + $or + ) + ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) + ->andWhere($qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) + )); + $cursor = $qb->execute(); + + $users = []; + $link = false; + while($row = $cursor->fetch()) { + $type = (int)$row['share_type']; + if ($type === \OCP\Share::SHARE_TYPE_USER) { + $uid = $row['share_with']; + $users[$uid] = isset($users[$uid]) ? $users[$uid] + 1 : 1; + } else if ($type === \OCP\Share::SHARE_TYPE_GROUP) { + $gid = $row['share_with']; + $group = $this->groupManager->get($gid); + + if ($gid === null) { + continue; + } + + $userList = $group->getUsers(); + foreach ($userList as $user) { + $users[$user->getUID()] = isset($users[$user->getUID()]) ? $users[$user->getUID()] + 1 : 1; + } + } else if ($type === \OCP\Share::SHARE_TYPE_LINK) { + $link = true; + } else if ($type === self::SHARE_TYPE_USERGROUP) { + if ($currentAccess === true) { + $uid = $row['share_with']; + $users[$uid] = isset($users[$uid]) ? $users[$uid] - 1 : -1; + } + } + } + $cursor->closeCursor(); + + $users = array_filter($users, function($count) { + return $count > 0; + }); + + return ['users' => array_keys($users), 'public' => $link, 'remote' => false]; + } } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index d93883e95d4..096d05fbec3 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -1200,69 +1200,50 @@ class Manager implements IManager { * * @param \OCP\Files\Node $path * @param bool $recursive Should we check all parent folders as well + * @param bool $currentAccess Should the user have currently access to the file * @return array */ - public function getAccessList(\OCP\Files\Node $path, $recursive = true) { + public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) { $owner = $path->getOwner()->getUID(); + $al = ['users' => [], 'public' => false, 'remote' => false]; + if (!$this->userManager->userExists($owner)) { + return $al; + } + //Get node for the owner $userFolder = $this->rootFolder->getUserFolder($owner); - if (!$userFolder->isSubNode($path)) { $path = $userFolder->getById($path->getId())[0]; } $providers = $this->factory->getAllProviders(); - /** @var IShare[] $shares */ - $shares = []; + /** @var Node[] $nodes */ + $nodes = []; + + $al['users'][] = $owner; // Collect all the shares while ($path->getPath() !== $userFolder->getPath()) { - foreach ($providers as $provider) { - $shares = array_merge($shares, $provider->getSharesByPath($path)); - } + $nodes[] = $path; if (!$recursive) { break; } $path = $path->getParent(); } - $users = [$owner => 'null']; - $public = false; - $remote = false; - foreach ($shares as $share) { - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { - $uid = $share->getSharedWith(); - - // Skip if user does not exist - if (!$this->userManager->userExists($uid)) { - continue; - } - - $users[$uid] = null; - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { - $group = $this->groupManager->get($share->getSharedWith()); + foreach ($providers as $provider) { + $tmp = $provider->getAccessList($nodes, $currentAccess); - // If group does not exist skip - if ($group === null) { - continue; - } - - $groupUsers = $group->getUsers(); - foreach ($groupUsers as $groupUser) { - $users[$groupUser->getUID()] = null; - } - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { - $public = true; - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { - $remote = true; - } + $al['users'] = array_merge($al['users'], $tmp['users']); + $al['public'] = $al['public'] || $tmp['public']; + $al['remote'] = $al['remote'] || $tmp['remote']; } - $users = array_keys($users); + $al['users'] = array_unique($al['users']); - return ['users' => $users, 'public' => $public, 'remote' => $remote]; + return $al; } /** diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php index 6257c97eb77..2533e81abf2 100644 --- a/lib/public/Share/IShareProvider.php +++ b/lib/public/Share/IShareProvider.php @@ -190,4 +190,21 @@ interface IShareProvider { * @since 9.1.0 */ public function userDeletedFromGroup($uid, $gid); + + /** + * Get the access list to the array of provided nodes. + * Return will look like: + * + * [ + * users => ['user1', 'user2', 'user4'], + * public => bool + * remote => bool + * ] + * + * @param Node[] $nodes The list of nodes to get access for + * @param bool $currentAccess If current access is required (like for removed shares that might get revived later) + * @return string[] + * @since 12 + */ + public function getAccessList($nodes, $currentAccess); } |