fix(files): Do not add click listener if there is no default action on public shares

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/45652/head
Ferdinand Thiessen 3 months ago
parent cb4c569486
commit 018af2a2fe
No known key found for this signature in database
GPG Key ID: 45FAE7268762B400
  1. 22
      apps/files/src/actions/downloadAction.ts
  2. 25
      apps/files/src/components/FileEntryMixin.ts
  3. 30
      apps/files/src/utils/permissions.ts

@ -2,13 +2,12 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { ShareAttribute } from '../../../files_sharing/src/sharing'
import { FileAction, Permission, Node, FileType, View, DefaultType } from '@nextcloud/files'
import { FileAction, Node, FileType, View, DefaultType } from '@nextcloud/files'
import { t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
import { getSharingToken, isPublicShare } from '@nextcloud/sharing/public'
import { basename } from 'path'
import { isDownloadable } from '../utils/permissions'
import ArrowDownSvg from '@mdi/svg/svg/arrow-down.svg?raw'
@ -40,23 +39,6 @@ const downloadNodes = function(dir: string, nodes: Node[]) {
triggerDownload(url)
}
const isDownloadable = function(node: Node) {
if ((node.permissions & Permission.READ) === 0) {
return false
}
// If the mount type is a share, ensure it got download permissions.
if (node.attributes['share-attributes']) {
const shareAttributes = JSON.parse(node.attributes['share-attributes'] || '[]') as Array<ShareAttribute>
const downloadAttribute = shareAttributes.find(({ scope, key }: ShareAttribute) => scope === 'permissions' && key === 'download')
if (downloadAttribute) {
return downloadAttribute.value === true
}
}
return true
}
export const action = new FileAction({
id: 'download',
default: DefaultType.DEFAULT,

@ -20,6 +20,7 @@ import { getDragAndDropPreview } from '../utils/dragUtils.ts'
import { hashCode } from '../utils/hashUtils.ts'
import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts'
import logger from '../logger.ts'
import { isDownloadable } from '../utils/permissions.ts'
Vue.directive('onClickOutside', vOnClickOutside)
@ -270,29 +271,31 @@ export default defineComponent({
event.stopPropagation()
},
execDefaultAction(event) {
execDefaultAction(event: MouseEvent) {
// Ignore click if we are renaming
if (this.isRenaming) {
return
}
// Ignore right click.
if (event.button > 1) {
// Ignore right click (button & 2) and any auxillary button expect mouse-wheel (button & 4)
if (Boolean(event.button & 2) || event.button > 4) {
return
}
// if ctrl+click or middle mouse button, open in new tab
// if ctrl+click / cmd+click (MacOS uses the meta key) or middle mouse button (button & 4), open in new tab
// also if there is no default action use this as a fallback
const metaKeyPressed = event.ctrlKey || event.metaKey || event.button === 1
const metaKeyPressed = event.ctrlKey || event.metaKey || Boolean(event.button & 4)
if (metaKeyPressed || !this.defaultFileAction) {
// If no download permission, then we can not allow to download (direct link) the files
if (isPublicShare() && !isDownloadable(this.source)) {
return
}
const url = isPublicShare()
? this.source.encodedSource
: generateUrl('/f/{fileId}', { fileId: this.fileid })
event.preventDefault()
event.stopPropagation()
let url: string
if (isPublicShare()) {
url = this.source.encodedSource
} else {
url = generateUrl('/f/{fileId}', { fileId: this.fileid })
}
window.open(url, metaKeyPressed ? '_self' : undefined)
return
}

@ -0,0 +1,30 @@
/*!
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { Node } from '@nextcloud/files'
import type { ShareAttribute } from '../../../files_sharing/src/sharing.ts'
import { Permission } from '@nextcloud/files'
/**
* Check permissions on the node if it can be downloaded
* @param node The node to check
* @return True if downloadable, false otherwise
*/
export function isDownloadable(node: Node): boolean {
if ((node.permissions & Permission.READ) === 0) {
return false
}
// If the mount type is a share, ensure it got download permissions.
if (node.attributes['share-attributes']) {
const shareAttributes = JSON.parse(node.attributes['share-attributes'] || '[]') as Array<ShareAttribute>
const downloadAttribute = shareAttributes.find(({ scope, key }: ShareAttribute) => scope === 'permissions' && key === 'download')
if (downloadAttribute !== undefined) {
return downloadAttribute.value === true
}
}
return true
}
Loading…
Cancel
Save