mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 05:47:20 +00:00
Allow owner users to change password of any user (#6698)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
dc5b92030f
commit
7a4c9b128c
@ -44,3 +44,14 @@ export const createAuthForUser = async (
|
|||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const adminChangePassword = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
userId: string,
|
||||||
|
password: string
|
||||||
|
) =>
|
||||||
|
hass.callWS<void>({
|
||||||
|
type: "config/auth_provider/homeassistant/admin_change_password",
|
||||||
|
user_id: userId,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "../../../components/ha-circular-progress";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
|
import "../../../components/ha-circular-progress";
|
||||||
import "../../../components/ha-dialog";
|
import "../../../components/ha-dialog";
|
||||||
import "../../../components/ha-switch";
|
|
||||||
import "../../../components/ha-formfield";
|
import "../../../components/ha-formfield";
|
||||||
|
import "../../../components/ha-switch";
|
||||||
import { createAuthForUser } from "../../../data/auth";
|
import { createAuthForUser } from "../../../data/auth";
|
||||||
import {
|
import {
|
||||||
createUser,
|
createUser,
|
||||||
@ -27,7 +28,6 @@ import { PolymerChangedEvent } from "../../../polymer-types";
|
|||||||
import { haStyleDialog } from "../../../resources/styles";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { AddUserDialogParams } from "./show-dialog-add-user";
|
import { AddUserDialogParams } from "./show-dialog-add-user";
|
||||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
|
||||||
|
|
||||||
@customElement("dialog-add-user")
|
@customElement("dialog-add-user")
|
||||||
export class DialogAddUser extends LitElement {
|
export class DialogAddUser extends LitElement {
|
||||||
@ -46,6 +46,8 @@ export class DialogAddUser extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _password?: string;
|
@internalProperty() private _password?: string;
|
||||||
|
|
||||||
|
@internalProperty() private _passwordConfirm?: string;
|
||||||
|
|
||||||
@internalProperty() private _isAdmin?: boolean;
|
@internalProperty() private _isAdmin?: boolean;
|
||||||
|
|
||||||
public showDialog(params: AddUserDialogParams) {
|
public showDialog(params: AddUserDialogParams) {
|
||||||
@ -53,6 +55,7 @@ export class DialogAddUser extends LitElement {
|
|||||||
this._name = "";
|
this._name = "";
|
||||||
this._username = "";
|
this._username = "";
|
||||||
this._password = "";
|
this._password = "";
|
||||||
|
this._passwordConfirm = "";
|
||||||
this._isAdmin = false;
|
this._isAdmin = false;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._loading = false;
|
this._loading = false;
|
||||||
@ -83,17 +86,20 @@ export class DialogAddUser extends LitElement {
|
|||||||
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
||||||
<paper-input
|
<paper-input
|
||||||
class="name"
|
class="name"
|
||||||
|
name="name"
|
||||||
.label=${this.hass.localize("ui.panel.config.users.add_user.name")}
|
.label=${this.hass.localize("ui.panel.config.users.add_user.name")}
|
||||||
.value=${this._name}
|
.value=${this._name}
|
||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
autocapitalize="on"
|
autocapitalize="on"
|
||||||
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
||||||
@value-changed=${this._nameChanged}
|
@value-changed=${this._handleValueChanged}
|
||||||
@blur=${this._maybePopulateUsername}
|
@blur=${this._maybePopulateUsername}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
|
|
||||||
<paper-input
|
<paper-input
|
||||||
class="username"
|
class="username"
|
||||||
|
name="username"
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.users.add_user.username"
|
"ui.panel.config.users.add_user.username"
|
||||||
)}
|
)}
|
||||||
@ -101,20 +107,40 @@ export class DialogAddUser extends LitElement {
|
|||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
autocapitalize="none"
|
autocapitalize="none"
|
||||||
@value-changed=${this._usernameChanged}
|
@value-changed=${this._handleValueChanged}
|
||||||
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
|
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.users.add_user.password"
|
"ui.panel.config.users.add_user.password"
|
||||||
)}
|
)}
|
||||||
type="password"
|
type="password"
|
||||||
|
name="password"
|
||||||
.value=${this._password}
|
.value=${this._password}
|
||||||
required
|
required
|
||||||
auto-validate
|
auto-validate
|
||||||
@value-changed=${this._passwordChanged}
|
@value-changed=${this._handleValueChanged}
|
||||||
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
.errorMessage=${this.hass.localize("ui.common.error_required")}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
|
|
||||||
|
<paper-input
|
||||||
|
label="${this.hass.localize(
|
||||||
|
"ui.panel.config.users.add_user.password_confirm"
|
||||||
|
)}"
|
||||||
|
name="passwordConfirm"
|
||||||
|
.value=${this._passwordConfirm}
|
||||||
|
@value-changed=${this._handleValueChanged}
|
||||||
|
required
|
||||||
|
type="password"
|
||||||
|
.invalid=${this._password !== "" &&
|
||||||
|
this._passwordConfirm !== "" &&
|
||||||
|
this._passwordConfirm !== this._password}
|
||||||
|
.errorMessage="${this.hass.localize(
|
||||||
|
"ui.panel.config.users.add_user.password_not_match"
|
||||||
|
)}"
|
||||||
|
></paper-input>
|
||||||
|
|
||||||
<ha-formfield
|
<ha-formfield
|
||||||
.label=${this.hass.localize("ui.panel.config.users.editor.admin")}
|
.label=${this.hass.localize("ui.panel.config.users.editor.admin")}
|
||||||
.dir=${computeRTLDirection(this.hass)}
|
.dir=${computeRTLDirection(this.hass)}
|
||||||
@ -147,7 +173,10 @@ export class DialogAddUser extends LitElement {
|
|||||||
: html`
|
: html`
|
||||||
<mwc-button
|
<mwc-button
|
||||||
slot="primaryAction"
|
slot="primaryAction"
|
||||||
.disabled=${!this._name || !this._username || !this._password}
|
.disabled=${!this._name ||
|
||||||
|
!this._username ||
|
||||||
|
!this._password ||
|
||||||
|
this._password !== this._passwordConfirm}
|
||||||
@click=${this._createUser}
|
@click=${this._createUser}
|
||||||
>
|
>
|
||||||
${this.hass.localize("ui.panel.config.users.add_user.create")}
|
${this.hass.localize("ui.panel.config.users.add_user.create")}
|
||||||
@ -173,19 +202,10 @@ export class DialogAddUser extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _nameChanged(ev: PolymerChangedEvent<string>) {
|
private _handleValueChanged(ev: PolymerChangedEvent<string>): void {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._name = ev.detail.value;
|
const name = (ev.target as any).name;
|
||||||
}
|
this[`_${name}`] = ev.detail.value;
|
||||||
|
|
||||||
private _usernameChanged(ev: PolymerChangedEvent<string>) {
|
|
||||||
this._error = undefined;
|
|
||||||
this._username = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _passwordChanged(ev: PolymerChangedEvent<string>) {
|
|
||||||
this._error = undefined;
|
|
||||||
this._password = ev.detail.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _adminChanged(ev): Promise<void> {
|
private async _adminChanged(ev): Promise<void> {
|
||||||
|
@ -6,23 +6,28 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||||
import "../../../components/ha-switch";
|
|
||||||
import "../../../components/ha-formfield";
|
import "../../../components/ha-formfield";
|
||||||
|
import "../../../components/ha-switch";
|
||||||
|
import { adminChangePassword } from "../../../data/auth";
|
||||||
import {
|
import {
|
||||||
SYSTEM_GROUP_ID_ADMIN,
|
SYSTEM_GROUP_ID_ADMIN,
|
||||||
SYSTEM_GROUP_ID_USER,
|
SYSTEM_GROUP_ID_USER,
|
||||||
} from "../../../data/user";
|
} from "../../../data/user";
|
||||||
|
import {
|
||||||
|
showAlertDialog,
|
||||||
|
showPromptDialog,
|
||||||
|
} from "../../../dialogs/generic/show-dialog-box";
|
||||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import { haStyleDialog } from "../../../resources/styles";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { UserDetailDialogParams } from "./show-dialog-user-detail";
|
import { UserDetailDialogParams } from "./show-dialog-user-detail";
|
||||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
|
||||||
|
|
||||||
@customElement("dialog-user-detail")
|
@customElement("dialog-user-detail")
|
||||||
class DialogUserDetail extends LitElement {
|
class DialogUserDetail extends LitElement {
|
||||||
@ -141,7 +146,15 @@ class DialogUserDetail extends LitElement {
|
|||||||
</paper-tooltip>
|
</paper-tooltip>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
|
${!user.system_generated && this.hass.user?.is_owner
|
||||||
|
? html`<mwc-button @click=${this._changePassword}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.users.editor.change_password"
|
||||||
|
)}
|
||||||
|
</mwc-button>`
|
||||||
|
: ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div slot="primaryAction">
|
<div slot="primaryAction">
|
||||||
<mwc-button
|
<mwc-button
|
||||||
@click=${this._updateEntry}
|
@click=${this._updateEntry}
|
||||||
@ -202,6 +215,52 @@ class DialogUserDetail extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _changePassword() {
|
||||||
|
const credential = this._params?.entry.credentials.find(
|
||||||
|
(cred) => 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 {
|
private _close(): void {
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
}
|
}
|
||||||
|
@ -1654,6 +1654,8 @@
|
|||||||
"caption": "View user",
|
"caption": "View user",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"change_password": "Change password",
|
"change_password": "Change password",
|
||||||
|
"new_password": "New Password",
|
||||||
|
"password_changed": "The password is changed!",
|
||||||
"activate_user": "Activate user",
|
"activate_user": "Activate user",
|
||||||
"deactivate_user": "Deactivate user",
|
"deactivate_user": "Deactivate user",
|
||||||
"delete_user": "Delete user",
|
"delete_user": "Delete user",
|
||||||
@ -1674,6 +1676,8 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
|
"password_confirm": "Confirm Password",
|
||||||
|
"password_not_match": "Passwords don't match",
|
||||||
"create": "Create"
|
"create": "Create"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user