aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornfebe <fenn25.fn@gmail.com>2025-06-24 13:16:22 +0100
committernfebe <fenn25.fn@gmail.com>2025-06-24 23:50:38 +0100
commit3a848ee9e03eeaeb981678581dbce9c22ff82685 (patch)
tree5bfaf8e08ade5f3fb8315628b64875528f8d3cbb
parent8ee06edffc8469c3de6597b4e8d379657c533264 (diff)
downloadnextcloud-server-feat/52635/toggle-for-trusted-server-sharing.tar.gz
nextcloud-server-feat/52635/toggle-for-trusted-server-sharing.zip
feat(files_sharing): Toggle display for trusted server sharesfeat/52635/toggle-for-trusted-server-sharing
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.php19
-rw-r--r--apps/files_sharing/lib/Listener/LoadSidebarListener.php1
-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/SharingTab.vue8
-rw-r--r--apps/files_sharing/tests/ApiTest.php3
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php87
8 files changed, 133 insertions, 2 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 23ba9da1568..fab57a2eb36 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -60,6 +60,8 @@ use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Share\IShareProviderWithNotification;
use OCP\UserStatus\IManager as IUserStatusManager;
+use OCA\Federation\TrustedServers;
+use OCP\User\IUserSession;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -95,6 +97,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);
@@ -197,6 +200,22 @@ 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])) {
+ $result['is_trusted_server'] = false;
+ $sharedBy = $share->getSharedBy();
+ $remoteIdentifier = is_string($sharedBy) ? strrchr($sharedBy, '@') : false;
+ if ($remoteIdentifier !== false) {
+ $remote = substr($remoteIdentifier, 1);
+ try {
+ if ($this->trustedServers->isTrustedServer($remote)) {
+ $result['is_trusted_server'] = true;
+ }
+ } catch (\Exception $e) {
+ // Server not found or other issue, we consider it not trusted
+ }
+ }
+ }
+
$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/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/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue
index 82a11dea2e0..b06a9ae5ee6 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)
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index a712903d768..970aa97cadc 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -34,6 +34,7 @@ use OCP\Server;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
+use OCA\Federation\TrustedServers;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -113,6 +114,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(
@@ -134,6 +136,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 f245f0a25c7..8ca113b83ab 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -44,6 +44,7 @@ use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
+use OCA\Federation\TrustedServers;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@@ -79,6 +80,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);
@@ -115,6 +117,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,
@@ -135,8 +138,10 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
- $this->currentUser,
+ $this->trustedServers,
+ $this->currentUser
);
+
}
/**
@@ -163,6 +168,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -848,6 +854,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])
->onlyMethods(['canAccessShare'])
@@ -1481,6 +1488,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])
->onlyMethods(['formatShare'])
@@ -1872,6 +1880,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -1970,6 +1979,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2396,6 +2406,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2467,6 +2478,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -2705,6 +2717,7 @@ class ShareAPIControllerTest extends TestCase {
$this->factory,
$this->mailer,
$this->tagManager,
+ $this->trustedServers,
$this->currentUser,
])->onlyMethods(['formatShare'])
->getMock();
@@ -5233,4 +5246,76 @@ 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::class);
+ $storageCache = $this->createMock(\OCP\Cache\Cache::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 = 'testserver.com';
+ $this->trustedServers->method('isTrustedServer')
+ ->with($serverName)
+ ->willReturn($isKnownServer);
+
+ $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
+
+ $this->assertSame($isTrusted, $result['is_trusted_server']);
+ }
}