diff --git a/changelog/unreleased/enhancement-hide-versions-panel b/changelog/unreleased/enhancement-hide-versions-panel new file mode 100644 index 00000000000..1163c7ea699 --- /dev/null +++ b/changelog/unreleased/enhancement-hide-versions-panel @@ -0,0 +1,6 @@ +Enhancement: Hide versions panel with insufficient permissions + +Users that have insufficient permissions to view file versions don't see the versions sidebar panel anymore. This currently affects regular share receivers, space viewers and space editors without the permission to view versions. + +https://github.com/owncloud/web/pull/11484 +https://github.com/owncloud/web/issues/11359 diff --git a/packages/web-app-files/src/composables/extensions/useFileSideBars.ts b/packages/web-app-files/src/composables/extensions/useFileSideBars.ts index e255c12a705..27e0b6e1a70 100644 --- a/packages/web-app-files/src/composables/extensions/useFileSideBars.ts +++ b/packages/web-app-files/src/composables/extensions/useFileSideBars.ts @@ -20,15 +20,13 @@ import { SidebarPanelExtension, useIsFilesAppActive, useGetMatchingSpace, - useUserStore, - useCapabilityStore + useCapabilityStore, + useCanListVersions } from '@ownclouders/web-pkg' import { - isPersonalSpaceResource, isProjectSpaceResource, isShareResource, isShareSpaceResource, - isSpaceResource, SpaceResource } from '@ownclouders/web-client' import { Resource } from '@ownclouders/web-client' @@ -44,7 +42,7 @@ export const useSideBarPanels = (): SidebarPanelExtension - (isProjectSpaceResource(props.space) && props.space.isMember(userStore.user)) || - (isPersonalSpaceResource(props.space) && props.space.isOwner(userStore.user)) - ) - const availablePanels = computed(() => extensionRegistry .requestExtensions>({ @@ -303,17 +297,14 @@ export default defineComponent({ loadVersionsTask.cancelAll() } - if ( - !resource.isFolder && - !isSpaceResource(resource) && - unref(userIsSpaceMember) && - !unref(isTrashLocation) - ) { - try { - await loadVersionsTask.perform(resource) - } catch (e) { - console.error(e) - } + if (!canListVersions({ space: props.space, resource })) { + return + } + + try { + await loadVersionsTask.perform(resource) + } catch (e) { + console.error(e) } }, { immediate: true, deep: true } @@ -339,7 +330,7 @@ export default defineComponent({ } isMetaDataLoading.value = true - if (unref(userIsSpaceMember) && !unref(isTrashLocation)) { + if (props.space?.isMember(userStore.user) && !unref(isTrashLocation)) { try { if (loadSharesTask.isRunning) { loadSharesTask.cancelAll() diff --git a/packages/web-pkg/src/composables/resources/index.ts b/packages/web-pkg/src/composables/resources/index.ts index 5e0299793b9..f2026f80f6e 100644 --- a/packages/web-pkg/src/composables/resources/index.ts +++ b/packages/web-pkg/src/composables/resources/index.ts @@ -1,3 +1,4 @@ export * from './useCanBeOpenedWithSecureView' +export * from './useCanListVersions' export * from './useGetResourceContext' export * from './useResourceContents' diff --git a/packages/web-pkg/src/composables/resources/useCanListVersions.ts b/packages/web-pkg/src/composables/resources/useCanListVersions.ts new file mode 100644 index 00000000000..730d5351bba --- /dev/null +++ b/packages/web-pkg/src/composables/resources/useCanListVersions.ts @@ -0,0 +1,26 @@ +import { useUserStore } from '../piniaStores' +import { isSpaceResource, isTrashResource, Resource, SpaceResource } from '@ownclouders/web-client' + +export const useCanListVersions = () => { + const userStore = useUserStore() + + const canListVersions = ({ space, resource }: { space: SpaceResource; resource: Resource }) => { + if (resource.type === 'folder') { + return false + } + if (isSpaceResource(resource)) { + return false + } + if (isTrashResource(resource)) { + return false + } + if (!space.canListVersions({ user: userStore.user })) { + return false + } + return true + } + + return { + canListVersions + } +} diff --git a/packages/web-pkg/tests/unit/components/sidebar/FileSideBar.spec.ts b/packages/web-pkg/tests/unit/components/sidebar/FileSideBar.spec.ts index 405d9110f31..d9100998add 100644 --- a/packages/web-pkg/tests/unit/components/sidebar/FileSideBar.spec.ts +++ b/packages/web-pkg/tests/unit/components/sidebar/FileSideBar.spec.ts @@ -24,6 +24,9 @@ const InnerSideBarComponent = defineComponent({ }) vi.mock('../../../../src/composables/selection', () => ({ useSelectedResources: vi.fn() })) +vi.mock('../../../../src/composables/resources/useCanListVersions', () => ({ + useCanListVersions: () => ({ canListVersions: vi.fn() }) +})) const selectors = { sideBar: '.files-side-bar', diff --git a/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts b/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts new file mode 100644 index 00000000000..2387c342f7f --- /dev/null +++ b/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts @@ -0,0 +1,72 @@ +import { getComposableWrapper } from 'web-test-helpers' +import { mock } from 'vitest-mock-extended' +import { Resource, SpaceResource, TrashResource } from '@ownclouders/web-client' +import { useCanListVersions } from '../../../../src/composables/resources' + +describe('useCanListVersions', () => { + describe('canListVersions', () => { + it('returns true for files when user has sufficient permissions in space', () => { + getWrapper({ + setup: ({ canListVersions }) => { + const space = mock({ canListVersions: () => true }) + const resource = mock({ type: 'file' }) + const canList = canListVersions({ space, resource }) + expect(canList).toBeTruthy() + } + }) + }) + it('returns false for folders', () => { + getWrapper({ + setup: ({ canListVersions }) => { + const space = mock({ canListVersions: () => true }) + const resource = mock({ type: 'folder' }) + const canList = canListVersions({ space, resource }) + expect(canList).toBeFalsy() + } + }) + }) + it('returns false for space resources', () => { + getWrapper({ + setup: ({ canListVersions }) => { + const space = mock({ canListVersions: () => true }) + const resource = mock({ type: 'space' }) + const canList = canListVersions({ space, resource }) + expect(canList).toBeFalsy() + } + }) + }) + it('returns false for trash resources', () => { + getWrapper({ + setup: ({ canListVersions }) => { + const space = mock({ canListVersions: () => true }) + const resource = mock({ type: 'file', ddate: '' }) + const canList = canListVersions({ space, resource }) + expect(canList).toBeFalsy() + } + }) + }) + it('returns false when user does not have sufficient permissions in space', () => { + getWrapper({ + setup: ({ canListVersions }) => { + const space = mock({ canListVersions: () => false }) + const resource = mock({ type: 'file' }) + const canList = canListVersions({ space, resource }) + expect(canList).toBeFalsy() + } + }) + }) + }) +}) + +function getWrapper({ + setup +}: { + setup: (instance: ReturnType) => void +}) { + return { + wrapper: getComposableWrapper(() => { + const instance = useCanListVersions() + setup(instance) + }) + } +} diff --git a/tests/e2e/cucumber/features/spaces/project.feature b/tests/e2e/cucumber/features/spaces/project.feature index a7f378fa8d4..115c44cb05b 100644 --- a/tests/e2e/cucumber/features/spaces/project.feature +++ b/tests/e2e/cucumber/features/spaces/project.feature @@ -152,7 +152,7 @@ Feature: spaces.personal When "Carol" logs in And "Carol" navigates to the project space "team.1" - And "Carol" should not see the version of the file + And "Carol" should not see the version panel for the file | resource | to | | textfile.txt | parent | And "Carol" logs out