fix: (regression beta) admin/accounts: any new account would store unwanted property "directMembers"
Massimo Melina committed
Apr 15, 2025 at 14:59 UTC
7e5ebdb6f8bf42de1a4beec14a2abe7c1879be17
2 files changed
+15
-8
src/api.accounts.ts
+6
-1
@@ -9,6 +9,7 @@ import _ from 'lodash'
9
import { HTTP_BAD_REQUEST, HTTP_CONFLICT, HTTP_NOT_FOUND } from './const'
10
import { getCurrentUsername, invalidateSessionBefore } from './auth'
11
import { apiAssertTypes, objFromKeys, onlyTruthy, with_ } from './misc'
12
+import { pickProps } from './api.vfs'
13
14
function prepareAccount(ac: Account | undefined) {
15
return ac && {
@@ -32,6 +33,9 @@ function prepareAccount(ac: Account | undefined) {
33
}
34
}
35
36
+const ALLOWED_KEYS: (keyof Account)[] = ['admin', 'allow_net', 'belongs', 'days_to_live', 'disable_password_change',
37
+ 'disabled', 'expire', 'ignore_limits', 'notes', 'password', 'redirect', 'require_password_change', 'username']
38
+
39
export default {
40
41
get_usernames() {
@@ -56,7 +60,7 @@ export default {
60
const acc = getAccount(username)
61
if (!acc)
62
return new ApiError(HTTP_BAD_REQUEST)
59
- await updateAccount(acc, changes)
63
+ await updateAccount(acc, pickProps(changes, ALLOWED_KEYS))
64
if (changes.username && ctx.session?.username === username)
65
ctx.session!.username = changes.username
66
return _.pick(acc, 'username')
@@ -65,6 +69,7 @@ export default {
69
async add_account({ overwrite, username, ...rest }) {
70
apiAssertTypes({ string: { username } })
71
const existing = getAccount(username)
72
+ rest = pickProps(rest, ALLOWED_KEYS)
73
if (existing) {
74
if (!overwrite) return new ApiError(HTTP_CONFLICT)
75
await updateAccount(existing, rest)
src/api.vfs.ts
+9
-7
@@ -1,7 +1,9 @@
1
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3
-import { getNodeName, isSameFilenameAs, nodeIsDirectory, saveVfs, urlToNode, vfs, VfsNode, applyParentToChild,
4
- permsFromParent, nodeIsLink } from './vfs'
3
+import {
4
+ getNodeName, isSameFilenameAs, nodeIsDirectory, saveVfs, urlToNode, vfs, VfsNode, applyParentToChild,
5
+ permsFromParent, nodeIsLink, VfsNodeStored
6
+} from './vfs'
7
import _ from 'lodash'
8
import { mkdir, stat } from 'fs/promises'
9
import { ApiError, ApiHandlers } from './apiMiddleware'
@@ -25,7 +27,8 @@ async function urlToNodeOriginal(uri: string) {
27
return n?.isTemp ? n.original : n
28
}
29
28
-const ALLOWED_KEYS = ['name','source','masks','default','accept','rename','mime','url','target','comment','icon','order', ...PERM_KEYS]
30
+const ALLOWED_KEYS: (keyof VfsNodeStored)[] = ['name', 'source', 'masks', 'default', 'accept', 'rename', 'mime', 'url',
31
+ 'target', 'comment', 'icon', 'order', ...PERM_KEYS]
32
33
export interface LsEntry { n:string, s?:number, m?:string, c?:string, k?:'d' }
34
@@ -92,7 +95,6 @@ const apis: ApiHandlers = {
95
const n = await urlToNodeOriginal(uri)
96
if (!n)
97
return new ApiError(HTTP_NOT_FOUND, 'path not found')
95
- props = pickProps(props, ALLOWED_KEYS) // sanitize
98
if (props.name && props.name !== getNodeName(n)) {
99
if (!isValidFileName(props.name))
100
return new ApiError(HTTP_BAD_REQUEST, 'bad name')
@@ -102,7 +104,7 @@ const apis: ApiHandlers = {
104
}
105
if (props.masks && typeof props.masks !== 'object')
106
delete props.masks
105
- Object.assign(n, props)
107
+ Object.assign(n, pickProps(props, ALLOWED_KEYS))
108
simplifyName(n)
109
saveVfs()
110
return n
@@ -268,8 +270,8 @@ const apis: ApiHandlers = {
270
271
export default apis
272
271
-// pick only selected props, and consider null and empty string as undefined
272
-function pickProps(o: any, keys: string[]) {
273
+// pick only selected props, and consider null and empty string as undefined, as it's the default value and we don't want to store it
274
+export function pickProps(o: any, keys: string[]) {
275
const ret: any = {}
276
if (o && typeof o === 'object')
277
for (const k of keys)