From 5dbd5c7395b3a12d75df7d5b8df968a9af25e323 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 10 Apr 2019 15:38:33 -0700 Subject: [PATCH 1/9] Fix hassio unavailable dashboard & update card --- hassio/src/components/hassio-card-content.ts | 6 ++++-- hassio/src/dashboard/hassio-hass-update.js | 21 ++++---------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/hassio/src/components/hassio-card-content.ts b/hassio/src/components/hassio-card-content.ts index d3ebefab48..3e9de6c253 100644 --- a/hassio/src/components/hassio-card-content.ts +++ b/hassio/src/components/hassio-card-content.ts @@ -17,7 +17,7 @@ class HassioCardContent extends LitElement { @property() public hass!: HomeAssistant; @property() public title!: string; @property() public description?: string; - @property({ type: Boolean }) public available: boolean = true; + @property({ type: Boolean }) public available?: boolean; @property() public datetime?: string; @property() public iconTitle?: string; @property() public iconClass?: string; @@ -33,7 +33,9 @@ class HassioCardContent extends LitElement {
${this.title}
- ${this.description} ${this.available ? undefined : " (Not available"} + ${this.description} + ${/* treat as available when undefined */ + this.available === false ? " (Not available)" : ""} ${this.datetime ? html`
-
Update available! 🎉
- +
- + Home Assistant [[hassInfo.last_version]] is available and you + are currently running Home Assistant [[hassInfo.version]]. -

- Read the release notes -

Update Release notes From bbae3291e1187e764088bdbbc28e95d3e20382d1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 11 Apr 2019 11:42:52 -0700 Subject: [PATCH 2/9] Support ingress custom panels (#3085) * Support ingress custom panels * Fix types * Add disabled placeholder to network card --- hassio/src/addon-view/hassio-addon-network.js | 1 + hassio/src/hassio-main.ts | 31 +++++++++++++++++++ src/components/ha-sidebar.ts | 6 ++-- src/data/hassio.ts | 9 +++++- src/data/panel_custom.ts | 6 ++++ src/entrypoints/custom-panel.ts | 7 ++--- src/panels/custom/ha-panel-custom.ts | 10 +++--- src/types.ts | 16 +++------- 8 files changed, 62 insertions(+), 24 deletions(-) diff --git a/hassio/src/addon-view/hassio-addon-network.js b/hassio/src/addon-view/hassio-addon-network.js index b516c5e576..3c5b768188 100644 --- a/hassio/src/addon-view/hassio-addon-network.js +++ b/hassio/src/addon-view/hassio-addon-network.js @@ -44,6 +44,7 @@ class HassioAddonNetwork extends EventsMixin(PolymerElement) { [[item.container]] diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts index cc4123630c..fb0766c77e 100644 --- a/hassio/src/hassio-main.ts +++ b/hassio/src/hassio-main.ts @@ -17,6 +17,9 @@ import { HassioSupervisorInfo, HassioHostInfo, HassioHomeAssistantInfo, + fetchHassioAddonInfo, + createHassioSession, + HassioPanelInfo, } from "../../src/data/hassio"; import { makeDialogManager } from "../../src/dialogs/make-dialog-manager"; import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin"; @@ -32,6 +35,7 @@ customElements.get("paper-icon-button").prototype._keyBindings = {}; @customElement("hassio-main") class HassioMain extends ProvideHassLitMixin(HassRouterPage) { @property() public hass!: HomeAssistant; + @property() public panel!: HassioPanelInfo; protected routerOptions: RouterOptions = { // Hass.io has a page with tabs, so we route all non-matching routes to it. @@ -117,6 +121,11 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { } private async _fetchData() { + if (this.panel.config && this.panel.config.ingress) { + await this._redirectIngress(this.panel.config.ingress); + return; + } + const [supervisorInfo, hostInfo, hassInfo] = await Promise.all([ fetchHassioSupervisorInfo(this.hass), fetchHassioHostInfo(this.hass), @@ -127,6 +136,28 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) { this._hassInfo = hassInfo; } + private async _redirectIngress(addonSlug: string) { + try { + const [addon] = await Promise.all([ + fetchHassioAddonInfo(this.hass, addonSlug).catch(() => { + throw new Error("Failed to fetch add-on info"); + }), + createHassioSession(this.hass).catch(() => { + throw new Error("Failed to create an ingress session"); + }), + ]); + if (!addon.ingress_url) { + throw new Error("Add-on does not support Ingress"); + } + location.assign(addon.ingress_url); + // await a promise that doesn't resolve, so we show the loading screen + // while we load the next page. + await new Promise(() => undefined); + } catch (err) { + alert(`Unable to open ingress connection `); + } + } + private _apiCalled(ev) { if (!ev.detail.success) { return; diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 98d0a5e097..50428786ad 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -15,7 +15,7 @@ import "./ha-icon"; import "../components/user/ha-user-badge"; import isComponentLoaded from "../common/config/is_component_loaded"; -import { HomeAssistant, Panel } from "../types"; +import { HomeAssistant, PanelInfo } from "../types"; import { fireEvent } from "../common/dom/fire_event"; import { DEFAULT_PANEL } from "../common/const"; @@ -32,7 +32,9 @@ const computePanels = (hass: HomeAssistant) => { logbook: 2, history: 3, }; - const result: Panel[] = Object.values(panels).filter((panel) => panel.title); + const result: PanelInfo[] = Object.values(panels).filter( + (panel) => panel.title + ); result.sort((a, b) => { const aBuiltIn = a.component_name in sortValue; diff --git a/src/data/hassio.ts b/src/data/hassio.ts index ab3b840df3..5790a90e40 100644 --- a/src/data/hassio.ts +++ b/src/data/hassio.ts @@ -1,4 +1,11 @@ -import { HomeAssistant } from "../types"; +import { HomeAssistant, PanelInfo } from "../types"; + +export type HassioPanelInfo = PanelInfo< + | undefined + | { + ingress?: string; + } +>; interface HassioResponse { data: T; diff --git a/src/data/panel_custom.ts b/src/data/panel_custom.ts index 7f8ad4a29e..ce09a24408 100644 --- a/src/data/panel_custom.ts +++ b/src/data/panel_custom.ts @@ -1,3 +1,5 @@ +import { PanelInfo } from "../types"; + export interface CustomPanelConfig { name: string; embed_iframe: boolean; @@ -6,3 +8,7 @@ export interface CustomPanelConfig { module_url?: string; html_url?: string; } + +export type CustomPanelInfo = PanelInfo< + T & { _panel_custom: CustomPanelConfig } +>; diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts index 7f0bc53dd0..46e3eb2527 100644 --- a/src/entrypoints/custom-panel.ts +++ b/src/entrypoints/custom-panel.ts @@ -4,8 +4,7 @@ import { createCustomPanelElement } from "../util/custom-panel/create-custom-pan import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties"; import { fireEvent } from "../common/dom/fire_event"; import { PolymerElement } from "@polymer/polymer"; -import { Panel } from "../types"; -import { CustomPanelConfig } from "../data/panel_custom"; +import { CustomPanelInfo } from "../data/panel_custom"; declare global { interface Window { @@ -39,12 +38,12 @@ function setProperties(properties) { setCustomPanelProperties(panelEl, properties); } -function initialize(panel: Panel, properties: {}) { +function initialize(panel: CustomPanelInfo, properties: {}) { const style = document.createElement("style"); style.innerHTML = "body{margin:0}"; document.head.appendChild(style); - const config = panel.config!._panel_custom as CustomPanelConfig; + const config = panel.config._panel_custom; let start: Promise = Promise.resolve(); if (!webComponentsSupported) { diff --git a/src/panels/custom/ha-panel-custom.ts b/src/panels/custom/ha-panel-custom.ts index b7de1b6b30..563ccb6a18 100644 --- a/src/panels/custom/ha-panel-custom.ts +++ b/src/panels/custom/ha-panel-custom.ts @@ -2,8 +2,8 @@ import { property, PropertyValues, UpdatingElement } from "lit-element"; import { loadCustomPanel } from "../../util/custom-panel/load-custom-panel"; import { createCustomPanelElement } from "../../util/custom-panel/create-custom-panel-element"; import { setCustomPanelProperties } from "../../util/custom-panel/set-custom-panel-properties"; -import { HomeAssistant, Route, Panel } from "../../types"; -import { CustomPanelConfig } from "../../data/panel_custom"; +import { HomeAssistant, Route } from "../../types"; +import { CustomPanelInfo } from "../../data/panel_custom"; import { navigate } from "../../common/navigate"; declare global { @@ -16,7 +16,7 @@ export class HaPanelCustom extends UpdatingElement { @property() public hass!: HomeAssistant; @property() public narrow!: boolean; @property() public route!: Route; - @property() public panel!: Panel; + @property() public panel!: CustomPanelInfo; private _setProperties?: (props: {}) => void | undefined; // Since navigate fires events on `window`, we need to expose this as a function @@ -66,8 +66,8 @@ export class HaPanelCustom extends UpdatingElement { } } - private _createPanel(panel: Panel) { - const config = panel.config!._panel_custom as CustomPanelConfig; + private _createPanel(panel: CustomPanelInfo) { + const config = panel.config!._panel_custom; const tempA = document.createElement("a"); tempA.href = config.html_url || config.js_url || config.module_url || ""; diff --git a/src/types.ts b/src/types.ts index 33665a4594..d5ffd71605 100644 --- a/src/types.ts +++ b/src/types.ts @@ -78,16 +78,16 @@ export interface Themes { themes: { [key: string]: Theme }; } -export interface Panel { +export interface PanelInfo { component_name: string; - config: { [key: string]: any } | null; + config: T; icon: string | null; title: string | null; url_path: string; } export interface Panels { - [name: string]: Panel; + [name: string]: PanelInfo; } export interface Translation { @@ -212,14 +212,6 @@ export type CameraEntity = HassEntityBase & { }; }; -export interface PanelInfo { - component_name: string; - icon?: string; - title?: string; - url_path: string; - config: T; -} - export interface Route { prefix: string; path: string; @@ -229,7 +221,7 @@ export interface PanelElement extends HTMLElement { hass?: HomeAssistant; narrow?: boolean; route?: Route | null; - panel?: Panel; + panel?: PanelInfo; } export interface LocalizeMixin { From 5c8e5d35391d17b83e9b59ca9631c928ed388784 Mon Sep 17 00:00:00 2001 From: ktnrg45 <38207570+ktnrg45@users.noreply.github.com> Date: Sat, 13 Apr 2019 20:35:24 -0700 Subject: [PATCH 3/9] Added padding definition for type game (#3059) --- src/cards/ha-media_player-card.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cards/ha-media_player-card.js b/src/cards/ha-media_player-card.js index d54176a832..e24f08cb68 100644 --- a/src/cards/ha-media_player-card.js +++ b/src/cards/ha-media_player-card.js @@ -57,6 +57,10 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) { padding-top: 100%; } + .banner.content-type-game:before { + padding-top: 100%; + } + .banner.no-cover:before { padding-top: 88px; } @@ -310,6 +314,8 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) { cls += " no-cover"; } else if (playerObj.stateObj.attributes.media_content_type === "music") { cls += " content-type-music"; + } else if (playerObj.stateObj.attributes.media_content_type === "game") { + cls += " content-type-game"; } return cls; } From 6ed2d288e6f1c2a80927b8ef6e29256fb533160e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 15 Apr 2019 10:53:53 -0700 Subject: [PATCH 4/9] addon -> add-on (#3094) --- hassio/src/addon-view/hassio-addon-info.js | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/hassio/src/addon-view/hassio-addon-info.js b/hassio/src/addon-view/hassio-addon-info.js index 10d8de3ad5..25f283a693 100644 --- a/hassio/src/addon-view/hassio-addon-info.js +++ b/hassio/src/addon-view/hassio-addon-info.js @@ -17,49 +17,49 @@ import "../components/hassio-card-content"; const PERMIS_DESC = { rating: { - title: "Addon Security Rating", + title: "Add-on Security Rating", description: - "Hass.io provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an addon requires on your system, the lower the score, thus raising the possible security risks.\n\nA score is on a scale from 1 to 6. Where 1 is the lowest score (considered the most insecure and highest risk) and a score of 6 is the highest score (considered the most secure and lowest risk).", + "Hass.io provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks.\n\nA score is on a scale from 1 to 6. Where 1 is the lowest score (considered the most insecure and highest risk) and a score of 6 is the highest score (considered the most secure and lowest risk).", }, host_network: { title: "Host Network", description: - "Add-ons usually run in their own isolated network layer, which prevents them from accessing the network of the host operating system. In some cases, this network isolation can limit add-ons in providing their services and therefore, the isolation can be lifted by the add-on author, giving the addon full access to the network capabilities of the host machine. This gives the addon more networking capabilities but lowers the security, hence, the security rating of the add-on will be lowered when this option is used by the addon.", + "Add-ons usually run in their own isolated network layer, which prevents them from accessing the network of the host operating system. In some cases, this network isolation can limit add-ons in providing their services and therefore, the isolation can be lifted by the add-on author, giving the add-on full access to the network capabilities of the host machine. This gives the add-on more networking capabilities but lowers the security, hence, the security rating of the add-on will be lowered when this option is used by the add-on.", }, homeassistant_api: { title: "Home Assistant API Access", description: - "This add-on is allowed to access your running Home Assistant instance directly via the Home Assistant API. This mode handles authentication for the addon as well, which enables an addon to interact with Home Assistant without the need for additional authentication tokens.", + "This add-on is allowed to access your running Home Assistant instance directly via the Home Assistant API. This mode handles authentication for the add-on as well, which enables an add-on to interact with Home Assistant without the need for additional authentication tokens.", }, full_access: { title: "Full Hardware Access", description: - "This addon is given full access to the hardware of your system, by request of the addon author. Access is comparable to the privileged mode in Docker. Since this opens up possible security risks, this feature impacts the addon security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the addon manually. Only disable the protection mode if you know, need AND trust the source of this addon.", + "This add-on is given full access to the hardware of your system, by request of the add-on author. Access is comparable to the privileged mode in Docker. Since this opens up possible security risks, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", }, hassio_api: { title: "Hass.io API Access", description: - "The addon was given access to the Hass.io API, by request of the addon author. By default, the addon can access general version information of your system. When the addon requests 'manager' or 'admin' level access to the API, it will gain access to control multiple parts of your Hass.io system. This permission is indicated by this badge and will impact the security score of the addon negatively.", + "The add-on was given access to the Hass.io API, by request of the add-on author. By default, the add-on can access general version information of your system. When the add-on requests 'manager' or 'admin' level access to the API, it will gain access to control multiple parts of your Hass.io system. This permission is indicated by this badge and will impact the security score of the addon negatively.", }, docker_api: { title: "Full Docker Access", description: - "The addon author has requested the addon to have management access to the Docker instance running on your system. This mode gives the addon full access and control to your entire Hass.io system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the addon security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the addon manually. Only disable the protection mode if you know, need AND trust the source of this addon.", + "The add-on author has requested the add-on to have management access to the Docker instance running on your system. This mode gives the add-on full access and control to your entire Hass.io system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", }, host_pid: { title: "Host Processes Namespace", description: - "Usually, the processes the addon runs, are isolated from all other system processes. The addon author has requested the addon to have access to the system processes running on the host system instance, and allow the addon to spawn processes on the host system as well. This mode gives the addon full access and control to your entire Hass.io system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the addon security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the addon manually. Only disable the protection mode if you know, need AND trust the source of this addon.", + "Usually, the processes the add-on runs, are isolated from all other system processes. The add-on author has requested the add-on to have access to the system processes running on the host system instance, and allow the add-on to spawn processes on the host system as well. This mode gives the add-on full access and control to your entire Hass.io system, which adds security risks, and could damage your system when misused. Therefore, this feature impacts the add-on security score negatively.\n\nThis level of access is not granted automatically and needs to be confirmed by you. To do this, you need to disable the protection mode on the add-on manually. Only disable the protection mode if you know, need AND trust the source of this add-on.", }, apparmor: { title: "AppArmor", description: - "AppArmor ('Application Armor') is a Linux kernel security module that restricts addons capabilities like network access, raw socket access, and permission to read, write, or execute specific files.\n\nAddon authors can provide their security profiles, optimized for the addon, or request it to be disabled. If AppArmor is disabled, it will raise security risks and therefore, has a negative impact on the security score of the addon.", + "AppArmor ('Application Armor') is a Linux kernel security module that restricts add-ons capabilities like network access, raw socket access, and permission to read, write, or execute specific files.\n\nAdd-on authors can provide their security profiles, optimized for the add-on, or request it to be disabled. If AppArmor is disabled, it will raise security risks and therefore, has a negative impact on the security score of the add-on.", }, auth_api: { title: "Home Assistant Authentication", description: - "An addon can authenticate users against Home Assistant, allowing add-ons to give users the possibility to log into applications running inside add-ons, using their Home Assistant username/password. This badge indicates if the add-on author requests this capability.", + "An add-on can authenticate users against Home Assistant, allowing add-ons to give users the possibility to log into applications running inside add-ons, using their Home Assistant username/password. This badge indicates if the add-on author requests this capability.", }, ingress: { title: "Ingress", @@ -229,7 +229,7 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
-

Addon Security Rating

+

Add-on Security Rating

- Hass.io provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an addon requires on your system, the lower the score, thus raising the possible security risks. + Hass.io provides a security rating to each of the add-ons, which indicates the risks involved when using this add-on. The more access an add-on requires on your system, the lower the score, thus raising the possible security risks.