Skip to content
Draft
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
14 changes: 14 additions & 0 deletions apps/files_sharing/src/components/SharingInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
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('[email protected]', 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('[email protected]', ['CLOUD', 'FN', 'EMAIL'])
->willReturn([
[
'FN' => 'John Doe',
'EMAIL' => '[email protected]',
'CLOUD' => '[email protected]',
'UID' => 'john-contact-id'
]
]);

$this->plugin->search('[email protected]', 2, 0, $this->searchResult);
$result = $this->searchResult->asArray();

$this->assertNotEmpty($result['exact']['remotes']);
$this->assertEquals('[email protected]', $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