From ee74c4788d97dbb624ff6b4f4c8ef1acba1ec9c7 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Mon, 21 Nov 2022 13:43:47 +0100 Subject: [PATCH 1/7] Fix public link loading on role change --- .../bugfix-public-link-load-on-role-change | 6 ++++++ .../src/views/spaces/GenericSpace.vue | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/bugfix-public-link-load-on-role-change diff --git a/changelog/unreleased/bugfix-public-link-load-on-role-change b/changelog/unreleased/bugfix-public-link-load-on-role-change new file mode 100644 index 00000000000..f03dc1ccede --- /dev/null +++ b/changelog/unreleased/bugfix-public-link-load-on-role-change @@ -0,0 +1,6 @@ +Bugfix: Public link loading on role change + +The loading and resolving of public links when their respective roles have changed has been fixed. + +https://github.com/owncloud/web/pull/8006 +https://github.com/owncloud/web/issues/8003 diff --git a/packages/web-app-files/src/views/spaces/GenericSpace.vue b/packages/web-app-files/src/views/spaces/GenericSpace.vue index ae7e04001f0..296ea12030c 100644 --- a/packages/web-app-files/src/views/spaces/GenericSpace.vue +++ b/packages/web-app-files/src/views/spaces/GenericSpace.vue @@ -141,6 +141,8 @@ import { createFileRouteOptions } from 'web-pkg/src/helpers/router' import omit from 'lodash-es/omit' import { useDocumentTitle } from 'web-pkg/src/composables/appDefaults/useDocumentTitle' import { basename } from 'path' +import { linkRoleUploaderFolder } from 'web-client/src/helpers/share' +import { locationPublicUpload } from 'web-app-files/src/router/public' const visibilityObserver = new VisibilityObserver() @@ -321,7 +323,17 @@ export default defineComponent({ } }, - mounted() { + async mounted() { + if (isPublicSpaceResource(this.space)) { + const publicSpace = await this.$clientService.webdav.getFileInfo(this.space) + if (linkRoleUploaderFolder.bitmask(false) === publicSpace.publicLinkPermission) { + return this.$router.push({ + name: locationPublicUpload.name, + params: { token: this.space.id } + }) + } + } + this.performLoaderTask(false) const loadResourcesEventToken = eventBus.subscribe( 'app.files.list.load', From 4cb79f77f26d89bad8738a8a660ff47f1e7701bc Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Mon, 21 Nov 2022 14:44:14 +0100 Subject: [PATCH 2/7] Add unit test --- .../unit/views/spaces/GenericSpace.spec.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts index bae98eef9c3..1f0b42ce08f 100644 --- a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts +++ b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts @@ -10,6 +10,11 @@ import { useResourcesViewDefaults } from 'web-app-files/src/composables' import { useResourcesViewDefaultsMock } from 'web-app-files/tests/mocks/useResourcesViewDefaultsMock' import { ref } from '@vue/composition-api' import { defaultStubs } from 'web-test-helpers/src/mocks/defaultStubs' +import { mockDeep } from 'jest-mock-extended' +import { ClientService } from 'web-pkg/src' +import { PublicSpaceResource } from 'web-client/src/helpers' +import { SharePermissionBit } from 'web-client/src/helpers/share' +import { locationPublicUpload } from 'web-app-files/src/router/public' jest.mock('web-app-files/src/composables') @@ -61,6 +66,23 @@ describe('GenericSpace view', () => { expect(wrapper.find('resource-table-stub').exists()).toBeTruthy() }) }) + it('redirects to the public drop page in a public context with "upload-only"-permissions', async () => { + const space = { id: 1, getDriveAliasAndItem: jest.fn(), driveType: 'public' } + const clientService = mockDeep() + clientService.webdav.getFileInfo.mockResolvedValue( + mockDeep({ publicLinkPermission: SharePermissionBit.Create }) + ) + const { wrapper, mocks } = getMountedWrapper({ + props: { space }, + mocks: { $clientService: clientService } + }) + + await wrapper.vm.$nextTick() + expect(mocks.$router.push).toHaveBeenCalledWith({ + name: locationPublicUpload.name, + params: { token: space.id } + }) + }) }) function getMountedWrapper({ mocks = {}, props = {}, files = [], loading = false } = {}) { From ca7fdd5da1b1376e156f048f33feb226b1d32389 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Mon, 21 Nov 2022 14:54:45 +0100 Subject: [PATCH 3/7] Add try...catch block --- packages/web-app-files/src/views/spaces/GenericSpace.vue | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/web-app-files/src/views/spaces/GenericSpace.vue b/packages/web-app-files/src/views/spaces/GenericSpace.vue index 296ea12030c..5a596dafc9b 100644 --- a/packages/web-app-files/src/views/spaces/GenericSpace.vue +++ b/packages/web-app-files/src/views/spaces/GenericSpace.vue @@ -325,7 +325,13 @@ export default defineComponent({ async mounted() { if (isPublicSpaceResource(this.space)) { - const publicSpace = await this.$clientService.webdav.getFileInfo(this.space) + let publicSpace + try { + publicSpace = await this.$clientService.webdav.getFileInfo(this.space) + } catch (e) { + publicSpace = this.space + } + if (linkRoleUploaderFolder.bitmask(false) === publicSpace.publicLinkPermission) { return this.$router.push({ name: locationPublicUpload.name, From 82d5d0648f4934e35cafcdd5104bca3ffd0808b9 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Tue, 22 Nov 2022 16:00:08 +0100 Subject: [PATCH 4/7] Move logic to DriveResolver --- .../src/views/spaces/DriveResolver.vue | 43 +++++++++++++++++-- .../src/views/spaces/GenericSpace.vue | 20 +-------- .../unit/views/spaces/DriveResolver.spec.ts | 23 ++++++++++ .../unit/views/spaces/GenericSpace.spec.ts | 22 ---------- .../driveResolver/useDriveResolver.ts | 8 +++- 5 files changed, 71 insertions(+), 45 deletions(-) diff --git a/packages/web-app-files/src/views/spaces/DriveResolver.vue b/packages/web-app-files/src/views/spaces/DriveResolver.vue index a0ce1636ccc..dfee4180757 100644 --- a/packages/web-app-files/src/views/spaces/DriveResolver.vue +++ b/packages/web-app-files/src/views/spaces/DriveResolver.vue @@ -15,10 +15,19 @@ import DriveRedirect from './DriveRedirect.vue' import GenericSpace from './GenericSpace.vue' import GenericTrash from './GenericTrash.vue' -import { defineComponent } from '@vue/composition-api' -import { useDriveResolver, useRouteParam, useStore } from 'web-pkg/src/composables' +import { defineComponent, onMounted, unref } from '@vue/composition-api' +import { + useClientService, + useDriveResolver, + useRouteParam, + useRouter, + useStore +} from 'web-pkg/src/composables' import { useActiveLocation } from '../../composables' import { isLocationSpacesActive, isLocationTrashActive } from '../../router' +import { isPublicSpaceResource, PublicSpaceResource, SpaceResource } from 'web-client/src/helpers' +import { locationPublicUpload } from 'web-app-files/src/router/public' +import { linkRoleUploaderFolder } from 'web-client/src/helpers/share' export default defineComponent({ components: { @@ -28,11 +37,39 @@ export default defineComponent({ }, setup() { const store = useStore() + const clientService = useClientService() + const router = useRouter() const driveAliasAndItem = useRouteParam('driveAliasAndItem') const isSpaceRoute = useActiveLocation(isLocationSpacesActive, 'files-spaces-generic') const isTrashRoute = useActiveLocation(isLocationTrashActive, 'files-trash-generic') + const resolvedDrive = useDriveResolver({ store, driveAliasAndItem }) + + const getSpaceResource = async (): Promise => { + const space = unref(resolvedDrive.space) + try { + const publicSpace = (await clientService.webdav.getFileInfo(space)) as SpaceResource + return publicSpace + } catch (e) { + return space + } + } + + onMounted(async () => { + const space = unref(resolvedDrive.space) + if (space && isPublicSpaceResource(space)) { + let publicSpace = (await getSpaceResource()) as PublicSpaceResource + + if (linkRoleUploaderFolder.bitmask(false) === publicSpace.publicLinkPermission) { + router.push({ + name: locationPublicUpload.name, + params: { token: space.id.toString() } + }) + } + } + }) + return { - ...useDriveResolver({ store, driveAliasAndItem }), + ...resolvedDrive, driveAliasAndItem, isSpaceRoute, isTrashRoute diff --git a/packages/web-app-files/src/views/spaces/GenericSpace.vue b/packages/web-app-files/src/views/spaces/GenericSpace.vue index 5a596dafc9b..ae7e04001f0 100644 --- a/packages/web-app-files/src/views/spaces/GenericSpace.vue +++ b/packages/web-app-files/src/views/spaces/GenericSpace.vue @@ -141,8 +141,6 @@ import { createFileRouteOptions } from 'web-pkg/src/helpers/router' import omit from 'lodash-es/omit' import { useDocumentTitle } from 'web-pkg/src/composables/appDefaults/useDocumentTitle' import { basename } from 'path' -import { linkRoleUploaderFolder } from 'web-client/src/helpers/share' -import { locationPublicUpload } from 'web-app-files/src/router/public' const visibilityObserver = new VisibilityObserver() @@ -323,23 +321,7 @@ export default defineComponent({ } }, - async mounted() { - if (isPublicSpaceResource(this.space)) { - let publicSpace - try { - publicSpace = await this.$clientService.webdav.getFileInfo(this.space) - } catch (e) { - publicSpace = this.space - } - - if (linkRoleUploaderFolder.bitmask(false) === publicSpace.publicLinkPermission) { - return this.$router.push({ - name: locationPublicUpload.name, - params: { token: this.space.id } - }) - } - } - + mounted() { this.performLoaderTask(false) const loadResourcesEventToken = eventBus.subscribe( 'app.files.list.load', diff --git a/packages/web-app-files/tests/unit/views/spaces/DriveResolver.spec.ts b/packages/web-app-files/tests/unit/views/spaces/DriveResolver.spec.ts index 62b7c7cb580..9ed6d1f5370 100644 --- a/packages/web-app-files/tests/unit/views/spaces/DriveResolver.spec.ts +++ b/packages/web-app-files/tests/unit/views/spaces/DriveResolver.spec.ts @@ -9,6 +9,11 @@ import { useDriveResolver } from 'web-pkg/src/composables' import { spaces } from 'web-app-files/tests/__fixtures__' import { computed, ref } from '@vue/composition-api' import { defaultStubs } from 'web-test-helpers/src/mocks/defaultStubs' +import { mockDeep } from 'jest-mock-extended' +import { ClientService } from 'web-pkg/src' +import { locationPublicUpload } from 'web-app-files/src/router/public' +import { PublicSpaceResource } from 'web-client/src/helpers' +import { SharePermissionBit } from 'web-client/src/helpers/share' jest.mock('web-pkg/src/composables/driveResolver') @@ -28,6 +33,24 @@ describe('DriveResolver view', () => { const { wrapper } = getMountedWrapper({ space: spaces[0] }) expect(wrapper.find('generic-space-stub').exists()).toBeTruthy() }) + it('redirects to the public drop page in a public context with "upload-only"-permissions', async () => { + const space = { id: '1', getDriveAliasAndItem: jest.fn(), driveType: 'public' } + const clientService = mockDeep() + clientService.webdav.getFileInfo.mockResolvedValue( + mockDeep({ publicLinkPermission: SharePermissionBit.Create }) + ) + const { wrapper, mocks } = getMountedWrapper({ + space, + mocks: { $clientService: clientService } + }) + + await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() + expect(mocks.$router.push).toHaveBeenCalledWith({ + name: locationPublicUpload.name, + params: { token: space.id } + }) + }) }) function getMountedWrapper({ diff --git a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts index 1f0b42ce08f..bae98eef9c3 100644 --- a/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts +++ b/packages/web-app-files/tests/unit/views/spaces/GenericSpace.spec.ts @@ -10,11 +10,6 @@ import { useResourcesViewDefaults } from 'web-app-files/src/composables' import { useResourcesViewDefaultsMock } from 'web-app-files/tests/mocks/useResourcesViewDefaultsMock' import { ref } from '@vue/composition-api' import { defaultStubs } from 'web-test-helpers/src/mocks/defaultStubs' -import { mockDeep } from 'jest-mock-extended' -import { ClientService } from 'web-pkg/src' -import { PublicSpaceResource } from 'web-client/src/helpers' -import { SharePermissionBit } from 'web-client/src/helpers/share' -import { locationPublicUpload } from 'web-app-files/src/router/public' jest.mock('web-app-files/src/composables') @@ -66,23 +61,6 @@ describe('GenericSpace view', () => { expect(wrapper.find('resource-table-stub').exists()).toBeTruthy() }) }) - it('redirects to the public drop page in a public context with "upload-only"-permissions', async () => { - const space = { id: 1, getDriveAliasAndItem: jest.fn(), driveType: 'public' } - const clientService = mockDeep() - clientService.webdav.getFileInfo.mockResolvedValue( - mockDeep({ publicLinkPermission: SharePermissionBit.Create }) - ) - const { wrapper, mocks } = getMountedWrapper({ - props: { space }, - mocks: { $clientService: clientService } - }) - - await wrapper.vm.$nextTick() - expect(mocks.$router.push).toHaveBeenCalledWith({ - name: locationPublicUpload.name, - params: { token: space.id } - }) - }) }) function getMountedWrapper({ mocks = {}, props = {}, files = [], loading = false } = {}) { diff --git a/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts b/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts index 1ab2adf3b47..7c941cb165c 100644 --- a/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts +++ b/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts @@ -16,7 +16,13 @@ interface DriveResolverOptions { driveAliasAndItem?: Ref } -export const useDriveResolver = (options: DriveResolverOptions = {}) => { +interface ResolvedDrive { + space: Ref + item: Ref + itemId: Ref +} + +export const useDriveResolver = (options: DriveResolverOptions = {}): ResolvedDrive => { const store = options.store || useStore() const { areSpacesLoading } = useSpacesLoading({ store }) const shareId = useRouteQuery('shareId') From 60eafe06358149d2c2dc8bb8b066e8ed3bbef7e6 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Tue, 22 Nov 2022 17:00:41 +0100 Subject: [PATCH 5/7] Rename interface to DriveResolverResult --- .../web-pkg/src/composables/driveResolver/useDriveResolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts b/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts index 7c941cb165c..90c289b743a 100644 --- a/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts +++ b/packages/web-pkg/src/composables/driveResolver/useDriveResolver.ts @@ -16,13 +16,13 @@ interface DriveResolverOptions { driveAliasAndItem?: Ref } -interface ResolvedDrive { +interface DriveResolverResult { space: Ref item: Ref itemId: Ref } -export const useDriveResolver = (options: DriveResolverOptions = {}): ResolvedDrive => { +export const useDriveResolver = (options: DriveResolverOptions = {}): DriveResolverResult => { const store = options.store || useStore() const { areSpacesLoading } = useSpacesLoading({ store }) const shareId = useRouteQuery('shareId') From 77eac5a7f488cce03e3204870838f3aa23a13e20 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Wed, 23 Nov 2022 13:00:23 +0100 Subject: [PATCH 6/7] Add unit tests for useDriveResolver composable --- .../unit/composables/composables.setup.ts | 9 +- .../driveResolver/useDriveResolver.spec.ts | 141 ++++++++++++++++++ 2 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 packages/web-app-files/tests/unit/composables/driveResolver/useDriveResolver.spec.ts diff --git a/packages/web-app-files/tests/unit/composables/composables.setup.ts b/packages/web-app-files/tests/unit/composables/composables.setup.ts index 4617b9f188b..4a37df21ef9 100644 --- a/packages/web-app-files/tests/unit/composables/composables.setup.ts +++ b/packages/web-app-files/tests/unit/composables/composables.setup.ts @@ -7,13 +7,18 @@ const localVue = createLocalVue() localVue.use(VueCompositionAPI) localVue.use(Vuex) -export const createComposableWrapper = (setup: SetupFunction): Wrapper => +export const createComposableWrapper = ( + setup: SetupFunction, + options = { mocks: undefined, store: undefined } +): Wrapper => mount( defineComponent({ setup, template: `
` }), { - localVue + localVue, + ...(options.mocks && { mocks: options.mocks }), + ...(options.store && { store: options.store }) } ) diff --git a/packages/web-app-files/tests/unit/composables/driveResolver/useDriveResolver.spec.ts b/packages/web-app-files/tests/unit/composables/driveResolver/useDriveResolver.spec.ts new file mode 100644 index 00000000000..c93dc7a138f --- /dev/null +++ b/packages/web-app-files/tests/unit/composables/driveResolver/useDriveResolver.spec.ts @@ -0,0 +1,141 @@ +import { useCapabilitySpacesEnabled, useDriveResolver } from 'web-pkg/src' +import { createComposableWrapper } from '../composables.setup' +import { defaultComponentMocks } from 'web-test-helpers/src/mocks/defaultComponentMocks' +import { computed, ref, unref } from '@vue/composition-api' +import { mockDeep } from 'jest-mock-extended' +import { defaultStoreMockOptions } from 'web-test-helpers/src/mocks/store/defaultStoreMockOptions' +import { isShareSpaceResource, SpaceResource } from 'web-client/src/helpers' +import { createStore } from 'vuex-extensions' +import Vuex from 'vuex' + +jest.unmock('web-app-files/src/composables') +jest.mock('web-pkg/src/composables/capability') + +describe('useDriveResolver', () => { + it('should be valid', () => { + expect(useDriveResolver).toBeDefined() + }) + it('space and item should be null when no driveAliasAndItem given', () => { + createComposableWrapper( + () => { + const { space, item } = useDriveResolver({ driveAliasAndItem: ref('') }) + expect(unref(space)).toEqual(null) + expect(unref(item)).toEqual(null) + }, + { mocks: defaultComponentMocks(), store: defaultStoreMockOptions } + ) + }) + it('returns a public space on a public page', () => { + const token = 'token' + const spaceMock = mockDeep({ id: token }) + const storeOptions = { ...defaultStoreMockOptions } + storeOptions.modules.runtime.modules.spaces.getters.spaces = jest.fn(() => [spaceMock]) + const store = createStore(Vuex.Store, storeOptions) + createComposableWrapper( + () => { + const { space, item } = useDriveResolver({ driveAliasAndItem: ref(`public/${token}`) }) + expect(unref(space)).toEqual(spaceMock) + expect(unref(item)).toEqual('/') + }, + { mocks: defaultComponentMocks(), store } + ) + }) + it('returns a share space for a share', () => { + const spaceMock = mockDeep() + const storeOptions = { ...defaultStoreMockOptions } + storeOptions.modules.runtime.modules.spaces.getters.spaces = jest.fn(() => [spaceMock]) + const store = createStore(Vuex.Store, storeOptions) + createComposableWrapper( + () => { + const { space, item } = useDriveResolver({ + driveAliasAndItem: ref(`share/someSharedFolder`) + }) + expect(isShareSpaceResource(unref(space))).toEqual(true) + expect(unref(item)).toEqual('/') + }, + { mocks: defaultComponentMocks(), store } + ) + }) + it('returns a space by fileId if given', () => { + const hasSpaces = true + const fileId = 'someFileId' + const resourcePath = '/someFolder' + const spaceMock = mockDeep({ fileId, driveAlias: 'driveAlias' }) + const storeOptions = { ...defaultStoreMockOptions } + storeOptions.modules.runtime.modules.spaces.getters.spaces = jest.fn(() => [spaceMock]) + const store = createStore(Vuex.Store, storeOptions) + + jest.mocked(useCapabilitySpacesEnabled).mockImplementation(() => computed(() => hasSpaces)) + + createComposableWrapper( + () => { + const { space, item, itemId } = useDriveResolver({ + driveAliasAndItem: ref(`/personal${resourcePath}`) + }) + expect(unref(space)).toEqual(spaceMock) + expect(unref(item)).toEqual(resourcePath) + expect(unref(itemId)).toEqual(fileId) + }, + { + mocks: defaultComponentMocks({ + currentRoute: { name: 'files-spaces-generic', path: '/', query: { fileId } } + }), + store + } + ) + }) + it('returns a space by driveAlias if no fileId given', () => { + const hasSpaces = true + const driveAlias = '/personal' + const resourcePath = '/someFolder' + const spaceMock = mockDeep({ driveAlias }) + const storeOptions = { ...defaultStoreMockOptions } + storeOptions.modules.runtime.modules.spaces.getters.spaces = jest.fn(() => [spaceMock]) + const store = createStore(Vuex.Store, storeOptions) + + jest.mocked(useCapabilitySpacesEnabled).mockImplementation(() => computed(() => hasSpaces)) + + createComposableWrapper( + () => { + const { space, item } = useDriveResolver({ + driveAliasAndItem: ref(`${driveAlias}${resourcePath}`) + }) + expect(unref(space)).toEqual(spaceMock) + expect(unref(item)).toEqual(resourcePath) + }, + { + mocks: defaultComponentMocks({ + currentRoute: { name: 'files-spaces-generic', path: '/', query: { fileId: undefined } } + }), + store + } + ) + }) + it.each([ + { driveType: 'projects', loadMembersCalls: 1 }, + { driveType: 'public', loadMembersCalls: 0 }, + { driveType: 'share', loadMembersCalls: 0 }, + { driveType: 'personal', loadMembersCalls: 0 } + ])('loads space members for a project space', (data) => { + const driveAlias = `/${data.driveType}` + const spaceMock = mockDeep({ driveAlias, driveType: data.driveType }) + const storeOptions = { ...defaultStoreMockOptions } + storeOptions.modules.runtime.modules.spaces.getters.spaces = jest.fn(() => [spaceMock]) + const store = createStore(Vuex.Store, storeOptions) + + createComposableWrapper( + () => { + useDriveResolver({ driveAliasAndItem: ref(`${driveAlias}/someFolder`) }) + expect( + storeOptions.modules.runtime.modules.spaces.actions.loadSpaceMembers + ).toHaveBeenCalledTimes(data.loadMembersCalls) + }, + { + mocks: defaultComponentMocks({ + currentRoute: { name: 'files-spaces-generic', path: '/', query: { fileId: undefined } } + }), + store + } + ) + }) +}) From 2de85198796e7c83a570d18eec4925c77b930d37 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Thu, 24 Nov 2022 15:35:07 +0100 Subject: [PATCH 7/7] Add console.error statement for error --- packages/web-app-files/src/views/spaces/DriveResolver.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web-app-files/src/views/spaces/DriveResolver.vue b/packages/web-app-files/src/views/spaces/DriveResolver.vue index dfee4180757..710b9bc42d7 100644 --- a/packages/web-app-files/src/views/spaces/DriveResolver.vue +++ b/packages/web-app-files/src/views/spaces/DriveResolver.vue @@ -50,6 +50,7 @@ export default defineComponent({ const publicSpace = (await clientService.webdav.getFileInfo(space)) as SpaceResource return publicSpace } catch (e) { + console.error(e) return space } }