fix: account rename caused inconsistencies in refs
Massimo Melina committed
Feb 11, 2022 at 12:38 UTC
53af72395be458a55eff4dd2e7d65a0316d61707
2 files changed
+33
-18
src/misc.ts
+8
@@ -5,6 +5,7 @@ import { watch } from 'fs'
5
import _ from 'lodash'
6
7
export type Callback<IN=void, OUT=void> = (x:IN) => OUT
8
+export type Dict<T = any> = Record<string, T>
9
10
export function enforceFinal(sub:string, s:string) {
11
return s.endsWith(sub) ? s : s+sub
@@ -186,3 +187,10 @@ export function dirTraversal(s?: string) {
187
export function isWindowsDrive(s?: string) {
188
return s && /^[a-zA-Z]:$/.test(s)
189
}
190
+
191
+export function objRenameKey(o: Dict | undefined, from: string, to: string) {
192
+ if (!o || !o.hasOwnProperty(from) || from === to) return
193
+ o[to] = o[from]
194
+ delete o[from]
195
+ return true
196
+}
src/perm.ts
+25
-18
@@ -1,7 +1,7 @@
1
import _ from 'lodash'
2
import yaml from 'yaml'
3
import { hashPassword } from './crypt'
4
-import { setHidden, wantArray } from './misc'
4
+import { objRenameKey, setHidden, wantArray } from './misc'
5
import { watchLoad } from './watchLoad'
6
import Koa from 'koa'
7
import { CFG_ALLOW_CLEAR_TEXT_LOGIN, getConfig, subscribeConfig } from './config'
@@ -106,37 +106,44 @@ async function applyAccounts(newAccounts: Accounts) {
106
// we should validate content here
107
accounts = newAccounts
108
await Promise.all(_.map(accounts, async (rec,k) => {
109
- const lc = k.toLocaleLowerCase()
109
+ const norm = normalizeUsername(k)
110
if (!rec) // an empty object in yaml is stored as null
111
- rec = accounts[lc] = { username: lc, srp:'' }
112
- else if (lc !== k) {
113
- accounts[lc] = rec
114
- delete accounts[k]
115
- k = lc
116
- }
117
- setHidden(rec, { username: k })
111
+ rec = accounts[norm] = { username: norm, srp:'' }
112
+ else
113
+ objRenameKey(accounts, k, norm)
114
+ setHidden(rec, { username: norm })
115
await updateAccount(rec)
116
}))
117
}
118
119
+function normalizeUsername(username: string) {
120
+ return username.toLocaleLowerCase()
121
+}
122
+
123
export function renameAccount(from: string, to: string) {
124
+ from = normalizeUsername(from)
125
+ to = normalizeUsername(to)
126
if (!to || !accounts[from] || accounts[to])
127
return false
128
if (to === from)
129
return true
127
- accounts[to] = accounts[from]
128
- delete accounts[from]
129
- setHidden(accounts[to], { username: to })
130
- recur(vfs.root)
130
+ objRenameKey(accounts, from, to)
131
+ updateReferences()
132
saveAccountsAsap()
133
return true
134
134
- function recur(n: VfsNode) {
135
- const p = n.perm
136
- if (p?.[from]) {
137
- p[to] = p[from]
138
- delete p[from]
135
+ function updateReferences() {
136
+ setHidden(accounts[to], { username: to })
137
+ recur(vfs.root)
138
+ for (const a of Object.values(accounts)) {
139
+ const idx = a.belongs?.indexOf(from)
140
+ if (idx !== undefined && idx >= 0)
141
+ a.belongs![idx] = to
142
}
143
+ }
144
+
145
+ function recur(n: VfsNode) {
146
+ objRenameKey(n.perm, from, to)
147
if (n.children)
148
for (const c of n.children)
149
recur(c)