Merge pull request #55643 from nextcloud/backport/55080/stable31

[stable31] fix(sharing): Adapt share suggestions to match trusted servers configs
This commit is contained in:
F. E Noel Nfebe 2025-11-11 13:26:52 +01:00 committed by GitHub
commit 28fbe238dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 62 additions and 25 deletions

View file

@ -254,10 +254,12 @@ export default {
// remove invalid data and format to user-select layout
const exactSuggestions = this.filterOutExistingShares(rawExactSuggestions)
.filter(result => this.filterByTrustedServer(result))
.map(share => this.formatForMultiselect(share))
// sort by type so we can get user&groups first...
.sort((a, b) => a.shareType - b.shareType)
const suggestions = this.filterOutExistingShares(rawSuggestions)
.filter(result => this.filterByTrustedServer(result))
.map(share => this.formatForMultiselect(share))
// sort by type so we can get user&groups first...
.sort((a, b) => a.shareType - b.shareType)
@ -340,6 +342,7 @@ export default {
// remove invalid data and format to user-select layout
this.recommendations = this.filterOutExistingShares(rawRecommendations)
.filter(result => this.filterByTrustedServer(result))
.map(share => this.formatForMultiselect(share))
.concat(externalResults)
@ -462,6 +465,20 @@ export default {
}
},
/**
* Filter suggestion results based on trusted server configuration
*
* @param {object} result The raw suggestion result from API
* @return {boolean} Whether to include this result in suggestions
*/
filterByTrustedServer(result) {
const isRemoteEntity = result.value.shareType === ShareType.Remote || result.value.shareType === ShareType.RemoteGroup
if (isRemoteEntity && this.config.showFederatedSharesToTrustedServersAsInternal) {
return result.value.isTrustedServer === true
}
return true
},
/**
* Format shares for the multiselect options
*

2
dist/1406-1406.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/1406-1406.js.map vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/1406-1406.js.map.license vendored Symbolic link
View file

@ -0,0 +1 @@
1406-1406.js.license

2
dist/3798-3798.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
3798-3798.js.license

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5,11 +5,13 @@
*/
namespace OC\Collaboration\Collaborators;
use OCA\Federation\TrustedServers;
use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\Contacts\IManager;
use OCP\Federation\ICloudIdManager;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IUserManager;
use OCP\IUserSession;
@ -26,17 +28,20 @@ class RemotePlugin implements ISearchPlugin {
private IConfig $config,
private IUserManager $userManager,
IUserSession $userSession,
private IAppConfig $appConfig,
private ?TrustedServers $trustedServers,
) {
$this->userId = $userSession->getUser()?->getUID() ?? '';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
}
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$resultType = new SearchResultType('remotes');
// Search in contacts
$addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN'], [
$addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN', 'EMAIL'], [
'limit' => $limit,
'offset' => $offset,
'enumeration' => false,
@ -66,9 +71,6 @@ class RemotePlugin implements ISearchPlugin {
}
$localUser = $this->userManager->get($remoteUser);
/**
* Add local share if remote cloud id matches a local user ones
*/
if ($localUser !== null && $remoteUser !== $this->userId && $cloudId === $localUser->getCloudId()) {
$result['wide'][] = [
'label' => $contact['FN'],
@ -81,7 +83,17 @@ class RemotePlugin implements ISearchPlugin {
];
}
if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
$emailMatch = false;
if (isset($contact['EMAIL'])) {
$emails = is_array($contact['EMAIL']) ? $contact['EMAIL'] : [$contact['EMAIL']];
foreach ($emails as $email) {
if (is_string($email) && strtolower($email) === $lowerSearch) {
$emailMatch = true;
break;
}
}
}
if ($emailMatch || strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
if (strtolower($cloudId) === $lowerSearch) {
$searchResult->markExactIdMatch($resultType);
}
@ -94,6 +106,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers?->isTrustedServer($serverUrl) ?? false,
],
];
} else {
@ -106,6 +119,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers?->isTrustedServer($serverUrl) ?? false,
],
];
}
@ -119,9 +133,6 @@ class RemotePlugin implements ISearchPlugin {
$result['wide'] = array_slice($result['wide'], $offset, $limit);
}
/**
* Add generic share with remote item for valid cloud ids that are not users of the local instance
*/
if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
try {
[$remoteUser, $serverUrl] = $this->splitUserRemote($search);
@ -135,6 +146,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $search,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers?->isTrustedServer($serverUrl) ?? false,
],
];
}

View file

@ -9,10 +9,12 @@ namespace Test\Collaboration\Collaborators;
use OC\Collaboration\Collaborators\RemotePlugin;
use OC\Collaboration\Collaborators\SearchResult;
use OC\Federation\CloudIdManager;
use OCA\Federation\TrustedServers;
use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\Contacts\IManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudIdManager;
use OCP\IAppConfig;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IURLGenerator;
@ -20,6 +22,7 @@ use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\IShare;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RemotePluginTest extends TestCase {
@ -35,6 +38,9 @@ class RemotePluginTest extends TestCase {
/** @var ICloudIdManager|\PHPUnit\Framework\MockObject\MockObject */
protected $cloudIdManager;
protected IAppConfig|MockObject $appConfig;
protected TrustedServers|MockObject $trustedServers;
/** @var RemotePlugin */
protected $plugin;
@ -54,6 +60,8 @@ class RemotePluginTest extends TestCase {
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class)
);
$this->appConfig = $this->createMock(IAppConfig::class);
$this->trustedServers = $this->createMock(TrustedServers::class);
$this->searchResult = new SearchResult();
}
@ -66,7 +74,7 @@ class RemotePluginTest extends TestCase {
$userSession->expects($this->any())
->method('getUser')
->willReturn($user);
$this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->userManager, $userSession);
$this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->userManager, $userSession, $this->appConfig, $this->trustedServers);
}
/**
@ -149,7 +157,7 @@ class RemotePluginTest extends TestCase {
'test@remote',
[],
true,
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote'], 'uuid' => 'test', 'name' => 'test']]]],
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote', 'isTrustedServer' => false], 'uuid' => 'test', 'name' => 'test']]]],
false,
true,
],
@ -157,7 +165,7 @@ class RemotePluginTest extends TestCase {
'test@remote',
[],
false,
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote'], 'uuid' => 'test', 'name' => 'test']]]],
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote', 'isTrustedServer' => false], 'uuid' => 'test', 'name' => 'test']]]],
false,
true,
],
@ -183,7 +191,7 @@ class RemotePluginTest extends TestCase {
],
],
true,
['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => []]],
['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost', 'isTrustedServer' => false]]], 'exact' => ['remotes' => []]],
false,
true,
],
@ -235,7 +243,7 @@ class RemotePluginTest extends TestCase {
],
],
true,
['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote'], 'uuid' => 'test', 'name' => 'test']]]],
['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost', 'isTrustedServer' => false]]], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote', 'isTrustedServer' => false], 'uuid' => 'test', 'name' => 'test']]]],
false,
true,
],
@ -261,7 +269,7 @@ class RemotePluginTest extends TestCase {
],
],
false,
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote'], 'uuid' => 'test', 'name' => 'test']]]],
['remotes' => [], 'exact' => ['remotes' => [['label' => 'test (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'test@remote', 'server' => 'remote', 'isTrustedServer' => false], 'uuid' => 'test', 'name' => 'test']]]],
false,
true,
],
@ -287,7 +295,7 @@ class RemotePluginTest extends TestCase {
],
],
true,
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]],
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost', 'isTrustedServer' => false]]]]],
true,
true,
],
@ -313,7 +321,7 @@ class RemotePluginTest extends TestCase {
],
],
false,
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]],
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User @ Localhost', 'label' => 'User @ Localhost (username@localhost)', 'uuid' => 'uid1', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost', 'isTrustedServer' => false]]]]],
true,
true,
],
@ -340,7 +348,7 @@ class RemotePluginTest extends TestCase {
],
],
false,
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User Name @ Localhost', 'label' => 'User Name @ Localhost (user name@localhost)', 'uuid' => 'uid3', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]]]],
['remotes' => [], 'exact' => ['remotes' => [['name' => 'User Name @ Localhost', 'label' => 'User Name @ Localhost (user name@localhost)', 'uuid' => 'uid3', 'type' => '', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost', 'isTrustedServer' => false]]]]],
true,
true,
],
@ -367,7 +375,7 @@ class RemotePluginTest extends TestCase {
],
],
false,
['remotes' => [], 'exact' => ['remotes' => [['label' => 'user space (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'user space@remote', 'server' => 'remote'], 'uuid' => 'user space', 'name' => 'user space']]]],
['remotes' => [], 'exact' => ['remotes' => [['label' => 'user space (remote)', 'value' => ['shareType' => IShare::TYPE_REMOTE, 'shareWith' => 'user space@remote', 'server' => 'remote', 'isTrustedServer' => false], 'uuid' => 'user space', 'name' => 'user space']]]],
false,
true,
],