From 959134df02da754b43fa895f9e94f613b3d3db2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Fri, 28 May 2021 14:37:16 +0200 Subject: [PATCH] Better secrets support in add-on configuration (#9275) --- .../addon-view/config/hassio-addon-config.ts | 20 ++++++++++++++++++- src/components/ha-yaml-editor.ts | 11 +++++++--- src/data/hassio/addon.ts | 4 +++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/hassio/src/addon-view/config/hassio-addon-config.ts b/hassio/src/addon-view/config/hassio-addon-config.ts index 52c3d73930..273bca178b 100644 --- a/hassio/src/addon-view/config/hassio-addon-config.ts +++ b/hassio/src/addon-view/config/hassio-addon-config.ts @@ -3,6 +3,7 @@ import { ActionDetail } from "@material/mwc-list"; import "@material/mwc-list/mwc-list-item"; import { mdiDotsVertical } from "@mdi/js"; import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea"; +import { DEFAULT_SCHEMA, Type } from "js-yaml"; import { css, CSSResultGroup, @@ -11,7 +12,7 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, state, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../src/common/dom/fire_event"; import "../../../../src/components/buttons/ha-progress-button"; @@ -27,6 +28,7 @@ import { HassioAddonDetails, HassioAddonSetOptionParams, setHassioAddonOption, + validateHassioAddonOption, } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; import { Supervisor } from "../../../../src/data/supervisor/supervisor"; @@ -38,6 +40,13 @@ import { hassioStyle } from "../../resources/hassio-style"; const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"]; +const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([ + new Type("!secret", { + kind: "scalar", + construct: (data) => `!secret ${data}`, + }), +]); + @customElement("hassio-addon-config") class HassioAddonConfig extends LitElement { @property({ attribute: false }) public addon!: HassioAddonDetails; @@ -125,6 +134,7 @@ class HassioAddonConfig extends LitElement { >` : html` `} ${this._error ? html`
${this._error}
` : ""} ${!this._yamlMode || @@ -269,6 +279,14 @@ class HassioAddonConfig extends LitElement { this._error = undefined; try { + const validation = await validateHassioAddonOption( + this.hass, + this.addon.slug, + this._editor?.value + ); + if (!validation.valid) { + throw Error(validation.message); + } await setHassioAddonOption(this.hass, this.addon.slug, { options: this._yamlMode ? this._editor?.value : this._options, }); diff --git a/src/components/ha-yaml-editor.ts b/src/components/ha-yaml-editor.ts index 8d79034c3e..8ff961aa10 100644 --- a/src/components/ha-yaml-editor.ts +++ b/src/components/ha-yaml-editor.ts @@ -1,4 +1,4 @@ -import { dump, load } from "js-yaml"; +import { DEFAULT_SCHEMA, dump, load, Schema } from "js-yaml"; import { html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; @@ -20,6 +20,8 @@ const isEmpty = (obj: Record): boolean => { export class HaYamlEditor extends LitElement { @property() public value?: any; + @property({ attribute: false }) public yamlSchema: Schema = DEFAULT_SCHEMA; + @property() public defaultValue?: any; @property() public isValid = true; @@ -30,7 +32,10 @@ export class HaYamlEditor extends LitElement { public setValue(value): void { try { - this._yaml = value && !isEmpty(value) ? dump(value) : ""; + this._yaml = + value && !isEmpty(value) + ? dump(value, { schema: this.yamlSchema }) + : ""; } catch (err) { // eslint-disable-next-line no-console console.error(err, value); @@ -67,7 +72,7 @@ export class HaYamlEditor extends LitElement { if (this._yaml) { try { - parsed = load(this._yaml); + parsed = load(this._yaml, { schema: this.yamlSchema }); } catch (err) { // Invalid YAML isValid = false; diff --git a/src/data/hassio/addon.ts b/src/data/hassio/addon.ts index 902bd88816..c2e43ac046 100644 --- a/src/data/hassio/addon.ts +++ b/src/data/hassio/addon.ts @@ -212,13 +212,15 @@ export const setHassioAddonOption = async ( export const validateHassioAddonOption = async ( hass: HomeAssistant, - slug: string + slug: string, + data?: any ): Promise<{ message: string; valid: boolean }> => { if (atLeastVersion(hass.config.version, 2021, 2, 4)) { return hass.callWS({ type: "supervisor/api", endpoint: `/addons/${slug}/options/validate`, method: "post", + data, }); }