allow file permissions to allow seeing and not downloading

Massimo Melina committed Mar 12, 2023 at 12:57 UTC 84d58f9948b35c461bc57af6d829c597be96c06d
5 files changed +8 -8
README.md
+2 -2
@@ -190,8 +190,8 @@ Valid keys in a node are:
190 - `false`: no one can.
191 - `"*"`: any account can, i.e. anyone who logged in.
192 - `[ frank, peter ]`: the list of accounts who can.
193 -- `can_see`: specify who can see this entry. Even if a user can download you can still make the file not appear in the list.
194 - Remember that to see in the list you must also be able to download (read), or else you won't see it anyway. Value is a `WhoCan` descriptor, refer above.
193 +- `can_see`: specify who can see this element. Even if a user can download you can still make the file not appear in the list.
194 + Value is a `WhoCan` descriptor, refer above.
195 - `can_upload` specify who can upload. Applies to folders with a source. Default is none.
196 - `can_delete` specify who can delete. Applies to folders with a source. Default is none.
197 - `masks`: maps a file mask to a set of properties as the one documented in this section. E.g.
admin/src/FileForm.ts
+2 -3
@@ -103,9 +103,8 @@ export default function FileForm({ file, anyMask, defaultPerms, addToBar, urls }
103 { k: 'source', label: "Source on disk", comp: FileField, files: !isDir, folders: isDir, multiline: true,
104 placeholder: "Not on disk, this is a virtual folder",
105 },
106 - perm('can_read', "Who can download", "Note: who can't download won't see it in the list"),
107 - can_read && perm('can_see', "Who can see", "You can hide and keep it downloadable if you have a direct link",
108 - { accounts: Array.isArray(can_read) ? allAccounts.filter(x => can_read.includes(x.username)) : undefined }),
106 + perm('can_read', "Who can download", "Who can see but not download will be asked to login"),
107 + perm('can_see', "Who can see", "You can hide and keep it downloadable if you have a direct link"),
108 isDir && perm('can_upload', "Who can upload", hasSource ? '' : "Works only on folders with source"),
109 isDir && perm('can_delete', "Who can delete", hasSource ? '' : "Works only on folders with source"),
110 showSize && { k: 'size', comp: DisplayField, lg: 4, toField: formatBytes },
src/vfs.ts
+1 -2
@@ -23,7 +23,7 @@ type Who = typeof WHO_ANYONE
23
24 interface VfsPerm {
25 can_read: Who
26 - can_see: Who // use this to hide something you can_read
26 + can_see: Who
27 can_upload: Who
28 can_delete: Who
29 }
@@ -151,7 +151,6 @@ export async function nodeIsDirectory(node: VfsNode) {
151 export function hasPermission(node: VfsNode, perm: keyof VfsPerm, ctx: Koa.Context): boolean {
152 return (node.source || perm !== 'can_upload') // Upload possible only if we know where to store. First check node.source because is supposedly faster.
153 && matchWho(node[perm] ?? defaultPerms[perm], ctx)
154 - && (perm !== 'can_see' || hasPermission(node, 'can_read', ctx)) // can_see is used to hide something you nonetheless can_read, so you MUST also can_read
154 }
155
156 export async function* walkNode(parent:VfsNode, ctx?: Koa.Context, depth:number=0, prefixPath:string=''): AsyncIterableIterator<VfsNode> {
tests/config.yaml
+2
@@ -46,8 +46,10 @@ vfs:
46 source: tests
47 masks:
48 page:
49 + can_see: false
50 can_read: false
51 page/*:
52 + can_see: true
53 can_read: true
54 - name: cantReadPageAlt
55 source: tests
tests/test.ts
+1 -1
@@ -66,7 +66,7 @@ describe('basics', () => {
66 it('cantSeeThisButChildren.children', reqList('/cantSeeThisButChildren', { inList:['hi/'] }))
67
68 it('protectFromAbove', req('/protectFromAbove/child/alfa.txt', 403))
69 - it('protectFromAbove.list', reqList('/protectFromAbove/child/', { outList:['alfa.txt'] }))
69 + it('protectFromAbove.list', reqList('/protectFromAbove/child/', { inList:['alfa.txt'] }))
70
71 const zipSize = 13010
72 const zipOfs = 5000