plugin.config.defaultValue

Massimo Melina committed May 1, 2022 at 00:10 UTC c323f81343ddbbe5b88ba6fb5b8d57ea546be35a
7 files changed +42 -21
admin/src/LogoutPage.ts
+1 -1
@@ -5,7 +5,7 @@ import { alertDialog } from "./dialog"
5 import { useSnapState } from './state'
6
7 export default function LogoutPage() {
8 - const [cfg] = useApiComp('get_config', { only: [] })
8 + const [cfg] = useApiComp('get_config', { only: [] }) // sort of noop
9 const { username } = useSnapState()
10 if (isValidElement(cfg))
11 return cfg
admin/src/PluginsPage.ts
+8 -14
@@ -1,5 +1,5 @@
1 -import { createElement as h, isValidElement } from "react"
2 -import { apiCall, useApiComp, useApiList } from './api'
1 +import { createElement as h } from "react"
2 +import { apiCall, useApiList } from './api'
3 import { DataGrid } from '@mui/x-data-grid'
4 import { Alert, Box } from '@mui/material'
5 import { IconBtn } from './misc'
@@ -8,16 +8,10 @@ import { alertDialog, formDialog } from './dialog'
8 import { BoolField, Field, MultiSelectField, NumberField, SelectField, StringField } from './Form'
9 import { ArrayField } from './ArrayField'
10
11 -const PLUGINS_CONFIG = 'plugins_config'
12 -
11 export default function PluginsPage() {
12 const { list, error, initializing } = useApiList('get_plugins')
15 - const [cfgRes, reloadCfg] = useApiComp('get_config', { only: [PLUGINS_CONFIG] })
16 - if (isValidElement(cfgRes))
17 - return cfgRes
13 if (error)
14 return h(Alert, { severity: 'error' }, error)
20 - const cfg = cfgRes[PLUGINS_CONFIG]
15 return h(DataGrid, {
16 rows: list,
17 loading: initializing,
@@ -61,15 +55,15 @@ export default function PluginsPage() {
55 icon: Settings,
56 title: "Configuration",
57 disabled: !config,
64 - onClick() {
65 - formDialog({
58 + async onClick() {
59 + const pl = await apiCall('get_plugin', { id })
60 + const values = await formDialog({
61 title: `${id} configuration`,
62 fields: [ h(Box, {}, row.description), ...makeFields(config) ],
68 - values: cfg?.[id],
69 - }).then(config => {
70 - if (config)
71 - apiCall('set_plugin', { id, config }).then(reloadCfg)
63 + values: pl.config,
64 })
65 + if (values)
66 + await apiCall('set_plugin', { id, config: values })
67 }
68 }),
69 )
plugins/vhosting/plugin.js
+2 -1
@@ -10,6 +10,7 @@ exports.config = {
10 host: { label: "Domain" },
11 root: { helperText: "Root path in VFS" },
12 },
13 + defaultValue: [],
14 height: 300,
15 }
16 }
@@ -23,7 +24,7 @@ exports.init = api => ({
24 return
25 }
26 const hosts = api.getConfig('hosts')
26 - if (!hosts) return
27 + if (!hosts?.length) return
28 for (const row of hosts)
29 if (ctx.host === row.host) {
30 toModify.path = row.root + toModify.path
server/src/adminApis.ts
+23 -3
@@ -7,7 +7,7 @@ import { API_VERSION, BUILD_TIMESTAMP, COMPATIBLE_API_VERSION, FORBIDDEN, HFS_ST
7 import vfsApis from './api.vfs'
8 import accountsApis from './api.accounts'
9 import { Connection, getConnections } from './connections'
10 -import { debounceAsync, isLocalHost, onOff, pendingPromise } from './misc'
10 +import { debounceAsync, isLocalHost, objSameKeys, onOff, pendingPromise, same } from './misc'
11 import _ from 'lodash'
12 import events from './events'
13 import { getFromAccount } from './perm'
@@ -18,7 +18,15 @@ import { writeFile } from 'fs/promises'
18 import { createReadStream } from 'fs'
19 import * as readline from 'readline'
20 import { loggers } from './log'
21 -import { mapPlugins, getAvailablePlugins, Plugin, AvailablePlugin, enablePlugins, pluginsConfig } from './plugins'
21 +import {
22 + mapPlugins,
23 + getAvailablePlugins,
24 + Plugin,
25 + AvailablePlugin,
26 + enablePlugins,
27 + pluginsConfig,
28 + getPluginConfigFields
29 +} from './plugins'
30 import { execFile } from 'child_process'
31 import { promisify } from 'util'
32 import assert from 'assert'
@@ -176,13 +184,25 @@ export const adminApis: ApiHandlers = {
184 enablePlugins.set( enabled ? [...a, id] : a.filter((x: string) => x !== id) )
185 }
186 if (config) {
179 - config = _.pickBy(config, v => v !== null)
187 + const fields = getPluginConfigFields(id)
188 + config = _.pickBy(config, (v, k) =>
189 + v !== null && !same(v, fields?.[k]?.defaultValue))
190 if (_.isEmpty(config))
191 config = undefined
192 pluginsConfig.set({ ...pluginsConfig.get(), [id]: config })
193 }
194 return {}
195 },
196 +
197 + async get_plugin({ id }) {
198 + return {
199 + enabled: enablePlugins.get().includes(id),
200 + config: {
201 + ...objSameKeys(getPluginConfigFields(id) ||{}, v => v?.defaultValue),
202 + ...pluginsConfig.get()[id]
203 + }
204 + }
205 + },
206 }
207
208 // offer an api for a generic dynamic list
server/src/config.ts
+2
@@ -110,6 +110,8 @@ export function setConfig(newCfg: Record<string,any>, save?: boolean) {
110 }
111
112 function setConfig1(k: string, newV: any, saveChanges=true) {
113 + if (_.isPlainObject(newV))
114 + newV = _.pickBy(newV, x => x !== undefined)
115 if (same(newV, configProps[k]?.defaultValue))
116 newV = undefined
117 if (started && same(newV, state[k])) return // no change
server/src/const.ts
+1 -1
@@ -12,7 +12,7 @@ export const VERSION = ''
12 export const SESSION_DURATION = 30*60_000
13 export const DAY = 86_400_000
14
15 -export const API_VERSION = 2
15 +export const API_VERSION = 3 // with 3 we introduced config.defaultValue
16 export const COMPATIBLE_API_VERSION = 1 // while changes in the api are not breaking, this number stays the same, otherwise is made equal to API_VERSION
17
18 export const SPECIAL_URI = '/~/'
server/src/plugins.ts
+5 -1
@@ -30,6 +30,10 @@ export function mapPlugins<T>(cb:(plugin:Readonly<Plugin>, pluginName:string)=>
30 }).filter(x => x !== undefined) as Exclude<T,undefined>[]
31 }
32
33 +export function getPluginConfigFields(id: string) {
34 + return plugins[id]?.getData().config
35 +}
36 +
37 export function pluginsMiddleware(): Koa.Middleware {
38 return async (ctx, next) => {
39 const after = []
@@ -190,7 +194,7 @@ async function rescan() {
194 getConnections,
195 events,
196 getConfig: (cfgKey: string) =>
193 - pluginsConfig.get()?.[id]?.[cfgKey]
197 + pluginsConfig.get()?.[id]?.[cfgKey] ?? data.config?.[cfgKey]?.defaultValue
198 })
199 Object.assign(data, res)
200 new Plugin(id, data, unwatch)