merge accounts in config

Massimo Melina committed Apr 3, 2022 at 21:00 UTC 99b4ffae575575bfb9c76f5799452bb60e5d62c0
4 files changed +15 -33
admin/src/ConfigPage.ts
-1
@@ -69,7 +69,6 @@ export default function ConfigPage() {
69 { k: 'log_rotation', comp: SelectField, options: [{ value:'', label:"disabled" }, 'daily', 'weekly', 'monthly' ],
70 helperText: "To avoid an endlessly-growing single log file, you can opt for rotation"
71 },
72 - { k: 'accounts', label: "Accounts file" },
72 { k: 'open_browser_at_start', comp: BoolField },
73 { k: 'localhost_admin', comp: BoolField, label: "Admin access for localhost connections", helperText: "To access Admin without entering credentials" },
74 { k: 'proxies', comp: NumberField, min: 0, max: 9, sm: 6, lg: 6, label: "How many proxies between this server and users?",
server/src/config.ts
+1 -1
@@ -118,7 +118,7 @@ export function setConfig(newCfg: Record<string,any>, save?: boolean) {
118 }
119
120 export const saveConfigAsap = debounceAsync(async () => {
121 - let txt = yaml.stringify(state)
121 + let txt = yaml.stringify(state, { lineWidth:1000 })
122 if (txt.trim() === '{}') // most users wouldn't understand
123 if (await promisify(exists)(path)) // if a file exists then empty it, else don't bother creating it
124 txt = ''
server/src/perm.ts
+14 -30
@@ -1,16 +1,14 @@
1 // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 import _ from 'lodash'
4 -import yaml from 'yaml'
4 import { hashPassword } from './crypt'
5 import { objRenameKey, setHidden, wantArray } from './misc'
7 -import { watchLoad } from './watchLoad'
6 import Koa from 'koa'
9 -import { CFG_ALLOW_CLEAR_TEXT_LOGIN, getConfig, subscribeConfig } from './config'
7 +import { CFG_ALLOW_CLEAR_TEXT_LOGIN, getConfig, saveConfigAsap, setConfig, subscribeConfig } from './config'
8 import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
9 import events from './events'
12 -
13 -let path = ''
10 +import { watchLoad } from './watchLoad'
11 +import { unlink } from 'fs'
12
13 export interface Account {
14 username: string, // we'll have username in it, so we don't need to pass it separately
@@ -83,42 +81,28 @@ export async function updateAccount(account: Account, changer?:Changer) {
81 saveAccountsAsap()
82 }
83
86 -let saving = false
87 -let watchResult: ReturnType<typeof watchLoad>
88 -const saveAccountsAsap = _.debounce(() => {
89 - saving = true
90 - watchResult.save(path, yaml.stringify({ accounts }, { lineWidth:1000 })) // we don't want big numbers to be folded
91 - .catch(err => console.error('Failed at saving accounts file, please ensure it is writable.', String(err)))
92 - .finally(()=> saving = false)
93 -}, 200) // group burst of requests
94 -
95 -subscribeConfig({ k:'accounts', defaultValue:'accounts.yaml' }, v => {
96 - watchResult?.unwatch()
97 - if (!v)
98 - return applyAccounts({})
99 - watchResult = watchLoad(path = v, async data => {
100 - if (saving) return
101 - const a = data?.accounts
102 - if (!a)
103 - return console.error('accounts file must contain "accounts" key')
104 - console.debug('#accounts', Object.keys(a).length)
105 - await applyAccounts(a)
106 - })
84 +const saveAccountsAsap = saveConfigAsap
85 +
86 +// legacy, remove after May 1
87 +watchLoad('accounts.yaml', accounts => {
88 + if (accounts)
89 + setConfig(accounts)
90 + unlink('accounts.yaml', () => console.log("accounts file merged"))
91 })
92
109 -async function applyAccounts(newAccounts: Accounts) {
93 +subscribeConfig<Accounts>({ k:'accounts', defaultValue: {} }, async v => {
94 // we should validate content here
111 - accounts = newAccounts
95 + accounts = v // keep local reference
96 await Promise.all(_.map(accounts, async (rec,k) => {
97 const norm = normalizeUsername(k)
98 if (!rec) // an empty object in yaml is stored as null
115 - rec = accounts[norm] = { username: norm, srp:'' }
99 + rec = accounts[norm] = { username: norm }
100 else
101 objRenameKey(accounts, k, norm)
102 setHidden(rec, { username: norm })
103 await updateAccount(rec)
104 }))
121 -}
105 +})
106
107 function normalizeUsername(username: string) {
108 return username.toLocaleLowerCase()
todo.md
-1
@@ -9,7 +9,6 @@
9 - admin/fs: make possible to bind source to home
10 - admin/monitor: show some info on what folder is browsing
11 - if specified config is a folder, check for file config.yaml inside
12 -- merge accounts in config
12 - frontend: ok button to inputDialogs
13 - admin: in a group, show linked accounts
14 - admin/config: use filepicker for https files