don't offer download button if no-one can download

Massimo Melina committed Apr 5, 2023 at 23:19 UTC 572f1ad8e229bcf18ce20ba7a1ca3d94b0b29ded
4 files changed +22 -13
frontend/src/BrowseFiles.ts
+5 -3
@@ -227,10 +227,12 @@ const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) =>
227 ev.preventDefault()
228 const OPEN_ICON = 'play'
229 const OPEN_LABEL = t('file_open', "Open")
230 + const couldRead = entry.p !== (isFolder ? 'l' : 'r')
231 const menu = [
231 - menuOnLink && (isFolder ? h(Link, { to: base + uri, onClick: () => close() }, hIcon(OPEN_ICON), OPEN_LABEL)
232 - : { label: OPEN_LABEL, href: uri, target: isFolder ? undefined : '_blank', icon: OPEN_ICON }),
233 - { label: t`Download`, href: uri + (isFolder ? '?get=zip' : '?dl'), icon: 'download' },
232 + couldRead && menuOnLink
233 + && (isFolder ? h(Link, { to: base + uri, onClick: () => close() }, hIcon(OPEN_ICON), OPEN_LABEL)
234 + : { label: OPEN_LABEL, href: uri, target: isFolder ? undefined : '_blank', icon: OPEN_ICON }),
235 + couldRead && { label: t`Download`, href: uri + (isFolder ? '?get=zip' : '?dl'), icon: 'download' },
236 can_delete && { label: t`Delete`, icon: 'trash', onClick: () => deleteFiles([uri], base) }
237 ]
238 const props = [
frontend/src/index.scss
+4 -2
@@ -401,14 +401,16 @@ button label {
401 & dd { margin-left: 1.5em; }
402 }
403 .file-menu {
404 - padding-top: .5em;
405 - border-top: 1px solid var(--faint-contrast);
404 margin-top: 1em;
405
406 display: flex;
407 flex-direction: column;
408 & a {
409 padding: .5em 0;
410 + &:first-child {
411 + padding-top: 1em;
412 + border-top: 1px solid var(--faint-contrast);
413 + }
414 & .icon { margin-right: 0.5em; }
415 &:hover { @extend .highlightedText }
416 }
src/api.file_list.ts
+9 -4
@@ -6,8 +6,8 @@ import {
6 nodeIsDirectory,
7 statusCodeForMissingPerm,
8 urlToNode,
9 - VfsNode,
10 - walkNode
9 + VfsNode, VfsPerm,
10 + walkNode, WHO_NO_ONE
11 } from './vfs'
12 import { ApiError, ApiHandler, SendListReadable } from './apiMiddleware'
13 import { stat } from 'fs/promises'
@@ -111,12 +111,17 @@ async function nodeToDirEntry(ctx: Koa.Context, node: VfsNode): Promise<DirEntry
111 c: ctime,
112 m: Math.abs(+mtime-+ctime) < 1000 ? undefined : mtime,
113 s: folder ? undefined : st.size,
114 - p: ((hasPermission(node, 'can_read', ctx) ? '' : 'R')
115 - + (hasPermission(node, 'can_list', ctx) ? '' : 'L'))
114 + p: (['can_read', 'can_list'] as (keyof VfsPerm)[]).map(perm2letter).join('')
115 || undefined
116 }
117 }
118 catch {
119 return null
120 }
121 +
122 + function perm2letter(k: keyof VfsPerm) {
123 + return node[k] === WHO_NO_ONE ? k[4]!
124 + : hasPermission(node, k, ctx) ? ''
125 + : k[4]!.toUpperCase()
126 + }
127 }
src/vfs.ts
+4 -4
@@ -10,16 +10,16 @@ import { HTTP_FOOL, HTTP_FORBIDDEN, HTTP_UNAUTHORIZED } from './const'
10 import events from './events'
11 import { getCurrentUsernameExpanded } from './perm'
12
13 -const WHO_ANYONE = true
14 -const WHO_NO_ONE = false
15 -const WHO_ANY_ACCOUNT = '*'
13 +export const WHO_ANYONE = true
14 +export const WHO_NO_ONE = false
15 +export const WHO_ANY_ACCOUNT = '*'
16 type AccountList = string[]
17 export type Who = typeof WHO_ANYONE
18 | typeof WHO_NO_ONE
19 | typeof WHO_ANY_ACCOUNT
20 | AccountList
21
22 -interface VfsPerm {
22 +export interface VfsPerm {
23 can_read: Who
24 can_see: Who
25 can_list: Who