Skip to content

Commit

Permalink
fix(dav): multiple fixes in usage of webdav library
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
pulsejet committed Nov 27, 2023
1 parent 5d669ab commit 3422780
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 63 deletions.
25 changes: 16 additions & 9 deletions apps/comments/src/services/DavClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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
10 changes: 4 additions & 6 deletions apps/comments/src/services/GetComments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
})
}
30 changes: 19 additions & 11 deletions apps/dav/src/dav/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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;
})
38 changes: 24 additions & 14 deletions apps/files/src/services/WebdavClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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
Expand All @@ -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;
}
25 changes: 19 additions & 6 deletions apps/files_trashbin/src/services/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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
30 changes: 19 additions & 11 deletions apps/files_versions/src/utils/davClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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
22 changes: 16 additions & 6 deletions apps/systemtags/src/services/davClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
function 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())

0 comments on commit 3422780

Please sign in to comment.