Skip to content

Commit

Permalink
Merge pull request #9862 from owncloud/pick-hotfix-for-7.1.1
Browse files Browse the repository at this point in the history
chore: cherry-pick hotfix and prepare release 7.1.1
  • Loading branch information
JammingBen authored Oct 26, 2023
2 parents a26f792 + 0251082 commit 5fec611
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 5 deletions.
6 changes: 6 additions & 0 deletions changelog/7.1.1_2023-10-25/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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "7.1.0",
"version": "7.1.1",
"private": true,
"homepage": "https://github.com/owncloud/web",
"license": "AGPL-3.0",
Expand Down
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
118 changes: 116 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,27 @@ 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'
import { dirname } from 'path'
export default defineComponent({
name: 'ExternalApp',
Expand All @@ -52,14 +69,107 @@ 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 getMatchingSpaceByFileId = (id): SpaceResource => {
return store.getters['runtime/spaces/spaces'].find((space) => id.startsWith(space.id))
}
const getMatchingMountPoint = (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 = getMatchingSpaceByFileId(id)
if (matchingSpace) {
path = await clientService.owncloudSdk.files.getPathForFileId(id)
const driveAliasAndItem = matchingSpace.getDriveAliasAndItem({ path } as Resource)
return router.push({
params: {
...unref(currentRoute).params,
driveAliasAndItem
},
query: {
fileId: id,
...(unref(currentRoute).query?.app && { app: unref(currentRoute).query?.app }),
contextRouteName: 'files-spaces-generic',
contextRouteParams: { driveAliasAndItem: dirname(driveAliasAndItem) } as any
}
})
}
// 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 = getMatchingMountPoint(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 = getMatchingMountPoint(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: {
fileId: id,
shareId: matchingSpace.shareId,
...(unref(currentRoute).query?.app && { app: unref(currentRoute).query?.app }),
contextRouteName: path === '/' ? 'files-shares-with-me' : 'files-spaces-generic',
contextRouteParams: {
driveAliasAndItem: dirname(driveAliasAndItem)
} as any,
contextRouteQuery: {
shareId: matchingSpace.shareId
} as any
}
})
}
return {
...useAppDefaults({
applicationId: 'external',
applicationName
}),
applicationName
applicationName,
driveAliasAndItem,
addMissingDriveAliasAndItem
}
},
Expand Down Expand Up @@ -94,6 +204,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
4 changes: 4 additions & 0 deletions packages/web-app-external/tests/unit/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useAppDefaultsMock } from 'web-test-helpers/src/mocks/useAppDefaultsMoc
import { ref } from 'vue'
import { mock } from 'jest-mock-extended'
import { RouteLocation } from 'web-test-helpers'
import { useRouteParam } from 'web-pkg/src/composables/router/useRouteParam'

jest.mock('web-pkg/src/composables/appDefaults', () => {
const { queryItemAsString } = jest.requireActual('web-pkg/src/composables/appDefaults')
Expand All @@ -21,6 +22,8 @@ jest.mock('web-pkg/src/composables/appDefaults', () => {
}
})

jest.mock('web-pkg/src/composables/router/useRouteParam')

const componentStubs = {
AppTopBar: true,
ErrorScreen: true,
Expand Down Expand Up @@ -124,6 +127,7 @@ function createShallowMountWrapper(makeRequest = jest.fn().mockResolvedValue({ s
makeRequest
})
)
jest.mocked(useRouteParam).mockReturnValue(ref('foo'))

const storeOptions = defaultStoreMockOptions
storeOptions.getters.capabilities.mockImplementation(() => ({
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
}
}
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
sonar.projectKey=owncloud_web
sonar.organization=owncloud-1
sonar.projectName=Web
sonar.projectVersion=7.1.0
sonar.projectVersion=7.1.1
sonar.host.url=https://sonarcloud.io

# =====================================================
Expand Down

0 comments on commit 5fec611

Please sign in to comment.