diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-09-01 00:37:56 +0200 |
---|---|---|
committer | Maksim Sukharev <antreesy.web@gmail.com> | 2024-09-10 14:05:42 +0200 |
commit | 696447d3acd77f928aec3dea622ccbb8ee784778 (patch) | |
tree | 9bdbcdc348c22d0f69b0f18551ab57c6e01f255c /apps | |
parent | 3c2ead71330b2510b2266c9883d1d0b157424425 (diff) | |
download | nextcloud-server-696447d3acd77f928aec3dea622ccbb8ee784778.tar.gz nextcloud-server-696447d3acd77f928aec3dea622ccbb8ee784778.zip |
fix(files): Correctly parse external shares for files UI
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files_sharing/src/services/SharingService.spec.ts | 48 | ||||
-rw-r--r-- | apps/files_sharing/src/services/SharingService.ts | 25 |
2 files changed, 65 insertions, 8 deletions
diff --git a/apps/files_sharing/src/services/SharingService.spec.ts b/apps/files_sharing/src/services/SharingService.spec.ts index ed3a0cb6590..ef9690d094e 100644 --- a/apps/files_sharing/src/services/SharingService.spec.ts +++ b/apps/files_sharing/src/services/SharingService.spec.ts @@ -287,6 +287,25 @@ describe('SharingService share to Node mapping', () => { tags: [window.OC.TAG_FAVORITE], } + const remoteFile = { + mimetype: 'text/markdown', + mtime: 1688721600, + permissions: 19, + type: 'file', + file_id: 1234, + id: 4, + share_type: Type.SHARE_TYPE_USER, + parent: null, + remote: 'http://exampe.com', + remote_id: '12345', + share_token: 'share-token', + name: '/test.md', + mountpoint: '/shares/test.md', + owner: 'owner-uid', + user: 'sharee-uid', + accepted: true, + } + test('File', async () => { jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ data: { @@ -346,6 +365,35 @@ describe('SharingService share to Node mapping', () => { expect(folder.attributes.favorite).toBe(1) }) + test('Remote file', async () => { + jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + data: { + ocs: { + data: [remoteFile], + }, + }, + })) + + const shares = await getContents(false, true, false, false) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(shares.contents).toHaveLength(1) + + const file = shares.contents[0] as File + expect(file).toBeInstanceOf(File) + expect(file.fileid).toBe(1234) + expect(file.source).toBe('http://localhost/remote.php/dav/files/test/shares/test.md') + expect(file.owner).toBe('owner-uid') + expect(file.mime).toBe('text/markdown') + expect(file.mtime?.getTime()).toBe(remoteFile.mtime * 1000) + // not available for remote shares + expect(file.size).toBe(undefined) + expect(file.permissions).toBe(0) + expect(file.root).toBe('/files/test') + expect(file.attributes).toBeInstanceOf(Object) + expect(file.attributes.favorite).toBe(0) + }) + test('Empty', async () => { jest.spyOn(logger, 'error').mockImplementationOnce(() => {}) jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ diff --git a/apps/files_sharing/src/services/SharingService.ts b/apps/files_sharing/src/services/SharingService.ts index a4c63bec7b0..11989bdb8a9 100644 --- a/apps/files_sharing/src/services/SharingService.ts +++ b/apps/files_sharing/src/services/SharingService.ts @@ -50,10 +50,16 @@ const ocsEntryToNode = async function(ocsEntry: any): Promise<Folder | File | nu try { // Federated share handling if (ocsEntry?.remote_id !== undefined) { - const mime = (await import('mime')).default - // This won't catch files without an extension, but this is the best we can do - ocsEntry.mimetype = mime.getType(ocsEntry.name) - ocsEntry.item_type = ocsEntry.mimetype ? 'file' : 'folder' + if (!ocsEntry.mimetype) { + const mime = (await import('mime')).default + // This won't catch files without an extension, but this is the best we can do + ocsEntry.mimetype = mime.getType(ocsEntry.name) + } + ocsEntry.item_type = ocsEntry.type || (ocsEntry.mimetype ? 'file' : 'folder') + + // different naming for remote shares + ocsEntry.item_mtime = ocsEntry.mtime + ocsEntry.file_target = ocsEntry.file_target || ocsEntry.mountpoint // Need to set permissions to NONE for federated shares ocsEntry.item_permissions = Permission.NONE @@ -70,14 +76,15 @@ const ocsEntryToNode = async function(ocsEntry: any): Promise<Folder | File | nu // If this is an external share that is not yet accepted, // we don't have an id. We can fallback to the row id temporarily - const fileid = ocsEntry.file_source || ocsEntry.id + // local shares (this server) use `file_source`, but remote shares (federated) use `file_id` + const fileid = ocsEntry.file_source || ocsEntry.file_id || ocsEntry.id // Generate path and strip double slashes - const path = ocsEntry?.path || ocsEntry.file_target || ocsEntry.name + const path = ocsEntry.path || ocsEntry.file_target || ocsEntry.name const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replaceAll(/\/\//gm, '/')) + let mtime = ocsEntry.item_mtime ? new Date((ocsEntry.item_mtime) * 1000) : undefined // Prefer share time if more recent than item mtime - let mtime = ocsEntry?.item_mtime ? new Date((ocsEntry.item_mtime) * 1000) : undefined if (ocsEntry?.stime > (ocsEntry?.item_mtime || 0)) { mtime = new Date((ocsEntry.stime) * 1000) } @@ -169,6 +176,8 @@ const getDeletedShares = function(): AxiosPromise<OCSResponse<any>> { /** * Group an array of objects (here Nodes) by a key * and return an array of arrays of them. + * @param nodes Nodes to group + * @param key The attribute to group by */ const groupBy = function(nodes: (Folder | File)[], key: string) { return Object.values(nodes.reduce(function(acc, curr) { @@ -178,7 +187,7 @@ const groupBy = function(nodes: (Folder | File)[], key: string) { } export const getContents = async (sharedWithYou = true, sharedWithOthers = true, pendingShares = false, deletedshares = false, filterTypes: number[] = []): Promise<ContentsWithRoot> => { - const promises = [] as AxiosPromise<OCSResponse<any>>[] + const promises = [] as AxiosPromise<OCSResponse<unknown>>[] if (sharedWithYou) { promises.push(getSharedWithYou(), getRemoteShares()) |