From a8b91aab6b285adccd19e9716cd6416e8c6e670e Mon Sep 17 00:00:00 2001 From: Pierre-Gilles Leymarie Date: Tue, 20 Oct 2020 11:43:40 +0300 Subject: [PATCH 1/3] Use officiel SQLite .restore command to restore backup + improve restore UI (#906) * Use officiel SQLite .restore command to restore backup * Add more explicit errors in UI when restore of backup failed --- front/src/actions/gateway.js | 1 + front/src/config/i18n/en.json | 3 ++- front/src/config/i18n/fr.json | 3 ++- .../routes/settings/settings-backup/GatewayBackupList.jsx | 5 +++++ front/src/routes/settings/settings-backup/index.js | 5 ++++- server/lib/gateway/gateway.restoreBackup.js | 4 ++-- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/front/src/actions/gateway.js b/front/src/actions/gateway.js index 7bdc7e2a02..e082617018 100644 --- a/front/src/actions/gateway.js +++ b/front/src/actions/gateway.js @@ -292,6 +292,7 @@ function createActions(store) { }, 2000); } else if (restoreStatus.restore_errored) { store.setState({ + gatewayRestoreInProgress: false, gatewayRestoreErrored: true }); } else { diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json index ad65250850..74d21295c6 100644 --- a/front/src/config/i18n/en.json +++ b/front/src/config/i18n/en.json @@ -1011,7 +1011,8 @@ "restoreInProgressTitle": "Restoring backup in progress...", "backupNowButton": "Backup now", "backupStarted": "Backup started...", - "notConfigured": "Gladys Plus need to be configured to enable backups. Go to the Gladys Plus tab to configure it." + "notConfigured": "Gladys Plus need to be configured to enable backups. Go to the Gladys Plus tab to configure it.", + "restoreFailed": "Restoring the backup failed. Are you sure you have the same backup key used during the backup ? You can go to the Gladys Plus tab in settings to set another backup key." }, "deviceFeatureUnit": { "celsius": "Celsius (°C)", diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json index 3b1720b2d3..0447f9370d 100644 --- a/front/src/config/i18n/fr.json +++ b/front/src/config/i18n/fr.json @@ -1011,7 +1011,8 @@ "restoreInProgressTitle": "Restauration de la sauvegarde en cours ...", "backupNowButton": "Sauvegarder maintenant", "backupStarted": "Début de la sauvegarde...", - "notConfigured": "Gladys Plus doit être configuré pour activer les sauvegardes. Accédez à l'onglet Gladys Plus pour le configurer." + "notConfigured": "Gladys Plus doit être configuré pour activer les sauvegardes. Accédez à l'onglet Gladys Plus pour le configurer.", + "restoreFailed": "La restauration de votre backup a échoué. Êtes-vous sûr que votre clé de sauvegarde est la même que celle utilisée par Gladys lorsque le backup a été créé ? Vous pouvez modifier la clé de sauvegarde dans l'onglet Gladys Plus des paramètres." }, "deviceFeatureUnit": { "celsius": "Celsius (°C)", diff --git a/front/src/routes/settings/settings-backup/GatewayBackupList.jsx b/front/src/routes/settings/settings-backup/GatewayBackupList.jsx index 19c4b24b51..6358241c38 100644 --- a/front/src/routes/settings/settings-backup/GatewayBackupList.jsx +++ b/front/src/routes/settings/settings-backup/GatewayBackupList.jsx @@ -20,6 +20,11 @@ const GatewayPage = ({ children, ...props }) => (
+ {props.gatewayRestoreErrored && ( + + )}

diff --git a/front/src/routes/settings/settings-backup/index.js b/front/src/routes/settings/settings-backup/index.js index 375a8af987..ea970af5e8 100644 --- a/front/src/routes/settings/settings-backup/index.js +++ b/front/src/routes/settings/settings-backup/index.js @@ -3,7 +3,10 @@ import { connect } from 'unistore/preact'; import GatewayBackupPage from './GatewayBackupPage'; import actions from '../../../actions/gateway'; -@connect('user,gatewayStatus,gatewayBackups,gatewayRestoreInProgress,gatewayCreateBackupStatus', actions) +@connect( + 'user,gatewayStatus,gatewayBackups,gatewayRestoreInProgress,gatewayCreateBackupStatus,gatewayRestoreErrored', + actions +) class SettingsGateway extends Component { componentWillMount() { this.props.getStatus(); diff --git a/server/lib/gateway/gateway.restoreBackup.js b/server/lib/gateway/gateway.restoreBackup.js index 4cc778d870..1e19bcb8ba 100644 --- a/server/lib/gateway/gateway.restoreBackup.js +++ b/server/lib/gateway/gateway.restoreBackup.js @@ -1,6 +1,6 @@ const fse = require('fs-extra'); const logger = require('../../utils/logger'); - +const { exec } = require('../../utils/childProcess'); const { NotFoundError } = require('../../utils/coreErrors'); /** @@ -19,7 +19,7 @@ async function restoreBackup(backupFilePath) { // shutting down the DB await this.sequelize.close(); // copy the backupFile to the new DB - await fse.copy(backupFilePath, this.config.storage); + await exec(`sqlite3 ${this.config.storage} ".restore '${backupFilePath}'"`); // done! logger.info(`Backup restored. Need reboot now.`); } From 4a2ce84af6f91c42b31c4ca7bce21c87c9747799 Mon Sep 17 00:00:00 2001 From: Pierre-Gilles Leymarie Date: Tue, 20 Oct 2020 14:49:50 +0300 Subject: [PATCH 2/3] removeColumn in migration in no longer authorized to prevent data loss (#907) --- server/.eslintrc.json | 5 +++-- .../migrations/20200201125436-add-caldav-data.js | 7 +------ .../20200207214849-add-calendar-event-url.js | 4 +--- .../20200513195013-session-with-useragent.js | 5 +---- .../20201018084535-service-with-status.js | 12 +----------- server/package-lock.json | 15 +++++++++++++++ server/package.json | 1 + 7 files changed, 23 insertions(+), 26 deletions(-) diff --git a/server/.eslintrc.json b/server/.eslintrc.json index 7def51b269..0aa42b7fc2 100644 --- a/server/.eslintrc.json +++ b/server/.eslintrc.json @@ -1,5 +1,5 @@ { - "plugins": ["jsdoc", "require-jsdoc"], + "plugins": ["jsdoc", "require-jsdoc", "no-call"], "extends": ["airbnb-base", "plugin:jsdoc/recommended", "prettier"], "parserOptions": { "ecmaVersion": 2018 @@ -121,7 +121,8 @@ "jsdoc/require-returns-description": 2, "jsdoc/require-returns-type": 2, "jsdoc/valid-types": 2, - "require-jsdoc": 2 + "require-jsdoc": 2, + "no-call/no-call": [2, ["queryInterface.removeColumn"]] }, "overrides": [ { diff --git a/server/migrations/20200201125436-add-caldav-data.js b/server/migrations/20200201125436-add-caldav-data.js index 416de5adc2..1d462f1770 100644 --- a/server/migrations/20200201125436-add-caldav-data.js +++ b/server/migrations/20200201125436-add-caldav-data.js @@ -10,10 +10,5 @@ module.exports = { ]); }, - down: (queryInterface, Sequelize) => { - return Promise.all([ - queryInterface.removeColumn('t_calendar', 'ctag'), - queryInterface.removeColumn('t_calendar', 'sync_token'), - ]); - }, + down: (queryInterface, Sequelize) => {}, }; diff --git a/server/migrations/20200207214849-add-calendar-event-url.js b/server/migrations/20200207214849-add-calendar-event-url.js index d32da94fe8..eb4cd3f1b4 100644 --- a/server/migrations/20200207214849-add-calendar-event-url.js +++ b/server/migrations/20200207214849-add-calendar-event-url.js @@ -7,7 +7,5 @@ module.exports = { ]); }, - down: (queryInterface, Sequelize) => { - return Promise.all([queryInterface.removeColumn('t_calendar_event', 'url')]); - }, + down: (queryInterface, Sequelize) => {}, }; diff --git a/server/migrations/20200513195013-session-with-useragent.js b/server/migrations/20200513195013-session-with-useragent.js index bb889823c8..cc4987b8e5 100644 --- a/server/migrations/20200513195013-session-with-useragent.js +++ b/server/migrations/20200513195013-session-with-useragent.js @@ -1,11 +1,8 @@ module.exports = { up: async (queryInterface, Sequelize) => { - // Add new mandatory column await queryInterface.addColumn('t_session', 'useragent', { type: Sequelize.TEXT, }); }, - down: async (queryInterface, Sequelize) => { - await queryInterface.removeColumn('t_session', 'useragent'); - }, + down: async (queryInterface, Sequelize) => {}, }; diff --git a/server/migrations/20201018084535-service-with-status.js b/server/migrations/20201018084535-service-with-status.js index 1aa7be7bd5..b18a0862ab 100644 --- a/server/migrations/20201018084535-service-with-status.js +++ b/server/migrations/20201018084535-service-with-status.js @@ -1,21 +1,11 @@ module.exports = { up: async (queryInterface, Sequelize) => { - // Add new mandatory column await queryInterface.addColumn('t_service', 'status', { allowNull: false, type: Sequelize.TEXT, defaultValue: 'UNKNWON', after: 'enabled', }); - await queryInterface.removeColumn('t_service', 'enabled'); - }, - down: async (queryInterface, Sequelize) => { - await queryInterface.addColumn('t_service', 'enabled', { - allowNull: false, - type: Sequelize.BOOLEAN, - defaultValue: true, - after: 'status', - }); - await queryInterface.removeColumn('t_service', 'status'); }, + down: async (queryInterface, Sequelize) => {}, }; diff --git a/server/package-lock.json b/server/package-lock.json index 7a1cace883..982de023be 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -2899,6 +2899,15 @@ "lodash": "^4.17.11" } }, + "eslint-plugin-no-call": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-call/-/eslint-plugin-no-call-1.2.5.tgz", + "integrity": "sha512-LU8PYvpCNQDZrb8sijEl3Ovrf6J472+uIAqw2Vprhu6zbzZF6d0s1Y1JlXQVX0K8rtJ73YR8kfBOydPAEvb1EA==", + "dev": true, + "requires": { + "requireindex": "1.2.0" + } + }, "eslint-plugin-require-jsdoc": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/eslint-plugin-require-jsdoc/-/eslint-plugin-require-jsdoc-1.0.4.tgz", @@ -8185,6 +8194,12 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", diff --git a/server/package.json b/server/package.json index 2fe753862d..0a9127fb75 100644 --- a/server/package.json +++ b/server/package.json @@ -49,6 +49,7 @@ "eslint-config-prettier": "^4.3.0", "eslint-plugin-import": "^2.16.0", "eslint-plugin-jsdoc": "^4.1.0", + "eslint-plugin-no-call": "^1.2.5", "eslint-plugin-require-jsdoc": "^1.0.4", "jsdoc": "^3.5.5", "mocha": "^5.2.0", From 5eb8e107d163b05ce29dc816488876d898c26c05 Mon Sep 17 00:00:00 2001 From: Pierre-Gilles Leymarie Date: Tue, 20 Oct 2020 17:17:03 +0300 Subject: [PATCH 3/3] v4.0.0-beta.18 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 036a7b698d..9dd31052a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "gladys", - "version": "4.0.0-beta.17", + "version": "4.0.0-beta.18", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 75faa29825..c21bb21f32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gladys", - "version": "4.0.0-beta.17", + "version": "4.0.0-beta.18", "description": "A privacy-first, open-source home assistant", "main": "index.js", "scripts": {