diff --git a/package.json b/package.json index 59c321dc97..583d05fc24 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "fuse.js": "7.0.0", "google-timezones-json": "1.2.0", "hls.js": "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch", - "home-assistant-js-websocket": "9.2.1", + "home-assistant-js-websocket": "9.3.0", "idb-keyval": "6.2.1", "intl-messageformat": "10.5.11", "js-yaml": "4.1.0", diff --git a/src/data/cloud.ts b/src/data/cloud.ts index 5db22590c4..e3d62b513b 100644 --- a/src/data/cloud.ts +++ b/src/data/cloud.ts @@ -1,6 +1,8 @@ import { EntityFilter } from "../common/entity/entity_filter"; import { HomeAssistant } from "../types"; +type StrictConnectionMode = "disabled" | "guard_page" | "drop_connection"; + interface CloudStatusNotLoggedIn { logged_in: false; cloud: "disconnected" | "connecting" | "connected"; @@ -19,6 +21,7 @@ export interface CloudPreferences { alexa_enabled: boolean; remote_enabled: boolean; remote_allow_remote_enable: boolean; + strict_connection: StrictConnectionMode; google_secure_devices_pin: string | undefined; cloudhooks: { [webhookId: string]: CloudWebhook }; alexa_report_state: boolean; @@ -141,6 +144,7 @@ export const updateCloudPref = ( google_secure_devices_pin?: CloudPreferences["google_secure_devices_pin"]; tts_default_voice?: CloudPreferences["tts_default_voice"]; remote_allow_remote_enable?: CloudPreferences["remote_allow_remote_enable"]; + strict_connection?: CloudPreferences["strict_connection"]; } ) => hass.callWS({ diff --git a/src/panels/config/cloud/account/cloud-remote-pref.ts b/src/panels/config/cloud/account/cloud-remote-pref.ts index cd9d509f81..508ac04f22 100644 --- a/src/panels/config/cloud/account/cloud-remote-pref.ts +++ b/src/panels/config/cloud/account/cloud-remote-pref.ts @@ -21,6 +21,7 @@ import { import type { HomeAssistant } from "../../../../types"; import { showToast } from "../../../../util/toast"; import { showCloudCertificateDialog } from "../dialog-cloud-certificate/show-dialog-cloud-certificate"; +import { showAlertDialog } from "../../../lovelace/custom-card-helpers"; @customElement("cloud-remote-pref") export class CloudRemotePref extends LitElement { @@ -33,7 +34,7 @@ export class CloudRemotePref extends LitElement { return nothing; } - const { remote_enabled, remote_allow_remote_enable } = + const { remote_enabled, remote_allow_remote_enable, strict_connection } = this.cloudStatus.prefs; const { @@ -153,6 +154,61 @@ export class CloudRemotePref extends LitElement { @change=${this._toggleAllowRemoteEnabledChanged} > + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_secondary" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.disabled" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.guard_page" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.drop_connection" + )} + + + + ${strict_connection !== "disabled" + ? html` + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link_secondary" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_create_link" + )} + ` + : nothing} ${this.hass.localize( @@ -223,6 +279,18 @@ export class CloudRemotePref extends LitElement { } } + private async _setStrictConnectionMode(ev) { + const mode = ev.target.value; + try { + await updateCloudPref(this.hass, { + strict_connection: mode, + }); + fireEvent(this, "ha-refresh-cloud-status"); + } catch (err: any) { + alert(err.message); + } + } + private async _copyURL(ev): Promise { const url = ev.currentTarget.url; await copyToClipboard(url); @@ -231,6 +299,40 @@ export class CloudRemotePref extends LitElement { }); } + private async _createLoginUrl() { + try { + const result = await this.hass.callService( + "cloud", + "create_temporary_strict_connection_url", + undefined, + undefined, + false, + true + ); + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link" + ), + text: html`${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link_created_message" + )} +
${result.response.url}
+ + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_copy_link" + )} + `, + }); + } catch (err: any) { + showAlertDialog(this, { text: err.message }); + } + } + static get styles(): CSSResultGroup { return css` .preparing { diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index b00cc43b28..e376529501 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -83,7 +83,8 @@ export const connectionMixin = >( service, serviceData, target, - notifyOnError = true + notifyOnError = true, + returnResponse = false ) => { if (__DEV__ || this.hass?.debugConnection) { // eslint-disable-next-line no-console @@ -101,7 +102,8 @@ export const connectionMixin = >( domain, service, serviceData ?? {}, - target + target, + returnResponse )) as ServiceCallResponse; } catch (err: any) { if ( diff --git a/src/translations/en.json b/src/translations/en.json index 18b28941f5..65b153f522 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3837,6 +3837,19 @@ "advanced_options": "Advanced options", "external_activation": "Allow external activation of remote control", "external_activation_secondary": "Allows you to turn on remote control from your Nabu Casa account page, even if you're outside your local network", + "strict_connection": "Restrict access to logged in users", + "strict_connection_secondary": "When a user is not logged in to your Home Assistant instance, they will not be able to access your instance remotely", + "strict_connection_mode": "Mode", + "strict_connection_modes": { + "disabled": "Disabled", + "guard_page": "Guard page", + "drop_connection": "Drop connection" + }, + "strict_connection_link": "Create login link", + "strict_connection_link_secondary": "You can create a link that will give temporary access to the login page.", + "strict_connection_create_link": "Create link", + "strict_connection_link_created_message": "Give this link to the person you want to give remote access to the login page of your Home Assistant instance.", + "strict_connection_copy_link": "Copy link", "certificate_info": "Certificate info", "certificate_expire": "Will be renewed at {date}", "more_info": "More info" diff --git a/src/types.ts b/src/types.ts index cb0e1931f9..c6b32be85d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -190,6 +190,7 @@ export interface Context { export interface ServiceCallResponse { context: Context; + response?: any; } export interface ServiceCallRequest { @@ -241,7 +242,8 @@ export interface HomeAssistant { service: ServiceCallRequest["service"], serviceData?: ServiceCallRequest["serviceData"], target?: ServiceCallRequest["target"], - notifyOnError?: boolean + notifyOnError?: boolean, + returnResponse?: boolean ): Promise; callApi( method: "GET" | "POST" | "PUT" | "DELETE", diff --git a/yarn.lock b/yarn.lock index 28ce42d768..b546d2a82f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9703,7 +9703,7 @@ __metadata: gulp-rename: "npm:2.0.0" gulp-zopfli-green: "npm:6.0.1" hls.js: "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch" - home-assistant-js-websocket: "npm:9.2.1" + home-assistant-js-websocket: "npm:9.3.0" html-minifier-terser: "npm:7.2.0" husky: "npm:9.0.11" idb-keyval: "npm:6.2.1" @@ -9777,10 +9777,10 @@ __metadata: languageName: unknown linkType: soft -"home-assistant-js-websocket@npm:9.2.1": - version: 9.2.1 - resolution: "home-assistant-js-websocket@npm:9.2.1" - checksum: 10/0508aacb4285c805953e620968ef7ca7fc9c3cdac18fa723dd9af128dff74ef2ec65fad4079353b80363cd1daec6d2798b46d2d40a7e4ff5c0807ac71080bf58 +"home-assistant-js-websocket@npm:9.3.0": + version: 9.3.0 + resolution: "home-assistant-js-websocket@npm:9.3.0" + checksum: 10/0afbe9f327c3f917187422db1b800383530846724ed8985bb076f6312a10580baeff706d45fba3d840348b76e261eab3f3f7c0b4597340d7575b9b09fc41b0c7 languageName: node linkType: hard