From ae5d57371a2d099740b70ff3a7c6a3a1d6213e5e Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 6 Aug 2025 17:10:42 +0200 Subject: [PATCH] feat(files_sharing): show GS users similar to internal users - resolves: https://github.com/nextcloud/server/issues/52497 Ensure that when global scale is enabled the federated users are shown just like internal users. Meaning no server part but instead use the email address like with internal. Signed-off-by: Ferdinand Thiessen --- .../lib/Listener/LoadSidebarListener.php | 12 ++++-- .../src/components/SharingInput.vue | 42 +++++++++---------- .../src/views/SharingDetailsTab.vue | 5 ++- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/apps/files_sharing/lib/Listener/LoadSidebarListener.php b/apps/files_sharing/lib/Listener/LoadSidebarListener.php index 88c39f38545..17fee71978f 100644 --- a/apps/files_sharing/lib/Listener/LoadSidebarListener.php +++ b/apps/files_sharing/lib/Listener/LoadSidebarListener.php @@ -15,6 +15,7 @@ use OCA\Files_Sharing\Config\ConfigLexicon; use OCP\AppFramework\Services\IInitialState; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\GlobalScale\IConfig; use OCP\IAppConfig; use OCP\Server; use OCP\Share\IManager; @@ -35,10 +36,15 @@ class LoadSidebarListener implements IEventListener { if (!($event instanceof LoadSidebar)) { return; } + Util::addScript(Application::APP_ID, 'files_sharing_tab', 'files'); $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'); + $gsConfig = Server::get(IConfig::class); + $showFederatedToTrustedAsInternal = $gsConfig->isGlobalScaleEnabled() || $appConfig->getValueBool('files_sharing', ConfigLexicon::SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL); + $showFederatedAsInternal = ($gsConfig->isGlobalScaleEnabled() && $gsConfig->onlyInternalFederation()) + || $appConfig->getValueBool('files_sharing', ConfigLexicon::SHOW_FEDERATED_AS_INTERNAL); + + $this->initialState->provideInitialState('showFederatedSharesAsInternal', $showFederatedAsInternal); + $this->initialState->provideInitialState('showFederatedSharesToTrustedServersAsInternal', $showFederatedToTrustedAsInternal); } } diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue index f50dc96fc08..46bacef0c6c 100644 --- a/apps/files_sharing/src/components/SharingInput.vue +++ b/apps/files_sharing/src/components/SharingInput.vue @@ -195,17 +195,15 @@ export default { const remoteTypes = [ShareType.Remote, ShareType.RemoteGroup] const shareType = [] - const showFederatedAsInternal - = this.config.showFederatedSharesAsInternal - || this.config.showFederatedSharesToTrustedServersAsInternal + 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) + // For internal users, add remote types if config says to show them as internal + const shouldAddRemoteTypes = (!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) { @@ -244,13 +242,10 @@ export default { return } - const data = request.data.ocs.data - const exact = request.data.ocs.data.exact - data.exact = [] // removing exact from general results - + const { exact, ...data } = request.data.ocs.data // flatten array of arrays - const rawExactSuggestions = Object.values(exact).reduce((arr, elem) => arr.concat(elem), []) - const rawSuggestions = Object.values(data).reduce((arr, elem) => arr.concat(elem), []) + const rawExactSuggestions = Object.values(exact).flat() + const rawSuggestions = Object.values(data).flat() // remove invalid data and format to user-select layout const exactSuggestions = this.filterOutExistingShares(rawExactSuggestions) @@ -470,14 +465,19 @@ export default { */ formatForMultiselect(result) { let subname + let displayName = result.name || result.label + if (result.value.shareType === ShareType.User && this.config.shouldAlwaysShowUnique) { subname = result.shareWithDisplayNameUnique ?? '' - } else if ((result.value.shareType === ShareType.Remote - || result.value.shareType === ShareType.RemoteGroup - ) && result.value.server) { - subname = t('files_sharing', 'on {server}', { server: result.value.server }) } else if (result.value.shareType === ShareType.Email) { subname = result.value.shareWith + } else if (result.value.shareType === ShareType.Remote || result.value.shareType === ShareType.RemoteGroup) { + if (this.config.showFederatedSharesAsInternal) { + subname = result.extra?.email?.value ?? '' + displayName = result.extra?.name?.value ?? displayName + } else if (result.value.server) { + subname = t('files_sharing', 'on {server}', { server: result.value.server }) + } } else { subname = result.shareWithDescription ?? '' } @@ -487,7 +487,7 @@ export default { shareType: result.value.shareType, user: result.uuid || result.value.shareWith, isNoUser: result.value.shareType !== ShareType.User, - displayName: result.name || result.label, + displayName, subname, shareWithDisplayNameUnique: result.shareWithDisplayNameUnique || '', ...this.shareTypeToIcon(result.value.shareType), diff --git a/apps/files_sharing/src/views/SharingDetailsTab.vue b/apps/files_sharing/src/views/SharingDetailsTab.vue index ee902a24c8a..b3a3b95d92e 100644 --- a/apps/files_sharing/src/views/SharingDetailsTab.vue +++ b/apps/files_sharing/src/views/SharingDetailsTab.vue @@ -373,7 +373,7 @@ export default { title() { switch (this.share.type) { case ShareType.User: - return t('files_sharing', 'Share with {userName}', { userName: this.share.shareWithDisplayName }) + return t('files_sharing', 'Share with {user}', { user: this.share.shareWithDisplayName }) case ShareType.Email: return t('files_sharing', 'Share with email {email}', { email: this.share.shareWith }) case ShareType.Link: @@ -384,6 +384,9 @@ export default { return t('files_sharing', 'Share in conversation') case ShareType.Remote: { const [user, server] = this.share.shareWith.split('@') + if (this.config.showFederatedSharesAsInternal) { + return t('files_sharing', 'Share with {user}', { user }) + } return t('files_sharing', 'Share with {user} on remote server {server}', { user, server }) } case ShareType.RemoteGroup: