Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a method to get all users with access to a file in OCP #38946

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 3 additions & 17 deletions apps/comments/lib/Activity/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use OCP\Comments\CommentsEvent;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShareHelper;
Expand All @@ -36,24 +35,11 @@ public function commentEvent(CommentsEvent $event): void {
return;
}

// Get all mount point owners
$cache = $this->mountCollection->getMountCache();
$mounts = $cache->getMountsForFileId((int)$event->getComment()->getObjectId());
if (empty($mounts)) {
return;
}

$users = [];
foreach ($mounts as $mount) {
$owner = $mount->getUser()->getUID();
$ownerFolder = $this->rootFolder->getUserFolder($owner);
$nodes = $ownerFolder->getById((int)$event->getComment()->getObjectId());
if (!empty($nodes)) {
/** @var Node $node */
$node = array_shift($nodes);
$al = $this->shareHelper->getPathsForAccessList($node);
$users += $al['users'];
}
$users = $cache->getReadablePathByUserForFileId((int)$event->getComment()->getObjectId());
if (empty($users)) {
return;
}

$actor = $this->session->getUser();
Expand Down
19 changes: 3 additions & 16 deletions apps/systemtags/lib/Activity/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use OCP\App\IAppManager;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
Expand Down Expand Up @@ -153,22 +152,10 @@ public function mapperEvent(MapperEvent $event) {

// Get all mount point owners
$cache = $this->mountCollection->getMountCache();
$mounts = $cache->getMountsForFileId($event->getObjectId());
if (empty($mounts)) {
return;
}

$users = [];
foreach ($mounts as $mount) {
$owner = $mount->getUser()->getUID();
$ownerFolder = $this->rootFolder->getUserFolder($owner);
$nodes = $ownerFolder->getById($event->getObjectId());
if (!empty($nodes)) {
/** @var Node $node */
$node = array_shift($nodes);
$al = $this->shareHelper->getPathsForAccessList($node);
$users += $al['users'];
}
$users = $cache->getReadablePathByUserForFileId((int)$event->getObjectId());
if (empty($users)) {
return;
}

$actor = $this->session->getUser();
Expand Down
13 changes: 1 addition & 12 deletions core/Command/Info/FileUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,7 @@ public function getFilesByUser(FileInfo $file): array {
return [];
}

$mounts = $this->userMountCache->getMountsForFileId($id);
$result = [];
foreach ($mounts as $mount) {
if (isset($result[$mount->getUser()->getUID()])) {
continue;
}

$userFolder = $this->rootFolder->getUserFolder($mount->getUser()->getUID());
$result[$mount->getUser()->getUID()] = $userFolder->getById($id);
}

return $result;
return $this->userMountCache->getReadableNodesByUserForFileId($id);
}

/**
Expand Down
59 changes: 59 additions & 0 deletions lib/private/Files/Config/UserMountCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
use OCP\Files\Config\ICachedMountFileInfo;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Server;
use Psr\Log\LoggerInterface;

/**
Expand Down Expand Up @@ -380,6 +384,61 @@ public function getMountsForFileId($fileId, $user = null) {
}, $filteredMounts);
}

/**
* Get all nodes that give access to a file
*
* @return array<string, Node[]> Nodes giving access to the given fileId, indexed by user ID
* @since 28.0.0
*/
public function getReadableNodesByUserForFileId(int $fileId): array {
$mounts = $this->getMountsForFileId($fileId);
$rootFolder = Server::get(IRootFolder::class);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Can this be added to the DI or is there a problem with that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make more sense to move this method to the RootFolder instead

Fixed Show fixed Hide fixed
$result = [];
foreach ($mounts as $mount) {
$uid = $mount->getUser()->getUID();
if (!isset($result[$uid])) {
$result[$uid] = [];
}

$userFolder = $rootFolder->getUserFolder($uid);
$result[$uid] = array_merge($result[$uid], $userFolder->getById($fileId));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that there should be a more efficient way to do this here since we already know the mount.

Perhaps extracting some of the logic from RootFolder::getByIdInPath to create a RootFolder::getByIdInMounts or similar.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #40482 (comment) for some alternate discussion around the same problem

}

return array_filter($result);
}

/**
* Get all users having read access to a file, with a path they see it as.
* They may see the same file under other paths,
* to get this information use the exhaustive getReadableNodesByUserForFileId
*
* @return array<string,string> Paths giving access to the given fileId, indexed by user ID
Fixed Show fixed Hide fixed
* @since 28.0.0
*/
public function getReadablePathByUserForFileId(int $fileId): array {
$mounts = $this->getMountsForFileId($fileId);
$rootFolder = Server::get(IRootFolder::class);
$result = [];
foreach ($mounts as $mount) {
$uid = $mount->getUser()->getUID();
if (isset($result[$uid])) {
continue;
}

$userFolder = $rootFolder->getUserFolder($uid);
$nodes = $userFolder->getById($fileId);
$node = reset($nodes);
if ($node) {
$path = $userFolder->getRelativePath($node->getPath());
if ($path !== null) {
$result[$uid] = $path;
}
}
}

return $result;
Fixed Show fixed Hide fixed
}

/**
* Remove all cached mounts for a user
*
Expand Down
18 changes: 18 additions & 0 deletions lib/public/Files/Config/IUserMountCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace OCP\Files\Config;

use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IUser;

Expand Down Expand Up @@ -65,6 +66,23 @@ public function getMountsForRootId($rootFileId);
*/
public function getMountsForFileId($fileId, $user = null);

/**
* Get all cached nodes that give access to a file
*
* @return array<string, Node[]> Nodes giving access to the given fileId, indexed by user ID
* @since 28.0.0
*/
public function getReadableNodesByUserForFileId(int $fileId): array;

/**
* Get all users having read access to a file, with a path they see it as.
* They may see the same file under other paths, to get this information use exhaustive getReadableNodesByUserForFileId
*
* @return array<string, string> Paths giving access to the given fileId, indexed by user ID
* @since 28.0.0
*/
public function getReadablePathByUserForFileId(int $fileId): array;

/**
* Remove all cached mounts for a user
*
Expand Down
Loading