Skip to content

Commit 334a077

Browse files
authored
feat: global config validation (#451)
* fix: dont use local storage for text config items * fix: input toggles dont use localStorage * fix: input-toggle uses resetKey * fix: do not use broadcast channels to tell sw to update config * chore: fix build * feat: global config validation fixes #399 * fix: validate before storing config Also adds more error handling to config-db
1 parent c838307 commit 334a077

File tree

4 files changed

+52
-34
lines changed

4 files changed

+52
-34
lines changed

src/context/config-context.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { createContext, useCallback, useEffect, useState } from 'react'
22
import { defaultDnsJsonResolvers, defaultEnableGatewayProviders, defaultEnableRecursiveGateways, defaultEnableWebTransport, defaultEnableWss, defaultGateways, defaultRouters, getConfig, resetConfig, type ConfigDb } from '../lib/config-db.js'
33
import { isConfigPage } from '../lib/is-config-page.js'
44
import { getUiComponentLogger } from '../lib/logger.js'
5+
import type { ComponentLogger } from '@libp2p/logger'
56

67
const isLoadedInIframe = window.self !== window.top
78

@@ -10,7 +11,7 @@ export interface ConfigContextType extends ConfigDb {
1011
isConfigExpanded: boolean
1112
setConfigExpanded(value: boolean): void
1213
setConfig(key: ConfigKey, value: any): void
13-
resetConfig(): Promise<void>
14+
resetConfig(logger?: ComponentLogger): Promise<void>
1415
}
1516

1617
export const ConfigContext = createContext<ConfigContextType>({
@@ -97,8 +98,8 @@ export const ConfigProvider = ({ children }: { children: JSX.Element[] | JSX.Ele
9798
}
9899
}, [])
99100

100-
const resetConfigLocal = async (): Promise<void> => {
101-
await resetConfig()
101+
const resetConfigLocal: ConfigContextType['resetConfig'] = async (givenLogger): Promise<void> => {
102+
await resetConfig(givenLogger ?? logger)
102103
await loadConfig()
103104
}
104105

src/lib/config-db.ts

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,45 @@ export const defaultEnableGatewayProviders = true
2424

2525
const configDb = new GenericIDB<ConfigDb>('helia-sw', 'config')
2626

27-
export async function resetConfig (): Promise<void> {
28-
await configDb.open()
29-
await configDb.put('gateways', defaultGateways)
30-
await configDb.put('routers', defaultRouters)
31-
await configDb.put('dnsJsonResolvers', defaultDnsJsonResolvers)
32-
await configDb.put('enableWss', defaultEnableWss)
33-
await configDb.put('enableWebTransport', defaultEnableWebTransport)
34-
await configDb.put('enableRecursiveGateways', defaultEnableRecursiveGateways)
35-
await configDb.put('enableGatewayProviders', defaultEnableGatewayProviders)
36-
await configDb.put('debug', '')
37-
configDb.close()
27+
export async function resetConfig (logger: ComponentLogger): Promise<void> {
28+
const log = logger.forComponent('reset-config')
29+
try {
30+
await configDb.open()
31+
await configDb.put('gateways', defaultGateways)
32+
await configDb.put('routers', defaultRouters)
33+
await configDb.put('dnsJsonResolvers', defaultDnsJsonResolvers)
34+
await configDb.put('enableWss', defaultEnableWss)
35+
await configDb.put('enableWebTransport', defaultEnableWebTransport)
36+
await configDb.put('enableRecursiveGateways', defaultEnableRecursiveGateways)
37+
await configDb.put('enableGatewayProviders', defaultEnableGatewayProviders)
38+
await configDb.put('debug', '')
39+
} catch (err) {
40+
log('error resetting config in db', err)
41+
} finally {
42+
configDb.close()
43+
}
3844
}
3945

4046
export async function setConfig (config: ConfigDb, logger: ComponentLogger): Promise<void> {
4147
const log = logger.forComponent('set-config')
4248
enable(config.debug ?? '') // set debug level first.
43-
log('config-debug: setting config %O for domain %s', config, window.location.origin)
44-
45-
await configDb.open()
46-
await configDb.put('gateways', config.gateways)
47-
await configDb.put('routers', config.routers)
48-
await configDb.put('dnsJsonResolvers', config.dnsJsonResolvers)
49-
await configDb.put('enableRecursiveGateways', config.enableRecursiveGateways)
50-
await configDb.put('enableWss', config.enableWss)
51-
await configDb.put('enableWebTransport', config.enableWebTransport)
52-
await configDb.put('enableGatewayProviders', config.enableGatewayProviders)
53-
await configDb.put('debug', config.debug ?? '')
54-
configDb.close()
49+
await validateConfig(config, logger)
50+
try {
51+
log('config-debug: setting config %O for domain %s', config, window.location.origin)
52+
await configDb.open()
53+
await configDb.put('gateways', config.gateways)
54+
await configDb.put('routers', config.routers)
55+
await configDb.put('dnsJsonResolvers', config.dnsJsonResolvers)
56+
await configDb.put('enableRecursiveGateways', config.enableRecursiveGateways)
57+
await configDb.put('enableWss', config.enableWss)
58+
await configDb.put('enableWebTransport', config.enableWebTransport)
59+
await configDb.put('enableGatewayProviders', config.enableGatewayProviders)
60+
await configDb.put('debug', config.debug ?? '')
61+
} catch (err) {
62+
log('error setting config in db', err)
63+
} finally {
64+
configDb.close()
65+
}
5566
}
5667

5768
export async function getConfig (logger: ComponentLogger): Promise<ConfigDb> {
@@ -81,10 +92,11 @@ export async function getConfig (logger: ComponentLogger): Promise<ConfigDb> {
8192
enableGatewayProviders = await configDb.get('enableGatewayProviders') ?? defaultEnableGatewayProviders
8293

8394
debug = await configDb.get('debug') ?? ''
84-
configDb.close()
8595
enable(debug)
8696
} catch (err) {
8797
log('error loading config from db', err)
98+
} finally {
99+
configDb.close()
88100
}
89101

90102
if (gateways == null || gateways.length === 0) {
@@ -110,3 +122,12 @@ export async function getConfig (logger: ComponentLogger): Promise<ConfigDb> {
110122
debug
111123
}
112124
}
125+
126+
export async function validateConfig (config: ConfigDb, logger: ComponentLogger): Promise<void> {
127+
const log = logger.forComponent('validate-config')
128+
129+
if (!config.enableRecursiveGateways && !config.enableGatewayProviders && !config.enableWss && !config.enableWebTransport) {
130+
log.error('Config is invalid. At least one of the following must be enabled: recursive gateways, gateway providers, wss, or webtransport.')
131+
throw new Error('Config is invalid. At least one of the following must be enabled: recursive gateways, gateway providers, wss, or webtransport.')
132+
}
133+
}

src/lib/get-verified-fetch.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ export async function getVerifiedFetch (config: ConfigDb, logger: ComponentLogge
2727
const log = logger.forComponent('get-verified-fetch')
2828
log(`config-debug: got config for sw location ${self.location.origin}`, JSON.stringify(config, null, 2))
2929

30-
if (!config.enableRecursiveGateways && !config.enableGatewayProviders && !config.enableWss && !config.enableWebTransport) {
31-
// crude validation
32-
throw new Error('Config is invalid. At least one of the following must be enabled: recursive gateways, gateway providers, wss, or webtransport.')
33-
}
34-
3530
// Start by adding the config routers as delegated routers
3631
const routers: Array<Partial<Routing>> = []
3732

src/pages/config.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ function ConfigPage (): React.JSX.Element | null {
110110

111111
const saveConfig = useCallback(async () => {
112112
try {
113+
const config = { gateways, routers, dnsJsonResolvers, debug, enableGatewayProviders, enableRecursiveGateways, enableWss, enableWebTransport }
113114
setIsSaving(true)
114-
await storeConfig({ gateways, routers, dnsJsonResolvers, debug, enableGatewayProviders, enableRecursiveGateways, enableWss, enableWebTransport }, uiComponentLogger)
115+
await storeConfig(config, uiComponentLogger)
115116
log.trace('config-page: sending RELOAD_CONFIG to service worker')
116117
// update the BASE_URL service worker
117118
await tellSwToReloadConfig()
@@ -132,7 +133,7 @@ function ConfigPage (): React.JSX.Element | null {
132133

133134
const doResetConfig = useCallback(async () => {
134135
// we need to clear out the localStorage items and make sure default values are set, and that all of our inputs are updated
135-
await resetConfig()
136+
await resetConfig(uiComponentLogger)
136137
// now reload all the inputs
137138
setResetKey((prev) => prev + 1)
138139
}, [])

0 commit comments

Comments
 (0)