-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathuseAppFileHandling.ts
147 lines (131 loc) · 4.83 KB
/
useAppFileHandling.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { Store } from 'vuex'
import { unref } from '@vue/composition-api'
import qs from 'qs'
import { Resource } from 'files/src/helpers/resource'
import { MaybeRef } from '../../utils'
import { ClientService, clientService as defaultClientService } from '../../services'
import { DavProperties } from '../../constants'
interface AppFileHandlingOptions {
store: Store<any>
clientService?: ClientService
isPublicLinkContext: MaybeRef<boolean>
accessToken: MaybeRef<string>
publicLinkPassword: MaybeRef<string>
publicToken: MaybeRef<string>
}
type QueryParameters = Record<string, string>
export interface AppFileHandlingResult {
getUrlForResource(r: Resource, query?: QueryParameters): string
makeRequest(method: string, url: string, extraHeaders: Record<string, any>): Promise<any>
getFileInfo(filePath: string, davProperties: DavProperties): Promise<any>
getFileContents(filePath: string, options: Record<string, any>): Promise<any>
putFileContents(filePath: string, content: string, options: Record<string, any>): Promise<any>
}
export function useAppFileHandling(options: AppFileHandlingOptions): AppFileHandlingResult {
const client = (options.clientService || defaultClientService).owncloudSdk
const isPublicLinkContext = options.isPublicLinkContext
const publicLinkPassword = options.publicLinkPassword
const publicToken = options.publicToken
const accessToken = options.accessToken
const getUrlForResource = (
{ webDavPath, downloadURL }: Resource,
query: QueryParameters = null
) => {
const queryStr = qs.stringify(query)
if (unref(isPublicLinkContext)) {
// If the resource does not contain the downloadURL we fallback to the normal
// public files path.
if (!downloadURL) {
// TODO: check whether we can fix the resource to always contain public-files in the webDavPath
const urlPath = ['public-files', webDavPath].join('/')
return [client.files.getFileUrl(urlPath), queryStr].filter(Boolean).join('?')
}
// In a public context, i.e. public shares, the downloadURL contains a pre-signed url to
// download the file.
const [url, signedQuery] = downloadURL.split('?')
// Since the pre-signed url contains query parameters and the caller of this method
// can also provide query parameters we have to combine them.
const combinedQuery = [queryStr, signedQuery].filter(Boolean).join('&')
return [url, combinedQuery].filter(Boolean).join('?')
}
return [client.files.getFileUrl(webDavPath), queryStr].filter(Boolean).join('?')
}
const makeRequest = async (method: string, url: string, extraHeaders: Record<string, any>) => {
const plToken = unref(publicToken)
const plPassword = unref(publicLinkPassword)
const isPlCtx = unref(isPublicLinkContext)
const aToken = unref(accessToken)
const headers = {
'X-Requested-With': 'XMLHttpRequest',
...(isPlCtx &&
plPassword && {
Authorization: 'Basic ' + Buffer.from(['public', plPassword].join(':')).toString('base64')
}),
...(isPlCtx && plToken && { 'public-token': plToken }),
...(aToken && { Authorization: 'Bearer ' + aToken })
}
return fetch(url, {
method,
headers: {
...headers,
...extraHeaders
}
})
}
const getFileContents = async (filePath: string, options: Record<string, any>) => {
if (unref(isPublicLinkContext)) {
const res = await client.publicFiles.download('', filePath, unref(publicLinkPassword))
res.statusCode = res.status
const responseType = ['arrayBuffer', 'blob', 'text'].includes(options?.responseType)
? options.responseType
: 'text'
return {
response: res,
body: await res[responseType](),
headers: {
ETag: res.headers.get('etag'),
'OC-FileId': res.headers.get('oc-fileid')
}
}
} else {
return client.files.getFileContents(filePath, {
resolveWithResponseObject: true,
...options
})
}
}
const getFileInfo = async (filePath: string, davProperties: DavProperties) => {
if (unref(isPublicLinkContext)) {
return await client.publicFiles.getFileInfo(
filePath,
unref(publicLinkPassword),
davProperties
)
}
return client.files.fileInfo(filePath, davProperties)
}
const putFileContents = (
filePath: string,
content: string,
putFileOptions: Record<string, any>
) => {
if (unref(isPublicLinkContext)) {
return client.publicFiles.putFileContents(
'',
filePath,
unref(publicLinkPassword),
content,
putFileOptions
)
} else {
return client.files.putFileContents(filePath, content, putFileOptions)
}
}
return {
makeRequest,
getFileContents,
getUrlForResource,
getFileInfo,
putFileContents
}
}