diff --git a/changelog/unreleased/enhancemnet-alias-links b/changelog/unreleased/enhancemnet-alias-links new file mode 100644 index 00000000000..0b2596464d5 --- /dev/null +++ b/changelog/unreleased/enhancemnet-alias-links @@ -0,0 +1,6 @@ +Enhancement: Resolve alias links + +Alias links can now be resolved successfully. + +https://github.com/owncloud/web/pull/7405 +https://github.com/owncloud/web/issues/7304 diff --git a/deployments/examples/ocis_web/config/ocis/proxy.yaml b/deployments/examples/ocis_web/config/ocis/proxy.yaml index e3244e00160..9e337df9b79 100644 --- a/deployments/examples/ocis_web/config/ocis/proxy.yaml +++ b/deployments/examples/ocis_web/config/ocis/proxy.yaml @@ -39,6 +39,10 @@ policies: endpoint: /ocs/v[12].php/config backend: http://localhost:9140 unprotected: true + - type: regex + endpoint: /ocs/v[12].php/apps/files_sharing/api/v1/tokeninfo/unprotected + backend: http://localhost:9140 + unprotected: true - endpoint: /ocs/ backend: http://localhost:9140 - type: query diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue index c083106667d..b44fc5301e5 100644 --- a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue +++ b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue @@ -19,7 +19,7 @@ /> - + @@ -183,7 +177,11 @@ import { basename } from 'path' import { DateTime } from 'luxon' import { mapActions, mapGetters } from 'vuex' import { createLocationSpaces } from '../../../../router' -import { LinkShareRoles } from 'web-client/src/helpers/share' +import { + linkRoleInternalFile, + linkRoleInternalFolder, + LinkShareRoles +} from 'web-client/src/helpers/share' import { defineComponent } from '@vue/runtime-core' import { formatDateFromDateTime, formatRelativeDateFromDateTime } from 'web-pkg/src/helpers' import { Resource } from 'web-client' @@ -239,15 +237,15 @@ export default defineComponent({ }, computed: { ...mapGetters('runtime/spaces', ['spaces']), + currentLinkRole() { + return LinkShareRoles.getByBitmask(this.link.permissions, this.isFolderShare) + }, currentLinkRoleDescription() { - return LinkShareRoles.getByBitmask( - parseInt(this.link.permissions), - this.isFolderShare - ).description(false) + return this.currentLinkRole.description(false) }, currentLinkRoleLabel() { - return LinkShareRoles.getByBitmask(parseInt(this.link.permissions), this.isFolderShare).label + return this.currentLinkRole.label }, editOptions() { @@ -317,7 +315,7 @@ export default defineComponent({ }) } } - if (!this.isPasswordEnforced && !this.link.password) { + if (!this.isPasswordEnforced && !this.link.password && !this.isAliasLink) { result.push({ id: 'add-password', title: this.$gettext('Add password'), @@ -389,6 +387,10 @@ export default defineComponent({ passwortProtectionTooltip() { return this.$gettext('This link is password-protected') + }, + + isAliasLink() { + return [linkRoleInternalFolder, linkRoleInternalFile].includes(this.currentLinkRole) } }, watch: { diff --git a/packages/web-app-files/src/components/SideBar/SideBar.vue b/packages/web-app-files/src/components/SideBar/SideBar.vue index 0c46ed3b06b..0e357f5263e 100644 --- a/packages/web-app-files/src/components/SideBar/SideBar.vue +++ b/packages/web-app-files/src/components/SideBar/SideBar.vue @@ -58,6 +58,7 @@ import isEqual from 'lodash-es/isEqual' import { useActiveLocation } from '../../composables' import { SpaceResource } from 'web-client/src/helpers' import { WebDAV } from 'web-client/src/webdav' +import { ShareTypes } from 'web-client/src/helpers/share' export default defineComponent({ components: { FileInfo, SpaceInfo, SideBar }, @@ -113,6 +114,7 @@ export default defineComponent({ const { webdav } = useClientService() return { + isSpacesGenericLocation: useActiveLocation(isLocationSpacesActive, 'files-spaces-generic'), isSpacesProjectsLocation: useActiveLocation(isLocationSpacesActive, 'files-spaces-projects'), isSharedWithMeLocation: useActiveLocation(isLocationSharesActive, 'files-shares-with-me'), isSharedWithOthersLocation: useActiveLocation( @@ -200,6 +202,15 @@ export default defineComponent({ if (this.hasShareJail && this.space?.driveType === 'share') { return false } + if ( + !pathSegments.length && + this.highlightedFile?.shareTypes?.includes(ShareTypes.link.value) && + this.isSpacesGenericLocation + ) { + console.log('ALIAS LINK') + // alias link for a single resource + return false + } return !pathSegments.length }, highlightedFileThumbnail() { diff --git a/packages/web-app-files/src/helpers/resources.ts b/packages/web-app-files/src/helpers/resources.ts index de4cbec2ab7..43dc2a7255b 100644 --- a/packages/web-app-files/src/helpers/resources.ts +++ b/packages/web-app-files/src/helpers/resources.ts @@ -45,6 +45,16 @@ export function buildResource(resource): Resource { } const id = resource.fileInfo[DavProperty.FileId] + const pathParts = resource.name.split('/') + let webDavPath + if (pathParts.length === 3 && !isFolder && pathParts[2].includes('!')) { + // idComponent includes the opaqueID which represents the resource name. + // For the webdav path, we need to replace the opaqueID with the actual resource name. + const withoutOpaqueId = resource.name.split('!')[0] + webDavPath = `${withoutOpaqueId}/${name}` + } else { + webDavPath = resource.name + } return { id, @@ -54,7 +64,7 @@ export function buildResource(resource): Resource { name, extension: isFolder ? '' : extension, path: resourcePath, - webDavPath: resource.name, + webDavPath, type: isFolder ? 'folder' : resource.type, isFolder, mdate: resource.fileInfo[DavProperty.LastModifiedDate], @@ -357,8 +367,9 @@ export function buildSpaceShare(s, storageId): Share { function _buildLink(link): Share { let description = '' + const permissions = parseInt(link.permissions) - const role = LinkShareRoles.getByBitmask(parseInt(link.permissions), link.item_type === 'folder') + const role = LinkShareRoles.getByBitmask(permissions, link.item_type === 'folder') if (role) { description = role.label } @@ -382,7 +393,7 @@ function _buildLink(link): Share { token: link.token as string, url: link.url, path: link.path, - permissions: link.permissions, + permissions, description, quicklink, stime: link.stime, diff --git a/packages/web-app-files/src/services/folder/legacy/loaderPersonal.ts b/packages/web-app-files/src/services/folder/legacy/loaderPersonal.ts index 6c175968a5e..8e8d84e2979 100644 --- a/packages/web-app-files/src/services/folder/legacy/loaderPersonal.ts +++ b/packages/web-app-files/src/services/folder/legacy/loaderPersonal.ts @@ -28,14 +28,17 @@ export class FolderLoaderLegacyPersonal implements FolderLoader { const resources = yield webdav.listFiles(space, { path }) - const currentFolder = resources.shift() - yield store.dispatch('Files/loadSharesTree', { - client, - path: currentFolder.path - }) - - for (const file of resources) { - file.indicators = getIndicators(file, store.state.Files.sharesTree, false) + const currentFolder = + resources.length > 1 || resources[0].isFolder ? resources.shift() : undefined + if (currentFolder) { + yield store.dispatch('Files/loadSharesTree', { + client, + path: currentFolder.path + }) + + for (const file of resources) { + file.indicators = getIndicators(file, store.state.Files.sharesTree, false) + } } store.commit('Files/LOAD_FILES', { diff --git a/packages/web-client/src/helpers/share/role.ts b/packages/web-client/src/helpers/share/role.ts index eacb954f069..2309dd81e58 100644 --- a/packages/web-client/src/helpers/share/role.ts +++ b/packages/web-client/src/helpers/share/role.ts @@ -364,9 +364,14 @@ export abstract class LinkShareRoles { linkRoleUploaderFolder ] - static list(isFolder: boolean, canEditFile = false, hasAliasLinks = false): ShareRole[] { + static list( + isFolder: boolean, + canEditFile = false, + hasAliasLinks = false, + hasPassword = false + ): ShareRole[] { return [ - ...(hasAliasLinks ? [linkRoleInternalFile, linkRoleInternalFolder] : []), + ...(hasAliasLinks && !hasPassword ? [linkRoleInternalFile, linkRoleInternalFolder] : []), ...this.all, ...(canEditFile ? [linkRoleEditorFile] : []) ].filter((r) => r.folder === isFolder) @@ -383,15 +388,17 @@ export abstract class LinkShareRoles { * @param isFolder * @param canEditFile * @param hasAliasLinks + * @param hasPassword */ static filterByBitmask( bitmask: number, isFolder: boolean, canEditFile = false, - hasAliasLinks = false + hasAliasLinks = false, + hasPassword = false ): ShareRole[] { return [ - ...(hasAliasLinks ? [linkRoleInternalFile, linkRoleInternalFolder] : []), + ...(hasAliasLinks && !hasPassword ? [linkRoleInternalFile, linkRoleInternalFolder] : []), ...this.all, ...(canEditFile ? [linkRoleEditorFile] : []) ].filter((r) => { diff --git a/packages/web-client/src/types.ts b/packages/web-client/src/types.ts index 30e9cc70604..0582b51ab00 100644 --- a/packages/web-client/src/types.ts +++ b/packages/web-client/src/types.ts @@ -33,6 +33,8 @@ export type OwnCloudSdk = { shares: { getShare(...args): any getShares(...args): any + getProtectedTokenInfo(...args): any + getUnprotectedTokenInfo(...args): any } users: { getUser(...args): any diff --git a/packages/web-pkg/src/composables/capability/useCapability.ts b/packages/web-pkg/src/composables/capability/useCapability.ts index 2b6407936ed..42a1f00c63e 100644 --- a/packages/web-pkg/src/composables/capability/useCapability.ts +++ b/packages/web-pkg/src/composables/capability/useCapability.ts @@ -28,12 +28,6 @@ export const useCapabilityCoreSupportUrlSigning = createCapabilityComposable( 'core.support-url-signing', false ) - -export const useCapabilityFilesSharingResharing = createCapabilityComposable( - 'files_sharing.resharing', - true -) - export const useCapabilitySpacesEnabled = createCapabilityComposable('spaces.enabled', false) export const useCapabilityProjectSpacesEnabled = createCapabilityComposable( 'spaces.projects', @@ -52,6 +46,10 @@ export const useCapabilityFilesTusExtension = createCapabilityComposable 'files.tus_support.extension', '' ) +export const useCapabilityFilesSharingResharing = createCapabilityComposable( + 'files_sharing.resharing', + true +) export const useCapabilityFilesSharingPublicCanEdit = createCapabilityComposable( 'files_sharing.public.can_edit', false diff --git a/packages/web-runtime/package.json b/packages/web-runtime/package.json index 414dab9f5ae..73e9513eca1 100644 --- a/packages/web-runtime/package.json +++ b/packages/web-runtime/package.json @@ -25,7 +25,7 @@ "marked": "^4.0.12", "oidc-client-ts": "^2.0.5", "owncloud-design-system": "14.0.0-alpha.18", - "owncloud-sdk": "~3.0.0-alpha.15", + "owncloud-sdk": "~3.0.0-alpha.17", "p-queue": "^6.6.2", "popper-max-size-modifier": "^0.2.0", "portal-vue": "^2.1.7", diff --git a/packages/web-runtime/src/composables/tokenInfo/index.ts b/packages/web-runtime/src/composables/tokenInfo/index.ts new file mode 100644 index 00000000000..e04af314e61 --- /dev/null +++ b/packages/web-runtime/src/composables/tokenInfo/index.ts @@ -0,0 +1 @@ +export * from './useLoadTokenInfo' diff --git a/packages/web-runtime/src/composables/tokenInfo/useLoadTokenInfo.ts b/packages/web-runtime/src/composables/tokenInfo/useLoadTokenInfo.ts new file mode 100644 index 00000000000..975d614af0a --- /dev/null +++ b/packages/web-runtime/src/composables/tokenInfo/useLoadTokenInfo.ts @@ -0,0 +1,22 @@ +import { unref } from '@vue/composition-api' +import { useTask } from 'vue-concurrency' +import { useClientService, useStore, useUserContext } from 'web-pkg/src/composables' + +export function useLoadTokenInfo(token) { + const { owncloudSdk } = useClientService() + const store = useStore() + const isUserContext = useUserContext({ store }) + + const loadTokenInfoTask = useTask(function* () { + try { + if (unref(isUserContext)) { + return yield owncloudSdk.shares.getProtectedTokenInfo(token) + } else { + return yield owncloudSdk.shares.getUnprotectedTokenInfo(token) + } + } catch (e) {} // backend doesn't support the token info endpoint + return {} + }) + + return { loadTokenInfoTask } +} diff --git a/packages/web-runtime/src/pages/resolveAliasLink.vue b/packages/web-runtime/src/pages/resolveAliasLink.vue new file mode 100644 index 00000000000..9fc874732cf --- /dev/null +++ b/packages/web-runtime/src/pages/resolveAliasLink.vue @@ -0,0 +1,79 @@ + + + diff --git a/packages/web-runtime/src/pages/resolvePublicLink.vue b/packages/web-runtime/src/pages/resolvePublicLink.vue index 97ecea97472..2b41a04c1dc 100644 --- a/packages/web-runtime/src/pages/resolvePublicLink.vue +++ b/packages/web-runtime/src/pages/resolvePublicLink.vue @@ -2,7 +2,14 @@