diff --git a/lib/FilesHooks.php b/lib/FilesHooks.php index e858320e6..3177cbb5b 100755 --- a/lib/FilesHooks.php +++ b/lib/FilesHooks.php @@ -30,10 +30,14 @@ use OCA\Activity\Extension\Files; use OCA\Activity\Extension\Files_Sharing; use OCP\Activity\IManager; +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\IConfig; use OCP\IDBConnection; use OCP\IGroup; use OCP\IGroupManager; @@ -82,6 +86,10 @@ class FilesHooks { /** @var CurrentUser */ protected $currentUser; + /** @var IUserMountCache */ + protected $userMountCache; + /** @var IConfig */ + protected $config; /** @var string|bool */ protected $moveCase = false; @@ -94,21 +102,6 @@ class FilesHooks { /** @var string */ protected $oldParentId; - /** - * Constructor - * - * @param IManager $manager - * @param Data $activityData - * @param UserSettings $userSettings - * @param IGroupManager $groupManager - * @param View $view - * @param IRootFolder $rootFolder - * @param IShareHelper $shareHelper - * @param IDBConnection $connection - * @param IURLGenerator $urlGenerator - * @param ILogger $logger - * @param CurrentUser $currentUser - */ public function __construct(IManager $manager, Data $activityData, UserSettings $userSettings, @@ -119,7 +112,9 @@ public function __construct(IManager $manager, IDBConnection $connection, IURLGenerator $urlGenerator, ILogger $logger, - CurrentUser $currentUser) { + CurrentUser $currentUser, + IUserMountCache $userMountCache, + IConfig $config) { $this->manager = $manager; $this->activityData = $activityData; $this->userSettings = $userSettings; @@ -131,6 +126,8 @@ public function __construct(IManager $manager, $this->urlGenerator = $urlGenerator; $this->logger = $logger; $this->currentUser = $currentUser; + $this->userMountCache = $userMountCache; + $this->config = $config; } /** @@ -197,7 +194,19 @@ protected function addNotificationsForFileAction($filePath, $activityType, $subj $this->generateRemoteActivity($accessList['remotes'], $activityType, time(), $this->currentUser->getCloudId(), $accessList['ownerPath']); - $affectedUsers = $accessList['users']; + if ($this->config->getSystemValueBool('activity_use_cached_mountpoints', false)) { + $mountsForFile = $this->userMountCache->getMountsForFileId($fileId); + $affectedUserIds = array_map(function (ICachedMountInfo $mount) { + return $mount->getUser()->getUID(); + }, $mountsForFile); + $affectedPaths = array_map(function (ICachedMountFileInfo $mount) { + return $this->getVisiblePath($mount->getPath()); + }, $mountsForFile); + $affectedUsers = array_combine($affectedUserIds, $affectedPaths); + } else { + $affectedUsers = $accessList['users']; + } + $filteredStreamUsers = $this->userSettings->filterUsersBySetting(array_keys($affectedUsers), 'stream', $activityType); $filteredEmailUsers = $this->userSettings->filterUsersBySetting(array_keys($affectedUsers), 'email', $activityType); @@ -616,15 +625,20 @@ protected function getUserPathsFromPath($path, $uidOwner) { $accessList = $this->shareHelper->getPathsForAccessList($node); $path = $node->getPath(); - $sections = explode('/', $path, 4); + $accessList['ownerPath'] = $this->getVisiblePath($path); + return $accessList; + } - $accessList['ownerPath'] = '/'; + protected function getVisiblePath(string $absolutePath): string { + $sections = explode('/', $absolutePath, 4); + + $path = '/'; if (isset($sections[3])) { // Not the case when a file in root is renamed - $accessList['ownerPath'] .= $sections[3]; + $path .= $sections[3]; } - return $accessList; + return $path; } /** diff --git a/tests/FilesHooksTest.php b/tests/FilesHooksTest.php index 2b0b1241e..a841517bd 100755 --- a/tests/FilesHooksTest.php +++ b/tests/FilesHooksTest.php @@ -23,11 +23,14 @@ namespace OCA\Activity; +use OC\Files\Config\CachedMountFileInfo; use OCA\Activity\Extension\Files; use OCA\Activity\Extension\Files_Sharing; use OCA\Activity\Tests\TestCase; +use OCP\Files\Config\IUserMountCache; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; +use OCP\IConfig; use OCP\ILogger; use OCP\IUser; use OCP\Share\IShare; @@ -36,11 +39,11 @@ use OCP\IGroupManager; use OC\Files\View; use OCP\IURLGenerator; -use PHPUnit\Framework\MockObject\MockObject; use OCP\IGroup; use OCA\Files_Sharing\SharedStorage; use OCP\Files\Mount\IMountPoint; use OCP\Activity\IEvent; +use PHPUnit\Framework\MockObject\MockObject; /** * Class FilesHooksTest @@ -68,6 +71,10 @@ class FilesHooksTest extends TestCase { protected $shareHelper; /** @var IURLGenerator|MockObject */ protected $urlGenerator; + /** @var IUserMountCache|MockObject */ + protected $userMountCache; + /** @var IConfig|MockObject */ + protected $config; protected function setUp(): void { parent::setUp(); @@ -80,6 +87,8 @@ protected function setUp(): void { $this->rootFolder = $this->createMock(IRootFolder::class); $this->shareHelper = $this->createMock(IShareHelper::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->userMountCache = $this->createMock(IUserMountCache::class); + $this->config = $this->createMock(IConfig::class); $this->filesHooks = $this->getFilesHooks(); } @@ -114,6 +123,8 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user $this->urlGenerator, $logger, $currentUser, + $this->userMountCache, + $this->config, ]) ->onlyMethods($mockedMethods) ->getMock(); @@ -130,7 +141,9 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user \OC::$server->getDatabaseConnection(), $this->urlGenerator, $logger, - $currentUser + $currentUser, + $this->userMountCache, + $this->config ); } @@ -238,11 +251,12 @@ public function dataAddNotificationsForFileAction(): array { [['user', 'user1', 'user2'], 'stream', Files::TYPE_SHARE_RESTORED, ['user' => true]], [['user', 'user1', 'user2'], 'email', Files::TYPE_SHARE_RESTORED, ['user' => 42]], ], + 'mountcache_used' => false, [ 'user' => [ 'subject' => 'restored_self', - 'subject_params' => [[1337 => '/user/path']], - 'path' => '/user/path', + 'subject_params' => [[1337 => '/user/files/path']], + 'path' => '/user/files/path', 'stream' => true, 'email' => 42, ], @@ -253,11 +267,44 @@ public function dataAddNotificationsForFileAction(): array { [['user', 'user1', 'user2'], 'stream', Files::TYPE_SHARE_RESTORED, ['user1' => true]], [['user', 'user1', 'user2'], 'email', Files::TYPE_SHARE_RESTORED, []], ], + 'mountcache_used' => false, [ 'user1' => [ 'subject' => 'restored_by', - 'subject_params' => [[1337 => '/user1/path'], 'user'], - 'path' => '/user1/path', + 'subject_params' => [[1337 => '/user1/files/path'], 'user'], + 'path' => '/user1/files/path', + 'stream' => true, + 'email' => 0, + ], + ], + ], + [ + [ + [['user', 'user1', 'user2'], 'stream', Files::TYPE_SHARE_RESTORED, ['user' => true]], + [['user', 'user1', 'user2'], 'email', Files::TYPE_SHARE_RESTORED, ['user' => 42]], + ], + 'mountcache_used' => true, + [ + 'user' => [ + 'subject' => 'restored_self', + 'subject_params' => [[1337 => '/path']], + 'path' => '/path', + 'stream' => true, + 'email' => 42, + ], + ], + ], + [ + [ + [['user', 'user1', 'user2'], 'stream', Files::TYPE_SHARE_RESTORED, ['user1' => true]], + [['user', 'user1', 'user2'], 'email', Files::TYPE_SHARE_RESTORED, []], + ], + 'mountcache_used' => true, + [ + 'user1' => [ + 'subject' => 'restored_by', + 'subject_params' => [[1337 => '/path'], 'user'], + 'path' => '/path', 'stream' => true, 'email' => 0, ], @@ -270,9 +317,10 @@ public function dataAddNotificationsForFileAction(): array { * @dataProvider dataAddNotificationsForFileAction * * @param array $filterUsers + * @param bool $mountCacheUsed * @param array $addNotifications */ - public function testAddNotificationsForFileAction(array $filterUsers, array $addNotifications): void { + public function testAddNotificationsForFileAction(array $filterUsers, bool $mountCacheUsed, array $addNotifications): void { $filesHooks = $this->getFilesHooks([ 'getSourcePathAndOwner', 'getUserPathsFromPath', @@ -289,13 +337,55 @@ public function testAddNotificationsForFileAction(array $filterUsers, array $add ->willReturn([ 'ownerPath' => '/owner/path', 'users' => [ - 'user' => '/user/path', - 'user1' => '/user1/path', - 'user2' => '/user2/path', + 'user' => '/user/files/path', + 'user1' => '/user1/files/path', + 'user2' => '/user2/files/path', ], 'remotes' => [], ]); + $this->config->expects($this->once()) + ->method('getSystemValueBool') + ->with('activity_use_cached_mountpoints', false) + ->willReturn($mountCacheUsed); + + if ($mountCacheUsed) { + $this->userMountCache->expects($this->once()) + ->method('getMountsForFileId') + ->willReturn([ + new CachedMountFileInfo( + $this->getUserMock('user'), + 1, + 1, + '/user/files/', + null, + '', + 'path' + ), + new CachedMountFileInfo( + $this->getUserMock('user1'), + 1, + 1, + '/user1/files/', + null, + '', + 'path' + ), + new CachedMountFileInfo( + $this->getUserMock('user2'), + 1, + 1, + '/user2/files/', + null, + '', + 'path' + ) + ]); + } else { + $this->userMountCache->expects($this->never()) + ->method('getMountsForFileId'); + } + $this->settings->expects($this->exactly(2)) ->method('filterUsersBySetting') ->willReturnMap($filterUsers); @@ -853,7 +943,7 @@ public function dataAddNotificationsForUser(): array { ['notAuthor', 'subject', ['parameter'], 42, 'path/subpath', 'path', true, false, true, Files::TYPE_SHARE_CREATED, false, false, 'files', false, true], ['notAuthor', 'subject', ['parameter'], 0, 'path/subpath', 'path', true, false, true, Files::TYPE_SHARE_CREATED, false, false, 'files', false, true], ['notAuthor', 'subject', ['parameter'], 0, 'path/subpath', 'path', true, false, true, Files::TYPE_SHARE_CREATED, false, false, 'files', false, true], - ['notAuthor', 'subject', ['parameter'], 0, 'path/subpath','path/subpath', false, false, true, Files::TYPE_SHARE_CREATED, false, false, 'files', false, true], + ['notAuthor', 'subject', ['parameter'], 0, 'path/subpath', 'path/subpath', false, false, true, Files::TYPE_SHARE_CREATED, false, false, 'files', false, true], ]; }