aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornfebe <fenn25.fn@gmail.com>2025-06-24 13:16:22 +0100
committerF. E Noel Nfebe <fenn25.fn@gmail.com>2025-07-17 15:02:21 +0100
commitfc7eaa2d935fc0583915a563da2d404d2891106d (patch)
tree6c7de25972a8d21e1c4bf84f6fd4e88030eedf15
parent2cbfdcc4932857cc9f335aab86b37cc31cfa863a (diff)
downloadnextcloud-server-fc7eaa2d935fc0583915a563da2d404d2891106d.tar.gz
nextcloud-server-fc7eaa2d935fc0583915a563da2d404d2891106d.zip
feat(files_sharing): Toggle display for trusted server shares
Signed-off-by: nfebe <fenn25.fn@gmail.com>
-rw-r--r--apps/files_sharing/lib/Config/ConfigLexicon.php2
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php29
-rw-r--r--apps/files_sharing/lib/Listener/LoadSidebarListener.php1
-rw-r--r--apps/files_sharing/lib/ResponseDefinitions.php1
-rw-r--r--apps/files_sharing/openapi.json3
-rw-r--r--apps/files_sharing/src/components/SharingEntry.vue4
-rw-r--r--apps/files_sharing/src/components/SharingInput.vue40
-rw-r--r--apps/files_sharing/src/models/Share.ts7
-rw-r--r--apps/files_sharing/src/services/ConfigService.ts8
-rw-r--r--apps/files_sharing/src/views/SharingLinkList.vue12
-rw-r--r--apps/files_sharing/src/views/SharingTab.vue12
-rw-r--r--apps/files_sharing/tests/ApiTest.php3
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php151
-rw-r--r--openapi.json3
14 files changed, 253 insertions, 23 deletions
diff --git a/apps/files_sharing/lib/Config/ConfigLexicon.php b/apps/files_sharing/lib/Config/ConfigLexicon.php
index a463b4e7ef2..fb2821e7f56 100644
--- a/apps/files_sharing/lib/Config/ConfigLexicon.php
+++ b/apps/files_sharing/lib/Config/ConfigLexicon.php
@@ -22,6 +22,7 @@ use NCU\Config\ValueType;
*/
class ConfigLexicon implements IConfigLexicon {
public const SHOW_FEDERATED_AS_INTERNAL = 'show_federated_shares_as_internal';
+ public const SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL = 'show_federated_shares_to_trusted_servers_as_internal';
public function getStrictness(): ConfigLexiconStrictness {
return ConfigLexiconStrictness::IGNORE;
@@ -30,6 +31,7 @@ class ConfigLexicon implements IConfigLexicon {
public function getAppConfigs(): array {
return [
new ConfigLexiconEntry(self::SHOW_FEDERATED_AS_INTERNAL, ValueType::BOOL, false, 'shows federated shares as internal shares', true),
+ new ConfigLexiconEntry(self::SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL, ValueType::BOOL, false, 'shows federated shares to trusted servers as internal shares', true),
];
}
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index a19eb50faf7..5660f4d84e3 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -14,6 +14,7 @@ use OC\Files\FileInfo;
use OC\Files\Storage\Wrapper\Wrapper;
use OCA\Circles\Api\v1\Circles;
use OCA\Deck\Sharing\ShareAPIHelper;
+use OCA\Federation\TrustedServers;
use OCA\Files\Helper;
use OCA\Files_Sharing\Exceptions\SharingRightsException;
use OCA\Files_Sharing\External\Storage;
@@ -74,6 +75,7 @@ use Psr\Log\LoggerInterface;
class ShareAPIController extends OCSController {
private ?Node $lockedNode = null;
+ private array $trustedServerCache = [];
/**
* Share20OCS constructor.
@@ -97,6 +99,7 @@ class ShareAPIController extends OCSController {
private IProviderFactory $factory,
private IMailer $mailer,
private ITagManager $tagManager,
+ private ?TrustedServers $trustedServers,
private ?string $userId = null,
) {
parent::__construct($appName, $request);
@@ -199,6 +202,32 @@ class ShareAPIController extends OCSController {
$result['item_size'] = $node->getSize();
$result['item_mtime'] = $node->getMTime();
+ if ($this->trustedServers !== null && in_array($share->getShareType(), [IShare::TYPE_REMOTE, IShare::TYPE_REMOTE_GROUP], true)) {
+ $result['is_trusted_server'] = false;
+ $sharedWith = $share->getSharedWith();
+ $remoteIdentifier = is_string($sharedWith) ? strrchr($sharedWith, '@') : false;
+ if ($remoteIdentifier !== false) {
+ $remote = substr($remoteIdentifier, 1);
+
+ if (isset($this->trustedServerCache[$remote])) {
+ $result['is_trusted_server'] = $this->trustedServerCache[$remote];
+ } else {
+ try {
+ $isTrusted = $this->trustedServers->isTrustedServer($remote);
+ $this->trustedServerCache[$remote] = $isTrusted;
+ $result['is_trusted_server'] = $isTrusted;
+ } catch (\Exception $e) {
+ // Server not found or other issue, we consider it not trusted
+ $this->trustedServerCache[$remote] = false;
+ $this->logger->error(
+ 'Error checking if remote server is trusted (treating as untrusted): ' . $e->getMessage(),
+ ['exception' => $e]
+ );
+ }
+ }
+ }
+ }
+
$expiration = $share->getExpirationDate();
if ($expiration !== null) {
$expiration->setTimezone($this->dateTimeZone->getTimeZone());
diff --git a/apps/files_sharing/lib/Listener/LoadSidebarListener.php b/apps/files_sharing/lib/Listener/LoadSidebarListener.php
index 9f0eee9159a..88c39f38545 100644
--- a/apps/files_sharing/lib/Listener/LoadSidebarListener.php
+++ b/apps/files_sharing/lib/Listener/LoadSidebarListener.php
@@ -38,6 +38,7 @@ class LoadSidebarListener implements IEventListener {
$appConfig = Server::get(IAppConfig::class);
$this->initialState->provideInitialState('showFederatedSharesAsInternal', $appConfig->getValueBool('files_sharing', ConfigLexicon::SHOW_FEDERATED_AS_INTERNAL));
+ $this->initialState->provideInitialState('showFederatedSharesToTrustedServersAsInternal', $appConfig->getValueBool('files_sharing', ConfigLexicon::SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL));
Util::addScript(Application::APP_ID, 'files_sharing_tab', 'files');
}
}
diff --git a/apps/files_sharing/lib/ResponseDefinitions.php b/apps/files_sharing/lib/ResponseDefinitions.php
index 6b6b0fcc4b6..71a2b25a70c 100644
--- a/apps/files_sharing/lib/ResponseDefinitions.php
+++ b/apps/files_sharing/lib/ResponseDefinitions.php
@@ -22,6 +22,7 @@ namespace OCA\Files_Sharing;
* file_target: string,
* has_preview: bool,
* hide_download: 0|1,
+ * is_trusted_server?: bool,
* is-mount-root: bool,
* id: string,
* item_mtime: int,
diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json
index 627c25ce8ea..aed112b17f1 100644
--- a/apps/files_sharing/openapi.json
+++ b/apps/files_sharing/openapi.json
@@ -548,6 +548,9 @@
1
]
},
+ "is_trusted_server": {
+ "type": "boolean"
+ },
"is-mount-root": {
"type": "boolean"
},
diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue
index 4ff5fae364b..1fbe740cb11 100644
--- a/apps/files_sharing/src/components/SharingEntry.vue
+++ b/apps/files_sharing/src/components/SharingEntry.vue
@@ -77,9 +77,9 @@ export default {
title += ` (${t('files_sharing', 'group')})`
} else if (this.share.type === ShareType.Room) {
title += ` (${t('files_sharing', 'conversation')})`
- } else if (this.share.type === ShareType.Remote) {
+ } else if (this.share.type === ShareType.Remote && !this.share.isTrustedServer) {
title += ` (${t('files_sharing', 'remote')})`
- } else if (this.share.type === ShareType.RemoteGroup) {
+ } else if (this.share.type === ShareType.RemoteGroup && !this.share.isTrustedServer) {
title += ` (${t('files_sharing', 'remote group')})`
} else if (this.share.type === ShareType.Guest) {
title += ` (${t('files_sharing', 'guest')})`
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index b886ba95a17..f50dc96fc08 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -192,14 +192,27 @@ export default {
lookup = true
}
- let shareType = []
-
const remoteTypes = [ShareType.Remote, ShareType.RemoteGroup]
-
- if (this.isExternal && !this.config.showFederatedSharesAsInternal) {
- shareType.push(...remoteTypes)
+ const shareType = []
+
+ const showFederatedAsInternal
+ = this.config.showFederatedSharesAsInternal
+ || this.config.showFederatedSharesToTrustedServersAsInternal
+
+ const shouldAddRemoteTypes
+ // For internal users, add remote types if config says to show them as internal
+ = (!this.isExternal && showFederatedAsInternal)
+ // For external users, add them if config *doesn't* say to show them as internal
+ || (this.isExternal && !showFederatedAsInternal)
+ // Edge case: federated-to-trusted is a separate "add" trigger for external users
+ || (this.isExternal && this.config.showFederatedSharesToTrustedServersAsInternal)
+
+ if (this.isExternal) {
+ if (getCapabilities().files_sharing.public.enabled === true) {
+ shareType.push(ShareType.Email)
+ }
} else {
- shareType = shareType.concat([
+ shareType.push(
ShareType.User,
ShareType.Group,
ShareType.Team,
@@ -207,15 +220,11 @@ export default {
ShareType.Guest,
ShareType.Deck,
ShareType.ScienceMesh,
- ])
-
- if (this.config.showFederatedSharesAsInternal) {
- shareType.push(...remoteTypes)
- }
+ )
}
- if (getCapabilities().files_sharing.public.enabled === true && this.isExternal) {
- shareType.push(ShareType.Email)
+ if (shouldAddRemoteTypes) {
+ shareType.push(...remoteTypes)
}
let request = null
@@ -366,6 +375,11 @@ export default {
// filter out existing mail shares
if (share.value.shareType === ShareType.Email) {
+ // When sharing internally, we don't want to suggest email addresses
+ // that the user previously created shares to
+ if (!this.isExternal) {
+ return arr
+ }
const emails = this.linkShares.map(elem => elem.shareWith)
if (emails.indexOf(share.value.shareWith.trim()) !== -1) {
return arr
diff --git a/apps/files_sharing/src/models/Share.ts b/apps/files_sharing/src/models/Share.ts
index fb76a655d53..b0638b29448 100644
--- a/apps/files_sharing/src/models/Share.ts
+++ b/apps/files_sharing/src/models/Share.ts
@@ -486,4 +486,11 @@ export default class Share {
return this._share.status
}
+ /**
+ * Is the share from a trusted server
+ */
+ get isTrustedServer(): boolean {
+ return !!this._share.is_trusted_server
+ }
+
}
diff --git a/apps/files_sharing/src/services/ConfigService.ts b/apps/files_sharing/src/services/ConfigService.ts
index 2114e2d1bae..f75f34c7936 100644
--- a/apps/files_sharing/src/services/ConfigService.ts
+++ b/apps/files_sharing/src/services/ConfigService.ts
@@ -315,4 +315,12 @@ export default class Config {
return loadState('files_sharing', 'showFederatedSharesAsInternal', false)
}
+ /**
+ * Show federated shares to trusted servers as internal shares
+ * @return {boolean}
+ */
+ get showFederatedSharesToTrustedServersAsInternal(): boolean {
+ return loadState('files_sharing', 'showFederatedSharesToTrustedServersAsInternal', false)
+ }
+
}
diff --git a/apps/files_sharing/src/views/SharingLinkList.vue b/apps/files_sharing/src/views/SharingLinkList.vue
index 3dd6fdf317b..c3d9a7f83dc 100644
--- a/apps/files_sharing/src/views/SharingLinkList.vue
+++ b/apps/files_sharing/src/views/SharingLinkList.vue
@@ -7,12 +7,6 @@
<ul v-if="canLinkShare"
:aria-label="t('files_sharing', 'Link shares')"
class="sharing-link-list">
- <!-- If no link shares, show the add link default entry -->
- <SharingEntryLink v-if="!hasLinkShares && canReshare"
- :can-reshare="canReshare"
- :file-info="fileInfo"
- @add:share="addShare" />
-
<!-- Else we display the list -->
<template v-if="hasShares">
<!-- using shares[index] to work with .sync -->
@@ -27,6 +21,12 @@
@remove:share="removeShare"
@open-sharing-details="openSharingDetails(share)" />
</template>
+
+ <!-- If no link shares, show the add link default entry -->
+ <SharingEntryLink v-if="!hasLinkShares && canReshare"
+ :can-reshare="canReshare"
+ :file-info="fileInfo"
+ @add:share="addShare" />
</ul>
</template>
diff --git a/apps/files_sharing/src/views/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue
index 82a11dea2e0..3a676fd973a 100644
--- a/apps/files_sharing/src/views/SharingTab.vue
+++ b/apps/files_sharing/src/views/SharingTab.vue
@@ -402,7 +402,13 @@ export default {
if ([ShareType.Link, ShareType.Email].includes(share.type)) {
this.linkShares.push(share)
} else if ([ShareType.Remote, ShareType.RemoteGroup].includes(share.type)) {
- if (this.config.showFederatedSharesAsInternal) {
+ if (this.config.showFederatedSharesToTrustedServersAsInternal) {
+ if (share.isTrustedServer) {
+ this.shares.push(share)
+ } else {
+ this.externalShares.push(share)
+ }
+ } else if (this.config.showFederatedSharesAsInternal) {
this.shares.push(share)
} else {
this.externalShares.push(share)
@@ -478,6 +484,10 @@ export default {
} else if ([ShareType.Remote, ShareType.RemoteGroup].includes(share.type)) {
if (this.config.showFederatedSharesAsInternal) {
this.shares.unshift(share)
+ } if (this.config.showFederatedSharesToTrustedServersAsInternal) {
+ if (share.isTrustedServer) {
+ this.shares.unshift(share)
+ }
} else {
this.externalShares.unshift(share)
}
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index bb686c1ea8c..bace915351a 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -12,6 +12,7 @@ use OC\Files\FileInfo;
use OC\Files\Filesystem;
use OC\Files\Storage\Temporary;
use OC\Files\View;
+use OCA\Federation\TrustedServers;
use OCA\Files_Sharing\Controller\ShareAPIController;
use OCP\App\IAppManager;
use OCP\AppFramework\OCS\OCSBadRequestException;
@@ -114,6 +115,7 @@ class ApiTest extends TestCase {
$providerFactory = $this->createMock(IProviderFactory::class);
$mailer = $this->createMock(IMailer::class);
$tagManager = $this->createMock(ITagManager::class);
+ $trustedServers = $this->createMock(TrustedServers::class);
$dateTimeZone->method('getTimeZone')->willReturn(new \DateTimeZone(date_default_timezone_get()));
return new ShareAPIController(
@@ -135,6 +137,7 @@ class ApiTest extends TestCase {
$providerFactory,
$mailer,
$tagManager,
+ $trustedServers,
$userId,
);
}
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 8bb220d684b..598789cdba1 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -7,6 +7,7 @@
*/
namespace OCA\Files_Sharing\Tests\Controller;
+use OCA\Federation\TrustedServers;
use OCA\Files_Sharing\Controller\ShareAPIController;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
@@ -80,6 +81,7 @@ class ShareAPIControllerTest extends TestCase {
private IProviderFactory&MockObject $factory;
private IMailer&MockObject $mailer;
private ITagManager&MockObject $tagManager;
+ private TrustedServers&MockObject $trustedServers;
protected function setUp(): void {
$this->shareManager = $this->createMock(IManager::class);
@@ -116,6 +118,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory = $this->createMock(IProviderFactory::class);
$this->mailer = $this->createMock(IMailer::class);
$this->tagManager = $this->createMock(ITagManager::class);
+ $this->trustedServers = $this->createMock(TrustedServers::class);
$this->ocs = new ShareAPIController(
$this->appName,
@@ -136,8 +139,10 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
- $this->currentUser,
+ $this->trustedServers,
+ $this->currentUser
);
+
}
/**
@@ -164,6 +169,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -847,6 +853,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])
->onlyMethods(['canAccessShare'])
@@ -1478,6 +1485,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])
->onlyMethods(['formatShare'])
@@ -1865,6 +1873,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -1963,6 +1972,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2389,6 +2399,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2460,6 +2471,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2698,6 +2710,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -4480,6 +4493,7 @@ class ShareAPIControllerTest extends TestCase {
'mount-type' => '',
'attributes' => null,
'item_permissions' => 1,
+ 'is_trusted_server' => false,
], $share, [], false
];
@@ -4533,6 +4547,7 @@ class ShareAPIControllerTest extends TestCase {
'mount-type' => '',
'attributes' => null,
'item_permissions' => 1,
+ 'is_trusted_server' => false,
], $share, [], false
];
@@ -5216,4 +5231,138 @@ class ShareAPIControllerTest extends TestCase {
['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']],
], $result);
}
+
+ public function trustedServerProvider(): array {
+ return [
+ 'Trusted server' => [true, true],
+ 'Untrusted server' => [false, false],
+ ];
+ }
+
+ /**
+ * @dataProvider trustedServerProvider
+ */
+ public function testFormatShareWithFederatedShare(bool $isKnownServer, bool $isTrusted): void {
+ $nodeId = 12;
+ $nodePath = '/test.txt';
+ $share = $this->createShare(
+ 1,
+ IShare::TYPE_REMOTE,
+ 'recipient@remoteserver.com', // shared with
+ 'sender@testserver.com', // shared by
+ 'shareOwner', // share owner
+ $nodePath, // path
+ Constants::PERMISSION_READ,
+ time(),
+ null,
+ null,
+ $nodePath,
+ $nodeId
+ );
+
+ $node = $this->createMock(\OCP\Files\File::class);
+ $node->method('getId')->willReturn($nodeId);
+ $node->method('getPath')->willReturn($nodePath);
+ $node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
+ $mountPoint = $this->createMock(\OCP\Files\Mount\IMountPoint::class);
+ $mountPoint->method('getMountType')->willReturn('local');
+ $node->method('getMountPoint')->willReturn($mountPoint);
+ $node->method('getMimetype')->willReturn('text/plain');
+ $storage = $this->createMock(\OCP\Files\Storage\IStorage::class);
+ $storageCache = $this->createMock(\OCP\Files\Cache\ICache::class);
+ $storageCache->method('getNumericStorageId')->willReturn(1);
+ $storage->method('getCache')->willReturn($storageCache);
+ $storage->method('getId')->willReturn('home::shareOwner');
+ $node->method('getStorage')->willReturn($storage);
+ $parent = $this->createMock(\OCP\Files\Folder::class);
+ $parent->method('getId')->willReturn(2);
+ $node->method('getParent')->willReturn($parent);
+ $node->method('getSize')->willReturn(1234);
+ $node->method('getMTime')->willReturn(1234567890);
+
+ $this->previewManager->method('isAvailable')->with($node)->willReturn(false);
+
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->currentUser)
+ ->willReturnSelf();
+
+ $this->rootFolder->method('getFirstNodeById')
+ ->with($share->getNodeId())
+ ->willReturn($node);
+
+ $this->rootFolder->method('getRelativePath')
+ ->with($node->getPath())
+ ->willReturnArgument(0);
+
+ $serverName = 'remoteserver.com';
+ $this->trustedServers->method('isTrustedServer')
+ ->with($serverName)
+ ->willReturn($isKnownServer);
+
+ $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
+
+ $this->assertSame($isTrusted, $result['is_trusted_server']);
+ }
+
+ public function testFormatShareWithFederatedShareWithAtInUsername(): void {
+ $nodeId = 12;
+ $nodePath = '/test.txt';
+ $share = $this->createShare(
+ 1,
+ IShare::TYPE_REMOTE,
+ 'recipient@domain.com@remoteserver.com',
+ 'sender@testserver.com',
+ 'shareOwner',
+ $nodePath,
+ Constants::PERMISSION_READ,
+ time(),
+ null,
+ null,
+ $nodePath,
+ $nodeId
+ );
+
+ $node = $this->createMock(\OCP\Files\File::class);
+ $node->method('getId')->willReturn($nodeId);
+ $node->method('getPath')->willReturn($nodePath);
+ $node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
+ $mountPoint = $this->createMock(\OCP\Files\Mount\IMountPoint::class);
+ $mountPoint->method('getMountType')->willReturn('local');
+ $node->method('getMountPoint')->willReturn($mountPoint);
+ $node->method('getMimetype')->willReturn('text/plain');
+ $storage = $this->createMock(\OCP\Files\Storage\IStorage::class);
+ $storageCache = $this->createMock(\OCP\Files\Cache\ICache::class);
+ $storageCache->method('getNumericStorageId')->willReturn(1);
+ $storage->method('getCache')->willReturn($storageCache);
+ $storage->method('getId')->willReturn('home::shareOwner');
+ $node->method('getStorage')->willReturn($storage);
+ $parent = $this->createMock(\OCP\Files\Folder::class);
+ $parent->method('getId')->willReturn(2);
+ $node->method('getParent')->willReturn($parent);
+ $node->method('getSize')->willReturn(1234);
+ $node->method('getMTime')->willReturn(1234567890);
+
+ $this->previewManager->method('isAvailable')->with($node)->willReturn(false);
+
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->currentUser)
+ ->willReturnSelf();
+
+ $this->rootFolder->method('getFirstNodeById')
+ ->with($share->getNodeId())
+ ->willReturn($node);
+
+ $this->rootFolder->method('getRelativePath')
+ ->with($node->getPath())
+ ->willReturnArgument(0);
+
+ $serverName = 'remoteserver.com';
+ $this->trustedServers->method('isTrustedServer')
+ ->with($serverName)
+ ->willReturn(true);
+
+ $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
+
+ $this->assertTrue($result['is_trusted_server']);
+ }
}
diff --git a/openapi.json b/openapi.json
index c888a82bb89..22d7b5b6668 100644
--- a/openapi.json
+++ b/openapi.json
@@ -2562,6 +2562,9 @@
1
]
},
+ "is_trusted_server": {
+ "type": "boolean"
+ },
"is-mount-root": {
"type": "boolean"
},