diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-09-05 01:34:48 +0200 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-09-06 03:38:48 +0200 |
commit | 018af2a2fef7ae9f4057ad4c111b995201ef6e0b (patch) | |
tree | 556eac309bbaf44b02ab9980b5c83b1b8b5b9d12 /apps/files | |
parent | cb4c5694866926a4209cf2ba25d23c6840273f56 (diff) | |
download | nextcloud-server-018af2a2fef7ae9f4057ad4c111b995201ef6e0b.tar.gz nextcloud-server-018af2a2fef7ae9f4057ad4c111b995201ef6e0b.zip |
fix(files): Do not add click listener if there is no default action on public shares
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps/files')
-rw-r--r-- | apps/files/src/actions/downloadAction.ts | 22 | ||||
-rw-r--r-- | apps/files/src/components/FileEntryMixin.ts | 25 | ||||
-rw-r--r-- | apps/files/src/utils/permissions.ts | 30 |
3 files changed, 46 insertions, 31 deletions
diff --git a/apps/files/src/actions/downloadAction.ts b/apps/files/src/actions/downloadAction.ts index bac5e4adf10..97d1cc773d4 100644 --- a/apps/files/src/actions/downloadAction.ts +++ b/apps/files/src/actions/downloadAction.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, diff --git a/apps/files/src/components/FileEntryMixin.ts b/apps/files/src/components/FileEntryMixin.ts index 73c6ce19387..58f5c1e9474 100644 --- a/apps/files/src/components/FileEntryMixin.ts +++ b/apps/files/src/components/FileEntryMixin.ts @@ -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 } diff --git a/apps/files/src/utils/permissions.ts b/apps/files/src/utils/permissions.ts new file mode 100644 index 00000000000..2c85ede1659 --- /dev/null +++ b/apps/files/src/utils/permissions.ts @@ -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 +} |