diff --git a/packages/web-app-office-settings/src/App.vue b/packages/web-app-office-settings/src/App.vue
index 61befe7e882..683a65444fe 100644
--- a/packages/web-app-office-settings/src/App.vue
+++ b/packages/web-app-office-settings/src/App.vue
@@ -15,7 +15,7 @@
= 0
)
},
+ canListVersions: function () {
+ return !this.isFolder
+ },
isMounted: function () {
return this.permissions.indexOf(DavPermission.Mounted) >= 0
},
@@ -259,6 +262,7 @@ export function buildDeletedResource(resource: WebDavResponseResource): TrashRes
isReceivedShare: () => false,
hasPreview: () => false,
isShareRoot: () => false,
+ canListVersions: () => false,
getDomSelector: () => extractDomSelector(id)
}
}
diff --git a/packages/web-client/src/helpers/resource/types.ts b/packages/web-client/src/helpers/resource/types.ts
index 87a5bd43d8b..25f12af9c9c 100644
--- a/packages/web-client/src/helpers/resource/types.ts
+++ b/packages/web-client/src/helpers/resource/types.ts
@@ -83,6 +83,7 @@ export interface Resource {
canRename?(args?: { user?: User; ability?: Ability }): boolean
canBeDeleted?(args?: { user?: User; ability?: Ability }): boolean
canEditTags?(): boolean
+ canListVersions?(args?: { user?: User }): boolean
getDomSelector?(): string
diff --git a/packages/web-client/src/helpers/share/functions.ts b/packages/web-client/src/helpers/share/functions.ts
index d6b369e5fc3..b2b3909a502 100644
--- a/packages/web-client/src/helpers/share/functions.ts
+++ b/packages/web-client/src/helpers/share/functions.ts
@@ -163,6 +163,8 @@ export function buildIncomingShareResource({
canCreate: () => sharePermissions.includes(GraphSharePermission.createChildren),
canBeDeleted: () => sharePermissions.includes(GraphSharePermission.deleteStandard),
canEditTags: () => sharePermissions.includes(GraphSharePermission.createUpload),
+ canListVersions: () =>
+ !driveItem.folder && sharePermissions.includes(GraphSharePermission.readVersions),
isMounted: () => false,
isReceivedShare: () => true,
canShare: () => false,
@@ -225,6 +227,7 @@ export function buildOutgoingShareResource({
canCreate: () => true,
canBeDeleted: () => true,
canEditTags: () => true,
+ canListVersions: () => !driveItem.folder,
isMounted: () => false,
isShareRoot: () => false,
isReceivedShare: () => true,
diff --git a/packages/web-client/src/helpers/space/functions.ts b/packages/web-client/src/helpers/space/functions.ts
index a1437d2fe0f..80a16c63351 100644
--- a/packages/web-client/src/helpers/space/functions.ts
+++ b/packages/web-client/src/helpers/space/functions.ts
@@ -116,12 +116,14 @@ export function buildShareSpaceResource({
driveAliasPrefix,
id,
shareName,
- serverUrl
+ serverUrl,
+ graphPermissions
}: {
driveAliasPrefix: 'share' | 'ocm-share'
id: string
shareName: string
serverUrl: string
+ graphPermissions?: GraphSharePermission[]
}): ShareSpaceResource {
const space = buildSpace({
id,
@@ -134,6 +136,10 @@ export function buildShareSpaceResource({
space.driveAlias = `${driveAliasPrefix}/${newName}`
space.name = newName
}
+ if (graphPermissions) {
+ space.graphPermissions = graphPermissions
+ }
+
return space
}
@@ -281,11 +287,8 @@ export function buildSpace(
// FIXME: server permissions are a mess currently: https://github.com/opencloud-eu/opencloud/issues/10
return this.graphPermissions?.includes(GraphSharePermission.deletePermissions)
},
- canListVersions: function ({ user }: { user?: User } = {}) {
- if (isPersonalSpaceResource(this) && this.isOwner(user)) {
- return true
- }
- return this.graphPermissions?.includes(GraphSharePermission.readVersions)
+ canListVersions: function () {
+ return false
},
canCreate: function () {
return true
diff --git a/packages/web-client/src/helpers/space/types.ts b/packages/web-client/src/helpers/space/types.ts
index 9eae5544cfa..70d252195c6 100644
--- a/packages/web-client/src/helpers/space/types.ts
+++ b/packages/web-client/src/helpers/space/types.ts
@@ -35,7 +35,6 @@ export interface SpaceResource extends Resource {
canRestore(args?: { user?: User; ability?: Ability }): boolean
canDeleteFromTrashBin(args?: { user?: User }): boolean
canRestoreFromTrashbin(args?: { user?: User }): boolean
- canListVersions(args?: { user?: User }): boolean
getWebDavUrl({ path }: { path: string }): string
getWebDavTrashUrl({ path }: { path: string }): string
diff --git a/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue b/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue
index 156d5a77e91..4702fdb6247 100644
--- a/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue
+++ b/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue
@@ -89,10 +89,15 @@ import { HttpError } from '@opencloud-eu/web-client'
import { dirname } from 'path'
import { useFileActionsOpenWithApp } from '../../composables'
import { UnsavedChangesModal } from '../Modals'
-import { formatFileSize, getSharedDriveItem } from '../../helpers'
+import {
+ formatFileSize,
+ getSharedDriveItem,
+ setCurrentUserShareSpacePermissions
+} from '../../helpers'
import toNumber from 'lodash-es/toNumber'
import { useIsMobile } from '@opencloud-eu/design-system/composables'
import { storeToRefs } from 'pinia'
+import { DriveItem } from '@opencloud-eu/web-client/graph/generated'
const {
applicationId,
@@ -301,17 +306,30 @@ const loadResourceTask = useTask(function* (signal) {
// FIXME: As soon the backend exposes oc-remote-id via webdav, remove the assignment below
unref(resource).remoteItemId = unref(space).id
- if (unref(resource).id === unref(resource).remoteItemId) {
- // use graph api to build incoming share resource
- const sharedDriveItem = yield* call(
+ let sharedDriveItem: DriveItem
+ const resourceIsShareSpaceRoot = unref(resource).id === unref(resource).remoteItemId
+ if (!unref(space).graphPermissions || resourceIsShareSpaceRoot) {
+ // we need to load the driveItem either for the share space permissions if not yet loaded,
+ // or for building the incoming share resource if it is a share space root
+ sharedDriveItem = yield* call(
getSharedDriveItem({
graphClient: clientService.graphAuthenticated,
spacesStore,
space: unref(space)
})
)
+ }
+
+ if (sharedDriveItem) {
+ // set graph permissions on the current share space
+ setCurrentUserShareSpacePermissions({
+ sharesStore,
+ spacesStore,
+ space: unref(space),
+ sharedDriveItem
+ })
- if (sharedDriveItem) {
+ if (resourceIsShareSpaceRoot) {
resource.value = {
...fileInfo,
...buildIncomingShareResource({
diff --git a/packages/web-pkg/src/composables/piniaStores/spaces.ts b/packages/web-pkg/src/composables/piniaStores/spaces.ts
index 53a11281424..ca7741cf0f7 100644
--- a/packages/web-pkg/src/composables/piniaStores/spaces.ts
+++ b/packages/web-pkg/src/composables/piniaStores/spaces.ts
@@ -7,7 +7,11 @@ import {
} from '@opencloud-eu/web-client'
import { Graph } from '@opencloud-eu/web-client/graph'
import { isPersonalSpaceResource, isProjectSpaceResource } from '@opencloud-eu/web-client'
-import type { CollaboratorShare, MountPointSpaceResource } from '@opencloud-eu/web-client'
+import type {
+ CollaboratorShare,
+ GraphSharePermission,
+ MountPointSpaceResource
+} from '@opencloud-eu/web-client'
import { useUserStore } from './user'
import { useConfigStore } from './config'
import { useSharesStore } from './shares'
@@ -118,17 +122,20 @@ export const useSpacesStore = defineStore('spaces', () => {
const createShareSpace = ({
driveAliasPrefix,
id,
- shareName
+ shareName,
+ graphPermissions
}: {
driveAliasPrefix: 'share' | 'ocm-share'
id: string
shareName: string
+ graphPermissions?: GraphSharePermission[]
}) => {
const space = buildShareSpaceResource({
driveAliasPrefix,
id,
shareName,
- serverUrl: configStore.serverUrl
+ serverUrl: configStore.serverUrl,
+ graphPermissions
})
addSpaces([space])
return space
diff --git a/packages/web-pkg/src/composables/resources/useCanListVersions.ts b/packages/web-pkg/src/composables/resources/useCanListVersions.ts
index 6bd1addceb4..1ae68029e85 100644
--- a/packages/web-pkg/src/composables/resources/useCanListVersions.ts
+++ b/packages/web-pkg/src/composables/resources/useCanListVersions.ts
@@ -1,20 +1,20 @@
import { useUserStore } from '../piniaStores'
-import { isSpaceResource, isTrashResource, Resource, SpaceResource } from '@opencloud-eu/web-client'
+import {
+ GraphSharePermission,
+ isPersonalSpaceResource,
+ Resource,
+ SpaceResource
+} from '@opencloud-eu/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
- }
- return space?.canListVersions({ user: userStore.user })
+ const spaceAllowsListingVersions =
+ (isPersonalSpaceResource(space) && space.isOwner(userStore.user)) ||
+ space.graphPermissions?.includes(GraphSharePermission.readVersions)
+
+ return spaceAllowsListingVersions && resource.canListVersions?.({ user: userStore.user })
}
return {
diff --git a/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts b/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts
index 60c80a8d56f..f777839e6f2 100644
--- a/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts
+++ b/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts
@@ -62,7 +62,8 @@ export const useGetMatchingSpace = (options?: GetMatchingSpaceOptions) => {
spacesStore.createShareSpace({
driveAliasPrefix,
id: resource.remoteItemId,
- shareName
+ shareName,
+ graphPermissions: isIncomingShareResource(resource) ? resource.sharePermissions : []
})
)
}
diff --git a/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts b/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts
index dfabf77bb4f..db8e689513d 100644
--- a/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts
+++ b/packages/web-pkg/tests/unit/composables/resources/useCanListVersions.spec.ts
@@ -1,55 +1,75 @@
import { getComposableWrapper } from '@opencloud-eu/web-test-helpers'
import { mock } from 'vitest-mock-extended'
-import { Resource, SpaceResource, TrashResource } from '@opencloud-eu/web-client'
+import { GraphSharePermission, Resource, SpaceResource } from '@opencloud-eu/web-client'
import { useCanListVersions } from '../../../../src/composables/resources'
describe('useCanListVersions', () => {
describe('canListVersions', () => {
- it('returns true for files when user has sufficient permissions in space', () => {
+ it('returns true for a personal space owned by the user', () => {
getWrapper({
setup: ({ canListVersions }) => {
- const space = mock({ canListVersions: () => true })
- const resource = mock({ type: 'file' })
+ const space = mock({
+ driveType: 'personal',
+ isOwner: () => true,
+ graphPermissions: []
+ })
+ const resource = mock({ canListVersions: () => true })
const canList = canListVersions({ space, resource })
expect(canList).toBeTruthy()
}
})
})
- it('returns false for folders', () => {
+ it('returns true when the space grants the readVersions permission', () => {
getWrapper({
setup: ({ canListVersions }) => {
- const space = mock({ canListVersions: () => true })
- const resource = mock({ type: 'folder' })
+ const space = mock({
+ driveType: 'project',
+ isOwner: () => false,
+ graphPermissions: [GraphSharePermission.readVersions]
+ })
+ const resource = mock({ canListVersions: () => true })
const canList = canListVersions({ space, resource })
- expect(canList).toBeFalsy()
+ expect(canList).toBeTruthy()
}
})
})
- it('returns false for space resources', () => {
+ it('returns false for a personal space not owned by the user', () => {
getWrapper({
setup: ({ canListVersions }) => {
- const space = mock({ canListVersions: () => true })
- const resource = mock({ type: 'space' })
+ const space = mock({
+ driveType: 'personal',
+ isOwner: () => false,
+ graphPermissions: []
+ })
+ const resource = mock({ canListVersions: () => true })
const canList = canListVersions({ space, resource })
expect(canList).toBeFalsy()
}
})
})
- it('returns false for trash resources', () => {
+ it('returns false when the space does not allow listing versions', () => {
getWrapper({
setup: ({ canListVersions }) => {
- const space = mock({ canListVersions: () => true })
- const resource = mock({ type: 'file', ddate: '' })
+ const space = mock({
+ driveType: 'project',
+ isOwner: () => false,
+ graphPermissions: []
+ })
+ const resource = mock({ canListVersions: () => true })
const canList = canListVersions({ space, resource })
expect(canList).toBeFalsy()
}
})
})
- it('returns false when user does not have sufficient permissions in space', () => {
+ it('returns false when the resource does not allow listing versions', () => {
getWrapper({
setup: ({ canListVersions }) => {
- const space = mock({ canListVersions: () => false })
- const resource = mock({ type: 'file' })
+ const space = mock({
+ driveType: 'personal',
+ isOwner: () => true,
+ graphPermissions: [GraphSharePermission.readVersions]
+ })
+ const resource = mock({ canListVersions: () => false })
const canList = canListVersions({ space, resource })
expect(canList).toBeFalsy()
}