From a9f7e66d3dbdd7740aa7f308665d576d3a491378 Mon Sep 17 00:00:00 2001 From: =?utf8?q?John=20Molakvo=C3=A6?= Date: Thu, 6 Jul 2023 15:21:07 +0200 Subject: [PATCH] fix(files): actions permissions requirements MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/actions/favoriteAction.spec.ts | 3 ++- apps/files/src/actions/favoriteAction.ts | 13 ++++++++----- apps/files/src/actions/sidebarAction.spec.ts | 19 ++++++++++++++++++- apps/files/src/actions/sidebarAction.ts | 6 +++--- .../src/actions/viewInFolderAction.spec.ts | 7 +++++-- apps/files/src/actions/viewInFolderAction.ts | 6 +++++- apps/files/src/store/files.ts | 2 +- apps/files/src/views/favorites.ts | 17 ++++++++++++++++- 8 files changed, 58 insertions(+), 15 deletions(-) diff --git a/apps/files/src/actions/favoriteAction.spec.ts b/apps/files/src/actions/favoriteAction.spec.ts index 48a00094a0d..57957e67a33 100644 --- a/apps/files/src/actions/favoriteAction.spec.ts +++ b/apps/files/src/actions/favoriteAction.spec.ts @@ -22,7 +22,7 @@ import * as favoriteAction from './favoriteAction' import { action } from './favoriteAction' import { expect } from '@jest/globals' -import { File, Folder, Permission } from '@nextcloud/files' +import { File, Permission } from '@nextcloud/files' import { FileAction } from '../services/FileAction' import * as eventBus from '@nextcloud/event-bus' import axios from '@nextcloud/axios' @@ -120,6 +120,7 @@ describe('Favorite action enabled tests', () => { source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt', owner: 'admin', mime: 'text/plain', + permissions: Permission.ALL, }) expect(action.enabled).toBeDefined() diff --git a/apps/files/src/actions/favoriteAction.ts b/apps/files/src/actions/favoriteAction.ts index 1ae77b6fb21..a33aacf4947 100644 --- a/apps/files/src/actions/favoriteAction.ts +++ b/apps/files/src/actions/favoriteAction.ts @@ -20,13 +20,15 @@ * */ import { emit } from '@nextcloud/event-bus' +import { generateUrl } from '@nextcloud/router' +import { Permission, type Node } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' import axios from '@nextcloud/axios' -import StarSvg from '@mdi/svg/svg/star.svg?raw' +import Vue from 'vue' + import StarOutlineSvg from '@mdi/svg/svg/star-outline.svg?raw' -import type { Node } from '@nextcloud/files' +import StarSvg from '@mdi/svg/svg/star.svg?raw' -import { generateUrl } from '@nextcloud/router' import { registerFileAction, FileAction } from '../services/FileAction' import logger from '../logger.js' import type { Navigation } from '../services/Navigation' @@ -54,7 +56,7 @@ export const favoriteNode = async (node: Node, view: Navigation, willFavorite: b } // Update the node webdav attribute - node.attributes.favorite = willFavorite ? 1 : 0 + Vue.set(node.attributes, 'favorite', willFavorite ? 1 : 0) // Dispatch event to whoever is interested if (willFavorite) { @@ -85,8 +87,9 @@ export const action = new FileAction({ }, enabled(nodes: Node[]) { - // We can only favorite nodes within files + // We can only favorite nodes within files and with permissions return !nodes.some(node => !node.root?.startsWith?.('/files')) + && nodes.every(node => node.permissions !== Permission.NONE) }, async exec(node: Node, view: Navigation) { diff --git a/apps/files/src/actions/sidebarAction.spec.ts b/apps/files/src/actions/sidebarAction.spec.ts index c4750092ebc..69eabe4be79 100644 --- a/apps/files/src/actions/sidebarAction.spec.ts +++ b/apps/files/src/actions/sidebarAction.spec.ts @@ -21,7 +21,7 @@ */ import { action } from './sidebarAction' import { expect } from '@jest/globals' -import { File } from '@nextcloud/files' +import { File, Permission } from '@nextcloud/files' import { FileAction } from '../services/FileAction' import type { Navigation } from '../services/Navigation' import logger from '../logger' @@ -51,12 +51,29 @@ describe('Open sidebar action enabled tests', () => { source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt', owner: 'admin', mime: 'text/plain', + permissions: Permission.ALL, }) expect(action.enabled).toBeDefined() expect(action.enabled!([file], view)).toBe(true) }) + test('Disabled without permissions', () => { + window.OCA = { Files: { Sidebar: {} } } + + const file = new File({ + id: 1, + source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt', + owner: 'admin', + mime: 'text/plain', + permissions: Permission.NONE, + }) + + expect(action.enabled).toBeDefined() + expect(action.enabled!([file], view)).toBe(false) + + }) + test('Disabled if more than one node', () => { window.OCA = { Files: { Sidebar: {} } } diff --git a/apps/files/src/actions/sidebarAction.ts b/apps/files/src/actions/sidebarAction.ts index 141cd75ff19..6c553d97902 100644 --- a/apps/files/src/actions/sidebarAction.ts +++ b/apps/files/src/actions/sidebarAction.ts @@ -21,9 +21,9 @@ */ import { translate as t } from '@nextcloud/l10n' import InformationSvg from '@mdi/svg/svg/information-variant.svg?raw' -import type { Node } from '@nextcloud/files' +import { Permission, type Node } from '@nextcloud/files' -import { registerFileAction, FileAction, DefaultType } from '../services/FileAction' +import { registerFileAction, FileAction } from '../services/FileAction' import logger from '../logger.js' export const ACTION_DETAILS = 'details' @@ -45,7 +45,7 @@ export const action = new FileAction({ return false } - return nodes[0].root?.startsWith('/files/') ?? false + return (nodes[0].root?.startsWith('/files/') && nodes[0].permissions !== Permission.NONE) ?? false }, async exec(node: Node) { diff --git a/apps/files/src/actions/viewInFolderAction.spec.ts b/apps/files/src/actions/viewInFolderAction.spec.ts index b16f2663f33..693a24fb1da 100644 --- a/apps/files/src/actions/viewInFolderAction.spec.ts +++ b/apps/files/src/actions/viewInFolderAction.spec.ts @@ -48,6 +48,7 @@ describe('View in folder action enabled tests', () => { source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt', owner: 'admin', mime: 'text/plain', + permissions: Permission.ALL, }) expect(action.enabled).toBeDefined() @@ -107,13 +108,14 @@ describe('View in folder action execute tests', () => { source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt', owner: 'admin', mime: 'text/plain', + permissions: Permission.READ, }) const exec = await action.exec(file, view, '/') // Silent action expect(exec).toBe(null) expect(goToRouteMock).toBeCalledTimes(1) - expect(goToRouteMock).toBeCalledWith(null, { view: 'files' }, { dir: '/' }) + expect(goToRouteMock).toBeCalledWith(null, { fileid: 1, view: 'files' }, { fileid: 1, dir: '/' }) }) test('View in (sub) folder', async () => { @@ -126,13 +128,14 @@ describe('View in folder action execute tests', () => { root: '/files/admin', owner: 'admin', mime: 'text/plain', + permissions: Permission.READ, }) const exec = await action.exec(file, view, '/') // Silent action expect(exec).toBe(null) expect(goToRouteMock).toBeCalledTimes(1) - expect(goToRouteMock).toBeCalledWith(null, { view: 'files' }, { dir: '/Foo/Bar' }) + expect(goToRouteMock).toBeCalledWith(null, { fileid: 1, view: 'files' }, { fileid: 1, dir: '/Foo/Bar' }) }) test('View in folder fails without node', async () => { diff --git a/apps/files/src/actions/viewInFolderAction.ts b/apps/files/src/actions/viewInFolderAction.ts index 67e276112dc..2f603e6cf3a 100644 --- a/apps/files/src/actions/viewInFolderAction.ts +++ b/apps/files/src/actions/viewInFolderAction.ts @@ -19,7 +19,7 @@ * along with this program. If not, see . * */ -import { Node, FileType } from '@nextcloud/files' +import { Node, FileType, Permission } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' import FolderMoveSvg from '@mdi/svg/svg/folder-move.svg?raw' @@ -46,6 +46,10 @@ export const action = new FileAction({ return false } + if (node.permissions === Permission.NONE) { + return false + } + return node.type === FileType.File }, diff --git a/apps/files/src/store/files.ts b/apps/files/src/store/files.ts index ac62512988b..c36ebcfecc2 100644 --- a/apps/files/src/store/files.ts +++ b/apps/files/src/store/files.ts @@ -58,7 +58,7 @@ export const useFilesStore = function(...args) { // Update the store all at once const files = nodes.reduce((acc, node) => { if (!node.fileid) { - logger.warn('Trying to update/set a node without fileid', node) + logger.error('Trying to update/set a node without fileid', node) return acc } acc[node.fileid] = node diff --git a/apps/files/src/views/favorites.ts b/apps/files/src/views/favorites.ts index 73293668664..571db4faab3 100644 --- a/apps/files/src/views/favorites.ts +++ b/apps/files/src/views/favorites.ts @@ -129,9 +129,16 @@ export default () => { // Add a folder to the favorites paths array and update the views const addPathToFavorites = function(path: string) { const view = generateFolderView(path) + + // Skip if already exists + if (favoriteFolders.find(folder => folder === path)) { + return + } + // Update arrays favoriteFolders.push(path) favoriteFoldersViews.push(view) + // Update and sort views updateAndSortViews() Navigation.register(view) @@ -140,10 +147,18 @@ export default () => { // Remove a folder from the favorites paths array and update the views const removePathFromFavorites = function(path: string) { const id = generateIdFromPath(path) - const index = favoriteFolders.findIndex(f => f === path) + const index = favoriteFolders.findIndex(folder => folder === path) + + // Skip if not exists + if (index === -1) { + return + } + // Update arrays favoriteFolders.splice(index, 1) favoriteFoldersViews.splice(index, 1) + + // Update and sort views Navigation.remove(id) updateAndSortViews() } -- 2.39.5