Skip to content

Commit 096047a

Browse files
fauzanfebrianskjnldsv
authored andcommitted
fix(files_sharing): Hide 'Open locally' action
This patch ensures that the "Open locally" context menu item is not displayed for files in a share where the "download and sync" permission has not been granted. This prevents user confusion, as the action would fail anyway. The fix adds a permission check before rendering the menu item, and adds a corresponding unit test to verify this behavior. Resolves: #54970 Signed-off-by: Fauzan <[email protected]>
1 parent e4f06e1 commit 096047a

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

apps/files/src/actions/openLocallyAction.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import IconWeb from '@mdi/svg/svg/web.svg?raw'
1010
import { getCurrentUser } from '@nextcloud/auth'
1111
import axios from '@nextcloud/axios'
1212
import { DialogBuilder, showError } from '@nextcloud/dialogs'
13-
import { FileAction, Permission } from '@nextcloud/files'
13+
import { FileAction } from '@nextcloud/files'
1414
import { translate as t } from '@nextcloud/l10n'
1515
import { encodePath } from '@nextcloud/paths'
1616
import { generateOcsUrl } from '@nextcloud/router'
1717
import { isPublicShare } from '@nextcloud/sharing/public'
1818
import logger from '../logger.ts'
19+
import { isSyncable } from '../utils/permissions.ts'
1920

2021
export const action = new FileAction({
2122
id: 'edit-locally',
@@ -34,7 +35,7 @@ export const action = new FileAction({
3435
return false
3536
}
3637

37-
return (nodes[0].permissions & Permission.UPDATE) !== 0
38+
return isSyncable(nodes[0])
3839
},
3940

4041
async exec(node: Node) {

apps/files/src/utils/permissions.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,34 @@ export function isDownloadable(node: Node): boolean {
3636

3737
return true
3838
}
39+
40+
41+
/**
42+
* Check permissions on the node if it can be synced/open locally
43+
*
44+
* @param node The node to check
45+
* @return True if syncable, false otherwise
46+
*/
47+
export function isSyncable(node: Node): boolean {
48+
if ((node.permissions & Permission.UPDATE) === 0) {
49+
return false
50+
}
51+
52+
// check hide-download property of shares
53+
if (node.attributes['hide-download'] === true
54+
|| node.attributes['hide-download'] === 'true'
55+
) {
56+
return false
57+
}
58+
59+
// If the mount type is a share, ensure it got download permissions.
60+
if (node.attributes['share-attributes']) {
61+
const shareAttributes = JSON.parse(node.attributes['share-attributes'] || '[]') as Array<ShareAttribute>
62+
const downloadAttribute = shareAttributes.find(({ scope, key }: ShareAttribute) => scope === 'permissions' && key === 'download')
63+
if (downloadAttribute !== undefined) {
64+
return downloadAttribute.value === true
65+
}
66+
}
67+
68+
return true
69+
}

0 commit comments

Comments
 (0)