diff --git a/.drone.env b/.drone.env index c0864c4c95b..0f9b827e33f 100644 --- a/.drone.env +++ b/.drone.env @@ -1,3 +1,3 @@ # The version of OCIS to use in pipelines that test against OCIS -OCIS_COMMITID=01d40c27833bf131db0c8251359e7a6cf3087bd0 +OCIS_COMMITID=33360327c0c6902849b30c1f016d02efe7c17211 OCIS_BRANCH=master diff --git a/.drone.star b/.drone.star index c1b64373708..6c3aecb56b3 100644 --- a/.drone.star +++ b/.drone.star @@ -138,8 +138,6 @@ config = { ], "oCISSharingAutocompletionResharing": [ "webUISharingAutocompletion", - "webUIResharing1", - "webUIResharing2", ], "oCISSharingPerm1": [ "webUISharingPermissionsUsers", @@ -193,7 +191,6 @@ config = { # These list contains all the test suites that are present # When adding new test suites, make sure to update these lists rootSharingTestSuites = [ - "webUIResharingToRoot", "webUISharingAcceptSharesToRoot", "webUISharingInternalGroupsToRoot", "webUISharingInternalGroupsToRootEdgeCases", @@ -221,8 +218,6 @@ basicTestSuites = [ "webUIPrivateLinks", "webUIRenameFiles", "webUIRenameFolders", - "webUIResharing1", - "webUIResharing2", "webUISharingAcceptShares", "webUISharingAutocompletion", "webUISharingFilePermissionMultipleUsers", diff --git a/packages/web-app-files/src/services/folder.ts b/packages/web-app-files/src/services/folder.ts index 27f69b07fa2..51c23e2da91 100644 --- a/packages/web-app-files/src/services/folder.ts +++ b/packages/web-app-files/src/services/folder.ts @@ -12,7 +12,9 @@ import { useConfigStore, ConfigStore, ResourcesStore, - useResourcesStore + useResourcesStore, + SharesStore, + useSharesStore } from '@ownclouders/web-pkg' import { unref } from 'vue' import { ClientService } from '@ownclouders/web-pkg' @@ -38,6 +40,7 @@ export type TaskContext = { router: Router capabilityStore: CapabilityStore resourcesStore: ResourcesStore + sharesStore: SharesStore } export interface FolderLoader { @@ -68,6 +71,7 @@ export class FolderService { const clientService = useClientService() const configStore = useConfigStore() const resourcesStore = useResourcesStore() + const sharesStore = useSharesStore() const loader = this.loaders.find((l) => l.isEnabled() && l.isActive(unref(router))) if (!loader) { @@ -83,6 +87,7 @@ export class FolderService { spacesStore, capabilityStore, resourcesStore, + sharesStore, router } try { diff --git a/packages/web-app-files/src/services/folder/loaderSharedViaLink.ts b/packages/web-app-files/src/services/folder/loaderSharedViaLink.ts index 84f08f139ce..168dc31dcc2 100644 --- a/packages/web-app-files/src/services/folder/loaderSharedViaLink.ts +++ b/packages/web-app-files/src/services/folder/loaderSharedViaLink.ts @@ -2,8 +2,7 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folder' import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { isLocationSharesActive } from '@ownclouders/web-pkg' -import { ShareTypes } from '@ownclouders/web-client/src/helpers/share' -import { aggregateResourceShares } from '@ownclouders/web-client/src/helpers/share' +import { buildOutgoingShareResource } from '@ownclouders/web-client/src/helpers/share/functionsNG' export class FolderLoaderSharedViaLink implements FolderLoader { public isEnabled(): boolean { @@ -15,9 +14,8 @@ export class FolderLoaderSharedViaLink implements FolderLoader { } public getTask(context: TaskContext): FolderLoaderTask { - const { userStore, spacesStore, clientService, configStore, capabilityStore, resourcesStore } = + const { userStore, spacesStore, clientService, configStore, resourcesStore, sharesStore } = context - const { owncloudSdk: client } = clientService // eslint-disable-next-line @typescript-eslint/no-unused-vars return useTask(function* (signal1, signal2) { @@ -28,28 +26,13 @@ export class FolderLoaderSharedViaLink implements FolderLoader { yield spacesStore.loadMountPoints({ graphClient: clientService.graphAuthenticated }) } - let resources = yield client.shares.getShares('', { - share_types: ShareTypes.link.value.toString(), - include_tags: false - }) - - resources = resources.map((r) => r.shareInfo) - if (resources.length) { - resources = aggregateResourceShares({ - shares: resources, - spaces: spacesStore.spaces, - incomingShares: false, - allowSharePermission: capabilityStore.sharingResharing, - hasShareJail: capabilityStore.spacesShareJail, - fullShareOwnerPaths: configStore.options.routing.fullShareOwnerPaths - }).map((resource) => { - // info: in oc10 we have no storageId in resources. All resources are mounted into the personal space. - if (!resource.storageId) { - resource.storageId = userStore.user.onPremisesSamAccountName - } - return resource - }) - } + const { + data: { value } + } = yield clientService.graphAuthenticated.drives.listSharedByMe() + + const resources = value + .filter((s) => s.permissions.some(({ link }) => !!link)) + .map((driveItem) => buildOutgoingShareResource({ driveItem, user: userStore.user })) resourcesStore.initResourceList({ currentFolder: null, resources }) }) diff --git a/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts b/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts index 8ee2231cf07..86d6111dce8 100644 --- a/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts +++ b/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts @@ -1,7 +1,7 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folder' import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' -import { aggregateResourceShares } from '@ownclouders/web-client/src/helpers/share' +import { buildIncomingShareResource } from '@ownclouders/web-client/src/helpers/share/functionsNG' import { isLocationSharesActive } from '@ownclouders/web-pkg' export class FolderLoaderSharedWithMe implements FolderLoader { @@ -14,7 +14,7 @@ export class FolderLoaderSharedWithMe implements FolderLoader { } public getTask(context: TaskContext): FolderLoaderTask { - const { userStore, spacesStore, clientService, configStore, capabilityStore, resourcesStore } = + const { spacesStore, clientService, configStore, resourcesStore, sharesStore, userStore } = context // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -26,31 +26,13 @@ export class FolderLoaderSharedWithMe implements FolderLoader { yield spacesStore.loadMountPoints({ graphClient: clientService.graphAuthenticated }) } - let resources = yield clientService.owncloudSdk.shares.getShares('', { - state: 'all', - include_tags: false, - shared_with_me: true, - show_hidden: true - }) - - resources = resources.map((r) => r.shareInfo) - - if (resources.length) { - resources = aggregateResourceShares({ - shares: resources, - spaces: spacesStore.spaces, - incomingShares: true, - allowSharePermission: capabilityStore.sharingResharing, - hasShareJail: capabilityStore.spacesShareJail, - fullShareOwnerPaths: configStore.options.routing.fullShareOwnerPaths - }).map((resource) => { - // info: in oc10 we have no storageId in resources. All resources are mounted into the personal space. - if (!resource.storageId) { - resource.storageId = userStore.user.onPremisesSamAccountName - } - return resource - }) - } + const { + data: { value } + } = yield clientService.graphAuthenticated.drives.listSharedWithMe() + + const resources = value.map((driveItem) => + buildIncomingShareResource({ driveItem, graphRoles: sharesStore.graphRoles }) + ) resourcesStore.initResourceList({ currentFolder: null, resources }) }) diff --git a/packages/web-app-files/src/services/folder/loaderSharedWithOthers.ts b/packages/web-app-files/src/services/folder/loaderSharedWithOthers.ts index 13493a9fc10..935da590978 100644 --- a/packages/web-app-files/src/services/folder/loaderSharedWithOthers.ts +++ b/packages/web-app-files/src/services/folder/loaderSharedWithOthers.ts @@ -2,8 +2,7 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folder' import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { isLocationSharesActive } from '@ownclouders/web-pkg' -import { aggregateResourceShares } from '@ownclouders/web-client/src/helpers/share' -import { peopleRoleDenyFolder, ShareTypes } from '@ownclouders/web-client/src/helpers/share' +import { buildOutgoingShareResource } from '@ownclouders/web-client/src/helpers/share/functionsNG' export class FolderLoaderSharedWithOthers implements FolderLoader { public isEnabled(): boolean { @@ -15,9 +14,8 @@ export class FolderLoaderSharedWithOthers implements FolderLoader { } public getTask(context: TaskContext): FolderLoaderTask { - const { userStore, spacesStore, clientService, configStore, capabilityStore, resourcesStore } = + const { userStore, spacesStore, clientService, configStore, resourcesStore, sharesStore } = context - const { owncloudSdk: client } = clientService // eslint-disable-next-line @typescript-eslint/no-unused-vars return useTask(function* (signal1, signal2) { @@ -28,37 +26,13 @@ export class FolderLoaderSharedWithOthers implements FolderLoader { yield spacesStore.loadMountPoints({ graphClient: clientService.graphAuthenticated }) } - const shareTypes = ShareTypes.authenticated - .filter( - (type) => ![ShareTypes.spaceUser.value, ShareTypes.spaceGroup.value].includes(type.value) - ) - .map((share) => share.value) - .join(',') + const { + data: { value } + } = yield clientService.graphAuthenticated.drives.listSharedByMe() - let resources = yield client.shares.getShares('', { - share_types: shareTypes, - reshares: true, - include_tags: false - }) - resources = resources - .filter((r) => parseInt(r.shareInfo.permissions) !== peopleRoleDenyFolder.bitmask(false)) - .map((r) => r.shareInfo) - if (resources.length) { - resources = aggregateResourceShares({ - shares: resources, - spaces: spacesStore.spaces, - incomingShares: false, - allowSharePermission: capabilityStore.sharingResharing, - hasShareJail: capabilityStore.spacesShareJail, - fullShareOwnerPaths: configStore.options.routing.fullShareOwnerPaths - }).map((resource) => { - // info: in oc10 we have no storageId in resources. All resources are mounted into the personal space. - if (!resource.storageId) { - resource.storageId = userStore.user.onPremisesSamAccountName - } - return resource - }) - } + const resources = value + .filter((s) => s.permissions.some(({ link }) => !link)) + .map((driveItem) => buildOutgoingShareResource({ driveItem, user: userStore.user })) resourcesStore.initResourceList({ currentFolder: null, resources }) }) diff --git a/packages/web-app-files/src/views/shares/SharedWithMe.vue b/packages/web-app-files/src/views/shares/SharedWithMe.vue index ae7ad49b98a..83f36cfc410 100644 --- a/packages/web-app-files/src/views/shares/SharedWithMe.vue +++ b/packages/web-app-files/src/views/shares/SharedWithMe.vue @@ -181,8 +181,10 @@ export default defineComponent({ const selectedShareTypes = queryItemAsString(unref(selectedShareTypesQuery))?.split('+') if (selectedShareTypes?.length) { - result = result.filter(({ shareType }) => { - return selectedShareTypes.map((t) => ShareTypes[t].value).includes(shareType) + result = result.filter(({ shareTypes }) => { + return selectedShareTypes + .map((t) => ShareTypes[t].value) + .some((t) => shareTypes.includes(t)) }) } @@ -244,7 +246,11 @@ export default defineComponent({ } const shareTypes = computed(() => { - const uniqueShareTypes = uniq(unref(paginatedResources).map((i) => i.shareType)) + const uniqueShareTypes = uniq( + unref(paginatedResources) + .map((i) => i.shareTypes) + .flat() + ) return ShareTypes.getByValues(uniqueShareTypes) }) diff --git a/packages/web-app-files/tests/unit/views/shares/SharedWithMe.spec.ts b/packages/web-app-files/tests/unit/views/shares/SharedWithMe.spec.ts index 03b244c3eab..c8eaeaa9561 100644 --- a/packages/web-app-files/tests/unit/views/shares/SharedWithMe.spec.ts +++ b/packages/web-app-files/tests/unit/views/shares/SharedWithMe.spec.ts @@ -84,8 +84,8 @@ describe('SharedWithMe view', () => { const shareType2 = ShareTypes.group const { wrapper } = getMountedWrapper({ files: [ - mock({ shareType: shareType1.value }), - mock({ shareType: shareType2.value }) + mock({ shareTypes: [shareType1.value] }), + mock({ shareTypes: [shareType2.value] }) ] }) const filterItems = wrapper.findComponent('.share-type-filter').props('items') @@ -101,11 +101,11 @@ describe('SharedWithMe view', () => { files: [ mock({ sharedBy: collaborator1, - shareType: ShareTypes.user.value + shareTypes: [ShareTypes.user.value] }), mock({ sharedBy: collaborator2, - shareType: ShareTypes.user.value + shareTypes: [ShareTypes.user.value] }) ] }) @@ -125,12 +125,12 @@ describe('SharedWithMe view', () => { mock({ name: 'share1', hidden: false, - shareType: ShareTypes.user.value + shareTypes: [ShareTypes.user.value] }), mock({ name: 'share2', hidden: false, - shareType: ShareTypes.user.value + shareTypes: [ShareTypes.user.value] }) ] }) diff --git a/packages/web-client/src/graph.ts b/packages/web-client/src/graph.ts index 27c8591bcc0..6b1c1a8caea 100644 --- a/packages/web-client/src/graph.ts +++ b/packages/web-client/src/graph.ts @@ -24,7 +24,11 @@ import { ApplicationsApiFactory, UserAppRoleAssignmentApiFactory, AppRoleAssignment, - ExportPersonalDataRequest + ExportPersonalDataRequest, + MeDriveApiFactory, + RoleManagementApiFactory, + UnifiedRoleDefinition, + CollectionOfDriveItems1 } from './generated' export interface Graph { @@ -39,6 +43,8 @@ export interface Graph { drives: { listMyDrives: (orderBy?: string, filter?: string) => Promise> listAllDrives: (orderBy?: string, filter?: string) => Promise> + listSharedWithMe: () => AxiosPromise + listSharedByMe: () => AxiosPromise getDrive: (id: string) => AxiosPromise createDrive: (drive: Drive, options: any) => AxiosPromise updateDrive: (id: string, drive: Drive, options: any) => AxiosPromise @@ -72,6 +78,9 @@ export interface Graph { addMember: (groupId: string, userId: string, server: string) => AxiosPromise deleteMember: (groupId: string, userId: string) => AxiosPromise } + roleManagement: { + listPermissionRoleDefinitions: () => AxiosPromise + } } export const graph = (baseURI: string, axiosClient: AxiosInstance): Graph => { @@ -84,6 +93,7 @@ export const graph = (baseURI: string, axiosClient: AxiosInstance): Graph => { const meDrivesApi = new MeDrivesApi(config, config.basePath, axiosClient) const allDrivesApi = new DrivesGetDrivesApi(config, config.basePath, axiosClient) const meUserApiFactory = MeUserApiFactory(config, config.basePath, axiosClient) + const meDriveApiFactory = MeDriveApiFactory(config, config.basePath, axiosClient) const meChangepasswordApiFactory = MeChangepasswordApiFactory( config, config.basePath, @@ -101,6 +111,7 @@ export const graph = (baseURI: string, axiosClient: AxiosInstance): Graph => { const groupsApiFactory = GroupsApiFactory(config, config.basePath, axiosClient) const drivesApiFactory = DrivesApiFactory(config, config.basePath, axiosClient) const tagsApiFactory = TagsApiFactory(config, config.basePath, axiosClient) + const roleManagementApiFactory = RoleManagementApiFactory(config, config.basePath, axiosClient) return { applications: { @@ -117,6 +128,8 @@ export const graph = (baseURI: string, axiosClient: AxiosInstance): Graph => { meDrivesApi.listMyDrives(orderBy, filter), listAllDrives: (orderBy?: string, filter?: string) => allDrivesApi.listAllDrives(orderBy, filter), + listSharedWithMe: () => meDriveApiFactory.listSharedWithMe(), + listSharedByMe: () => meDriveApiFactory.listSharedByMe(), getDrive: (id: string) => drivesApiFactory.getDrive(id), createDrive: (drive: Drive, options: any): AxiosPromise => drivesApiFactory.createDrive(drive, options), @@ -174,6 +187,9 @@ export const graph = (baseURI: string, axiosClient: AxiosInstance): Graph => { groupApiFactory.addMember(groupId, { '@odata.id': `${server}graph/v1.0/users/${userId}` }), deleteMember: (groupId: string, userId: string) => groupApiFactory.deleteMember(groupId, userId) + }, + roleManagement: { + listPermissionRoleDefinitions: () => roleManagementApiFactory.listPermissionRoleDefinitions() } } } diff --git a/packages/web-client/src/helpers/share/functions.ts b/packages/web-client/src/helpers/share/functions.ts index 577be4b629a..73363a6eed6 100644 --- a/packages/web-client/src/helpers/share/functions.ts +++ b/packages/web-client/src/helpers/share/functions.ts @@ -12,17 +12,18 @@ import path from 'path' import { SHARE_JAIL_ID, SpaceResource, buildWebDavSpacesPath } from '../space' import { ShareStatus } from './status' import { SharePermissions } from './permission' -import { Share } from './share' import { buildSpaceShare } from './space' import { LinkShareRoles, PeopleShareRoles } from './role' -import { ShareResource } from './types' +import { ShareResource, Share } from './types' export const isShareResource = (resource: Resource): resource is ShareResource => { - return Object.hasOwn(resource, 'shareType') + return Object.hasOwn(resource, 'sharedWith') } /** * Transforms given shares into a resource format and returns only their unique occurences + * + * @deprecated */ export function aggregateResourceShares({ shares, @@ -133,6 +134,7 @@ function addMatchingSpaceToShares(shares, spaces) { return resources } +/** @deprecated */ export function buildSharedResource( share, incomingShares = false, @@ -155,7 +157,7 @@ export function buildSharedResource( path: undefined, webDavPath: undefined, processing: share.processing || false, - shareType: parseInt(share.share_type), + shareTypes: [parseInt(share.share_type)], owner: { id: share.uid_owner, displayName: share.displayname_owner }, sharedBy: { id: share.uid_owner, displayName: share.displayname_owner }, sharedWith: share.sharedWith || [] diff --git a/packages/web-client/src/helpers/share/functionsNG.ts b/packages/web-client/src/helpers/share/functionsNG.ts new file mode 100644 index 00000000000..b584f86c953 --- /dev/null +++ b/packages/web-client/src/helpers/share/functionsNG.ts @@ -0,0 +1,185 @@ +import { extractDomSelector, extractExtensionFromFile, extractStorageId } from '../resource' +import { ShareTypes } from './type' +import { SHARE_JAIL_ID, buildWebDavSpacesPath } from '../space' +import { ShareStatus } from './status' +import { DriveItem, UnifiedRoleDefinition, User } from '../../generated' +import { GraphSharePermission, ShareResource } from './types' + +export const getShareResourceRoles = ({ + driveItem, + graphRoles +}: { + driveItem: DriveItem + graphRoles: UnifiedRoleDefinition[] +}) => { + return driveItem.remoteItem?.permissions.reduce((acc, permission) => { + permission.roles?.forEach((roleId) => { + const role = graphRoles.find(({ id }) => id === roleId) + if (role && !acc.some(({ id }) => id === role.id)) { + acc.push(role) + } + }) + + return acc + }, []) +} + +export const getShareResourcePermissions = ({ + driveItem, + shareRoles +}: { + driveItem: DriveItem + shareRoles: UnifiedRoleDefinition[] +}): GraphSharePermission[] => { + if (!shareRoles.length) { + // the server lists plain permissions if it doesn't find a corresponding role + const permissions = driveItem.remoteItem?.permissions.reduce( + (acc, permission) => { + const permissions = permission['@libre.graph.permissions.actions'] as any + if (permissions) { + acc.push(...permissions) + } + + return acc + }, + [] + ) + return [...new Set(permissions)] + } + + const permissions = shareRoles.reduce((acc, role) => { + role.rolePermissions.forEach((permission) => { + acc.push(...permission.allowedResourceActions) + }) + return acc + }, []) + + return [...new Set(permissions)] +} + +export function buildIncomingShareResource({ + driveItem, + graphRoles +}: { + driveItem: DriveItem + graphRoles: UnifiedRoleDefinition[] +}): ShareResource { + const resourceName = driveItem.name || driveItem.remoteItem.name + const storageId = extractStorageId(driveItem.remoteItem.id) + const permission = driveItem.remoteItem?.permissions[0] + const id = permission?.id || driveItem.id + const shareType = permission?.grantedToV2.group ? ShareTypes.group.value : ShareTypes.user.value + + const shareRoles = getShareResourceRoles({ driveItem, graphRoles }) + const sharePermissions = getShareResourcePermissions({ driveItem, shareRoles }) + + const resource: ShareResource = { + id, + shareId: id, + path: '/', + name: resourceName, + fileId: driveItem.remoteItem.id, + storageId, + parentFolderId: driveItem.parentReference?.id, + sdate: driveItem.remoteItem.shared.sharedDateTime, + indicators: [], + tags: [], + webDavPath: buildWebDavSpacesPath([SHARE_JAIL_ID, id].join('!'), '/'), + sharedBy: driveItem.remoteItem.createdBy.user, + owner: driveItem.remoteItem.shared.owner.user, + sharedWith: [ + permission?.grantedToV2.group + ? { ...permission.grantedToV2.group, shareType } + : { ...permission?.grantedToV2.user, shareType } + ], + shareTypes: [shareType], + share: driveItem, + isFolder: !!driveItem.remoteItem.folder, + type: !!driveItem.remoteItem.folder ? 'folder' : 'file', + mimeType: driveItem.remoteItem.file?.mimeType || 'httpd/unix-directory', + status: permission?.['@client.synchronize'] ? ShareStatus.accepted : ShareStatus.declined, + syncEnabled: permission?.['@client.synchronize'], + hidden: permission?.['@ui.hidden'], + shareRoles, + sharePermissions, + canRename: () => !!permission?.['@client.synchronize'], + canDownload: () => sharePermissions.includes(GraphSharePermission.readBasic), + canUpload: () => sharePermissions.includes(GraphSharePermission.createUpload), + canCreate: () => sharePermissions.includes(GraphSharePermission.createChildren), + canBeDeleted: () => sharePermissions.includes(GraphSharePermission.deleteStandard), + canEditTags: () => sharePermissions.includes(GraphSharePermission.createChildren), + isMounted: () => false, + isReceivedShare: () => true, + canShare: () => false, + canDeny: () => false, // currently not possible with sharing NG (?) + getDomSelector: () => extractDomSelector(id) + } + + resource.extension = extractExtensionFromFile(resource) + + return resource +} + +export function buildOutgoingShareResource({ + driveItem, + user +}: { + driveItem: DriveItem + user: User +}): ShareResource { + const resource: ShareResource = { + id: driveItem.id, + shareId: driveItem.id, + path: driveItem.parentReference.path, + name: driveItem.name, + fileId: driveItem.id, + storageId: extractStorageId(driveItem.id), + parentFolderId: driveItem.parentReference?.id, + sdate: driveItem.lastModifiedDateTime, // FIXME + indicators: [], + tags: [], + webDavPath: buildWebDavSpacesPath([SHARE_JAIL_ID, driveItem.id].join('!'), '/'), + sharedBy: { id: user.id, displayName: user.displayName }, + owner: { id: user.id, displayName: user.displayName }, + sharedWith: driveItem.permissions.map((p) => { + if (p.link) { + return { + id: p.id, + displayName: p.link['@libre.graph.displayName'], + shareType: ShareTypes.link.value + } + } + if (p.grantedToV2.group) { + return { ...p.grantedToV2.group, shareType: ShareTypes.group.value } + } + return { ...p.grantedToV2.user, shareType: ShareTypes.user.value } + }), + shareTypes: driveItem.permissions.map((p) => { + if (p.link) { + return ShareTypes.link.value + } + if (p.grantedToV2.group) { + return ShareTypes.group.value + } + return ShareTypes.user.value + }), + share: driveItem, + isFolder: !!driveItem.folder, + type: !!driveItem.folder ? 'folder' : 'file', + canRename: () => true, + canDownload: () => true, + canUpload: () => true, + canCreate: () => true, + canBeDeleted: () => true, + canEditTags: () => true, + isMounted: () => false, + isReceivedShare: () => true, + canShare: () => true, + canDeny: () => true, + getDomSelector: () => extractDomSelector(driveItem.id) + } + + resource.extension = extractExtensionFromFile(resource) + + return resource +} diff --git a/packages/web-client/src/helpers/share/index.ts b/packages/web-client/src/helpers/share/index.ts index e7c182b7f4f..baf34f688ff 100644 --- a/packages/web-client/src/helpers/share/index.ts +++ b/packages/web-client/src/helpers/share/index.ts @@ -2,7 +2,6 @@ export * from './constants' export * from './functions' export * from './permission' export * from './role' -export * from './share' export * from './space' export * from './status' export * from './type' diff --git a/packages/web-client/src/helpers/share/share.ts b/packages/web-client/src/helpers/share/share.ts deleted file mode 100644 index def6173080e..00000000000 --- a/packages/web-client/src/helpers/share/share.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { User } from '../user' -import type { ShareRole } from './role' -import type { SharePermission } from './permission' - -export interface Share { - shareType: number - id: string - collaborator?: User - permissions?: number - role?: ShareRole - token?: string - url?: string - path?: string - description?: string - stime?: string - name?: string - password?: boolean - expiration?: string - itemSource?: string - file?: { parent: string; source: string; target: string } - owner?: User - fileOwner?: User - customPermissions?: SharePermission[] - expires?: Date - quicklink?: boolean - outgoing?: boolean - indirect?: boolean - notifyUploads?: boolean - notifyUploadsExtraRecipients?: string -} diff --git a/packages/web-client/src/helpers/share/space.ts b/packages/web-client/src/helpers/share/space.ts index fee5af4345f..f4c37635d36 100644 --- a/packages/web-client/src/helpers/share/space.ts +++ b/packages/web-client/src/helpers/share/space.ts @@ -1,5 +1,5 @@ import { spaceRoleEditor, spaceRoleManager, spaceRoleViewer } from './role' -import { Share } from './share' +import { Share } from './types' import { ShareTypes } from './type' export function buildSpaceShare(s, storageId): Share { diff --git a/packages/web-client/src/helpers/share/types.ts b/packages/web-client/src/helpers/share/types.ts index e84d697ae5c..b45ae931614 100644 --- a/packages/web-client/src/helpers/share/types.ts +++ b/packages/web-client/src/helpers/share/types.ts @@ -1,5 +1,8 @@ import { Identity, UnifiedRoleDefinition } from '../../generated' import { Resource } from '../resource' +import type { User } from '../user' +import type { ShareRole } from './role' +import type { SharePermission } from './permission' export enum GraphSharePermission { createUpload = 'libre.graph/driveItem/upload/create', @@ -17,15 +20,42 @@ export enum GraphSharePermission { } export interface ShareResource extends Resource { - shareType: number + sharedWith: Array<{ shareType: number } & Identity> + sharedBy: Identity syncEnabled?: boolean shareRoles?: UnifiedRoleDefinition[] sharePermissions?: GraphSharePermission[] - sharedWith?: Identity[] - sharedBy?: Identity hidden?: boolean status?: number // FIXME: remove in favour of syncEnabled share?: any // FIXME: type DriveItem OR remove? do we want to expose the share on each resource? } + +/** @deprecated */ +export interface Share { + shareType: number + id: string + collaborator?: User + permissions?: number + role?: ShareRole + token?: string + url?: string + path?: string + description?: string + stime?: string + name?: string + password?: boolean + expiration?: string + itemSource?: string + file?: { parent: string; source: string; target: string } + owner?: User + fileOwner?: User + customPermissions?: SharePermission[] + expires?: Date + quicklink?: boolean + outgoing?: boolean + indirect?: boolean + notifyUploads?: boolean + notifyUploadsExtraRecipients?: string +} diff --git a/packages/web-pkg/src/components/FilesList/ResourceTable.vue b/packages/web-pkg/src/components/FilesList/ResourceTable.vue index 328b503d56e..b089064aba4 100644 --- a/packages/web-pkg/src/components/FilesList/ResourceTable.vue +++ b/packages/web-pkg/src/components/FilesList/ResourceTable.vue @@ -828,10 +828,8 @@ export default defineComponent({ let panelToOpen if (file.type === 'space') { panelToOpen = 'space-share' - } else if (isShareResource(file) && file.shareType === ShareTypes.link.value) { - panelToOpen = 'sharing#linkShares' } else { - panelToOpen = 'sharing#peopleShares' + panelToOpen = 'sharing' } eventBus.publish(SideBarEventTopics.openWithPanel, panelToOpen) }, @@ -1022,35 +1020,38 @@ export default defineComponent({ if (!isShareResource(resource)) { return } - const resourceType = resource.type === 'folder' ? this.$gettext('folder') : this.$gettext('file') - if (!resource.sharedWith.length) { - return '' - } - - if (resource.shareType === ShareTypes.link.value) { - return this.$ngettext( - 'This %{ resourceType } is shared via %{ count } link', - 'This %{ resourceType } is shared via %{ count } links', - resource.sharedWith.length, - { - resourceType, - count: resource.sharedWith.length.toString() - } - ) - } + const shareCount = resource.sharedWith.filter(({ shareType }) => + [ShareTypes.user.value, ShareTypes.link.value].includes(shareType) + ).length + const linkCount = resource.sharedWith.filter( + ({ shareType }) => shareType === ShareTypes.link.value + ).length - return this.$ngettext( - 'This %{ resourceType } is shared via %{ count } invite', - 'This %{ resourceType } is shared via %{ count } invites', - resource.sharedWith.length, - { - resourceType, - count: resource.sharedWith.length.toString() - } - ) + const shareText = + shareCount > 0 + ? this.$ngettext( + 'This %{ resourceType } is shared via %{ shareCount } invite', + 'This %{ resourceType } is shared via %{ shareCount } invites', + shareCount + ) + : '' + const linkText = + linkCount > 0 + ? this.$ngettext( + 'This %{ resourceType } is shared via %{ linkCount } link', + 'This %{ resourceType } is shared via %{ linkCount } links', + linkCount + ) + : '' + const description = [shareText, linkText].join(' ') + return this.$gettext(description, { + resourceType, + shareCount: shareCount.toString(), + linkCount: linkCount.toString() + }) }, getOwnerAvatarDescription(resource: Resource) { const resourceType = @@ -1082,7 +1083,7 @@ export default defineComponent({ return resource.sharedWith.map((s) => ({ displayName: s.displayName, name: s.displayName, - shareType: resource.shareType, + shareType: s.shareType, username: s.id })) } @@ -1326,23 +1327,15 @@ export default defineComponent({ } // shared with me: on tablets hide shared with column and display owner column instead -#files-shared-with-me-pending-section .files-table .oc-table-header-cell-owner, -#files-shared-with-me-pending-section .files-table .oc-table-data-cell-owner, -#files-shared-with-me-accepted-section .files-table .oc-table-header-cell-owner, -#files-shared-with-me-accepted-section .files-table .oc-table-data-cell-owner, -#files-shared-with-me-declined-section .files-table .oc-table-header-cell-owner, -#files-shared-with-me-declined-section .files-table .oc-table-data-cell-owner { +#files-shared-with-me-view .files-table .oc-table-header-cell-owner, +#files-shared-with-me-view .files-table .oc-table-data-cell-owner { @media only screen and (min-width: 640px) { display: table-cell; } } -#files-shared-with-me-pending-section .files-table .oc-table-header-cell-sharedWith, -#files-shared-with-me-pending-section .files-table .oc-table-data-cell-sharedWith, -#files-shared-with-me-accepted-section .files-table .oc-table-header-cell-sharedWith, -#files-shared-with-me-accepted-section .files-table .oc-table-data-cell-sharedWith, -#files-shared-with-me-declined-section .files-table .oc-table-header-cell-sharedWith, -#files-shared-with-me-declined-section .files-table .oc-table-data-cell-sharedWith { +#files-shared-with-me-view .files-table .oc-table-header-cell-sharedWith, +#files-shared-with-me-view .files-table .oc-table-data-cell-sharedWith { @media only screen and (max-width: 1199px) { display: none; } diff --git a/packages/web-pkg/src/composables/piniaStores/shares/shares.ts b/packages/web-pkg/src/composables/piniaStores/shares/shares.ts index 5b62a22d0d7..9e4203ee685 100644 --- a/packages/web-pkg/src/composables/piniaStores/shares/shares.ts +++ b/packages/web-pkg/src/composables/piniaStores/shares/shares.ts @@ -21,6 +21,7 @@ import { UpdateShareOptions } from './types' import { useResourcesStore } from '../resources' +import { UnifiedRoleDefinition } from '@ownclouders/web-client/src/generated' export const useSharesStore = defineStore('shares', () => { const configStore = useConfigStore() @@ -29,6 +30,7 @@ export const useSharesStore = defineStore('shares', () => { const loading = ref>() const shares = ref([]) as Ref + const graphRoles = ref([]) const incomingShares = computed(() => unref(shares).filter(({ outgoing }) => !outgoing) || []) const incomingCollaborators = computed( @@ -56,6 +58,10 @@ export const useSharesStore = defineStore('shares', () => { () => capabilityStore.sharingResharing && capabilityStore.sharingResharingDefault ) + const setGraphRoles = (values: UnifiedRoleDefinition[]) => { + graphRoles.value = values + } + const upsertShare = (share: Share) => { const existingShare = unref(shares).find(({ id }) => id === share.id) @@ -347,12 +353,15 @@ export const useSharesStore = defineStore('shares', () => { return { loading, shares, + graphRoles, incomingShares, incomingCollaborators, outgoingShares, outgoingLinks, outgoingCollaborators, + setGraphRoles, + pruneShares, loadShares, addShare, diff --git a/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts b/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts index a6b9416027a..3a040722367 100644 --- a/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts +++ b/packages/web-pkg/src/composables/spaces/useGetMatchingSpace.ts @@ -52,7 +52,7 @@ export const useGetMatchingSpace = (options?: GetMatchingSpaceOptions) => { } const driveAliasPrefix = - (isShareResource(resource) && resource.shareType === ShareTypes.remote.value) || + (isShareResource(resource) && resource.shareTypes.includes(ShareTypes.remote.value)) || resource?.id?.toString().startsWith(OCM_PROVIDER_ID) ? 'ocm-share' : 'share' diff --git a/packages/web-pkg/src/helpers/share/triggerShareAction.ts b/packages/web-pkg/src/helpers/share/triggerShareAction.ts index 1cf9845fae2..fd9e407d0f5 100644 --- a/packages/web-pkg/src/helpers/share/triggerShareAction.ts +++ b/packages/web-pkg/src/helpers/share/triggerShareAction.ts @@ -31,7 +31,7 @@ export async function triggerShareAction({ throw new Error('invalid new share status') } - let action = `api/v1/shares/pending/${resource.share.id}` + let action = `api/v1/shares/pending/${resource.shareId}` if (hidden !== undefined) { action += `?hidden=${hidden ? 'true' : 'false'}` } diff --git a/packages/web-pkg/tests/unit/components/FilesList/ResourceTable.spec.ts b/packages/web-pkg/tests/unit/components/FilesList/ResourceTable.spec.ts index 3290d9c6dba..e880902f278 100644 --- a/packages/web-pkg/tests/unit/components/FilesList/ResourceTable.spec.ts +++ b/packages/web-pkg/tests/unit/components/FilesList/ResourceTable.spec.ts @@ -102,6 +102,7 @@ const resourcesWithAllFields = [ ddate: getCurrentDate(), owner, sharedWith, + shareTypes: [], canRename: jest.fn, getDomSelector: () => extractDomSelector('forest') }, @@ -119,6 +120,7 @@ const resourcesWithAllFields = [ sdate: getCurrentDate(), ddate: getCurrentDate(), sharedWith, + shareTypes: [], owner, canRename: jest.fn, getDomSelector: () => extractDomSelector('notes') @@ -136,6 +138,7 @@ const resourcesWithAllFields = [ sdate: getCurrentDate(), ddate: getCurrentDate(), sharedWith, + shareTypes: [], owner, canRename: jest.fn, getDomSelector: () => extractDomSelector('documents') @@ -152,6 +155,7 @@ const resourcesWithAllFields = [ sdate: getCurrentDate(), ddate: getCurrentDate(), sharedWith, + shareTypes: [], tags: [], owner, canRename: jest.fn, diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts index 1dcd9bc14a8..893530e6f9d 100644 --- a/packages/web-runtime/src/index.ts +++ b/packages/web-runtime/src/index.ts @@ -43,6 +43,7 @@ import { createPinia } from 'pinia' import Avatar from './components/Avatar.vue' import focusMixin from './mixins/focusMixin' import { ArchiverService } from '@ownclouders/web-pkg' +import { UnifiedRoleDefinition } from '@ownclouders/web-client/src/generated' export const bootstrapApp = async (configurationPath: string): Promise => { const pinia = createPinia() @@ -57,7 +58,8 @@ export const bootstrapApp = async (configurationPath: string): Promise => extensionRegistry, spacesStore, userStore, - resourcesStore + resourcesStore, + sharesStore } = announcePiniaStores() app.provide('$router', router) @@ -204,6 +206,13 @@ export const bootstrapApp = async (configurationPath: string): Promise => field: 'name', value: app.config.globalProperties.$gettext('Personal') }) + + // load sharing roles from graph API + const { data } = + await clientService.graphAuthenticated.roleManagement.listPermissionRoleDefinitions() + + // FIXME: graph type is wrong + sharesStore.setGraphRoles(data as UnifiedRoleDefinition[]) }, { immediate: true diff --git a/tests/acceptance/features/webUIResharing1/reshareUsers.feature b/tests/acceptance/features/webUIResharing1/reshareUsers.feature deleted file mode 100644 index 5e407b7b4d1..00000000000 --- a/tests/acceptance/features/webUIResharing1/reshareUsers.feature +++ /dev/null @@ -1,76 +0,0 @@ -# Reshare permission is not available now in the oCIS webUI -Feature: Resharing shared files with different permissions - As a user - I want to reshare received files and folders with other users with different permissions - So that I can control the access on those files/folders by other collaborators - - Background: - Given the administrator has set the default folder for received shares to "Shares" in the server - And these users have been created with default attributes and without skeleton files in the server: - | username | - | Alice | - | Brian | - | Carol | - And user "Brian" has created folder "simple-folder" in the server - - - @skipOnOCIS - Scenario: User is allowed to reshare a file/folder with the equivalent received permissions, and collaborators should not be listed for the receiver - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "read, share, delete" permissions in the server - And user "Alice" has logged in using the webUI - And the user opens folder "Shares" using the webUI - When the user shares folder "simple-folder" with user "Carol King" as "Custom permissions" with permissions "share, delete" using the webUI - And the user re-logs in as "Carol" using the webUI - And the user opens folder "Shares" using the webUI - And the collaborators list for folder "simple-folder" should be empty - # Then the current collaborators list should have order "Brian Murphy,Carol King" - # And user "Brian Murphy" should be listed as "Owner" reshared through "Alice Hansen" in the collaborators list on the webUI - And user "Carol" should have received a share with these details in the server: - | field | value | - | uid_owner | Alice | - | share_with | Carol | - | file_target | /Shares/simple-folder | - | item_type | folder | - | permissions | share, delete, read | - - @skipOnOCIS - Scenario: User is allowed to reshare a file/folder with the lesser permissions, and check if it is listed for original owner - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "read, share, delete" permissions in the server - And user "Alice" has logged in using the webUI - And the user opens folder "Shares" using the webUI - When the user shares folder "simple-folder" with user "Carol King" as "Custom permissions" with permissions "delete" using the webUI - And the user re-logs in as "Brian" using the webUI - Then user "Alice Hansen" should be listed as "Custom permissions" in the collaborators list for folder "simple-folder" on the webUI - And custom permissions "share, delete" should be set for user "Alice Hansen" for folder "simple-folder" on the webUI - And user "Carol King" should be listed as "Custom permissions" in the collaborators list for folder "simple-folder" on the webUI - And custom permissions "delete" should be set for user "Carol King" for folder "simple-folder" on the webUI - And user "Carol" should have received a share with these details in the server: - | field | value | - | uid_owner | Alice | - | share_with | Carol | - | file_target | /Shares/simple-folder | - | item_type | folder | - | permissions | delete, read | - - - Scenario: Reshare a file and folder from shared with others page - Given user "Brian" has created file "lorem.txt" in the server - And user "Brian" has shared folder "simple-folder" with user "Alice" in the server - And user "Brian" has shared file "lorem.txt" with user "Alice" in the server - And user "Brian" has logged in using the webUI - And the user has browsed to the shared-with-others page - When the user shares folder "simple-folder" with user "Carol King" as "Editor" using the webUI - And the user shares file "lorem.txt" with user "Carol King" as "Editor" using the webUI - Then as "Carol" folder "/Shares/simple-folder" should exist in the server - And as "Carol" file "/Shares/lorem.txt" should exist in the server - - - @issue-product-270 - Scenario: Resource owner sees resharer in collaborators list - Given user "Brian" has created file "lorem.txt" in the server - And user "Brian" has shared folder "simple-folder" with user "Alice" in the server - And user "Alice" has shared folder "/Shares/simple-folder" with user "Carol" in the server - When user "Brian" has logged in using the webUI - And the user opens the share dialog for folder "simple-folder" using the webUI - Then user "Alice Hansen" should be listed as "Can edit" in the collaborators list on the webUI - And user "Carol King" should be listed as "Can edit" in the collaborators list on the webUI diff --git a/tests/acceptance/features/webUIResharing2/reshareUsers.feature b/tests/acceptance/features/webUIResharing2/reshareUsers.feature deleted file mode 100644 index 7b93b86ba31..00000000000 --- a/tests/acceptance/features/webUIResharing2/reshareUsers.feature +++ /dev/null @@ -1,94 +0,0 @@ -# Reshare permission is not available now in the oCIS webUI -Feature: Resharing shared files with different permissions - As a user - I want to reshare received files and folders with other users with different permissions - So that I can control the access on those files/folders by other collaborators - - Background: - Given the administrator has set the default folder for received shares to "Shares" in the server - And these users have been created with default attributes and without skeleton files in the server: - | username | - | Alice | - | Brian | - | Carol | - And user "Brian" has created folder "simple-folder" in the server - - @issue-ocis-1922 - Scenario: Reshare a folder without share permissions using API and check if it is listed on the collaborators list for original owner - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "read, share" permissions in the server - And user "Alice" has shared folder "Shares/simple-folder" with user "Carol" with "read" permissions in the server - And user "Brian" has logged in using the webUI - When the user opens the share dialog for folder "simple-folder" using the webUI - Then user "Carol King" should be listed as "Custom permissions" in the collaborators list for folder "simple-folder" on the webUI - And no custom permissions should be set for collaborator "Carol King" for folder "simple-folder" on the webUI - - # this scenario is skipped on ocis because it opens share folder which in not possible in OCIS - # but it works for OC10 see issue https://github.com/owncloud/web/issues/6896 for more detail - @skipOnOCIS - Scenario: Reshare a folder without share permissions using API and check if it is listed on the collaborators list for resharer - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "read, share" permissions in the server - And user "Alice" has logged in using the webUI - And the user opens folder "Shares" using the webUI - When the user opens the share dialog for folder "simple-folder" using the webUI - Then user "Carol King" should be listed as "Custom permissions" in the collaborators list for folder "simple-folder" on the webUI - And no custom permissions should be set for collaborator "Carol King" for folder "simple-folder" on the webUI - - # this scenario is skipped on ocis because it opens share folder which in not possible in OCIS - # but it works for OC10 see issue https://github.com/owncloud/web/issues/6896 for more detail - @skipOnOCIS - Scenario Outline: share a received folder with another user with same permissions(including share permissions) and check if the user is displayed in collaborators list for resharer - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "" permissions in the server - And user "Alice" has logged in using the webUI - And the user opens folder "Shares" using the webUI - When the user shares folder "simple-folder" with user "Carol King" as "" with permissions "" using the webUI - Then user "Carol King" should be listed as "" in the collaborators list for folder "simple-folder" on the webUI - And custom permissions "" should be set for user "Carol King" for folder "simple-folder" on the webUI - And user "Carol" should have received a share with these details in the server: - | field | value | - | uid_owner | Alice | - | share_with | Carol | - | file_target | /Shares/simple-folder | - | item_type | folder | - | permissions | | - Examples: - | role | displayed-role | collaborators-permissions | displayed-permissions | permissions | - | Viewer | Can view | , | share | read, share | - | Editor | Can edit | , | share, delete, update, create | all | - | Custom permissions | Custom permissions | update, share | share, update | read, update, share | - | Custom permissions | Custom permissions | share, create | share, create | read, share, create | - | Custom permissions | Can edit | delete, share, create, update | share, delete, update, create | read, share, delete, update, create | - - # this scenario is skipped on ocis because it opens share folder which in not possible in OCIS - # but it works for OC10 see issue https://github.com/owncloud/web/issues/6896 for more detail - @skipOnOCIS - Scenario Outline: share a received folder with another user with same permissions(including share permissions) and check if the user is displayed in collaborators list for original owner - Given user "Brian" has shared folder "simple-folder" with user "Alice" with "" permissions in the server - And user "Alice" has logged in using the webUI - And the user opens folder "Shares" using the webUI - When the user shares folder "simple-folder" with user "Carol King" as "" with permissions "" using the webUI - And the user re-logs in as "Brian" using the webUI - Then user "Carol King" should be listed as "" in the collaborators list for folder "simple-folder" on the webUI - And custom permissions "" should be set for user "Carol King" for folder "simple-folder" on the webUI - And user "Alice Hansen" should be listed as "" in the collaborators list for folder "simple-folder" on the webUI - And custom permissions "" should be set for user "Alice Hansen" for folder "simple-folder" on the webUI - And user "Carol" should have received a share with these details in the server: - | field | value | - | uid_owner | Alice | - | share_with | Carol | - | file_target | /Shares/simple-folder | - | item_type | folder | - | permissions | | - And user "Alice" should have received a share with these details in the server: - | field | value | - | uid_owner | Brian | - | share_with | Alice | - | file_target | /Shares/simple-folder | - | item_type | folder | - | permissions | | - Examples: - | role | displayed-role | collaborators-permissions | displayed-permissions | permissions | - | Viewer | Can view | , | share | read, share | - | Editor | Can edit | , | share, delete, update, create | all | - | Custom permissions | Custom permissions | share, create | share, create | read, share, create | - | Custom permissions | Custom permissions | update, share | share, update | read, update, share | - | Custom permissions | Can edit | delete, share, create, update | share, delete, update, create | read, share, delete, update, create | diff --git a/tests/acceptance/features/webUISharingAcceptShares/acceptShares.feature b/tests/acceptance/features/webUISharingAcceptShares/acceptShares.feature index 6b77902ac5d..d4cb7598a9e 100644 --- a/tests/acceptance/features/webUISharingAcceptShares/acceptShares.feature +++ b/tests/acceptance/features/webUISharingAcceptShares/acceptShares.feature @@ -11,7 +11,7 @@ Feature: accept/decline shares coming from internal users | Brian | And user "Brian" has logged in using the webUI - @issue-ocis-1950 + @issue-ocis-1950 @skipOnOCIS Scenario: reject a share that you received as user and as group member Given these groups have been created in the server: | groupname | diff --git a/tests/e2e/cucumber/features/smoke/search/search.feature b/tests/e2e/cucumber/features/smoke/search/search.feature index a9ccc3e6172..c03cc5fdd0e 100644 --- a/tests/e2e/cucumber/features/smoke/search/search.feature +++ b/tests/e2e/cucumber/features/smoke/search/search.feature @@ -116,29 +116,8 @@ Feature: Search | resource | | strängéनेपालीName | - And "Alice" navigates to the shared with me page - When "Alice" reshares the following resource - | resource | recipient | type | role | resourceType | - | new_share_from_brian | Carol | user | Can view | folder | - | new-lorem-big.txt | Carol | user | Can view | file | And "Alice" logs out - # search re-shared resources - When "Carol" logs in - And "Carol" opens the "files" app - And "Carol" creates the following resources - | resource | type | - | folder | folder | - And "Carol" searches "NEW" using the global search and the "everywhere" filter - Then following resources should be displayed in the search list for user "Carol" - | resource | - | new_share_from_brian | - | new-lorem-big.txt | - But following resources should not be displayed in the search list for user "Carol" - | resource | - | folder | - And "Carol" logs out - Scenario: Search using "current folder" filter Given "Admin" creates following users using API diff --git a/tests/e2e/cucumber/features/smoke/shares/reshare.feature b/tests/e2e/cucumber/features/smoke/shares/reshare.feature deleted file mode 100644 index 429fbeb9dda..00000000000 --- a/tests/e2e/cucumber/features/smoke/shares/reshare.feature +++ /dev/null @@ -1,57 +0,0 @@ -Feature: reshare - - Scenario: re-sharing - Given "Admin" creates following users using API - | id | - | Alice | - | Brian | - | Carol | - And "Admin" creates following group using API - | id | - | sales | - | finance | - And "Admin" adds user to the group using API - | user | group | - | Carol | sales | - And "Alice" logs in - And "Alice" creates the following folder in personal space using API - | name | - | folder_to_shared | - And "Alice" shares the following resource using API - | resource | recipient | type | role | - | folder_to_shared | Brian | user | Can edit | - - And "Brian" logs in - And "Brian" opens the "files" app - And "Brian" navigates to the shared with me page - - # re-share with expiration date - And "Brian" reshares the following resource - | resource | recipient | type | role | resourceType | expirationDate | - | folder_to_shared | sales | group | Can view | folder | +5 days | - - And "Carol" logs in - And "Carol" opens the "files" app - And "Carol" navigates to the shared with me page - And "Carol" reshares the following resource - | resource | recipient | type | role | resourceType | - | folder_to_shared | Alice | user | Can view | folder | - - And "Alice" opens the "files" app - And "Alice" navigates to the personal space page - Then "Alice" should see the following recipients - | resource | recipient | type | role | - | folder_to_shared | Brian | user | can edit | - | folder_to_shared | sales | group | can view | - And "Alice" logs out - - When "Brian" updates following sharee role - | resource | recipient | type | role | resourceType | - | folder_to_shared | sales | group | custom_permissions:read | folder | - And "Brian" logs out - - And "Carol" navigates to the shared with me page - Then "Carol" should not be able to reshare the following resource - | resource | - | folder_to_shared | - And "Carol" logs out diff --git a/tests/e2e/cucumber/steps/ui/shares.ts b/tests/e2e/cucumber/steps/ui/shares.ts index 6eb2e122e9a..b63f22f7536 100644 --- a/tests/e2e/cucumber/steps/ui/shares.ts +++ b/tests/e2e/cucumber/steps/ui/shares.ts @@ -49,22 +49,6 @@ When( } ) -When( - '{string} reshares the following resource(s)', - async function (this: World, stepUser: string, stepTable: DataTable) { - const { page } = this.actorsEnvironment.getActor({ key: stepUser }) - const shareObject = new objects.applicationFiles.Share({ page }) - const shareInfo = parseShareTable(stepTable, this.usersEnvironment) - - for (const resource of Object.keys(shareInfo)) { - await shareObject.create({ - resource, - recipients: shareInfo[resource] - }) - } - } -) - When( '{string} accepts the following share(s)', async function (this: World, stepUser: string, stepTable: DataTable) { diff --git a/tests/e2e/support/objects/app-files/resource/actions.ts b/tests/e2e/support/objects/app-files/resource/actions.ts index 0d59e849bfe..cc7f86708c7 100644 --- a/tests/e2e/support/objects/app-files/resource/actions.ts +++ b/tests/e2e/support/objects/app-files/resource/actions.ts @@ -23,7 +23,7 @@ const checkBoxForTrashbin = `//*[@data-test-resource-path="%s"]//ancestor::tr//i export const fileRow = '//ancestor::*[(contains(@class, "oc-tile-card") or contains(@class, "oc-tbody-tr"))]' export const resourceNameSelector = - ':is(#files-files-table, .oc-tiles-item, #files-shared-with-me-accepted-section, .files-table) [data-test-resource-name="%s"]' + ':is(#files-files-table, .oc-tiles-item, .files-table) [data-test-resource-name="%s"]' const breadcrumbResourceNameSelector = '//span[contains(@class, "oc-breadcrumb-item-text") and text()="%s"]' const addNewResourceButton = `#new-file-menu-btn`