@samitouri / QOSami-HFS / commits / b1e25eed

fix: admin/fs: shouldn't show "as" permissions that don't exist

Massimo Melina committed Nov 30, 2023 at 23:28 UTC b1e25eed58b9004dca79bde153b354b22cd85f9d
1 file changed +43 -11
admin/src/FileForm.ts
+43 -11
@@ -14,8 +14,29 @@ import {
14 StringField
15 } from '@hfs/mui-grid-form'
16 import { apiCall, UseApi, useApiEx } from './api'
17 -import { basename, Btn, defaultPerms, formatBytes, formatTimestamp, IconBtn, isEqualLax, isWhoObject, LinkBtn, modifiedSx,
18 - newDialog, objSameKeys, onlyTruthy, prefix, useBreakpoint, VfsPerms, wantArray, Who, WhoObject, wikiLink } from './misc'
17 +import {
18 + _log,
19 + basename,
20 + Btn,
21 + defaultPerms,
22 + formatBytes,
23 + formatTimestamp,
24 + IconBtn,
25 + isEqualLax,
26 + isWhoObject,
27 + LinkBtn,
28 + modifiedSx,
29 + newDialog,
30 + objSameKeys,
31 + onlyTruthy,
32 + prefix,
33 + useBreakpoint,
34 + VfsPerms,
35 + wantArray,
36 + Who,
37 + WhoObject,
38 + wikiLink
39 +} from './misc'
40 import { reloadVfs, VfsNode } from './VfsPage'
41 import md from './md'
42 import _ from 'lodash'
@@ -70,6 +91,14 @@ export default function FileForm({ file, anyMask, addToBar, statusApi }: FileFor
91 const accounts = data.list
92
93 const needSourceWarning = !hasSource && "Works only on folders with source! "
94 + const show: Record<keyof VfsPerms, boolean> = {
95 + can_read: !isLink,
96 + can_see: true,
97 + can_archive: !isLink,
98 + can_list: isDir,
99 + can_upload: isDir && hasSource,
100 + can_delete: isDir && hasSource,
101 + }
102 return h(Form, {
103 values,
104 set(v, k) {
@@ -133,12 +162,12 @@ export default function FileForm({ file, anyMask, addToBar, statusApi }: FileFor
162 : "This field is empty, and thus this element is a virtual-folder. You can set this field, pointing at any folder/file on disk.",
163 },
164 !isLink && { k: 'id', comp: LinkField, statusApi, xs: 12 },
136 - !isLink && perm('can_read', "Who can see but not download will be asked to login"),
165 + perm('can_read', "Who can see but not download will be asked to login"),
166 perm('can_see', "If you can't see, you may still download with a direct link"),
138 - !isLink && perm('can_archive', "Should this be included when user downloads as ZIP", { label: "Who can zip", lg: isDir ? true : 12 }),
139 - isDir && perm('can_list', "Permission to see content of folders", { contentText: "subfolders" }),
140 - isDir && perm('can_delete', [needSourceWarning, "Those who can delete can also rename"]),
141 - isDir && perm('can_upload', needSourceWarning, { contentText: "subfolders" }),
167 + perm('can_archive', "Should this be included when user downloads as ZIP", { lg: isDir ? true : 12 }),
168 + perm('can_list', "Permission to see content of folders", { contentText: "subfolders" }),
169 + perm('can_delete', [needSourceWarning, "Those who can delete can also rename"]),
170 + perm('can_upload', needSourceWarning, { contentText: "subfolders" }),
171 showSize && { k: 'size', comp: DisplayField, lg: 4, toField: formatBytes },
172 showTimestamps && { k: 'ctime', comp: DisplayField, md: 6, lg: showSize && 4, label: "Created", toField: formatTimestamp },
173 showTimestamps && { k: 'mtime', comp: DisplayField, md: 6, lg: showSize && 4, label: "Modified", toField: formatTimestamp },
@@ -159,12 +188,15 @@ export default function FileForm({ file, anyMask, addToBar, statusApi }: FileFor
188 })
189
190 function perm(perm: keyof VfsPerms, helperText?: ReactNode, props: Partial<WhoFieldProps>={}) {
191 + if (!show[perm]) return null
192 + const dontShow = [perm, ...onlyTruthy(_.map(show, (v,k) => !v && k))]
193 + const others = _.difference(Object.keys(defaultPerms), dontShow)
194 return {
195 comp: WhoField,
196 k: perm, lg: 6, xl: 4,
197 parent, accounts, helperText, isDir,
198 showInherited: anyMask, // with masks, you may need to set a permission to override the mask
167 - otherPerms: _.without(Object.keys(defaultPerms), perm).map(x => ({ value: x, label: "As " +perm2word(x) })),
199 + otherPerms: others.map(x => ({ value: x, label: "As " +perm2word(x) })),
200 label: "Who can " + perm2word(perm),
201 inherit: file.inherited?.[perm] ?? defaultPerms[perm],
202 byMasks: byMasks?.[perm],
@@ -177,7 +209,7 @@ export default function FileForm({ file, anyMask, addToBar, statusApi }: FileFor
209
210 function perm2word(perm: string) {
211 const word = perm.split('_')[1]
180 - return word === 'read' ? 'download' : word
212 + return word === 'read' ? 'download' : word === 'archive' ? 'zip' : word
213 }
214
215 interface WhoFieldProps extends FieldProps<Who | undefined> {
@@ -205,7 +237,7 @@ function WhoField({ value, onChange, parent, inherit, accounts, helperText, show
237 // don't offer inherited value twice, unless it was already selected, or it is forced
238 ].map(x => !hideValues?.includes(x.value) && (x.value === thisValue || showInherited || x.value !== inherit)
239 && { label: _.capitalize(who2desc(x.value)), ...x })), // default label
208 - [inherit, parent, thisValue])
240 + [inherit, parent, thisValue])
241
242 const timeout = 500
243 const arrayMode = Array.isArray(thisValue)
@@ -221,7 +253,7 @@ function WhoField({ value, onChange, parent, inherit, accounts, helperText, show
253 }),
254 h(Collapse, { in: arrayMode, timeout },
255 arrayMode && h(MultiSelectField as Field<string[]>, {
224 - label: accounts?.length ? "Choose accounts for " + rest.label : "You didn't create any account yet",
256 + label: accounts?.length ? "Accounts for " + rest.label : "You didn't create any account yet",
257 value: thisValue,
258 onChange,
259 options: accounts?.map(a => ({ value: a.username, label: a.username })) || [],