feat: add new link endpoint when using globalscale

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/55750/head
Ferdinand Thiessen 2025-10-14 15:19:15 +07:00 committed by nextcloud-command
parent 50f287402a
commit 7fbc2ca25e
6 changed files with 72 additions and 16 deletions

@ -13,8 +13,8 @@ import type { Node as NcNode } from '@nextcloud/files'
import { FilePickerBuilder } from '@nextcloud/dialogs' import { FilePickerBuilder } from '@nextcloud/dialogs'
import { t } from '@nextcloud/l10n' import { t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
import { onMounted } from 'vue' import { onMounted } from 'vue'
import { generateFileUrl } from '../../../files_sharing/src/utils/generateUrl.ts'
import logger from '../logger.ts' import logger from '../logger.ts'
defineProps<{ defineProps<{
@ -74,9 +74,6 @@ function buttonFactory(selected: NcNode[]): IFilePickerButton[] {
* @param node - selected node * @param node - selected node
*/ */
function onSubmit(node: NcNode) { function onSubmit(node: NcNode) {
const url = new URL(window.location.href) emit('submit', generateFileUrl(node.fileid!))
url.pathname = generateUrl('/f/{fileId}', { fileId: node.fileid! })
url.search = ''
emit('submit', url.href)
} }
</script> </script>

@ -67,6 +67,7 @@ import path from 'path'
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import FileIcon from 'vue-material-design-icons/File.vue' import FileIcon from 'vue-material-design-icons/File.vue'
import FolderIcon from 'vue-material-design-icons/Folder.vue' import FolderIcon from 'vue-material-design-icons/Folder.vue'
import { generateFileUrl } from '../../../files_sharing/src/utils/generateUrl.ts'
import logger from '../logger.ts' import logger from '../logger.ts'
// see lib/private/Collaboration/Reference/File/FileReferenceProvider.php // see lib/private/Collaboration/Reference/File/FileReferenceProvider.php
@ -234,11 +235,9 @@ export default defineComponent({
.addButton({ .addButton({
id: 'open', id: 'open',
label: this.t('settings', 'Open in files'), label: this.t('settings', 'Open in files'),
callback(nodes: Node[]) { callback([node]: Node[]) {
if (nodes[0]) { if (node) {
window.open(generateUrl('/f/{fileid}', { window.open(generateFileUrl(node.fileid!))
fileid: nodes[0].fileid,
}))
} }
}, },
type: 'primary', type: 'primary',

@ -34,7 +34,6 @@
<script> <script>
import { basename } from '@nextcloud/paths' import { basename } from '@nextcloud/paths'
import { generateUrl } from '@nextcloud/router'
import NcActionButton from '@nextcloud/vue/components/NcActionButton' import NcActionButton from '@nextcloud/vue/components/NcActionButton'
import NcActionLink from '@nextcloud/vue/components/NcActionLink' import NcActionLink from '@nextcloud/vue/components/NcActionLink'
import NcActionText from '@nextcloud/vue/components/NcActionText' import NcActionText from '@nextcloud/vue/components/NcActionText'
@ -42,6 +41,7 @@ import NcAvatar from '@nextcloud/vue/components/NcAvatar'
import SharingEntrySimple from '../components/SharingEntrySimple.vue' import SharingEntrySimple from '../components/SharingEntrySimple.vue'
import SharesMixin from '../mixins/SharesMixin.js' import SharesMixin from '../mixins/SharesMixin.js'
import Share from '../models/Share.js' import Share from '../models/Share.js'
import { generateFileUrl } from '../utils/generateUrl.js'
export default { export default {
name: 'SharingEntryInherited', name: 'SharingEntryInherited',
@ -65,9 +65,7 @@ export default {
computed: { computed: {
viaFileTargetUrl() { viaFileTargetUrl() {
return generateUrl('/f/{fileid}', { return generateFileUrl(this.share.viaFileid)
fileid: this.share.viaFileid,
})
}, },
viaFolderName() { viaFolderName() {

@ -31,12 +31,12 @@
<script> <script>
import { showSuccess } from '@nextcloud/dialogs' import { showSuccess } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router'
import NcActionButton from '@nextcloud/vue/components/NcActionButton' import NcActionButton from '@nextcloud/vue/components/NcActionButton'
import CheckIcon from 'vue-material-design-icons/Check.vue' import CheckIcon from 'vue-material-design-icons/Check.vue'
import ClipboardIcon from 'vue-material-design-icons/ContentCopy.vue' import ClipboardIcon from 'vue-material-design-icons/ContentCopy.vue'
import SharingEntrySimple from './SharingEntrySimple.vue' import SharingEntrySimple from './SharingEntrySimple.vue'
import logger from '../services/logger.ts' import logger from '../services/logger.ts'
import { generateFileUrl } from '../utils/generateUrl.ts'
export default { export default {
name: 'SharingEntryInternal', name: 'SharingEntryInternal',
@ -69,7 +69,7 @@ export default {
* @return {string} * @return {string}
*/ */
internalLink() { internalLink() {
return window.location.protocol + '//' + window.location.host + generateUrl('/f/') + this.fileInfo.id return generateFileUrl(this.fileInfo.id)
}, },
/** /**

@ -0,0 +1,30 @@
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { describe, expect, it, vi } from 'vitest'
import { generateFileUrl } from './generateUrl.ts'
const getCapabilities = vi.hoisted(() => vi.fn())
vi.mock('@nextcloud/capabilities', () => ({ getCapabilities }))
describe('generateFileUrl', () => {
it('should work without globalscale', () => {
getCapabilities.mockReturnValue({ globalscale: null })
const url = generateFileUrl(12345)
expect(url).toBe('http://nextcloud.local/index.php/f/12345')
})
it('should work with older globalscale', () => {
getCapabilities.mockReturnValue({ globalscale: { enabled: true } })
const url = generateFileUrl(12345)
expect(url).toBe('http://nextcloud.local/index.php/f/12345')
})
it('should work with globalscale', () => {
getCapabilities.mockReturnValue({ globalscale: { enabled: true, token: 'abc123' } })
const url = generateFileUrl(12345)
expect(url).toBe('http://nextcloud.local/index.php/gf/abc123/12345')
})
})

@ -0,0 +1,32 @@
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getCapabilities } from '@nextcloud/capabilities'
import { generateUrl } from '@nextcloud/router'
interface IGlobalScaleCapabilities {
token?: string
}
/**
* @param fileid - The file ID to generate the direct file link for
*/
export function generateFileUrl(fileid: number): string {
const baseURL = window.location.protocol + '//' + window.location.host
const { globalscale } = getCapabilities() as { globalscale?: IGlobalScaleCapabilities }
if (globalscale?.token) {
return generateUrl('/gf/{token}/{fileid}', {
token: globalscale.token,
fileid,
}, { baseURL })
}
return generateUrl('/f/{fileid}', {
fileid,
}, {
baseURL,
})
}