fix(sharing): Adapt share suggestions to match trusted servers configs

When `show_federated_shares_to_trusted_servers_as_internal` is enabled
but `show_federated_shares_as_internal` is not, filter federated share
suggestions to only include trusted servers. Previously, searching for
an email address would suggest non-trusted federated servers.

Resolved: #54511
Signed-off-by: nfebe <fenn25.fn@gmail.com>
This commit is contained in:
nfebe 2025-09-12 11:56:50 +01:00 committed by F. E Noel Nfebe
parent 9f1027bed2
commit f94d30cbc6
3 changed files with 71 additions and 16 deletions

View file

@ -457,6 +457,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
*

View file

@ -6,11 +6,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;
@ -27,11 +29,14 @@ 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');
@ -67,9 +72,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'],
@ -95,6 +97,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
} else {
@ -107,6 +110,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
}
@ -120,9 +124,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);
@ -136,6 +137,7 @@ class RemotePlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $search,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
}

View file

@ -10,10 +10,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;
@ -21,6 +23,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 {
@ -36,6 +39,9 @@ class RemotePluginTest extends TestCase {
/** @var ICloudIdManager|\PHPUnit\Framework\MockObject\MockObject */
protected $cloudIdManager;
protected IAppConfig|MockObject $appConfig;
protected ICloudIdManager|MockObject $trustedServers;
/** @var RemotePlugin */
protected $plugin;
@ -55,6 +61,8 @@ class RemotePluginTest extends TestCase {
$this->createMock(IURLGenerator::class),
$this->createMock(IUserManager::class),
);
$this->appConfig = $this->createMock(IAppConfig::class);
$this->trustedServers = $this->createMock(TrustedServers::class);
$this->searchResult = new SearchResult();
}
@ -67,7 +75,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);
}
/**
@ -141,6 +149,37 @@ class RemotePluginTest extends TestCase {
$this->plugin->splitUserRemote($id);
}
public function testTrustedServerMetadata(): void {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(
function ($appName, $key, $default) {
if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
return 'yes';
}
return $default;
}
);
$this->trustedServers->expects($this->any())
->method('isTrustedServer')
->willReturnCallback(function ($serverUrl) {
return $serverUrl === 'trustedserver.com';
});
$this->instantiatePlugin();
$this->contactsManager->expects($this->any())
->method('search')
->willReturn([]);
$this->plugin->search('test@trustedserver.com', 2, 0, $this->searchResult);
$result = $this->searchResult->asArray();
$this->assertNotEmpty($result['exact']['remotes']);
$this->assertTrue($result['exact']['remotes'][0]['value']['isTrustedServer']);
}
public static function dataGetRemote() {
return [
['test', [], true, ['remotes' => [], 'exact' => ['remotes' => []]], false, true],
@ -149,7 +188,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 +196,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 +222,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 +274,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 +300,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 +326,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 +352,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 +379,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 +406,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,
],