Skip to content

Commit

Permalink
fix: resolving external URLs via file ID
Browse files Browse the repository at this point in the history
  • Loading branch information
JammingBen committed Oct 20, 2023
1 parent 2820aa8 commit 945170d
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 4 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/bugfix-external-url-resolving
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Resolving external URLs

Resolving external URLs when only the file ID is given has been fixed.

https://github.com/owncloud/web/issues/9804
https://github.com/owncloud/web/pull/9833
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{ title }}
</div>
</div>
<oc-button appearance="raw" @click="close" :aria-label="$gettext('Close')"
<oc-button appearance="raw" :aria-label="$gettext('Close')" @click="close"
><oc-icon name="close"
/></oc-button>
</div>
Expand Down
109 changes: 107 additions & 2 deletions packages/web-app-external/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,26 @@ import { mapGetters } from 'vuex'
import { computed, defineComponent, unref } from 'vue'
import { urlJoin } from 'web-client/src/utils'
import AppTopBar from 'web-pkg/src/components/AppTopBar.vue'
import { queryItemAsString, useAppDefaults, useRouteQuery } from 'web-pkg/src/composables'
import {
queryItemAsString,
useAppDefaults,
useClientService,
useRoute,
useRouteParam,
useRouteQuery,
useRouter,
useStore
} from 'web-pkg/src/composables'
import { configurationManager } from 'web-pkg/src/configuration'
import ErrorScreen from './components/ErrorScreen.vue'
import LoadingScreen from './components/LoadingScreen.vue'
import {
Resource,
SpaceResource,
buildShareSpaceResource,
isMountPointSpaceResource
} from 'web-client/src/helpers'
import { useLoadFileInfoById } from 'web-pkg/src/composables/fileInfo'
export default defineComponent({
name: 'ExternalApp',
Expand All @@ -52,14 +68,99 @@ export default defineComponent({
LoadingScreen
},
setup() {
const store = useStore()
const router = useRouter()
const currentRoute = useRoute()
const clientService = useClientService()
const { loadFileInfoByIdTask } = useLoadFileInfoById({ clientService })
const appName = useRouteQuery('app')
const applicationName = computed(() => queryItemAsString(unref(appName)))
const fileIdQueryItem = useRouteQuery('fileId')
const fileId = computed(() => {
return queryItemAsString(unref(fileIdQueryItem))
})
const driveAliasAndItem = useRouteParam('driveAliasAndItem')
const getMatchingSpace = (id): SpaceResource => {
return store.getters['runtime/spaces/spaces'].find((space) => id.startsWith(space.id))
}
const findMatchingMountPoint = (id: string | number): SpaceResource => {
return store.getters['runtime/spaces/spaces'].find(
(space) => isMountPointSpaceResource(space) && space.root?.remoteItem?.id === id
)
}
const addMissingDriveAliasAndItem = async () => {
const id = unref(fileId)
let path: string
let matchingSpace = getMatchingSpace(id)
if (matchingSpace) {
path = await clientService.owncloudSdk.files.getPathForFileId(id)
const driveAliasAndItem = matchingSpace.getDriveAliasAndItem({ path } as Resource)
console.log(unref(currentRoute).query)
return router.push({
params: {
...unref(currentRoute).params,
driveAliasAndItem
},
query: {
...(unref(currentRoute).query?.app && { app: unref(currentRoute).query?.app }),
contextRouteName: 'files-spaces-generic'
}
})
}
// no matching space found => the file doesn't lie in own spaces => it's a share.
// do PROPFINDs on parents until root of accepted share is found in `mountpoint` spaces
await store.dispatch('runtime/spaces/loadMountPoints', {
graphClient: clientService.graphAuthenticated
})
let mountPoint = findMatchingMountPoint(id)
const resource = await loadFileInfoByIdTask.perform(id)
const sharePathSegments = mountPoint ? [] : [unref(resource).name]
let tmpResource = unref(resource)
while (!mountPoint) {
try {
tmpResource = await loadFileInfoByIdTask.perform(tmpResource.parentFolderId)
} catch (e) {
throw Error(e)
}
mountPoint = findMatchingMountPoint(tmpResource.id)
if (!mountPoint) {
sharePathSegments.unshift(tmpResource.name)
}
}
matchingSpace = buildShareSpaceResource({
shareId: mountPoint.nodeId,
shareName: mountPoint.name,
serverUrl: configurationManager.serverUrl
})
path = urlJoin(...sharePathSegments)
const driveAliasAndItem = matchingSpace.getDriveAliasAndItem({ path } as Resource)
return router.push({
params: {
...unref(currentRoute).params,
driveAliasAndItem
},
query: {
shareId: matchingSpace.shareId,
...(unref(currentRoute).query?.app && { app: unref(currentRoute).query?.app }),
contextRouteName: 'files-shares-with-me'
}
})
}
return {
...useAppDefaults({
applicationId: 'external',
applicationName
}),
applicationName
applicationName,
driveAliasAndItem,
addMissingDriveAliasAndItem
}
},
Expand Down Expand Up @@ -94,6 +195,10 @@ export default defineComponent({
async created() {
this.loading = true
try {
if (!this.driveAliasAndItem) {
await this.addMissingDriveAliasAndItem()
}
this.resource = await this.getFileInfo(this.currentFileContext, {
davProperties: []
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
>
<oc-icon name="calendar-event" fill-type="line" size="medium" variation="passive" />
<span
class="oc-ml-s"
v-if="isExpirationDateSet"
class="oc-ml-s"
v-text="$gettext('Edit expiration date')"
/>
<span v-else v-text="$gettext('Set expiration date')" />
Expand Down
1 change: 1 addition & 0 deletions packages/web-pkg/src/composables/fileInfo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useLoadFileInfoById'
38 changes: 38 additions & 0 deletions packages/web-pkg/src/composables/fileInfo/useLoadFileInfoById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ClientService } from 'web-pkg/src/services'
import { useClientService } from 'web-pkg/src/composables'
import { useTask } from 'vue-concurrency'
import { buildSpace, buildWebDavSpacesPath } from 'web-client/src/helpers'
import { DavProperty } from 'web-client/src/webdav/constants'

export interface LoadFileInfoByIdOptions {
clientService?: ClientService
davProperties?: DavProperty[]
}

export const useLoadFileInfoById = (options: LoadFileInfoByIdOptions) => {
const { webdav } = options.clientService || useClientService()
const davProperties = options.davProperties || [
DavProperty.FileId,
DavProperty.FileParent,
DavProperty.Name,
DavProperty.ResourceType
]

const loadFileInfoByIdTask = useTask(function* (signal, fileId: string | number) {
const space = buildSpace({
id: fileId,
webDavPath: buildWebDavSpacesPath(fileId)
})
return yield webdav.getFileInfo(
space,
{},
{
davProperties
}
)
})

return {
loadFileInfoByIdTask
}
}

0 comments on commit 945170d

Please sign in to comment.