mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
Merge pull request #47691 from nextcloud/fix/remote-share-parsing
[stable30] fix(files): Correctly parse external shares for files UI
This commit is contained in:
commit
6e982631ad
5 changed files with 74 additions and 19 deletions
|
|
@ -4,12 +4,12 @@
|
|||
*/
|
||||
import type { OCSResponse } from '@nextcloud/typings/ocs'
|
||||
import { expect } from '@jest/globals'
|
||||
import { Type } from '@nextcloud/sharing'
|
||||
import { File, Folder } from '@nextcloud/files'
|
||||
import { ShareType } from '@nextcloud/sharing'
|
||||
import * as auth from '@nextcloud/auth'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
import { getContents } from './SharingService'
|
||||
import { File, Folder } from '@nextcloud/files'
|
||||
import logger from './logger'
|
||||
|
||||
window.OC = {
|
||||
|
|
@ -142,7 +142,7 @@ describe('SharingService filtering', () => {
|
|||
data: [
|
||||
{
|
||||
id: '62',
|
||||
share_type: Type.SHARE_TYPE_USER,
|
||||
share_type: ShareType.User,
|
||||
uid_owner: 'test',
|
||||
displayname_owner: 'test',
|
||||
permissions: 31,
|
||||
|
|
@ -173,7 +173,7 @@ describe('SharingService filtering', () => {
|
|||
})
|
||||
|
||||
test('Shared with others filtering', async () => {
|
||||
const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_USER])
|
||||
const shares = await getContents(false, true, false, false, [ShareType.User])
|
||||
|
||||
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||
expect(shares.contents).toHaveLength(1)
|
||||
|
|
@ -182,7 +182,7 @@ describe('SharingService filtering', () => {
|
|||
})
|
||||
|
||||
test('Shared with others filtering empty', async () => {
|
||||
const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_LINK])
|
||||
const shares = await getContents(false, true, false, false, [ShareType.Link])
|
||||
|
||||
expect(axios.get).toHaveBeenCalledTimes(1)
|
||||
expect(shares.contents).toHaveLength(0)
|
||||
|
|
@ -278,6 +278,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: ShareType.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: {
|
||||
|
|
@ -337,6 +356,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({
|
||||
|
|
|
|||
|
|
@ -26,10 +26,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
|
||||
|
|
@ -46,14 +52,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)
|
||||
}
|
||||
|
|
@ -75,7 +82,7 @@ const ocsEntryToNode = async function(ocsEntry: any): Promise<Folder | File | nu
|
|||
'owner-display-name': ocsEntry?.displayname_owner,
|
||||
'share-types': ocsEntry?.share_type,
|
||||
'share-attributes': ocsEntry?.attributes || '[]',
|
||||
favorite: ocsEntry?.tags?.includes((window.OC as Nextcloud.v28.OC & { TAG_FAVORITE: string }).TAG_FAVORITE) ? 1 : 0,
|
||||
favorite: ocsEntry?.tags?.includes((window.OC as Nextcloud.v29.OC & { TAG_FAVORITE: string }).TAG_FAVORITE) ? 1 : 0,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
|
|
@ -164,8 +171,8 @@ export const isFileRequest = (attributes = '[]'): boolean => {
|
|||
/**
|
||||
* Group an array of objects (here Nodes) by a key
|
||||
* and return an array of arrays of them.
|
||||
* @param nodes
|
||||
* @param key
|
||||
* @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) {
|
||||
|
|
|
|||
2
dist/8707-8707.js.map
vendored
2
dist/8707-8707.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-init.js
vendored
4
dist/files_sharing-init.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-init.js.map
vendored
2
dist/files_sharing-init.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue