mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Allow storing thread credentials in phone keychain (#20743)
* Allow storing thread credentials in phone keychain * Update dialog-thread-dataset.ts * use preferred of dataset if available
This commit is contained in:
parent
9264adb799
commit
bfa293ae3a
@ -129,6 +129,15 @@ interface EMOutgoingMessageAssistShow extends EMMessage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface EMOutgoingMessageThreadStoreInPlatformKeychain extends EMMessage {
|
||||||
|
type: "thread/store_in_platform_keychain";
|
||||||
|
payload: {
|
||||||
|
mac_extended_address: string;
|
||||||
|
border_agent_id: string | null;
|
||||||
|
active_operational_dataset: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
type EMOutgoingMessageWithoutAnswer =
|
type EMOutgoingMessageWithoutAnswer =
|
||||||
| EMMessageResultError
|
| EMMessageResultError
|
||||||
| EMMessageResultSuccess
|
| EMMessageResultSuccess
|
||||||
@ -146,7 +155,8 @@ type EMOutgoingMessageWithoutAnswer =
|
|||||||
| EMOutgoingMessageMatterCommission
|
| EMOutgoingMessageMatterCommission
|
||||||
| EMOutgoingMessageSidebarShow
|
| EMOutgoingMessageSidebarShow
|
||||||
| EMOutgoingMessageTagWrite
|
| EMOutgoingMessageTagWrite
|
||||||
| EMOutgoingMessageThemeUpdate;
|
| EMOutgoingMessageThemeUpdate
|
||||||
|
| EMOutgoingMessageThreadStoreInPlatformKeychain;
|
||||||
|
|
||||||
interface EMIncomingMessageRestart {
|
interface EMIncomingMessageRestart {
|
||||||
id: number;
|
id: number;
|
||||||
@ -239,6 +249,7 @@ export interface ExternalConfig {
|
|||||||
hasExoPlayer: boolean;
|
hasExoPlayer: boolean;
|
||||||
canCommissionMatter: boolean;
|
canCommissionMatter: boolean;
|
||||||
canImportThreadCredentials: boolean;
|
canImportThreadCredentials: boolean;
|
||||||
|
canTransferThreadCredentialsToKeychain: boolean;
|
||||||
hasAssist: boolean;
|
hasAssist: boolean;
|
||||||
hasBarCodeScanner: number;
|
hasBarCodeScanner: number;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
import { LitElement, html, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import { HassDialog } from "../../../../../dialogs/make-dialog-manager";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import { DialogThreadDatasetParams } from "./show-dialog-thread-dataset";
|
||||||
|
import { createCloseHeading } from "../../../../../components/ha-dialog";
|
||||||
|
|
||||||
|
@customElement("ha-dialog-thread-dataset")
|
||||||
|
class DialogThreadDataset extends LitElement implements HassDialog {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _params?: DialogThreadDatasetParams;
|
||||||
|
|
||||||
|
public async showDialog(
|
||||||
|
params: DialogThreadDatasetParams
|
||||||
|
): Promise<Promise<void>> {
|
||||||
|
this._params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this._params = undefined;
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this._params) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
const network = this._params.network;
|
||||||
|
const dataset = network.dataset!;
|
||||||
|
const otbrInfo = this._params.otbrInfo;
|
||||||
|
|
||||||
|
const hasOTBR =
|
||||||
|
otbrInfo &&
|
||||||
|
dataset.extended_pan_id &&
|
||||||
|
otbrInfo.active_dataset_tlvs?.includes(dataset.extended_pan_id);
|
||||||
|
|
||||||
|
const canImportKeychain =
|
||||||
|
hasOTBR &&
|
||||||
|
!this.hass.auth.external?.config.canTransferThreadCredentialsToKeychain &&
|
||||||
|
network.routers?.length;
|
||||||
|
|
||||||
|
return html`<ha-dialog
|
||||||
|
open
|
||||||
|
.hideActions=${!canImportKeychain}
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
.heading=${createCloseHeading(this.hass, network.name)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
Network name: ${dataset.network_name}<br />
|
||||||
|
Channel: ${dataset.channel}<br />
|
||||||
|
Dataset id: ${dataset.dataset_id}<br />
|
||||||
|
Pan id: ${dataset.pan_id}<br />
|
||||||
|
Extended Pan id: ${dataset.extended_pan_id}<br />
|
||||||
|
|
||||||
|
${hasOTBR
|
||||||
|
? html`OTBR URL: ${otbrInfo.url}<br />
|
||||||
|
Active dataset TLVs: ${otbrInfo.active_dataset_tlvs}`
|
||||||
|
: nothing}
|
||||||
|
</div>
|
||||||
|
${canImportKeychain
|
||||||
|
? html`<ha-button slot="primary-action" @click=${this._sendCredentials}
|
||||||
|
>Send credentials to phone</ha-button
|
||||||
|
>`
|
||||||
|
: nothing}
|
||||||
|
</ha-dialog>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _sendCredentials() {
|
||||||
|
this.hass.auth.external!.fireMessage({
|
||||||
|
type: "thread/store_in_platform_keychain",
|
||||||
|
payload: {
|
||||||
|
mac_extended_address:
|
||||||
|
this._params?.network.dataset?.preferred_extended_address ||
|
||||||
|
this._params!.network.routers![0]!.extended_address,
|
||||||
|
border_agent_id:
|
||||||
|
this._params?.network.dataset?.preferred_border_agent_id ||
|
||||||
|
this._params!.network.routers![0]!.border_agent_id,
|
||||||
|
active_operational_dataset: this._params!.otbrInfo!.active_dataset_tlvs,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-dialog-thread-dataset": DialogThreadDataset;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import { OTBRInfo } from "../../../../../data/otbr";
|
||||||
|
import { ThreadNetwork } from "./thread-config-panel";
|
||||||
|
|
||||||
|
export interface DialogThreadDatasetParams {
|
||||||
|
network: ThreadNetwork;
|
||||||
|
otbrInfo?: OTBRInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showThreadDatasetDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
dialogParams: DialogThreadDatasetParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "ha-dialog-thread-dataset",
|
||||||
|
dialogImport: () => import("./dialog-thread-dataset"),
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -55,8 +55,9 @@ import { HomeAssistant } from "../../../../../types";
|
|||||||
import { brandsUrl } from "../../../../../util/brands-url";
|
import { brandsUrl } from "../../../../../util/brands-url";
|
||||||
import { fileDownload } from "../../../../../util/file_download";
|
import { fileDownload } from "../../../../../util/file_download";
|
||||||
import { documentationUrl } from "../../../../../util/documentation-url";
|
import { documentationUrl } from "../../../../../util/documentation-url";
|
||||||
|
import { showThreadDatasetDialog } from "./show-dialog-thread-dataset";
|
||||||
|
|
||||||
interface ThreadNetwork {
|
export interface ThreadNetwork {
|
||||||
name: string;
|
name: string;
|
||||||
dataset?: ThreadDataSet;
|
dataset?: ThreadDataSet;
|
||||||
routers?: ThreadRouter[];
|
routers?: ThreadRouter[];
|
||||||
@ -164,7 +165,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
|
|||||||
${network.name}${network.dataset
|
${network.name}${network.dataset
|
||||||
? html`<div>
|
? html`<div>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.networkDataset=${network.dataset}
|
.network=${network}
|
||||||
.path=${mdiInformationOutline}
|
.path=${mdiInformationOutline}
|
||||||
@click=${this._showDatasetInfo}
|
@click=${this._showDatasetInfo}
|
||||||
></ha-icon-button
|
></ha-icon-button
|
||||||
@ -306,33 +307,8 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _showDatasetInfo(ev: Event) {
|
private async _showDatasetInfo(ev: Event) {
|
||||||
const dataset = (ev.currentTarget as any).networkDataset as ThreadDataSet;
|
const network = (ev.currentTarget as any).network as ThreadNetwork;
|
||||||
if (this._otbrInfo) {
|
showThreadDatasetDialog(this, { network, otbrInfo: this._otbrInfo });
|
||||||
if (
|
|
||||||
dataset.extended_pan_id &&
|
|
||||||
this._otbrInfo.active_dataset_tlvs?.includes(dataset.extended_pan_id)
|
|
||||||
) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: dataset.network_name,
|
|
||||||
text: html`Network name: ${dataset.network_name}<br />
|
|
||||||
Channel: ${dataset.channel}<br />
|
|
||||||
Dataset id: ${dataset.dataset_id}<br />
|
|
||||||
Pan id: ${dataset.pan_id}<br />
|
|
||||||
Extended Pan id: ${dataset.extended_pan_id}<br />
|
|
||||||
OTBR URL: ${this._otbrInfo.url}<br />
|
|
||||||
Active dataset TLVs: ${this._otbrInfo.active_dataset_tlvs}`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: dataset.network_name,
|
|
||||||
text: html`Network name: ${dataset.network_name}<br />
|
|
||||||
Channel: ${dataset.channel}<br />
|
|
||||||
Dataset id: ${dataset.dataset_id}<br />
|
|
||||||
Pan id: ${dataset.pan_id}<br />
|
|
||||||
Extended Pan id: ${dataset.extended_pan_id}`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _importExternalThreadCredentials() {
|
private _importExternalThreadCredentials() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user