better code: all uri-type parameters shall be named uri*, so to be treated properly
Massimo Melina committed
Apr 14, 2023 at 10:26 UTC
10f302c46fbc21bf0c5498054295c096ee792c5e
10 files changed
+40
-33
dev-plugins.md
+1
-1
@@ -48,7 +48,7 @@ All the following properties are essentially optional.
48
If you want to execute something in the "upstream" of middlewares, return a function.
49
50
- `unload: function` called when unloading a plugin. This is a good place for example to clearInterval().
51
-- `onDirEntry: ({ entry: DirEntry, listPath: string }) => void | false` by providing this callback you can manipulate the record
51
+- `onDirEntry: ({ entry: DirEntry, listUri: string }) => void | false` by providing this callback you can manipulate the record
52
that is sent to the frontend (`entry`), or you can return false to exclude this entry from the results.
53
- `config: { [key]: FieldDescriptor }` declare a set of admin-configurable values owned by the plugin
54
that will be displayed inside Admin-panel for change. Each property is identified by its key,
frontend/src/menu.ts
+1
-1
@@ -206,7 +206,7 @@ export async function deleteFiles(uris: string[], root: string='') {
206
if (!await confirmDialog(t('delete_confirm', {n}, "Delete {n,plural, one{# item} other{# items}}?")))
207
return false
208
const errors = onlyTruthy(await Promise.all(uris.map(uri =>
209
- apiCall('del', { path: root + uri }).then(() => null, err => ({ uri, err }))
209
+ apiCall('del', { uri: root + uri }).then(() => null, err => ({ uri, err }))
210
)))
211
reloadList()
212
const e = errors.length
frontend/src/upload.ts
+3
-3
@@ -379,14 +379,14 @@ export function acceptDropFiles(cb: false | undefined | ((files:File[]) => void)
379
async function createFolder() {
380
const name = await promptDialog(t`Enter folder name`)
381
if (!name) return
382
- const path = location.pathname
382
+ const uri = location.pathname
383
try {
384
- await apiCall('create_folder', { path, name })
384
+ await apiCall('create_folder', { uri, name })
385
reloadList()
386
return alertDialog(h(() =>
387
h(FlexV, {},
388
h('div', {}, t`Successfully created`),
389
- h(Link, { to: path + name + '/', onClick() {
389
+ h(Link, { to: uri + name + '/', onClick() {
390
closeDialog()
391
closeDialog()
392
} }, t('enter_folder', "Enter the folder")),
frontend/src/useFetchList.ts
+1
-1
@@ -48,7 +48,7 @@ export default function useFetchList() {
48
}
49
50
const baseParams = {
51
- path: desiredPath,
51
+ uri: desiredPath,
52
search,
53
sse: true,
54
omit: 'c',
plugins/download-counter/plugin.js
+2
-2
@@ -47,8 +47,8 @@ exports.init = async api => {
47
counters[path] = counters[path] + 1 || 1
48
save()
49
},
50
- onDirEntry: ({ entry, listPath }) => {
51
- const path = listPath + entry.n
50
+ onDirEntry: ({ entry, listUri }) => {
51
+ const path = listUri + entry.n
52
const n = counters[path]
53
if (n)
54
entry.hits = n
plugins/vhosting/plugin.js
+17
-11
@@ -21,26 +21,32 @@ exports.init = api => {
21
const { matches } = api.require('./misc')
22
return {
23
middleware(ctx) {
24
- let toModify = ctx
24
+ let params // undefined if we are not going to work on api parameters
25
if (ctx.path.startsWith(api.const.SPECIAL_URI)) { // special uris should be excluded...
26
// ...unless it's a frontend api with a path param
27
- if (!ctx.path.startsWith(api.const.API_URI) || ctx.params.path === undefined) return
27
+ if (!ctx.path.startsWith(api.const.API_URI)) return
28
let { referer } = ctx.headers
29
referer &&= new URL(referer).pathname
30
- if (referer?.startsWith(ctx.state.revProxyPath + api.const.ADMIN_URI)) return
31
- toModify = ctx.params
30
+ if (referer?.startsWith(ctx.state.revProxyPath + api.const.ADMIN_URI)) return // exclude apis for admin-panel
31
+ params = ctx.params
32
}
33
+
34
const hosts = api.getConfig('hosts')
35
if (!hosts?.length) return
35
- for (const row of hosts)
36
- if (matches(ctx.host, row.host)) {
37
- toModify.path = row.root + toModify.path
38
- return
36
+ const row = hosts?.find(x => matches(ctx.host, x.host))
37
+ if (!row) {
38
+ if (api.getConfig('mandatory')) {
39
+ ctx.socket.destroy()
40
+ return true
41
}
40
- if (api.getConfig('mandatory')) {
41
- ctx.socket.destroy()
42
- return true
42
+ return
43
}
44
+ if (!params)
45
+ ctx.path = row.root + ctx.path
46
+ else
47
+ for (const [k,v] of Object.entries(params))
48
+ if (k.startsWith('uri'))
49
+ params[k] = row.root + v
50
}
51
}
52
}
src/api.file_list.ts
+4
-4
@@ -19,8 +19,8 @@ import _ from 'lodash'
19
import { HTTP_BAD_REQUEST, HTTP_FOOL, HTTP_METHOD_NOT_ALLOWED, HTTP_NOT_FOUND } from './const'
20
import Koa from 'koa'
21
22
-export const file_list: ApiHandler = async ({ path, offset, limit, search, omit, sse }, ctx) => {
23
- let node = await urlToNode(path || '/', ctx)
22
+export const file_list: ApiHandler = async ({ uri, offset, limit, search, omit, sse }, ctx) => {
23
+ let node = await urlToNode( uri || '/', ctx)
24
const list = new SendListReadable()
25
if (!node)
26
return fail(HTTP_NOT_FOUND)
@@ -31,7 +31,7 @@ export const file_list: ApiHandler = async ({ path, offset, limit, search, omit,
31
return fail(HTTP_FOOL)
32
if (node.default)
33
return (sse ? list.custom : _.identity)({ // sse will wrap the object in a 'custom' message, otherwise we plainly return the object
34
- redirect: path // tell the browser to access the folder (instead of using this api), so it will get the default file
34
+ redirect: uri // tell the browser to access the folder (instead of using this api), so it will get the default file
35
})
36
if (!await nodeIsDirectory(node))
37
return fail(HTTP_METHOD_NOT_ALLOWED)
@@ -69,7 +69,7 @@ export const file_list: ApiHandler = async ({ path, offset, limit, search, omit,
69
const entry = await nodeToDirEntry(ctx, sub)
70
if (!entry)
71
continue
72
- const cbParams = { entry, ctx, listPath:path, node:sub }
72
+ const cbParams = { entry, ctx, listUri: uri, node: sub }
73
try {
74
if (onDirEntryHandlers.some(cb => cb(cbParams) === false))
75
continue
src/apiMiddleware.ts
+3
-2
@@ -30,8 +30,9 @@ export function apiMiddleware(apis: ApiHandlers) : Koa.Middleware {
30
// we don't rely on SameSite cookie option because it's https-only
31
let res
32
try {
33
- if (params.path)
34
- params.path = removeStarting(ctx.state.revProxyPath, params.path)
33
+ for (const [k,v] of Object.entries(params))
34
+ if (k.startsWith('uri') && typeof v === 'string')
35
+ params[k] = removeStarting(ctx.state.revProxyPath, v)
36
res = csrf && csrf !== params.csrf ? new ApiError(HTTP_UNAUTHORIZED, 'csrf')
37
: await apiFun(params || {}, ctx)
38
}
src/frontEndApis.ts
+6
-6
@@ -36,11 +36,11 @@ export const frontEndApis: ApiHandlers = {
36
})
37
},
38
39
- async create_folder({ path, name }, ctx) {
40
- apiAssertTypes({ string: { path, name } })
39
+ async create_folder({ uri, name }, ctx) {
40
+ apiAssertTypes({ string: { uri, name } })
41
if (!isValidFileName(name) || dirTraversal(name))
42
return new ApiError(HTTP_BAD_REQUEST, 'bad name')
43
- const parentNode = await urlToNode(path, ctx)
43
+ const parentNode = await urlToNode(uri, ctx)
44
if (!parentNode)
45
return new ApiError(HTTP_NOT_FOUND, 'parent not found')
46
if (!hasPermission(parentNode, 'can_upload', ctx))
@@ -54,9 +54,9 @@ export const frontEndApis: ApiHandlers = {
54
}
55
},
56
57
- async del({ path }, ctx) {
58
- apiAssertTypes({ string: { path } })
59
- const node = await urlToNode(path, ctx)
57
+ async del({ uri }, ctx) {
58
+ apiAssertTypes({ string: { uri } })
59
+ const node = await urlToNode(uri, ctx)
60
if (!node)
61
throw new ApiError(HTTP_NOT_FOUND)
62
if (!node.source)
tests/test.ts
+2
-2
@@ -196,8 +196,8 @@ function reqApi(api: string, params: object, test:Tester) {
196
return req(API+api, test, { data: params })
197
}
198
199
-function reqList(path:string, tester:Tester, params?: object) {
200
- return reqApi('file_list', { path, ...params }, tester)
199
+function reqList(uri:string, tester:Tester, params?: object) {
200
+ return reqApi('file_list', { uri, ...params }, tester)
201
}
202
203
function isInList(res:any, name:string) {