Skip to content

Commit

Permalink
fix(dav): Fix DAV functions to make work with them easier
Browse files Browse the repository at this point in the history
* `davGetClient` should default to the DAV remote URL instead of including the users root (to allow SEARCH)
* `getFavoriteNodes` should work with any path
* Add missing documentation

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Aug 11, 2023
1 parent 5ddd5bc commit 77a929e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 20 deletions.
16 changes: 8 additions & 8 deletions __tests__/dav/dav.spec.ts
@@ -1,7 +1,7 @@
import { afterAll, describe, expect, test, vi } from 'vitest'
import { readFile } from 'fs/promises'
import { readFile } from 'node:fs/promises'

import { File, Folder, davDefaultRootUrl, davGetDefaultPropfind, davGetFavoritesReport, davRootPath, getFavoriteNodes } from '../../lib'
import { File, Folder, davRemoteURL, davGetFavoritesReport, davRootPath, getFavoriteNodes } from '../../lib'

vi.mock('@nextcloud/auth')
vi.mock('@nextcloud/router')
Expand All @@ -15,8 +15,8 @@ describe('DAV functions', () => {
expect(davRootPath).toBe('/files/test')
})

test('root url is correct', () => {
expect(davDefaultRootUrl).toBe('https://localhost/dav/files/test')
test('remote url is correct', () => {
expect(davRemoteURL).toBe('https://localhost/dav')
})
})

Expand All @@ -39,7 +39,7 @@ describe('DAV requests', () => {
const nodes = await getFavoriteNodes(client as never)
// Check client was called correctly
expect(client.getDirectoryContents).toBeCalled()
expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe('/')
expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe(`${davRootPath}/`)
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.data).toBe(davGetFavoritesReport())
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.headers?.method).toBe('REPORT')
// Check for correct output
Expand Down Expand Up @@ -68,9 +68,9 @@ describe('DAV requests', () => {
const nodes = await getFavoriteNodes(client as never, '/Neuer Ordner')
// Check client was called correctly
expect(client.getDirectoryContents).toBeCalled()
expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe('/Neuer Ordner')
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.data).toBe(davGetDefaultPropfind())
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.headers?.method).toBe('PROPFIND')
expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe(`${davRootPath}/Neuer Ordner`)
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.data).toBe(davGetFavoritesReport())
expect(client.getDirectoryContents.mock.lastCall?.at(1)?.headers?.method).toBe('REPORT')
// There are no inner nodes
expect(nodes.length).toBe(0)
})
Expand Down
43 changes: 31 additions & 12 deletions lib/dav/dav.ts
Expand Up @@ -27,7 +27,7 @@ import { File } from '../files/file'
import { Folder } from '../files/folder'
import { NodeData } from '../files/nodeData'
import { davParsePermissions } from './davPermissions'
import { davGetDefaultPropfind, davGetFavoritesReport } from './davProperties'
import { davGetFavoritesReport } from './davProperties'

import { getCurrentUser, getRequestToken } from '@nextcloud/auth'
import { generateRemoteUrl } from '@nextcloud/router'
Expand All @@ -43,15 +43,22 @@ interface ResponseProps extends DAVResultResponseProps {
size: number
}

/**
* The DAV root path for the current user
*/
export const davRootPath = `/files/${getCurrentUser()?.uid}`
export const davDefaultRootUrl = generateRemoteUrl('dav' + davRootPath)

/**
* The DAV remote URL used as base URL for the WebDAV client
*/
export const davRemoteURL = generateRemoteUrl('dav')

/**
* Get a WebDAV client configured to include the Nextcloud request token
*
* @param davURL The DAV root URL
* @param davURL The DAV remote URL
*/
export const davGetClient = function(davURL = davDefaultRootUrl) {
export const davGetClient = function(davURL = davRemoteURL) {
const client = createClient(davURL, {
headers: {
requesttoken: getRequestToken() || '',
Expand Down Expand Up @@ -82,20 +89,32 @@ export const davGetClient = function(davURL = davDefaultRootUrl) {
*
* @param davClient The WebDAV client to use for performing the request
* @param path Base path for the favorites, if unset all favorites are queried
* @param davRoot The root path for the DAV user (defaults to `davRootPath`)
* @example
* ```js
* import { davGetClient, davRootPath, getFavoriteNodes } from '@nextcloud/files'
*
* const client = davGetClient()
* // query favorites for the root
* const favorites = await getFavoriteNodes(client)
* // which is the same as writing:
* const favorites = await getFavoriteNodes(client, '/', davRootPath)
* ```
*/
export const getFavoriteNodes = async (davClient: WebDAVClient, path = '/') => {
const contentsResponse = await davClient.getDirectoryContents(path, {
export const getFavoriteNodes = async (davClient: WebDAVClient, path = '/', davRoot = davRootPath) => {
const contentsResponse = await davClient.getDirectoryContents(`${davRoot}${path}`, {
details: true,
// Only filter favorites if we're at the root
data: path === '/' ? davGetFavoritesReport() : davGetDefaultPropfind(),
data: davGetFavoritesReport(),
headers: {
// Patched in WebdavClient.ts
method: path === '/' ? 'REPORT' : 'PROPFIND',
// see davGetClient for patched webdav client
method: 'REPORT',
},
includeSelf: true,
}) as ResponseDataDetailed<FileStat[]>

return contentsResponse.data.filter(node => node.filename !== path).map((result) => davResultToNode(result))
return contentsResponse.data
.filter(node => node.filename !== path) // exclude current dir
.map((result) => davResultToNode(result, davRoot))
}

/**
Expand All @@ -114,7 +133,7 @@ export const davResultToNode = function(node: FileStat, davRoot = davRootPath):
source: generateRemoteUrl(`dav${davRoot}${node.filename}`),
mtime: new Date(Date.parse(node.lastmod)),
mime: node.mime as string,
size: (props?.size as number) || 0,
size: props?.size || Number.parseInt(props.getcontentlength || '0'),
permissions,
owner,
root: davRoot,
Expand Down

0 comments on commit 77a929e

Please sign in to comment.