fix: folders 'read' permission in file_list was not considering inner elements
Massimo Melina committed
Apr 7, 2023 at 13:09 UTC
cd2deb972a0d5875bf0d145e71d96a3249c4001b
2 files changed
+20
-20
src/api.file_list.ts
+15
-8
@@ -3,11 +3,13 @@
3
import {
4
getNodeName,
5
hasPermission,
6
+ masksCouldGivePermission,
7
nodeIsDirectory,
8
statusCodeForMissingPerm,
9
urlToNode,
9
- VfsNode, VfsPerm,
10
- walkNode, WHO_NO_ONE
10
+ VfsNode,
11
+ walkNode,
12
+ WHO_NO_ONE
13
} from './vfs'
14
import { ApiError, ApiHandler, SendListReadable } from './apiMiddleware'
15
import { stat } from 'fs/promises'
@@ -106,22 +108,27 @@ async function nodeToDirEntry(ctx: Koa.Context, node: VfsNode): Promise<DirEntry
108
const st = await stat(source)
109
const folder = st.isDirectory()
110
const { ctime, mtime } = st
111
+ const pl = node.can_list === WHO_NO_ONE ? 'l'
112
+ : !hasPermission(node, 'can_list', ctx) ? 'L'
113
+ : ''
114
+ // no download here, but maybe inside?
115
+ const pr = node.can_read === WHO_NO_ONE && !(folder && filesInsideCould()) ? 'r'
116
+ : !hasPermission(node, 'can_read', ctx) ? 'R'
117
+ : ''
118
return {
119
n: name + (folder ? '/' : ''),
120
c: ctime,
121
m: Math.abs(+mtime-+ctime) < 1000 ? undefined : mtime,
122
s: folder ? undefined : st.size,
114
- p: (['can_read', 'can_list'] as (keyof VfsPerm)[]).map(perm2letter).join('')
115
- || undefined
123
+ p: (pr + pl) || undefined
124
}
125
}
126
catch {
127
return null
128
}
129
122
- function perm2letter(k: keyof VfsPerm) {
123
- return node[k] === WHO_NO_ONE ? k[4]!
124
- : hasPermission(node, k, ctx) ? ''
125
- : k[4]!.toUpperCase()
130
+ function filesInsideCould(n: VfsNode=node): boolean | undefined {
131
+ return masksCouldGivePermission(n.masks, 'can_read')
132
+ || n.children?.some(c => c.can_read || filesInsideCould(c)) // we count on the boolean-compliant nature of the permission type here
133
}
134
}
src/vfs.ts
+5
-12
@@ -228,20 +228,13 @@ export async function* walkNode(parent:VfsNode, ctx?: Koa.Context, depth:number=
228
item.isTemp = true
229
return item
230
}
231
+}
232
232
- function masksCouldGivePermission(masks: Masks | undefined) {
233
- if (!masks) return false
234
- for (const [,props] of Object.entries(masks)) {
235
- const v = props[requiredPerm!]
236
- if (v && (!ctx || matchWho(v, ctx))) // without ctx we can't say, so it could
237
- return true
238
- if (masksCouldGivePermission(props.masks))
239
- return true
240
- }
241
- return false
242
- }
243
-
233
+export function masksCouldGivePermission(masks: Masks | undefined, perm: keyof VfsPerm): boolean {
234
+ return masks !== undefined && Object.values(masks).some(props =>
235
+ props[perm] || masksCouldGivePermission(props.masks, perm))
236
}
237
+
238
function applyMasks(item: VfsNode, parent: VfsNode, virtualBasename: string) {
239
const { masks } = parent
240
if (!masks) return