fix(dav): multiple fixes in usage of webdav library

1. Refresh token on update
2. Fix some very weird imports
3. Patch fetch instead of request to prevent accessing impl details

Signed-off-by: Varun Patil <varunpatil@ucla.edu>
This commit is contained in:
Varun Patil 2024-05-29 15:17:49 -07:00 committed by Christopher Ng
parent 0f90cc97ca
commit 39ddfb07b5
7 changed files with 117 additions and 63 deletions

View file

@ -22,16 +22,23 @@
import { createClient } from 'webdav'
import { getRootPath } from '../utils/davUtils.js'
import { getRequestToken } from '@nextcloud/auth'
import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
// init webdav client
const client = createClient(getRootPath(), {
headers: {
// Add this so the server knows it is an request from the browser
'X-Requested-With': 'XMLHttpRequest',
// Inject user auth
requesttoken: getRequestToken() ?? '',
},
})
const client = createClient(getRootPath())
// set CSRF token header
const setHeaders = (token) => {
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())
export default client

View file

@ -23,8 +23,8 @@
import { parseXML, type DAVResult, type FileStat, type ResponseDataDetailed } from 'webdav'
// https://github.com/perry-mitchell/webdav-client/issues/339
import { processResponsePayload } from '../../../../node_modules/webdav/dist/node/response.js'
import { prepareFileFromProps } from '../../../../node_modules/webdav/dist/node/tools/dav.js'
import { processResponsePayload } from 'webdav/dist/node/response.js'
import { prepareFileFromProps } from 'webdav/dist/node/tools/dav.js'
import client from './DavClient.js'
export const DEFAULT_LIMIT = 20
@ -77,10 +77,8 @@ const getDirectoryFiles = function(
// Map all items to a consistent output structure (results)
return responseItems.map(item => {
// Each item should contain a stat object
const {
propstat: { prop: props },
} = item
const props = item.propstat!.prop!;
return prepareFileFromProps(props, props.id.toString(), isDetailed)
return prepareFileFromProps(props, props.id!.toString(), isDetailed)
})
}

View file

@ -19,21 +19,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import * as webdav from 'webdav'
import axios from '@nextcloud/axios'
import { createClient } from 'webdav'
import memoize from 'lodash/fp/memoize.js'
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
export const getClient = memoize((service) => {
// Add this so the server knows it is an request from the browser
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
// init webdav client
const remote = generateRemoteUrl(`dav/${service}/${getCurrentUser().uid}`)
const client = createClient(remote)
// force our axios
const patcher = webdav.getPatcher()
patcher.patch('request', axios)
// set CSRF token header
const setHeaders = (token) => {
client.setHeaders({
// Add this so the server knows it is an request from the browser
'X-Requested-With': 'XMLHttpRequest',
// Inject user auth
requesttoken: token ?? '',
})
}
return webdav.createClient(
generateRemoteUrl(`dav/${service}/${getCurrentUser().uid}`)
)
// refresh headers when request token changes
onRequestTokenUpdate(setHeaders)
setHeaders(getRequestToken())
return client;
})

View file

@ -19,22 +19,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import type { RequestOptions, Response } from 'webdav'
import { createClient, getPatcher } from 'webdav'
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser, getRequestToken } from '@nextcloud/auth'
import { request } from 'webdav/dist/node/request.js'
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, {
headers: {
requesttoken: getRequestToken() || '',
},
})
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
@ -45,12 +53,14 @@ export const getClient = (rootUrl = defaultRootUrl) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// https://github.com/perry-mitchell/hot-patcher/issues/6
patcher.patch('request', (options: RequestOptions): Promise<Response> => {
if (options.headers?.method) {
options.method = options.headers.method
delete options.headers.method
patcher.patch('fetch', (url: string, options: RequestInit): Promise<Response> => {
const headers = options.headers as Record<string, string>
if (headers?.method) {
options.method = headers.method
delete headers.method
}
return request(options)
return fetch(url, options)
})
return client
return client;
}

View file

@ -19,15 +19,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { createClient } from 'webdav'
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser, getRequestToken } from '@nextcloud/auth'
import { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
// init webdav client
export const rootPath = `/trashbin/${getCurrentUser()?.uid}/trash`
export const rootUrl = generateRemoteUrl('dav' + rootPath)
const client = createClient(rootUrl, {
headers: {
requesttoken: getRequestToken(),
},
})
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())
export default client

View file

@ -21,17 +21,25 @@
import { createClient } from 'webdav'
import { generateRemoteUrl } from '@nextcloud/router'
import { getRequestToken } from '@nextcloud/auth'
import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
// init webdav client
const rootPath = 'dav'
// init webdav client on default dav endpoint
const remote = generateRemoteUrl(rootPath)
export default createClient(remote, {
headers: {
// Add this so the server knows it is an request from the browser
'X-Requested-With': 'XMLHttpRequest',
// Inject user auth
requesttoken: getRequestToken() ?? '',
},
})
const client = createClient(remote)
// set CSRF token header
const setHeaders = (token) => {
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())
export default client

View file

@ -22,12 +22,22 @@
import { createClient } from 'webdav'
import { generateRemoteUrl } from '@nextcloud/router'
import { getRequestToken } from '@nextcloud/auth'
import { getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
// init webdav client
const rootUrl = generateRemoteUrl('dav')
export const davClient = createClient(rootUrl)
export const davClient = createClient(rootUrl, {
headers: {
requesttoken: getRequestToken() ?? '',
},
})
// set CSRF token header
const setHeaders = (token: string | null) => {
davClient.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())