Return the paths for the users without setting them all up
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
parent
0c2dc3bc8c
commit
91e650791d
|
@ -983,18 +983,23 @@ class FederatedShareProvider implements IShareProvider {
|
|||
}
|
||||
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->select('share_with')
|
||||
$qb->select('share_with', 'file_source', 'file_target')
|
||||
->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;
|
||||
$remote = [];
|
||||
while ($row = $cursor->fetch()) {
|
||||
$remote[$row['share_with']] = [
|
||||
'node_id' => $row['file_source'],
|
||||
'node_path' => $row['file_target'],
|
||||
];
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
return ['remote' => $remote];
|
||||
|
|
|
@ -95,14 +95,14 @@ class File implements \OCP\Encryption\IFile {
|
|||
$this->cache[$parent] = $resultForParents;
|
||||
}
|
||||
$userIds = \array_merge($userIds, $resultForParents['users']);
|
||||
$public = $resultForParents['public'] || $resultForParents['remote'];
|
||||
$public = $resultForParents['public'] || !empty($resultForParents['remote']);
|
||||
|
||||
|
||||
// Find out who, if anyone, is sharing the file
|
||||
if ($file !== null) {
|
||||
$resultForFile = $this->shareManager->getAccessList($file, false);
|
||||
$userIds = array_merge($userIds, $resultForFile['users']);
|
||||
$public = $resultForFile['public'] || $resultForFile['remote'] || $public;
|
||||
$public = $resultForFile['public'] || !empty($resultForFile['remote']) || $public;
|
||||
}
|
||||
|
||||
// check if it is a group mount
|
||||
|
|
|
@ -1092,7 +1092,7 @@ class DefaultShareProvider implements IShareProvider {
|
|||
$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
|
||||
}
|
||||
|
||||
$qb->select('share_type', 'share_with')
|
||||
$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
|
||||
->from('share')
|
||||
->where(
|
||||
$or
|
||||
|
@ -1110,7 +1110,8 @@ class DefaultShareProvider implements IShareProvider {
|
|||
$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;
|
||||
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||
$users[$uid][$row['id']] = $row;
|
||||
} else if ($type === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||
$gid = $row['share_with'];
|
||||
$group = $this->groupManager->get($gid);
|
||||
|
@ -1121,23 +1122,60 @@ class DefaultShareProvider implements IShareProvider {
|
|||
|
||||
$userList = $group->getUsers();
|
||||
foreach ($userList as $user) {
|
||||
$users[$user->getUID()] = isset($users[$user->getUID()]) ? $users[$user->getUID()] + 1 : 1;
|
||||
$uid = $user->getUID();
|
||||
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||
$users[$uid][$row['id']] = $row;
|
||||
}
|
||||
} 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;
|
||||
$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
|
||||
$users[$uid][$row['id']] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
$users = array_filter($users, function($count) {
|
||||
return $count > 0;
|
||||
});
|
||||
$users = array_map([$this, 'filterSharesOfUser'], $users);
|
||||
|
||||
return ['users' => array_keys($users), 'public' => $link];
|
||||
return ['users' => $users, 'public' => $link];
|
||||
}
|
||||
|
||||
/**
|
||||
* For each user the path with the fewest slashes is returned
|
||||
* @param array $shares
|
||||
* @return array
|
||||
*/
|
||||
protected function filterSharesOfUser(array $shares) {
|
||||
// Group shares when the user has a share exception
|
||||
foreach ($shares as $id => $share) {
|
||||
$type = (int) $share['share_type'];
|
||||
$permissions = (int) $share['permissions'];
|
||||
|
||||
if ($type === self::SHARE_TYPE_USERGROUP) {
|
||||
unset($shares[$share['parent']]);
|
||||
|
||||
if ($permissions === 0) {
|
||||
unset($shares[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$best = [];
|
||||
$bestDepth = 0;
|
||||
foreach ($shares as $id => $share) {
|
||||
$depth = substr_count($share['file_target'], '/');
|
||||
if (empty($best) || $depth < $bestDepth) {
|
||||
$bestDepth = $depth;
|
||||
$best = [
|
||||
'node_id' => $share['file_source'],
|
||||
'node_path' => $share['file_target'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $best;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1191,9 +1191,10 @@ class Manager implements IManager {
|
|||
*
|
||||
* Then the access list will to '/folder1/folder2/fileA' is:
|
||||
* [
|
||||
* users => ['user1', 'user2', 'user4'],
|
||||
* users => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* remote => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* public => bool
|
||||
* remote => bool
|
||||
* mail => bool
|
||||
* ]
|
||||
*
|
||||
* This is required for encryption/activity
|
||||
|
@ -1206,7 +1207,7 @@ class Manager implements IManager {
|
|||
public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
|
||||
$owner = $path->getOwner()->getUID();
|
||||
|
||||
$al = ['users' => [], 'public' => false, 'remote' => false];
|
||||
$al = ['users' => [], 'remote' => [], 'public' => false];
|
||||
if (!$this->userManager->userExists($owner)) {
|
||||
return $al;
|
||||
}
|
||||
|
@ -1222,7 +1223,12 @@ class Manager implements IManager {
|
|||
/** @var Node[] $nodes */
|
||||
$nodes = [];
|
||||
|
||||
$al['users'][] = $owner;
|
||||
$ownerPath = $path->getPath();
|
||||
list(,,,$ownerPath) = explode('/', $ownerPath, 4);
|
||||
$al['users'][$owner] = [
|
||||
'node_id' => $path->getId(),
|
||||
'node_path' => '/' . $ownerPath,
|
||||
];
|
||||
|
||||
// Collect all the shares
|
||||
while ($path->getPath() !== $userFolder->getPath()) {
|
||||
|
@ -1249,8 +1255,6 @@ class Manager implements IManager {
|
|||
}
|
||||
}
|
||||
|
||||
$al['users'] = array_unique($al['users']);
|
||||
|
||||
return $al;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,43 +22,113 @@
|
|||
*/
|
||||
namespace OC\Share20;
|
||||
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShareHelper;
|
||||
|
||||
class ShareHelper {
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
class ShareHelper implements IShareHelper {
|
||||
|
||||
public function __construct(IRootFolder $rootFolder) {
|
||||
$this->rootFolder = $rootFolder;
|
||||
/** @var IManager */
|
||||
private $shareManager;
|
||||
|
||||
public function __construct(IManager $shareManager) {
|
||||
$this->shareManager = $shareManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a user has access to a file
|
||||
*
|
||||
* @param Node $node
|
||||
* @param array $users Array of userIds
|
||||
* @return array Mapping $uid to an array of nodes
|
||||
* @return array [ users => [Mapping $uid => $path], remotes => [Mapping $cloudId => $path]]
|
||||
*/
|
||||
public function getPathsForAccessList(Node $node, $users) {
|
||||
$result = [];
|
||||
public function getPathsForAccessList(Node $node) {
|
||||
$result = [
|
||||
'users' => [],
|
||||
'remotes' => [],
|
||||
];
|
||||
|
||||
foreach ($users as $user) {
|
||||
try {
|
||||
$userFolder = $this->rootFolder->getUserFolder($user);
|
||||
} catch (NotFoundException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nodes = $userFolder->getById($node->getId());
|
||||
if ($nodes === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[$user] = $nodes;
|
||||
$accessList = $this->shareManager->getAccessList($node, true, true);
|
||||
if (!empty($accessList['users'])) {
|
||||
$result['users'] = $this->getPathsForUsers($node, $accessList['users']);
|
||||
}
|
||||
if (!empty($accessList['remote'])) {
|
||||
$result['remotes'] = $this->getPathsForRemotes($node, $accessList['remote']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getPathsForUsers(Node $node, array $users) {
|
||||
$byId = $results = [];
|
||||
foreach ($users as $uid => $info) {
|
||||
if (!isset($byId[$info['node_id']])) {
|
||||
$byId[$info['node_id']] = [];
|
||||
}
|
||||
$byId[$info['node_id']][$uid] = $info['node_path'];
|
||||
}
|
||||
|
||||
if (isset($byId[$node->getId()])) {
|
||||
foreach ($byId[$node->getId()] as $uid => $path) {
|
||||
$results[$uid] = $path;
|
||||
}
|
||||
unset($byId[$node->getId()]);
|
||||
}
|
||||
|
||||
if (empty($byId)) {
|
||||
return $results;
|
||||
}
|
||||
|
||||
$item = $node;
|
||||
$appendix = '/' . $node->getName();
|
||||
while (!empty($byId)) {
|
||||
$item = $item->getParent();
|
||||
|
||||
if (!empty($byId[$item->getId()])) {
|
||||
foreach ($byId[$item->getId()] as $uid => $path) {
|
||||
$results[$uid] = $path . $appendix;
|
||||
}
|
||||
unset($byId[$item->getId()]);
|
||||
}
|
||||
|
||||
$appendix = '/' . $item->getName() . $appendix;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function getPathsForRemotes(Node $node, array $remotes) {
|
||||
$byId = $results = [];
|
||||
foreach ($remotes as $cloudId => $info) {
|
||||
if (!isset($byId[$info['node_id']])) {
|
||||
$byId[$info['node_id']] = [];
|
||||
}
|
||||
$byId[$info['node_id']][$cloudId] = $info['node_path'];
|
||||
}
|
||||
|
||||
if (isset($byId[$node->getId()])) {
|
||||
foreach ($byId[$node->getId()] as $cloudId => $_) {
|
||||
$results[$cloudId] = '/' . $node->getName();
|
||||
}
|
||||
unset($byId[$node->getId()]);
|
||||
}
|
||||
|
||||
if (empty($byId)) {
|
||||
return $results;
|
||||
}
|
||||
|
||||
$item = $node;
|
||||
$path = '/' . $node->getName();
|
||||
while (!empty($byId)) {
|
||||
$item = $item->getParent();
|
||||
|
||||
if (!empty($byId[$item->getId()])) {
|
||||
foreach ($byId[$item->getId()] as $uid => $_) {
|
||||
$results[$uid] = $path;
|
||||
}
|
||||
unset($byId[$item->getId()]);
|
||||
}
|
||||
|
||||
$path = '/' . $item->getName() . $path;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,9 +207,10 @@ interface IManager {
|
|||
*
|
||||
* Then the access list will to '/folder1/folder2/fileA' is:
|
||||
* [
|
||||
* users => ['user1', 'user2', 'user4'],
|
||||
* users => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* remote => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* public => bool
|
||||
* remote => bool
|
||||
* mail => bool
|
||||
* ]
|
||||
*
|
||||
* This is required for encryption/activity
|
||||
|
|
|
@ -33,12 +33,9 @@ use OCP\Files\Node;
|
|||
interface IShareHelper {
|
||||
|
||||
/**
|
||||
* If a user has access to a file
|
||||
*
|
||||
* @param Node $node
|
||||
* @param array $users Array of userIds
|
||||
* @return array Mapping $uid to an array of nodes
|
||||
* @return array [ users => [Mapping $uid => $path], remotes => [Mapping $cloudId => $path]]
|
||||
* @since 12
|
||||
*/
|
||||
public function getPathsForAccessList(Node $node, $users);
|
||||
public function getPathsForAccessList(Node $node);
|
||||
}
|
||||
|
|
|
@ -196,14 +196,15 @@ interface IShareProvider {
|
|||
* Return will look like:
|
||||
*
|
||||
* [
|
||||
* users => ['user1', 'user2', 'user4'],
|
||||
* users => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* remote => ['user1' => ['node_id' => 42, 'node_path' => '/path'], 'user2' => [...]],
|
||||
* mail => bool
|
||||
* 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[]
|
||||
* @return array
|
||||
* @since 12
|
||||
*/
|
||||
public function getAccessList($nodes, $currentAccess);
|
||||
|
|
Loading…
Reference in New Issue