From 940a4bb151f844c2b1bc26e2ac4ef475791109b0 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 29 Jan 2026 20:58:02 +0100 Subject: [PATCH 1/2] test(mention): Correctly assert that users are added to room when mentioned This was implemented in Talk 6 with nextcloud/spreed#1641 It seems a bug in the file handling prevented success Ref 99b96b08ca7fbf52e37112240d2f9b9be14f9f8a Signed-off-by: Joas Schilling --- tests/integration/features/chat-2/mentions.feature | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration/features/chat-2/mentions.feature b/tests/integration/features/chat-2/mentions.feature index 66e935a7f38..012809675eb 100644 --- a/tests/integration/features/chat-2/mentions.feature +++ b/tests/integration/features/chat-2/mentions.feature @@ -573,8 +573,11 @@ Feature: chat-2/mentions And user "guest" joins room "file last share room" with 200 (v4) And user "participant2" is not participant of room "file last share room" (v4) When user "participant3" sends message "hi @participant2" to room "file last share room" with 201 + And user "participant2" is participant of room "file last share room" (v4) + And user "participant2" removes themselves from room "file last share room" with 200 (v4) + And user "participant2" is not participant of room "file last share room" (v4) And user "guest" sends message "hello @participant2" to room "file last share room" with 201 - Then user "participant2" is not participant of room "file last share room" (v4) + Then user "participant2" is participant of room "file last share room" (v4) Scenario: mention a participant without access to the file but joined in a room for a file shared by link Given user "participant1" shares "welcome.txt" with user "participant2" with OCS 100 From 1dac64b3df325bab652283854c87017f8c98bcb0 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 3 Feb 2026 19:46:42 +0100 Subject: [PATCH 2/2] perf(sharing): Use `getFirstNodeById()` and limit to IUserFolder Signed-off-by: Joas Schilling --- lib/Chat/AutoComplete/SearchPlugin.php | 6 +++++- lib/Controller/FilesIntegrationController.php | 2 +- lib/Files/Util.php | 15 +++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/Chat/AutoComplete/SearchPlugin.php b/lib/Chat/AutoComplete/SearchPlugin.php index dcb303708de..284aa180c51 100644 --- a/lib/Chat/AutoComplete/SearchPlugin.php +++ b/lib/Chat/AutoComplete/SearchPlugin.php @@ -52,7 +52,11 @@ public function setContext(array $context): void { #[\Override] public function search($search, $limit, $offset, ISearchResult $searchResult): bool { if ($this->room->getObjectType() === 'file') { - $usersWithFileAccess = $this->util->getUsersWithAccessFile($this->room->getObjectId()); + if ($this->userId === null) { + $usersWithFileAccess = $this->util->canGuestsAccessFile($this->room->getObjectId()); + } else { + $usersWithFileAccess = $this->util->getUsersWithAccessFile($this->room->getObjectId(), $this->userId); + } if (!empty($usersWithFileAccess)) { $users = []; foreach ($usersWithFileAccess as $userId) { diff --git a/lib/Controller/FilesIntegrationController.php b/lib/Controller/FilesIntegrationController.php index c5d276ed1d3..67928369a41 100644 --- a/lib/Controller/FilesIntegrationController.php +++ b/lib/Controller/FilesIntegrationController.php @@ -104,7 +104,7 @@ public function getRoomByFileId(string $fileId): DataResponse { throw new OCSNotFoundException($this->l->t('File is not shared, or shared but not with the user')); } - $users = $this->util->getUsersWithAccessFile($fileId); + $users = $this->util->getUsersWithAccessFile($fileId, $currentUser->getUID()); if (count($users) <= 1 && !$this->util->canGuestsAccessFile($fileId)) { throw new OCSNotFoundException($this->l->t('File is not shared, or shared but not with the user')); } diff --git a/lib/Files/Util.php b/lib/Files/Util.php index 0f98479e5d2..1632b30202e 100644 --- a/lib/Files/Util.php +++ b/lib/Files/Util.php @@ -35,15 +35,15 @@ public function __construct( /** * @return string[] */ - public function getUsersWithAccessFile(string $fileId): array { + public function getUsersWithAccessFile(string $fileId, string $userId): array { if (!isset($this->accessLists[$fileId])) { - $nodes = $this->rootFolder->getById((int)$fileId); + $userFolder = $this->rootFolder->getUserFolder($userId); + $node = $userFolder->getFirstNodeById((int)$fileId); - if (empty($nodes)) { + if ($node === null) { return []; } - $node = array_shift($nodes); $accessList = $this->shareManager->getAccessList($node); $accessList['users'] ??= []; if (!$node->getStorage()->instanceOfStorage(SharedStorage::class)) { @@ -64,18 +64,17 @@ public function getUsersWithAccessFile(string $fileId): array { } public function canUserAccessFile(string $fileId, string $userId): bool { - return \in_array($userId, $this->getUsersWithAccessFile($fileId), true); + return \in_array($userId, $this->getUsersWithAccessFile($fileId, $userId), true); } public function canGuestsAccessFile(string $fileId): bool { if (!isset($this->publicAccessLists[$fileId])) { - $nodes = $this->rootFolder->getById((int)$fileId); + $node = $this->rootFolder->getFirstNodeById((int)$fileId); - if (empty($nodes)) { + if ($node === null) { return false; } - $node = array_shift($nodes); $accessList = $this->shareManager->getAccessList($node, false); $this->publicAccessLists[$fileId] = $accessList['public'] ?? false; }