Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions apps/files_sharing/src/components/SharingInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,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)
Expand Down Expand Up @@ -341,6 +343,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)

Expand Down Expand Up @@ -463,6 +466,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
*
Expand Down
2 changes: 2 additions & 0 deletions dist/7416-7416.js

Large diffs are not rendered by default.

File renamed without changes.
1 change: 1 addition & 0 deletions dist/7416-7416.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/7416-7416.js.map.license
2 changes: 0 additions & 2 deletions dist/9215-9215.js

This file was deleted.

1 change: 0 additions & 1 deletion dist/9215-9215.js.map

This file was deleted.

1 change: 0 additions & 1 deletion dist/9215-9215.js.map.license

This file was deleted.

4 changes: 2 additions & 2 deletions dist/files_sharing-files_sharing_tab.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/files_sharing-files_sharing_tab.js.map

Large diffs are not rendered by default.

28 changes: 20 additions & 8 deletions lib/private/Collaboration/Collaborators/RemotePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,17 +29,20 @@ public function __construct(
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,
Expand Down Expand Up @@ -67,9 +72,6 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
}

$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'],
Expand All @@ -82,7 +84,17 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
];
}

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);
}
Expand All @@ -95,6 +107,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
} else {
Expand All @@ -107,6 +120,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $cloudId,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
}
Expand All @@ -120,9 +134,6 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
$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);
Expand All @@ -136,6 +147,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
'shareType' => IShare::TYPE_REMOTE,
'shareWith' => $search,
'server' => $serverUrl,
'isTrustedServer' => $this->trustedServers->isTrustedServer($serverUrl),
],
];
}
Expand Down
99 changes: 89 additions & 10 deletions tests/lib/Collaboration/Collaborators/RemotePluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@
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;
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 {
Expand All @@ -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;

Expand All @@ -55,6 +61,8 @@ protected function setUp(): void {
$this->createMock(IURLGenerator::class),
$this->createMock(IUserManager::class),
);
$this->appConfig = $this->createMock(IAppConfig::class);
$this->trustedServers = $this->createMock(TrustedServers::class);
$this->searchResult = new SearchResult();
}

Expand All @@ -67,7 +75,7 @@ public function instantiatePlugin() {
$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);
}

/**
Expand Down Expand Up @@ -141,6 +149,77 @@ public function testSplitUserRemoteError($id): void {
$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 function testEmailSearchInContacts(): 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->once())
->method('search')
->with('john@gmail.com', ['CLOUD', 'FN', 'EMAIL'])
->willReturn([
[
'FN' => 'John Doe',
'EMAIL' => 'john@gmail.com',
'CLOUD' => 'john@trustedserver.com',
'UID' => 'john-contact-id'
]
]);

$this->plugin->search('john@gmail.com', 2, 0, $this->searchResult);
$result = $this->searchResult->asArray();

$this->assertNotEmpty($result['exact']['remotes']);
$this->assertEquals('john@trustedserver.com', $result['exact']['remotes'][0]['value']['shareWith']);
$this->assertTrue($result['exact']['remotes'][0]['value']['isTrustedServer']);
}

public static function dataGetRemote() {
return [
['test', [], true, ['remotes' => [], 'exact' => ['remotes' => []]], false, true],
Expand All @@ -149,15 +228,15 @@ public static function dataGetRemote() {
'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,
],
[
'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,
],
Expand All @@ -183,7 +262,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand Down Expand Up @@ -235,7 +314,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand All @@ -261,7 +340,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand All @@ -287,7 +366,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand All @@ -313,7 +392,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand All @@ -340,7 +419,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand All @@ -367,7 +446,7 @@ public static function dataGetRemote() {
],
],
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,
],
Expand Down
Loading