From 48a09e5a99e80959ef494d7e4bbf0b5905c48dc8 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 11 Oct 2022 20:26:07 -0700 Subject: [PATCH] Refactor info widget sanitizing / privateOptions --- src/pages/api/widgets/glances.js | 2 +- src/utils/config/api-response.js | 28 +++++------ src/utils/config/config.js | 13 ----- src/utils/config/service-helpers.js | 23 +-------- src/utils/config/widget-helpers.js | 73 +++++++++++++++++++++++++++++ src/widgets/unifi/proxy.js | 3 +- 6 files changed, 89 insertions(+), 53 deletions(-) create mode 100644 src/utils/config/widget-helpers.js diff --git a/src/pages/api/widgets/glances.js b/src/pages/api/widgets/glances.js index f4b7c010e..5d4622b8d 100644 --- a/src/pages/api/widgets/glances.js +++ b/src/pages/api/widgets/glances.js @@ -1,6 +1,6 @@ import { httpProxy } from "utils/proxy/http"; import createLogger from "utils/logger"; -import { getPrivateWidgetOptions } from "utils/config/service-helpers"; +import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; const logger = createLogger("glances"); diff --git a/src/utils/config/api-response.js b/src/utils/config/api-response.js index 778877eb1..5cc1127e3 100644 --- a/src/utils/config/api-response.js +++ b/src/utils/config/api-response.js @@ -4,8 +4,9 @@ import path from "path"; import yaml from "js-yaml"; -import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; +import checkAndCopyConfig from "utils/config/config"; import { servicesFromConfig, servicesFromDocker, cleanServiceGroups } from "utils/config/service-helpers"; +import { cleanWidgetGroups, widgetsFromConfig } from "utils/config/widget-helpers"; export async function bookmarksResponse() { checkAndCopyConfig("bookmarks.yaml"); @@ -29,24 +30,17 @@ export async function bookmarksResponse() { } export async function widgetsResponse() { - checkAndCopyConfig("widgets.yaml"); + let configuredWidgets; - const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); - const fileContents = await fs.readFile(widgetsYaml, "utf8"); - const widgets = yaml.load(fileContents); - - if (!widgets) return []; - - // map easy to write YAML objects into easy to consume JS arrays - const widgetsArray = widgets.map((group, index) => ({ - type: Object.keys(group)[0], - options: { - index, - ...sanitizePrivateOptions(group[Object.keys(group)[0]]) - }, - })); + try { + configuredWidgets = cleanWidgetGroups(await widgetsFromConfig()); + } catch (e) { + console.error("Failed to load widgets, please check widgets.yaml for errors or remove example entries."); + if (e) console.error(e); + configuredWidgets = []; + } - return widgetsArray; + return configuredWidgets; } export async function servicesResponse() { diff --git a/src/utils/config/config.js b/src/utils/config/config.js index 1f6d13fcb..0003c589d 100644 --- a/src/utils/config/config.js +++ b/src/utils/config/config.js @@ -33,17 +33,4 @@ export function getSettings() { const settingsYaml = join(process.cwd(), "config", "settings.yaml"); const fileContents = readFileSync(settingsYaml, "utf8"); return yaml.load(fileContents); -} - -export function sanitizePrivateOptions(options, privateOnly = false) { - const privateOptions = ["url", "username", "password", "key"]; - const sanitizedOptions = {}; - Object.keys(options).forEach((key) => { - if (!privateOnly && !privateOptions.includes(key)) { - sanitizedOptions[key] = options[key]; - } else if (privateOnly && privateOptions.includes(key)) { - sanitizedOptions[key] = options[key]; - } - }); - return sanitizedOptions; } \ No newline at end of file diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index ba58b991d..15740d22b 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -5,7 +5,7 @@ import yaml from "js-yaml"; import Docker from "dockerode"; import * as shvl from "shvl"; -import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; +import checkAndCopyConfig from "utils/config/config"; import getDockerArguments from "utils/config/docker"; export async function servicesFromConfig() { @@ -165,23 +165,4 @@ export default async function getServiceWidget(group, service) { } return false; -} - -export async function getPrivateWidgetOptions(type, index) { - checkAndCopyConfig("widgets.yaml"); - - const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); - const fileContents = await fs.readFile(widgetsYaml, "utf8"); - const widgets = yaml.load(fileContents); - - if (!widgets) return []; - - const privateOptions = widgets.map((group, widgetIndex) => ({ - type: Object.keys(group)[0], - index: widgetIndex, - options: sanitizePrivateOptions(group[Object.keys(group)[0]], true), - })); - - return (type !== undefined && index !== undefined) ? privateOptions.find(o => o.type === type && o.index === parseInt(index, 10))?.options : privateOptions; -} - \ No newline at end of file +} \ No newline at end of file diff --git a/src/utils/config/widget-helpers.js b/src/utils/config/widget-helpers.js new file mode 100644 index 000000000..c9bdd0fbb --- /dev/null +++ b/src/utils/config/widget-helpers.js @@ -0,0 +1,73 @@ +import { promises as fs } from "fs"; +import path from "path"; + +import yaml from "js-yaml"; + +import checkAndCopyConfig from "utils/config/config"; + +export async function widgetsFromConfig() { + checkAndCopyConfig("widgets.yaml"); + + const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); + const fileContents = await fs.readFile(widgetsYaml, "utf8"); + const widgets = yaml.load(fileContents); + + if (!widgets) return []; + + // map easy to write YAML objects into easy to consume JS arrays + const widgetsArray = widgets.map((group, index) => ({ + type: Object.keys(group)[0], + options: { + index, + ...group[Object.keys(group)[0]] + }, + })); + return widgetsArray; +} + +export async function cleanWidgetGroups(widgets) { + return widgets.map((widget, index) => { + const sanitizedOptions = widget.options; + const optionKeys = Object.keys(sanitizedOptions); + ["url", "username", "password", "key"].forEach((pO) => { + if (optionKeys.includes(pO)) { + delete sanitizedOptions[pO]; + } + }); + + return { + type: widget.type, + options: { + index, + ...sanitizedOptions + }, + } + }); +} + +export async function getPrivateWidgetOptions(type, widgetIndex) { + const widgets = await widgetsFromConfig(); + + const privateOptions = widgets.map((widget) => { + const { + index, + url, + username, + password, + key + } = widget.options; + + return { + type: widget.type, + options: { + index, + url, + username, + password, + key + }, + } + }); + + return (type !== undefined && widgetIndex !== undefined) ? privateOptions.find(o => o.type === type && o.options.index === parseInt(widgetIndex, 10))?.options : privateOptions; +} \ No newline at end of file diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js index 890c2c73c..dc1c437b9 100644 --- a/src/widgets/unifi/proxy.js +++ b/src/widgets/unifi/proxy.js @@ -3,7 +3,8 @@ import cache from "memory-cache"; import { formatApiCall } from "utils/proxy/api-helpers"; import { httpProxy } from "utils/proxy/http"; import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; -import getServiceWidget, { getPrivateWidgetOptions } from "utils/config/service-helpers"; +import getServiceWidget from "utils/config/service-helpers"; +import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; import createLogger from "utils/logger"; import widgets from "widgets/widgets";