Skip to content

Commit

Permalink
Offload acceslist creation to providers
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
rullzer committed Dec 23, 2016
1 parent 2d2e5f8 commit 2309e25
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 82 deletions.
25 changes: 25 additions & 0 deletions apps/federatedfilesharing/lib/FederatedShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
namespace OCA\FederatedFileSharing;

use OC\Share20\Share;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\IConfig;
Expand Down Expand Up @@ -953,4 +954,28 @@ public function isLookupServerQueriesEnabled() {
$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
return ($result === 'yes') ? true : false;
}

public function getAccessList($nodes, $currentAccess) {
$ids = [];
foreach ($nodes as $node) {
$ids[] = $node->getId();
}

$qb = $this->dbConnection->getQueryBuilder();
$qb->select('share_with')
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
->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'))
))
->setMaxResults(1);
$cursor = $qb->execute();

$remote = $cursor->fetch() !== false;
$cursor->closeCursor();

return ['users' => [], 'remote' => $remote, 'public' => false];
}
}
4 changes: 4 additions & 0 deletions apps/sharebymail/lib/ShareByMailProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -767,4 +767,8 @@ public function getSharesInFolder($userId, Folder $node, $reshares) {
return $shares;
}

public function getAccessList($nodes, $currentAccess) {
return ['users' => [], 'remote' => false, 'public' => false];
}

}
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@
'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',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,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',
Expand Down
76 changes: 73 additions & 3 deletions lib/private/Share20/DefaultShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ public function deleteFromSelf(\OCP\Share\IShare $share, $recipient) {
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')
Expand All @@ -366,8 +366,8 @@ public function deleteFromSelf(\OCP\Share\IShare $share, $recipient) {
'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()),
Expand Down Expand Up @@ -1062,4 +1062,74 @@ public function userDeletedFromGroup($uid, $gid) {
}
}
}

/**
* @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];
}
}
57 changes: 19 additions & 38 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -1194,69 +1194,50 @@ public function userDeletedFromGroup($uid, $gid) {
*
* @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;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions lib/public/Share/IShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,21 @@ public function groupDeleted($gid);
* @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);
}
Loading

0 comments on commit 2309e25

Please sign in to comment.