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 2023-10-30 10:52:08 -07:00 committed by skjnldsv
parent dfd42307f0
commit b03fd6e363
34 changed files with 117 additions and 63 deletions

View File

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

View File

@ -23,8 +23,8 @@
import { parseXML, type DAVResult, type FileStat, type ResponseDataDetailed } from 'webdav' import { parseXML, type DAVResult, type FileStat, type ResponseDataDetailed } from 'webdav'
// https://github.com/perry-mitchell/webdav-client/issues/339 // https://github.com/perry-mitchell/webdav-client/issues/339
import { processResponsePayload } from '../../../../node_modules/webdav/dist/node/response.js' import { processResponsePayload } from 'webdav/dist/node/response.js'
import { prepareFileFromProps } from '../../../../node_modules/webdav/dist/node/tools/dav.js' import { prepareFileFromProps } from 'webdav/dist/node/tools/dav.js'
import client from './DavClient.js' import client from './DavClient.js'
export const DEFAULT_LIMIT = 20 export const DEFAULT_LIMIT = 20
@ -77,10 +77,8 @@ const getDirectoryFiles = function(
// Map all items to a consistent output structure (results) // Map all items to a consistent output structure (results)
return responseItems.map(item => { return responseItems.map(item => {
// Each item should contain a stat object // Each item should contain a stat object
const { const props = item.propstat!.prop!;
propstat: { prop: props },
} = item
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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import * as webdav from 'webdav' import { createClient } from 'webdav'
import axios from '@nextcloud/axios'
import memoize from 'lodash/fp/memoize.js' import memoize from 'lodash/fp/memoize.js'
import { generateRemoteUrl } from '@nextcloud/router' import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'
export const getClient = memoize((service) => { export const getClient = memoize((service) => {
// Add this so the server knows it is an request from the browser // init webdav client
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest' const remote = generateRemoteUrl(`dav/${service}/${getCurrentUser().uid}`)
const client = createClient(remote)
// force our axios // set CSRF token header
const patcher = webdav.getPatcher() const setHeaders = (token) => {
patcher.patch('request', axios) 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( // refresh headers when request token changes
generateRemoteUrl(`dav/${service}/${getCurrentUser().uid}`) onRequestTokenUpdate(setHeaders)
) setHeaders(getRequestToken())
return client;
}) })

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
dist/core-common.js vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
dist/files-init.js vendored

Binary file not shown.

BIN
dist/files-init.js.map vendored

Binary file not shown.

BIN
dist/files-main.js vendored

Binary file not shown.

Binary file not shown.

BIN
dist/files-main.js.map vendored

Binary file not shown.

BIN
dist/files-sidebar.js vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.