mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-05 16:36:38 +00:00
Add "Keep me logged in" checkbox within login flow (#10226)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
29a1167782
commit
1140e6026c
@ -7,9 +7,10 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import "./ha-password-manager-polyfill";
|
|
||||||
import { property, state } from "lit/decorators";
|
import { property, state } from "lit/decorators";
|
||||||
|
import "../components/ha-checkbox";
|
||||||
import "../components/ha-form/ha-form";
|
import "../components/ha-form/ha-form";
|
||||||
|
import "../components/ha-formfield";
|
||||||
import "../components/ha-markdown";
|
import "../components/ha-markdown";
|
||||||
import "../components/ha-alert";
|
import "../components/ha-alert";
|
||||||
import { AuthProvider } from "../data/auth";
|
import { AuthProvider } from "../data/auth";
|
||||||
@ -19,6 +20,7 @@ import {
|
|||||||
} from "../data/data_entry_flow";
|
} from "../data/data_entry_flow";
|
||||||
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
|
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
|
||||||
|
import "./ha-password-manager-polyfill";
|
||||||
|
|
||||||
type State = "loading" | "error" | "step";
|
type State = "loading" | "error" | "step";
|
||||||
|
|
||||||
@ -41,6 +43,8 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
|
|
||||||
@state() private _submitting = false;
|
@state() private _submitting = false;
|
||||||
|
|
||||||
|
@state() private _storeToken = false;
|
||||||
|
|
||||||
willUpdate(changedProps: PropertyValues) {
|
willUpdate(changedProps: PropertyValues) {
|
||||||
super.willUpdate(changedProps);
|
super.willUpdate(changedProps);
|
||||||
|
|
||||||
@ -201,12 +205,29 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
.computeError=${this._computeErrorCallback(step)}
|
.computeError=${this._computeErrorCallback(step)}
|
||||||
@value-changed=${this._stepDataChanged}
|
@value-changed=${this._stepDataChanged}
|
||||||
></ha-form>
|
></ha-form>
|
||||||
|
${this.clientId === window.location.origin && step.step_id !== "mfa"
|
||||||
|
? html`
|
||||||
|
<ha-formfield
|
||||||
|
class="store-token"
|
||||||
|
.label=${this.localize("ui.panel.page-authorize.store_token")}
|
||||||
|
>
|
||||||
|
<ha-checkbox
|
||||||
|
.checked=${this._storeToken}
|
||||||
|
@change=${this._storeTokenChanged}
|
||||||
|
></ha-checkbox>
|
||||||
|
</ha-formfield>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
`;
|
`;
|
||||||
default:
|
default:
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _storeTokenChanged(e: CustomEvent<HTMLInputElement>) {
|
||||||
|
this._storeToken = (e.currentTarget as HTMLInputElement).checked;
|
||||||
|
}
|
||||||
|
|
||||||
private async _providerChanged(newProvider?: AuthProvider) {
|
private async _providerChanged(newProvider?: AuthProvider) {
|
||||||
if (this._step && this._step.type === "form") {
|
if (this._step && this._step.type === "form") {
|
||||||
fetch(`/auth/login_flow/${this._step.flow_id}`, {
|
fetch(`/auth/login_flow/${this._step.flow_id}`, {
|
||||||
@ -274,6 +295,9 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
if (this.oauth2State) {
|
if (this.oauth2State) {
|
||||||
url += `&state=${encodeURIComponent(this.oauth2State)}`;
|
url += `&state=${encodeURIComponent(this.oauth2State)}`;
|
||||||
}
|
}
|
||||||
|
if (this._storeToken) {
|
||||||
|
url += `&storeToken=true`;
|
||||||
|
}
|
||||||
|
|
||||||
document.location.assign(url);
|
document.location.assign(url);
|
||||||
}
|
}
|
||||||
@ -357,6 +381,11 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
margin: 24px 0 8px;
|
margin: 24px 0 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
/* Align with the rest of the form. */
|
||||||
|
.store-token {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: -16px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,14 @@ export function askWrite() {
|
|||||||
|
|
||||||
export function saveTokens(tokens: AuthData | null) {
|
export function saveTokens(tokens: AuthData | null) {
|
||||||
tokenCache.tokens = tokens;
|
tokenCache.tokens = tokens;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!tokenCache.writeEnabled &&
|
||||||
|
new URLSearchParams(window.location.search).get("storeToken") === "true"
|
||||||
|
) {
|
||||||
|
tokenCache.writeEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenCache.writeEnabled) {
|
if (tokenCache.writeEnabled) {
|
||||||
try {
|
try {
|
||||||
storage.hassTokens = JSON.stringify(tokens);
|
storage.hassTokens = JSON.stringify(tokens);
|
||||||
@ -45,7 +53,6 @@ export function enableWrite() {
|
|||||||
saveTokens(tokenCache.tokens);
|
saveTokens(tokenCache.tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadTokens() {
|
export function loadTokens() {
|
||||||
if (tokenCache.tokens === undefined) {
|
if (tokenCache.tokens === undefined) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
import { LitElement, TemplateResult, html, css } from "lit";
|
|
||||||
import { property } from "lit/decorators";
|
|
||||||
import { enableWrite } from "../common/auth/token_storage";
|
|
||||||
import { HomeAssistant } from "../types";
|
|
||||||
import "../components/ha-card";
|
|
||||||
import type { HaCard } from "../components/ha-card";
|
|
||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
|
|
||||||
class HaStoreAuth extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
return html`
|
|
||||||
<ha-card>
|
|
||||||
<div class="card-content">
|
|
||||||
${this.hass.localize("ui.auth_store.ask")}
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
|
||||||
<mwc-button @click=${this._dismiss}>
|
|
||||||
${this.hass.localize("ui.auth_store.decline")}
|
|
||||||
</mwc-button>
|
|
||||||
<mwc-button raised @click=${this._save}>
|
|
||||||
${this.hass.localize("ui.auth_store.confirm")}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
firstUpdated() {
|
|
||||||
this.classList.toggle("small", window.innerWidth < 600);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _save(): void {
|
|
||||||
enableWrite();
|
|
||||||
this._dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _dismiss(): void {
|
|
||||||
const card = this.shadowRoot!.querySelector("ha-card") as HaCard;
|
|
||||||
card.style.bottom = `-${card.offsetHeight + 8}px`;
|
|
||||||
setTimeout(() => this.parentNode!.removeChild(this), 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
|
||||||
return css`
|
|
||||||
ha-card {
|
|
||||||
position: fixed;
|
|
||||||
padding: 8px 0;
|
|
||||||
bottom: 16px;
|
|
||||||
right: 16px;
|
|
||||||
transition: bottom 0.25s;
|
|
||||||
--ha-card-box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2),
|
|
||||||
0px 6px 10px 0px rgba(0, 0, 0, 0.14),
|
|
||||||
0px 1px 18px 0px rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-actions {
|
|
||||||
text-align: right;
|
|
||||||
border-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.small) ha-card {
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("ha-store-auth-card", HaStoreAuth);
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-store-auth-card": HaStoreAuth;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,3 @@
|
|||||||
import { askWrite } from "../common/auth/token_storage";
|
|
||||||
import { subscribeUser, userCollection } from "../data/ws-user";
|
import { subscribeUser, userCollection } from "../data/ws-user";
|
||||||
import { Constructor } from "../types";
|
import { Constructor } from "../types";
|
||||||
import { clearState } from "../util/ha-pref-storage";
|
import { clearState } from "../util/ha-pref-storage";
|
||||||
@ -26,16 +25,6 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
|||||||
subscribeUser(this.hass!.connection, (user) =>
|
subscribeUser(this.hass!.connection, (user) =>
|
||||||
this._updateHass({ user })
|
this._updateHass({ user })
|
||||||
);
|
);
|
||||||
|
|
||||||
if (askWrite()) {
|
|
||||||
this.updateComplete
|
|
||||||
.then(() => import("../dialogs/ha-store-auth-card"))
|
|
||||||
.then(() => {
|
|
||||||
const el = document.createElement("ha-store-auth-card");
|
|
||||||
this.provideHass(el);
|
|
||||||
document.body.appendChild(el);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handleLogout() {
|
private async _handleLogout() {
|
||||||
|
@ -105,11 +105,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"auth_store": {
|
|
||||||
"ask": "Do you want to stay logged in?",
|
|
||||||
"decline": "No",
|
|
||||||
"confirm": "Yes"
|
|
||||||
},
|
|
||||||
"card": {
|
"card": {
|
||||||
"alarm_control_panel": {
|
"alarm_control_panel": {
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
@ -3666,6 +3661,7 @@
|
|||||||
"logging_in_with": "Logging in with **{authProviderName}**.",
|
"logging_in_with": "Logging in with **{authProviderName}**.",
|
||||||
"pick_auth_provider": "Or log in with",
|
"pick_auth_provider": "Or log in with",
|
||||||
"abort_intro": "Login aborted",
|
"abort_intro": "Login aborted",
|
||||||
|
"store_token": "Keep me logged in",
|
||||||
"form": {
|
"form": {
|
||||||
"working": "Please wait",
|
"working": "Please wait",
|
||||||
"unknown_error": "Something went wrong",
|
"unknown_error": "Something went wrong",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user