From 7a4c9b128cbe8c53933efdd4b2d6985145874ff9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 28 Aug 2020 14:30:42 +0200 Subject: [PATCH] Allow owner users to change password of any user (#6698) Co-authored-by: Paulus Schoutsen --- src/data/auth.ts | 11 ++++ src/panels/config/users/dialog-add-user.ts | 60 +++++++++++------ src/panels/config/users/dialog-user-detail.ts | 65 ++++++++++++++++++- src/translations/en.json | 4 ++ 4 files changed, 117 insertions(+), 23 deletions(-) diff --git a/src/data/auth.ts b/src/data/auth.ts index 162ade2fbd..aea90dd335 100644 --- a/src/data/auth.ts +++ b/src/data/auth.ts @@ -44,3 +44,14 @@ export const createAuthForUser = async ( username, password, }); + +export const adminChangePassword = async ( + hass: HomeAssistant, + userId: string, + password: string +) => + hass.callWS({ + type: "config/auth_provider/homeassistant/admin_change_password", + user_id: userId, + password, + }); diff --git a/src/panels/config/users/dialog-add-user.ts b/src/panels/config/users/dialog-add-user.ts index f9f83566fb..6d6fd0ce76 100644 --- a/src/panels/config/users/dialog-add-user.ts +++ b/src/panels/config/users/dialog-add-user.ts @@ -1,20 +1,21 @@ import "@material/mwc-button"; import "@polymer/paper-input/paper-input"; -import "../../../components/ha-circular-progress"; import { css, CSSResult, customElement, html, + internalProperty, LitElement, property, - internalProperty, PropertyValues, TemplateResult, } from "lit-element"; +import { computeRTLDirection } from "../../../common/util/compute_rtl"; +import "../../../components/ha-circular-progress"; import "../../../components/ha-dialog"; -import "../../../components/ha-switch"; import "../../../components/ha-formfield"; +import "../../../components/ha-switch"; import { createAuthForUser } from "../../../data/auth"; import { createUser, @@ -27,7 +28,6 @@ import { PolymerChangedEvent } from "../../../polymer-types"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { AddUserDialogParams } from "./show-dialog-add-user"; -import { computeRTLDirection } from "../../../common/util/compute_rtl"; @customElement("dialog-add-user") export class DialogAddUser extends LitElement { @@ -46,6 +46,8 @@ export class DialogAddUser extends LitElement { @internalProperty() private _password?: string; + @internalProperty() private _passwordConfirm?: string; + @internalProperty() private _isAdmin?: boolean; public showDialog(params: AddUserDialogParams) { @@ -53,6 +55,7 @@ export class DialogAddUser extends LitElement { this._name = ""; this._username = ""; this._password = ""; + this._passwordConfirm = ""; this._isAdmin = false; this._error = undefined; this._loading = false; @@ -83,17 +86,20 @@ export class DialogAddUser extends LitElement { ${this._error ? html`
${this._error}
` : ""} + + + + + ${this.hass.localize("ui.panel.config.users.add_user.create")} @@ -173,19 +202,10 @@ export class DialogAddUser extends LitElement { } } - private _nameChanged(ev: PolymerChangedEvent) { + private _handleValueChanged(ev: PolymerChangedEvent): void { this._error = undefined; - this._name = ev.detail.value; - } - - private _usernameChanged(ev: PolymerChangedEvent) { - this._error = undefined; - this._username = ev.detail.value; - } - - private _passwordChanged(ev: PolymerChangedEvent) { - this._error = undefined; - this._password = ev.detail.value; + const name = (ev.target as any).name; + this[`_${name}`] = ev.detail.value; } private async _adminChanged(ev): Promise { diff --git a/src/panels/config/users/dialog-user-detail.ts b/src/panels/config/users/dialog-user-detail.ts index 504ef0a4b5..fb5e29ce27 100644 --- a/src/panels/config/users/dialog-user-detail.ts +++ b/src/panels/config/users/dialog-user-detail.ts @@ -6,23 +6,28 @@ import { CSSResult, customElement, html, + internalProperty, LitElement, property, - internalProperty, TemplateResult, } from "lit-element"; +import { computeRTLDirection } from "../../../common/util/compute_rtl"; import { createCloseHeading } from "../../../components/ha-dialog"; -import "../../../components/ha-switch"; import "../../../components/ha-formfield"; +import "../../../components/ha-switch"; +import { adminChangePassword } from "../../../data/auth"; import { SYSTEM_GROUP_ID_ADMIN, SYSTEM_GROUP_ID_USER, } from "../../../data/user"; +import { + showAlertDialog, + showPromptDialog, +} from "../../../dialogs/generic/show-dialog-box"; import { PolymerChangedEvent } from "../../../polymer-types"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { UserDetailDialogParams } from "./show-dialog-user-detail"; -import { computeRTLDirection } from "../../../common/util/compute_rtl"; @customElement("dialog-user-detail") class DialogUserDetail extends LitElement { @@ -141,7 +146,15 @@ class DialogUserDetail extends LitElement { ` : ""} + ${!user.system_generated && this.hass.user?.is_owner + ? html` + ${this.hass.localize( + "ui.panel.config.users.editor.change_password" + )} + ` + : ""} +
cred.type === "homeassistant" + ); + if (!credential) { + showAlertDialog(this, { + title: "No Home Assistant credentials found.", + }); + return; + } + const newPassword = await showPromptDialog(this, { + title: this.hass.localize("ui.panel.config.users.editor.change_password"), + inputType: "password", + inputLabel: this.hass.localize( + "ui.panel.config.users.editor.new_password" + ), + }); + if (!newPassword) { + return; + } + const confirmPassword = await showPromptDialog(this, { + title: this.hass.localize("ui.panel.config.users.editor.change_password"), + inputType: "password", + inputLabel: this.hass.localize( + "ui.panel.config.users.add_user.password_confirm" + ), + }); + if (!confirmPassword) { + return; + } + if (newPassword !== confirmPassword) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.users.add_user.password_not_match" + ), + }); + return; + } + await adminChangePassword(this.hass, this._params!.entry.id, newPassword); + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.users.add_user.password_changed" + ), + }); + } + private _close(): void { this._params = undefined; } diff --git a/src/translations/en.json b/src/translations/en.json index e228ccb712..940bdd61f6 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1654,6 +1654,8 @@ "caption": "View user", "name": "Name", "change_password": "Change password", + "new_password": "New Password", + "password_changed": "The password is changed!", "activate_user": "Activate user", "deactivate_user": "Deactivate user", "delete_user": "Delete user", @@ -1674,6 +1676,8 @@ "name": "Name", "username": "Username", "password": "Password", + "password_confirm": "Confirm Password", + "password_not_match": "Passwords don't match", "create": "Create" } },