From 85e6cb4cccac2e0108c5053360d7d80049e34fd8 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 10 Jun 2024 22:38:14 +0200 Subject: [PATCH] refactor(files): Migrate files service to functions from `@nextcloud/files` Signed-off-by: Ferdinand Thiessen --- apps/files/src/services/Files.ts | 72 ++++++------------------- apps/files/src/services/WebdavClient.ts | 46 +--------------- 2 files changed, 17 insertions(+), 101 deletions(-) diff --git a/apps/files/src/services/Files.ts b/apps/files/src/services/Files.ts index 1fcd9d7fee1..dc83f16187b 100644 --- a/apps/files/src/services/Files.ts +++ b/apps/files/src/services/Files.ts @@ -3,68 +3,25 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { ContentsWithRoot } from '@nextcloud/files' -import type { FileStat, ResponseDataDetailed, DAVResultResponseProps } from 'webdav' +import type { FileStat, ResponseDataDetailed } from 'webdav' import { CancelablePromise } from 'cancelable-promise' -import { File, Folder, davParsePermissions, davGetDefaultPropfind } from '@nextcloud/files' -import { generateRemoteUrl } from '@nextcloud/router' -import { getCurrentUser } from '@nextcloud/auth' +import { File, Folder, davGetDefaultPropfind, davResultToNode, davRootPath } from '@nextcloud/files' +import { client } from './WebdavClient.ts' +import logger from '../logger.js' -import { getClient, rootPath } from './WebdavClient' -import { hashCode } from '../utils/hashUtils' -import logger from '../logger' +/** + * Slim wrapper over `@nextcloud/files` `davResultToNode` to allow using the function with `Array.map` + * @param node The node returned by the webdav library + */ +export const resultToNode = (node: FileStat): File | Folder => davResultToNode(node) -const client = getClient() - -interface ResponseProps extends DAVResultResponseProps { - permissions: string, - fileid: number, - size: number, -} - -export const resultToNode = function(node: FileStat): File | Folder { - const userId = getCurrentUser()?.uid - if (!userId) { - throw new Error('No user id found') - } - - const props = node.props as ResponseProps - const permissions = davParsePermissions(props?.permissions) - const owner = (props['owner-id'] || userId).toString() - - const source = generateRemoteUrl('dav' + rootPath + node.filename) - const id = props?.fileid < 0 - ? hashCode(source) - : props?.fileid as number || 0 - - const nodeData = { - id, - source, - mtime: new Date(node.lastmod), - mime: node.mime || 'application/octet-stream', - size: props?.size as number || 0, - permissions, - owner, - root: rootPath, - attributes: { - ...node, - ...props, - hasPreview: props?.['has-preview'], - failed: props?.fileid < 0, - }, - } - - delete nodeData.attributes.props - - return node.type === 'file' - ? new File(nodeData) - : new Folder(nodeData) -} - -export const getContents = (path = '/'): Promise => { +export const getContents = (path = '/'): CancelablePromise => { const controller = new AbortController() const propfindPayload = davGetDefaultPropfind() + path = `${davRootPath}${path}` + return new CancelablePromise(async (resolve, reject, onCancel) => { onCancel(() => controller.abort()) try { @@ -77,13 +34,14 @@ export const getContents = (path = '/'): Promise => { const root = contentsResponse.data[0] const contents = contentsResponse.data.slice(1) - if (root.filename !== path) { + if (root.filename !== path && `${root.filename}/` !== path) { + logger.debug(`Exepected "${path}" but got filename "${root.filename}" instead.`) throw new Error('Root node does not match requested path') } resolve({ folder: resultToNode(root) as Folder, - contents: contents.map(result => { + contents: contents.map((result) => { try { return resultToNode(result) } catch (error) { diff --git a/apps/files/src/services/WebdavClient.ts b/apps/files/src/services/WebdavClient.ts index 506f3f1e07e..5563508e2c7 100644 --- a/apps/files/src/services/WebdavClient.ts +++ b/apps/files/src/services/WebdavClient.ts @@ -2,48 +2,6 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ +import { davGetClient } from '@nextcloud/files' -import { createClient, getPatcher } from 'webdav' -import { generateRemoteUrl } from '@nextcloud/router' -import { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth' - -export const rootPath = `/files/${getCurrentUser()?.uid}` -export const defaultRootUrl = generateRemoteUrl('dav' + rootPath) - -export const getClient = (rootUrl = defaultRootUrl) => { - const client = createClient(rootUrl) - - // set CSRF token header - const setHeaders = (token: string | null) => { - client?.setHeaders({ - // Add this so the server knows it is an request from the browser - 'X-Requested-With': 'XMLHttpRequest', - // Inject user auth - requesttoken: token ?? '', - }); - } - - // refresh headers when request token changes - onRequestTokenUpdate(setHeaders) - setHeaders(getRequestToken()) - - /** - * Allow to override the METHOD to support dav REPORT - * - * @see https://github.com/perry-mitchell/webdav-client/blob/8d9694613c978ce7404e26a401c39a41f125f87f/source/request.ts - */ - const patcher = getPatcher() - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - // https://github.com/perry-mitchell/hot-patcher/issues/6 - patcher.patch('fetch', (url: string, options: RequestInit): Promise => { - const headers = options.headers as Record - if (headers?.method) { - options.method = headers.method - delete headers.method - } - return fetch(url, options) - }) - - return client; -} +export const client = davGetClient()