Hassio password protected snapshots (#936)

* Hassio password protected snapshots

* Remove space

* Travis

* Add checkmark to password

* Improve empty password detection

* Update

* Improvement for snapshot name

* Update

* Update hassio-snapshot.html

* Feedback

* Remove autofocus from password

* hidden -> dom-if
This commit is contained in:
c727 2018-02-28 03:09:06 +01:00 committed by Paulus Schoutsen
parent 3430996700
commit 579adb0455
2 changed files with 47 additions and 14 deletions

View File

@ -2,6 +2,7 @@
<link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'> <link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'>
<link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'> <link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'>
<link rel='import' href='../../bower_components/paper-button/paper-button.html'> <link rel='import' href='../../bower_components/paper-button/paper-button.html'>
<link rel="import" href='../../bower_components/paper-input/paper-input.html'>
<dom-module id='hassio-snapshot'> <dom-module id='hassio-snapshot'>
<template> <template>
@ -63,6 +64,9 @@
</template> </template>
</div> </div>
</template> </template>
<template is='dom-if' if='[[snapshot.protected]]'>
<paper-input autofocus label='Password' type='password' value='{{snapshotPassword}}'></paper-input>
</template>
<template is='dom-if' if='[[error]]'> <template is='dom-if' if='[[error]]'>
<p class='error'>Error: [[error]]</p> <p class='error'>Error: [[error]]</p>
</template> </template>
@ -99,6 +103,7 @@ class HassioSnapshot extends Polymer.Element {
type: Boolean, type: Boolean,
value: true, value: true,
}, },
snapshotPassword: String,
error: String, error: String,
}; };
} }
@ -142,11 +147,14 @@ class HassioSnapshot extends Polymer.Element {
const folders = const folders =
this.snapshot.folders.filter(folder => folder.checked).map(folder => folder.slug); this.snapshot.folders.filter(folder => folder.checked).map(folder => folder.slug);
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/partial`, { const data = {
homeassistant: this.restoreHass, homeassistant: this.restoreHass,
addons: addons, addons: addons,
folders: folders folders: folders
}).then(() => { };
if (this.snapshot.protected) data.password = this.snapshotPassword;
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/partial`, data).then(() => {
alert('Snapshot restored!'); alert('Snapshot restored!');
this.$.dialog.close(); this.$.dialog.close();
}, (error) => { }, (error) => {
@ -158,7 +166,8 @@ class HassioSnapshot extends Polymer.Element {
if (!confirm('Are you sure you want to restore this snapshot?')) { if (!confirm('Are you sure you want to restore this snapshot?')) {
return; return;
} }
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/full`) const data = this.snapshot.protected ? { password: this.snapshotPassword } : null;
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/full`, data)
.then(() => { .then(() => {
alert('Snapshot restored!'); alert('Snapshot restored!');
this.$.dialog.close(); this.$.dialog.close();

View File

@ -14,7 +14,8 @@
<dom-module id="hassio-snapshots"> <dom-module id="hassio-snapshots">
<template> <template>
<style include="ha-style hassio-style"> <style include="ha-style hassio-style">
paper-checkbox { paper-checkbox,
paper-input[type="password"] {
display: block; display: block;
margin: 4px 0 4px 48px; margin: 4px 0 4px 48px;
} }
@ -36,8 +37,7 @@
</div> </div>
<paper-card> <paper-card>
<div class='card-content'> <div class='card-content'>
<paper-input autofocus label='Name' value='{{snapshotName}}'> <paper-input autofocus label='Name' value='{{snapshotName}}'></paper-input>
</paper-input>
<label id='lbltype'>Type:</label> <label id='lbltype'>Type:</label>
<paper-radio-group selected='{{snapshotType}}' aria-labelledby='lbltype' on-paper-radio-group-changed='typeChanged'> <paper-radio-group selected='{{snapshotType}}' aria-labelledby='lbltype' on-paper-radio-group-changed='typeChanged'>
<paper-radio-button name='full'> <paper-radio-button name='full'>
@ -63,13 +63,20 @@
</paper-checkbox> </paper-checkbox>
</template> </template>
</div> </div>
</div> <div>
<div class='card-actions'> Password:
<paper-button disabled='[[creatingSnapshot]]' on-click='createSnapshot'>Create</paper-button> <paper-checkbox checked='{{snapshotHasPassword}}'>Password protected</paper-checkbox>
<template is='dom-if' if='[[snapshotHasPassword]]'>
<paper-input label='Password' type='password' value='{{snapshotPassword}}'></paper-input>
</template>
</div>
<template is='dom-if' if='[[error]]'> <template is='dom-if' if='[[error]]'>
<p class='error'>[[error]]</p> <p class='error'>[[error]]</p>
</template> </template>
</div> </div>
<div class='card-actions'>
<paper-button disabled='[[creatingSnapshot]]' on-click='createSnapshot'>Create</paper-button>
</div>
</paper-card> </paper-card>
</div> </div>
@ -85,7 +92,7 @@
<div class='card-content'> <div class='card-content'>
<hassio-card-content <hassio-card-content
title='[[computeName(snapshot)]]' title='[[computeName(snapshot)]]'
description='[[computeType(snapshot.type)]]' description='[[computeDetails(snapshot)]]'
datetime='[[snapshot.date]]' datetime='[[snapshot.date]]'
icon='[[computeIcon(snapshot.type)]]' icon='[[computeIcon(snapshot.type)]]'
icon-class='snapshot' icon-class='snapshot'
@ -105,7 +112,15 @@ class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,
snapshotName: String, snapshotName: {
type: String,
value: '',
},
snapshotPassword: {
type: String,
value: '',
},
snapshotHasPassword: Boolean,
snapshotType: { snapshotType: {
type: String, type: String,
value: 'full', value: 'full',
@ -165,9 +180,14 @@ class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
} }
createSnapshot() { createSnapshot() {
this.error = '';
if (this.snapshotHasPassword && !this.snapshotPassword.length) {
this.error = 'Please enter a password.';
return;
}
this.creatingSnapshot = true; this.creatingSnapshot = true;
let name = this.snapshotName; let name = this.snapshotName;
if (!name || name.length === 0) { if (!name.length) {
name = new Date().toLocaleDateString(navigator.language, { name = new Date().toLocaleDateString(navigator.language, {
weekday: 'long', weekday: 'long',
year: 'numeric', year: 'numeric',
@ -186,6 +206,9 @@ class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
data = { name: name, folders: folders, addons: addons }; data = { name: name, folders: folders, addons: addons };
path = 'hassio/snapshots/new/partial'; path = 'hassio/snapshots/new/partial';
} }
if (this.snapshotHasPassword) {
data.password = this.snapshotPassword;
}
this.hass.callApi('post', path, data) this.hass.callApi('post', path, data)
.then(() => { .then(() => {
@ -213,8 +236,9 @@ class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
return snapshot.name || snapshot.slug; return snapshot.name || snapshot.slug;
} }
computeType(type) { computeDetails(snapshot) {
return type === 'full' ? 'Full snapshot' : 'Partial snapshot'; const type = snapshot.type === 'full' ? 'Full snapshot' : 'Partial snapshot';
return snapshot.protected ? `${type}, password protected` : type;
} }
computeIcon(type) { computeIcon(type) {