fix: folder listing stuck if one element had an endless-loop permission

Massimo Melina committed Jun 16, 2024 at 18:54 UTC 7d96d3ccdae9f9f444650816e2ed52f6a8f3d10d
2 files changed +30 -8
src/log.ts
+1 -1
@@ -106,7 +106,7 @@ export const logMw: Koa.Middleware = async (ctx, next) => {
106 renameSync(path, newPath)
107 }
108 catch(e: any) { // ok, rename failed, but this doesn't mean we ain't gonna log
109 - console.error(String(e || e.message))
109 + console.error(e.message || String(e))
110 }
111 stream = logger.reopen() // keep variable updated
112 if (!stream) return
src/vfs.ts
+29 -7
@@ -2,8 +2,25 @@
2
3 import fs from 'fs/promises'
4 import { basename, dirname, join, resolve } from 'path'
5 -import { dirStream, enforceFinal, getOrSet, isDirectory, makeMatcher, setHidden, onlyTruthy, isValidFileName,
6 - throw_, VfsPerms, Who, isWhoObject, WHO_ANY_ACCOUNT, defaultPerms, PERM_KEYS, removeStarting } from './misc'
5 +import {
6 + dirStream,
7 + getOrSet,
8 + isDirectory,
9 + makeMatcher,
10 + setHidden,
11 + onlyTruthy,
12 + isValidFileName,
13 + throw_,
14 + VfsPerms,
15 + Who,
16 + isWhoObject,
17 + WHO_ANY_ACCOUNT,
18 + defaultPerms,
19 + PERM_KEYS,
20 + removeStarting,
21 + HTTP_SERVER_ERROR,
22 + try_
23 +} from './misc'
24 import Koa from 'koa'
25 import _ from 'lodash'
26 import { defineConfig, setConfig } from './config'
@@ -204,14 +221,19 @@ export function statusCodeForMissingPerm(node: VfsNode, perm: keyof VfsPerms, ct
221 // calculate value of permission resolving references to other permissions, avoiding infinite loop
222 let who: Who | undefined
223 let max = PERM_KEYS.length
224 + let cur = perm
225 do {
208 - who = node[perm]
226 + who = node[cur]
227 if (isWhoObject(who))
228 who = who.this
211 - who ??= defaultPerms[perm]
212 - if (!max-- || typeof who !== 'string' || who === WHO_ANY_ACCOUNT)
229 + who ??= defaultPerms[cur]
230 + if (typeof who !== 'string' || who === WHO_ANY_ACCOUNT)
231 break
214 - perm = who
232 + if (!max--) {
233 + console.error(`endless loop in permission ${perm}=${node[perm] ?? defaultPerms[perm]} for ${node.url || getNodeName(node)}`)
234 + return HTTP_SERVER_ERROR
235 + }
236 + cur = who
237 } while (1)
238
239 if (Array.isArray(who)) {
@@ -223,7 +245,7 @@ export function statusCodeForMissingPerm(node: VfsNode, perm: keyof VfsPerms, ct
245 }
246 return typeof who === 'boolean' ? (who ? 0 : HTTP_FORBIDDEN)
247 : who === WHO_ANY_ACCOUNT ? (getCurrentUsername(ctx) ? 0 : HTTP_UNAUTHORIZED)
226 - : throw_(Error('invalid permission: ' + JSON.stringify(who)))
248 + : throw_(Error(`invalid permission: ${perm}=${try_(() => JSON.stringify(who))}`))
249 }
250 }
251