Skip to content

Commit cfda889

Browse files
committed
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
1 parent 1e7b45d commit cfda889

File tree

3 files changed

+84
-4
lines changed

3 files changed

+84
-4
lines changed

apps/files_sharing/src/components/SharingInput.vue

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,12 @@ export default {
249249
250250
// remove invalid data and format to user-select layout
251251
const exactSuggestions = this.filterOutExistingShares(rawExactSuggestions)
252+
.filter(result => this.filterByTrustedServer(result))
252253
.map(share => this.formatForMultiselect(share))
253254
// sort by type so we can get user&groups first...
254255
.sort((a, b) => a.shareType - b.shareType)
255256
const suggestions = this.filterOutExistingShares(rawSuggestions)
257+
.filter(result => this.filterByTrustedServer(result))
256258
.map(share => this.formatForMultiselect(share))
257259
// sort by type so we can get user&groups first...
258260
.sort((a, b) => a.shareType - b.shareType)
@@ -335,6 +337,7 @@ export default {
335337
336338
// remove invalid data and format to user-select layout
337339
this.recommendations = this.filterOutExistingShares(rawRecommendations)
340+
.filter(result => this.filterByTrustedServer(result))
338341
.map(share => this.formatForMultiselect(share))
339342
.concat(externalResults)
340343
@@ -457,6 +460,34 @@ export default {
457460
}
458461
},
459462
463+
/**
464+
* Filter suggestion results based on trusted server configuration
465+
*
466+
* @param {object} result The raw suggestion result from API
467+
* @return {boolean} Whether to include this result in suggestions
468+
*/
469+
filterByTrustedServer(result) {
470+
// Only apply filtering to remote shares
471+
if (result.value.shareType !== ShareType.Remote && result.value.shareType !== ShareType.RemoteGroup) {
472+
return true
473+
}
474+
475+
// If showFederatedSharesToTrustedServersAsInternal is not enabled, show all
476+
if (!this.config.showFederatedSharesToTrustedServersAsInternal) {
477+
return true
478+
}
479+
480+
const isTrustedServer = result.value.isTrustedServer || false
481+
482+
// For internal section: only show trusted servers
483+
if (!this.isExternal) {
484+
return isTrustedServer
485+
}
486+
487+
// For external section: only show non-trusted servers
488+
return !isTrustedServer
489+
},
490+
460491
/**
461492
* Format shares for the multiselect options
462493
*

lib/private/Collaboration/Collaborators/RemotePlugin.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
*/
77
namespace OC\Collaboration\Collaborators;
88

9+
use OCA\Federation\TrustedServers;
910
use OCP\Collaboration\Collaborators\ISearchPlugin;
1011
use OCP\Collaboration\Collaborators\ISearchResult;
1112
use OCP\Collaboration\Collaborators\SearchResultType;
1213
use OCP\Contacts\IManager;
1314
use OCP\Federation\ICloudIdManager;
15+
use OCP\IAppConfig;
1416
use OCP\IConfig;
1517
use OCP\IUserManager;
1618
use OCP\IUserSession;
@@ -27,11 +29,17 @@ public function __construct(
2729
private IConfig $config,
2830
private IUserManager $userManager,
2931
IUserSession $userSession,
32+
private IAppConfig $appConfig,
33+
private TrustedServers $trustedServers,
3034
) {
3135
$this->userId = $userSession->getUser()?->getUID() ?? '';
3236
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
3337
}
3438

39+
private function isServerTrusted(string $serverUrl): bool {
40+
return $this->trustedServers->isTrustedServer($serverUrl);
41+
}
42+
3543
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
3644
$result = ['wide' => [], 'exact' => []];
3745
$resultType = new SearchResultType('remotes');
@@ -95,6 +103,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
95103
'shareType' => IShare::TYPE_REMOTE,
96104
'shareWith' => $cloudId,
97105
'server' => $serverUrl,
106+
'isTrustedServer' => $this->isServerTrusted($serverUrl),
98107
],
99108
];
100109
} else {
@@ -107,6 +116,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
107116
'shareType' => IShare::TYPE_REMOTE,
108117
'shareWith' => $cloudId,
109118
'server' => $serverUrl,
119+
'isTrustedServer' => $this->isServerTrusted($serverUrl),
110120
],
111121
];
112122
}
@@ -120,9 +130,6 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
120130
$result['wide'] = array_slice($result['wide'], $offset, $limit);
121131
}
122132

123-
/**
124-
* Add generic share with remote item for valid cloud ids that are not users of the local instance
125-
*/
126133
if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
127134
try {
128135
[$remoteUser, $serverUrl] = $this->splitUserRemote($search);
@@ -136,6 +143,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
136143
'shareType' => IShare::TYPE_REMOTE,
137144
'shareWith' => $search,
138145
'server' => $serverUrl,
146+
'isTrustedServer' => $this->isServerTrusted($serverUrl),
139147
],
140148
];
141149
}

tests/lib/Collaboration/Collaborators/RemotePluginTest.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
use OC\Collaboration\Collaborators\RemotePlugin;
1111
use OC\Collaboration\Collaborators\SearchResult;
1212
use OC\Federation\CloudIdManager;
13+
use OCA\Federation\TrustedServers;
1314
use OCP\Collaboration\Collaborators\SearchResultType;
1415
use OCP\Contacts\IManager;
1516
use OCP\EventDispatcher\IEventDispatcher;
1617
use OCP\Federation\ICloudIdManager;
18+
use OCP\IAppConfig;
1719
use OCP\ICacheFactory;
1820
use OCP\IConfig;
1921
use OCP\IURLGenerator;
@@ -36,6 +38,12 @@ class RemotePluginTest extends TestCase {
3638
/** @var ICloudIdManager|\PHPUnit\Framework\MockObject\MockObject */
3739
protected $cloudIdManager;
3840

41+
/** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */
42+
protected $appConfig;
43+
44+
/** @var TrustedServers|\PHPUnit\Framework\MockObject\MockObject */
45+
protected $trustedServers;
46+
3947
/** @var RemotePlugin */
4048
protected $plugin;
4149

@@ -55,6 +63,8 @@ protected function setUp(): void {
5563
$this->createMock(IURLGenerator::class),
5664
$this->createMock(IUserManager::class),
5765
);
66+
$this->appConfig = $this->createMock(IAppConfig::class);
67+
$this->trustedServers = $this->createMock(TrustedServers::class);
5868
$this->searchResult = new SearchResult();
5969
}
6070

@@ -67,7 +77,7 @@ public function instantiatePlugin() {
6777
$userSession->expects($this->any())
6878
->method('getUser')
6979
->willReturn($user);
70-
$this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->userManager, $userSession);
80+
$this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->userManager, $userSession, $this->appConfig, $this->trustedServers);
7181
}
7282

7383
/**
@@ -141,6 +151,37 @@ public function testSplitUserRemoteError($id): void {
141151
$this->plugin->splitUserRemote($id);
142152
}
143153

154+
public function testTrustedServerMetadata(): void {
155+
$this->config->expects($this->any())
156+
->method('getAppValue')
157+
->willReturnCallback(
158+
function ($appName, $key, $default) {
159+
if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
160+
return 'yes';
161+
}
162+
return $default;
163+
}
164+
);
165+
166+
$this->trustedServers->expects($this->any())
167+
->method('isTrustedServer')
168+
->willReturnCallback(function ($serverUrl) {
169+
return $serverUrl === 'trustedserver.com';
170+
});
171+
172+
$this->instantiatePlugin();
173+
174+
$this->contactsManager->expects($this->any())
175+
->method('search')
176+
->willReturn([]);
177+
178+
$this->plugin->search('test@trustedserver.com', 2, 0, $this->searchResult);
179+
$result = $this->searchResult->asArray();
180+
181+
$this->assertNotEmpty($result['exact']['remotes']);
182+
$this->assertTrue($result['exact']['remotes'][0]['value']['isTrustedServer']);
183+
}
184+
144185
public static function dataGetRemote() {
145186
return [
146187
['test', [], true, ['remotes' => [], 'exact' => ['remotes' => []]], false, true],

0 commit comments

Comments
 (0)