Add UI for tokens (#1656)

* Add UI for tokens

* Update strings

* Update text

* Update text
This commit is contained in:
Paulus Schoutsen 2018-09-11 21:29:40 +02:00 committed by GitHub
parent 494e3dc62c
commit 34567d451f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 261 additions and 1 deletions

View File

@ -0,0 +1,127 @@
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import EventsMixin from '../../mixins/events-mixin.js';
import LocalizeMixin from '../../mixins/localize-mixin.js';
import formatDateTime from '../../common/datetime/format_date_time.js';
import '../../resources/ha-style.js';
import './ha-settings-row.js';
/*
* @appliesMixin EventsMixin
* @appliesMixin LocalizeMixin
*/
class HaLongLivedTokens extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get template() {
return html`
<style include="ha-style">
paper-card {
display: block;
}
.card-content {
margin: -1em 0;
}
a {
color: var(--primary-color);
}
paper-icon-button {
color: var(--primary-text-color);
}
</style>
<paper-card heading="[[localize('ui.panel.profile.long_lived_access_tokens.header')]]">
<div class="card-content">
<p>
[[localize('ui.panel.profile.long_lived_access_tokens.description')]]
<a href='https://developers.home-assistant.io/docs/en/auth_api.html#making-authenticated-requests' target='_blank'>
[[localize('ui.panel.profile.long_lived_access_tokens.learn_auth_requests')]]
</a>
</p>
<template is='dom-if' if='[[!_tokens.length]]'>
<p>[[localize('ui.panel.profile.long_lived_access_tokens.empty_state')]]</p>
</template>
</div>
<template is='dom-repeat' items='[[_tokens]]'>
<ha-settings-row>
<span slot='heading'>[[item.client_name]]</span>
<span slot='description'>[[_formatCreatedAt(item.created_at)]]</span>
<paper-icon-button icon="hass:delete" on-click='_handleDelete'></paper-icon-button>
</ha-settings-row>
</template>
<div class='card-actions'>
<paper-button on-click='_handleCreate'>
[[localize('ui.panel.profile.long_lived_access_tokens.create')]]
</paper-button>
</div>
</paper-card>
`;
}
static get properties() {
return {
hass: Object,
refreshTokens: Array,
_tokens: {
type: Array,
computed: '_computeTokens(refreshTokens)'
}
};
}
_computeTokens(refreshTokens) {
return refreshTokens.filter(tkn => tkn.type === 'long_lived_access_token').reverse();
}
_formatTitle(name) {
return this.localize(
'ui.panel.profile.long_lived_access_tokens.token_title',
'name', name
);
}
_formatCreatedAt(created) {
return this.localize(
'ui.panel.profile.long_lived_access_tokens.created_at',
'date', formatDateTime(new Date(created))
);
}
async _handleCreate() {
const name = prompt(this.localize('ui.panel.profile.long_lived_access_tokens.prompt_name'));
if (!name) return;
try {
const token = await this.hass.callWS({
type: 'auth/long_lived_access_token',
lifespan: 3650,
client_name: name,
});
prompt(this.localize('ui.panel.profile.long_lived_access_tokens.prompt_copy_token'), token);
this.fire('hass-refresh-tokens');
} catch (err) {
// eslint-disable-next-line
console.error(err);
alert(this.localize('ui.panel.profile.long_lived_access_tokens.create_failed'));
}
}
async _handleDelete(ev) {
if (!confirm(this.localize('ui.panel.profile.long_lived_access_tokens.confirm_delete', 'name', ev.model.item.client_name))) {
return;
}
try {
await this.hass.callWS({
type: 'auth/delete_refresh_token',
refresh_token_id: ev.model.item.id,
});
this.fire('hass-refresh-tokens');
} catch (err) {
// eslint-disable-next-line
console.error(err);
alert(this.localize('ui.panel.profile.long_lived_access_tokens.delete_failed'));
}
}
}
customElements.define('ha-long-lived-access-tokens-card', HaLongLivedTokens);

View File

@ -15,6 +15,9 @@ import EventsMixin from '../../mixins/events-mixin.js';
import './ha-change-password-card.js';
import './ha-mfa-modules-card.js';
import './ha-refresh-tokens-card.js';
import './ha-long-lived-access-tokens-card.js';
import './ha-pick-language-row.js';
import './ha-pick-theme-row.js';
import './ha-push-notifications-row.js';
@ -84,7 +87,22 @@ class HaPanelProfile extends EventsMixin(PolymerElement) {
<ha-change-password-card hass="[[hass]]"></ha-change-password-card>
</template>
<ha-mfa-modules-card hass='[[hass]]' mfa-modules='[[hass.user.mfa_modules]]'></ha-mfa-modules-card>
<ha-mfa-modules-card
hass='[[hass]]'
mfa-modules='[[hass.user.mfa_modules]]'
></ha-mfa-modules-card>
<ha-refresh-tokens-card
hass='[[hass]]'
refresh-tokens='[[_refreshTokens]]'
on-hass-refresh-tokens='_refreshRefreshTokens'
></ha-refresh-tokens-card>
<ha-long-lived-access-tokens-card
hass='[[hass]]'
refresh-tokens='[[_refreshTokens]]'
on-hass-refresh-tokens='_refreshRefreshTokens'
></ha-long-lived-access-tokens-card>
</div>
</app-header-layout>
`;
@ -95,9 +113,21 @@ class HaPanelProfile extends EventsMixin(PolymerElement) {
hass: Object,
narrow: Boolean,
showMenu: Boolean,
_refreshTokens: Array,
};
}
connectedCallback() {
super.connectedCallback();
this._refreshRefreshTokens();
}
async _refreshRefreshTokens() {
this._refreshTokens = await this.hass.callWS({
type: 'auth/refresh_tokens'
});
}
_handleLogOut() {
this.fire('hass-logout');
}

View File

@ -0,0 +1,82 @@
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import EventsMixin from '../../mixins/events-mixin.js';
import LocalizeMixin from '../../mixins/localize-mixin.js';
import formatDateTime from '../../common/datetime/format_date_time.js';
import './ha-settings-row.js';
/*
* @appliesMixin EventsMixin
* @appliesMixin LocalizeMixin
*/
class HaRefreshTokens extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
paper-card {
display: block;
}
paper-icon-button {
color: var(--primary-text-color);
}
</style>
<paper-card heading="[[localize('ui.panel.profile.refresh_tokens.header')]]">
<div class="card-content">[[localize('ui.panel.profile.refresh_tokens.description')]]</div>
<template is='dom-repeat' items='[[_computeTokens(refreshTokens)]]'>
<ha-settings-row>
<span slot='heading'>[[_formatTitle(item.client_id)]]</span>
<span slot='description'>[[_formatCreatedAt(item.created_at)]]</span>
<paper-icon-button icon="hass:delete" on-click='_handleDelete'></paper-icon-button>
</ha-settings-row>
</template>
</paper-card>
`;
}
static get properties() {
return {
hass: Object,
refreshTokens: Array,
};
}
_computeTokens(refreshTokens) {
return refreshTokens.filter(tkn => tkn.type === 'normal').reverse();
}
_formatTitle(clientId) {
return this.localize(
'ui.panel.profile.refresh_tokens.token_title',
'clientId', clientId
);
}
_formatCreatedAt(created) {
return this.localize(
'ui.panel.profile.refresh_tokens.created_at',
'date', formatDateTime(new Date(created))
);
}
async _handleDelete(ev) {
if (!confirm(this.localize('ui.panel.profile.refresh_tokens.confirm_delete', 'name', ev.model.item.client_id))) {
return;
}
try {
await this.hass.callWS({
type: 'auth/delete_refresh_token',
refresh_token_id: ev.model.item.id,
});
this.fire('hass-refresh-tokens');
} catch (err) {
// eslint-disable-next-line
console.error(err);
alert(this.localize('ui.panel.profile.refresh_tokens.delete_failed'));
}
}
}
customElements.define('ha-refresh-tokens-card', HaRefreshTokens);

View File

@ -746,6 +746,27 @@
"error_no_theme": "No themes available.",
"link_promo": "Learn about themes",
"dropdown_label": "Theme"
},
"refresh_tokens": {
"header": "Refresh Tokens",
"description": "Each refresh token represents a login session. Refresh tokens will be automatically removed when you click log out. Below a list of refresh tokens that are currently active for your account.",
"token_title": "Refresh token for {clientId}",
"created_at": "Created at {date}",
"confirm_delete": "Are you sure you want to delete the refresh token for {name}?",
"delete_failed": "Failed to delete the refresh token."
},
"long_lived_access_tokens": {
"header": "Long-Lived Access Tokens",
"description": "Create long-lived access tokens to allow your scripts to interact with your Home Assistant instance. Each token will be valid for 10 years from creation. The following long-lived access tokens are currently active.",
"learn_auth_requests": "Learn how to make authenticated requests.",
"created_at": "Created at {date}",
"confirm_delete": "Are you sure you want to delete the access token for {name}?",
"delete_failed": "Failed to delete the access token.",
"create": "Create Token",
"create_failed": "Failed to create the access token.",
"prompt_name": "Name?",
"prompt_copy_token": "Copy your access token. It will not be shown again.",
"empty_state": "You have no long-lived access tokens yet."
}
},
"shopping-list": {