From ec957041e1abd44b8a872a1da47b879e4ad7287b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Cl=C3=A9ment?= Date: Sat, 30 Apr 2022 16:19:31 +0200 Subject: [PATCH] :hammer: Migrate all code to ESM (#124) * :hammer: Convert everything to es6 modules * :hammer: Cath in manual backup * :hammer: Change status storage method * :hammer: Move token to static in hassioApiTools * :ambulance: Fix crash on backup upload to ha * :ambulance: Fix multiple upload * :hammer: Add logs for protected * :hammer: Catch some errors --- .../rootfs/opt/nextcloud_backup/app.js | 47 +++-- .../opt/nextcloud_backup/bin/{www => www.js} | 8 +- .../opt/nextcloud_backup/config/winston.js | 5 +- .../opt/nextcloud_backup/package-lock.json | 168 +++++++++++------- .../rootfs/opt/nextcloud_backup/package.json | 5 +- .../opt/nextcloud_backup/public/js/index.js | 7 +- .../rootfs/opt/nextcloud_backup/routes/api.js | 50 +++--- .../opt/nextcloud_backup/routes/index.js | 6 +- .../opt/nextcloud_backup/tools/cronTools.js | 39 +--- .../nextcloud_backup/tools/hassioApiTools.js | 156 ++++++---------- .../opt/nextcloud_backup/tools/pathTools.js | 8 +- .../nextcloud_backup/tools/settingsTools.js | 16 +- .../opt/nextcloud_backup/tools/status.js | 57 +++--- .../opt/nextcloud_backup/tools/toolbox.js | 2 +- .../opt/nextcloud_backup/tools/webdavTools.js | 49 ++--- 15 files changed, 299 insertions(+), 324 deletions(-) rename nextcloud_backup/rootfs/opt/nextcloud_backup/bin/{www => www.js} (92%) diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js index a19d77a..cd951f6 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js @@ -1,11 +1,26 @@ -const createError = require("http-errors"); -const express = require("express"); -const path = require("path"); -const cookieParser = require("cookie-parser"); -const logger = require("morgan"); +import createError from "http-errors"; +import express from "express"; +import path from "path"; +import cookieParser from "cookie-parser"; +import logger from "morgan"; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import fs from "fs" +import newlog from "./config/winston.js" +import * as statusTools from "./tools/status.js" +import * as hassioApiTools from "./tools/hassioApiTools.js" +import webdav from "./tools/webdavTools.js" +import * as settingsTools from "./tools/settingsTools.js" +import cronTools from "./tools/cronTools.js" -const indexRouter = require("./routes/index"); -const apiRouter = require("./routes/api"); +import indexRouter from "./routes/index.js" +import apiRouter from "./routes/api.js" + + + + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); const app = express(); // view engine setup @@ -71,17 +86,15 @@ app.use(function (err, req, res, next) { ---------------------------------------------------------- */ -const fs = require("fs"); -const newlog = require("./config/winston"); + newlog.info(`Log level: ${ process.env.LOG_LEVEL }`); newlog.info(`Backup timeout: ${ parseInt(process.env.CREATE_BACKUP_TIMEOUT) || ( 90 * 60 * 1000 ) }`) if (!fs.existsSync("/data")) fs.mkdirSync("/data"); -const statusTools = require("./tools/status"); statusTools.init(); newlog.info("Satus : \x1b[32mGo !\x1b[0m"); -const hassioApiTools = require("./tools/hassioApiTools"); + hassioApiTools.getSnapshots().then( () => { newlog.info("Hassio API : \x1b[32mGo !\x1b[0m"); @@ -92,8 +105,6 @@ hassioApiTools.getSnapshots().then( } ); -const WebdavTools = require("./tools/webdavTools"); -const webdav = new WebdavTools().getInstance(); webdav.confIsValid().then( () => { newlog.info("Nextcloud connection : \x1b[32mGo !\x1b[0m"); @@ -103,11 +114,9 @@ webdav.confIsValid().then( newlog.error("... " + err); } ); -const settingTool = require('./tools/settingsTools') -settingTool.check(settingTool.getSettings(), true); -const cronTools = require("./tools/cronTools"); -cronTools.startCron(); + +settingsTools.check(settingsTools.getSettings(), true); +cronTools.init(); - -module.exports = app; +export default app; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www b/nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www.js similarity index 92% rename from nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www rename to nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www.js index a92c5b9..4621dc1 100755 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/bin/www.js @@ -4,9 +4,11 @@ * Module dependencies. */ -var app = require('../app'); -var debug = require('debug')('nexcloud-backup:server'); -var http = require('http'); +import app from "../app.js" +import http from "http" +import _debug from 'debug'; +const debug = _debug('nexcloud-backup:server'); + /** * Get port from environment and store in Express. diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/config/winston.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/config/winston.js index 4146856..886d5ba 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/config/winston.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/config/winston.js @@ -1,4 +1,4 @@ -const winston = require("winston"); +import winston from "winston"; const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', @@ -24,4 +24,5 @@ const logger = winston.createLogger({ ], }); -module.exports = logger; + +export default logger; \ No newline at end of file diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/package-lock.json b/nextcloud_backup/rootfs/opt/nextcloud_backup/package-lock.json index 8e26b16..1869d0c 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/package-lock.json +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/package-lock.json @@ -17,7 +17,7 @@ "ejs": "~3.1.6", "express": "~4.17.2", "form-data": "^4.0.0", - "got": "^11.8.2", + "got": "12.0.1", "http-errors": "~2.0.0", "jquery": "^3.6.0", "moment": "^2.29.1", @@ -64,9 +64,9 @@ } }, "node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", "engines": { "node": ">=10" }, @@ -75,14 +75,14 @@ } }, "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dependencies": { - "defer-to-connect": "^2.0.0" + "defer-to-connect": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=14.16" } }, "node_modules/@types/cacheable-request": { @@ -275,9 +275,9 @@ } }, "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz", + "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==", "engines": { "node": ">=10.6.0" } @@ -766,6 +766,11 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", + "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==" + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -797,29 +802,53 @@ } }, "node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.0.1.tgz", + "integrity": "sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew==", "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", + "@sindresorhus/is": "^4.2.0", + "@szmarczak/http-timer": "^5.0.1", + "@types/cacheable-request": "^6.0.2", "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-lookup": "^6.0.4", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", + "form-data-encoder": "1.7.1", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.9", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", "responselike": "^2.0.0" }, "engines": { - "node": ">=10.19.0" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/got/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got/node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -878,12 +907,12 @@ } }, "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.10.tgz", + "integrity": "sha512-QHgsdYkieKp+6JbXP25P+tepqiHYd+FVnDwXpxi/BlUcoIB0nsmTOymTNvETuTO+pDuwcSklPE72VR3DqV+Haw==", "dependencies": { "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" + "resolve-alpn": "^1.2.0" }, "engines": { "node": ">=10.19.0" @@ -1199,11 +1228,11 @@ } }, "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "engines": { - "node": ">=8" + "node": ">=12.20" } }, "node_modules/parseurl": { @@ -1662,16 +1691,16 @@ "peer": true }, "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==" }, "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "requires": { - "defer-to-connect": "^2.0.0" + "defer-to-connect": "^2.0.1" } }, "@types/cacheable-request": { @@ -1839,9 +1868,9 @@ "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" }, "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz", + "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==" }, "cacheable-request": { "version": "7.0.2", @@ -2205,6 +2234,11 @@ "mime-types": "^2.1.12" } }, + "form-data-encoder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", + "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==" + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2224,21 +2258,35 @@ } }, "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.0.1.tgz", + "integrity": "sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew==", "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", + "@sindresorhus/is": "^4.2.0", + "@szmarczak/http-timer": "^5.0.1", + "@types/cacheable-request": "^6.0.2", "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-lookup": "^6.0.4", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", + "form-data-encoder": "1.7.1", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.9", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", "responselike": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==" + } } }, "has-flag": { @@ -2286,12 +2334,12 @@ } }, "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.10.tgz", + "integrity": "sha512-QHgsdYkieKp+6JbXP25P+tepqiHYd+FVnDwXpxi/BlUcoIB0nsmTOymTNvETuTO+pDuwcSklPE72VR3DqV+Haw==", "requires": { "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" + "resolve-alpn": "^1.2.0" } }, "iconv-lite": { @@ -2534,9 +2582,9 @@ } }, "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==" }, "parseurl": { "version": "1.3.3", diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/package.json b/nextcloud_backup/rootfs/opt/nextcloud_backup/package.json index 12ad6aa..9e198d9 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/package.json +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/package.json @@ -2,8 +2,9 @@ "name": "nexcloud-backup", "version": "0.8.0", "private": true, + "type": "module", "scripts": { - "start": "node ./bin/www " + "start": "node ./bin/www.js " }, "dependencies": { "@fortawesome/fontawesome-free": "^6.0.0", @@ -15,7 +16,7 @@ "ejs": "~3.1.6", "express": "~4.17.2", "form-data": "^4.0.0", - "got": "^11.8.2", + "got": "12.0.1", "http-errors": "~2.0.0", "jquery": "^3.6.0", "moment": "^2.29.1", diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/public/js/index.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/public/js/index.js index b112116..c3fbc68 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/public/js/index.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/public/js/index.js @@ -29,13 +29,15 @@ function updateDynamicListeners() { console.log(id); }); let manual_back_list = $(".manual-back-list"); - manual_back_list.off(); + manual_back_list.unbind(); manual_back_list.on("click", function () { let id = this.getAttribute("data-id"); let name = this.getAttribute("data-name"); manualBackup(id, name); }); - $(".restore").click(function () { + let restore_btn = $(".restore"); + restore_btn.unbind(); + restore_btn.click(function () { let to_restore = this.getAttribute("data-id"); console.log(to_restore); restore(to_restore); @@ -243,7 +245,6 @@ function sendNextcloudSettings() { console.log("Saved"); $("#nextcloud_settings_message").parent().addClass("d-none"); create_toast("success", "Nextcloud settings saved !", default_toast_timeout); - 0; }) .fail((data) => { let nextcloud_settings_message = $("#nextcloud_settings_message"); diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js index 4e0ac60..d08ea77 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js @@ -1,20 +1,18 @@ -const express = require("express"); -const router = express.Router(); -const moment = require("moment"); -const statusTools = require("../tools/status"); -const WebdavTools = require("../tools/webdavTools"); -const webdav = new WebdavTools().getInstance(); -const settingsTools = require("../tools/settingsTools"); -const pathTools = require("../tools/pathTools"); -const hassioApiTools = require("../tools/hassioApiTools"); -const humanFileSize = require("../tools/toolbox").humanFileSize; +import express from 'express'; +import moment from "moment"; +import * as statusTools from "../tools/status.js" +import webdav from "../tools/webdavTools.js" +import * as settingsTools from "../tools/settingsTools.js" +import * as pathTools from "../tools/pathTools.js" +import * as hassioApiTools from "../tools/hassioApiTools.js" +import { humanFileSize } from "../tools/toolbox.js"; +import cronTools from "../tools/cronTools.js" +import logger from "../config/winston.js" -const cronTools = require("../tools/cronTools"); - -const logger = require("../config/winston"); +var router = express.Router(); router.get("/status", (req, res, next) => { - cronTools.updatetNextDate(); + cronTools.updateNextDate(); let status = statusTools.getStatus(); res.json(status); }); @@ -130,9 +128,15 @@ router.post("/manual-backup", function (req, res, next) { hassioApiTools .downloadSnapshot(id) .then(() => { - webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar").catch(); - res.status(201); - res.send(); + webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar").then(()=>{ + res.status(201); + res.send(); + }).catch(()=>{ + res.status(500); + res.send(); + } + ); + }) .catch(() => { res.status(500); @@ -161,10 +165,10 @@ router.post("/new-backup", function (req, res, next) { .then(() => { hassioApiTools.startAddons().catch(() => { }) - }); - }); - }); - }); + }).catch(()=>{}); + }).catch(()=>{}); + }).catch(()=>{}); + }).catch(()=>{}); }) .catch(() => { hassioApiTools.startAddons().catch(() => { @@ -191,7 +195,7 @@ router.post("/backup-settings", function (req, res, next) { let [result, message] = settingsTools.check(req.body) if (result) { settingsTools.setSettings(req.body); - cronTools.startCron(); + cronTools.init(); res.send(); } else { res.status(400); @@ -225,5 +229,5 @@ router.post("/restore", function (req, res, next) { } }); -module.exports = router; +export default router; \ No newline at end of file diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/index.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/index.js index f680d97..dc388ae 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/index.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/index.js @@ -1,9 +1,9 @@ -const express = require("express"); -const router = express.Router(); +import express from 'express'; +var router = express.Router(); /* GET home page. */ router.get("/", function (req, res, next) { res.render("index"); }); -module.exports = router; +export default router; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js index ba1da05..d7d92f0 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js @@ -1,23 +1,13 @@ -const CronJob = require("cron").CronJob; +import { CronJob } from "cron" +import * as settingsTools from "./settingsTools.js" +import * as hassioApiTools from "./hassioApiTools.js" +import * as statusTools from "./status.js" +import * as pathTools from "./pathTools.js" +import webdav from "./webdavTools.js" -const settingsTools = require("./settingsTools"); -const WebdavTools = require("./webdavTools"); -const webdav = new WebdavTools().getInstance(); -const hassioApiTools = require("./hassioApiTools"); -const statusTools = require("./status"); -const pathTools = require("./pathTools"); -const logger = require("../config/winston"); +import logger from "../config/winston.js" -function startCron() { - let cronContainer = new Singleton().getInstance(); - cronContainer.init(); -} - -function updatetNextDate() { - let cronContainer = new Singleton().getInstance(); - cronContainer.updateNextDate(); -} class CronContainer { constructor() { @@ -126,17 +116,6 @@ class CronContainer { } } -class Singleton { - constructor() { - if (!Singleton.instance) { - Singleton.instance = new CronContainer(); - } - } +const INSTANCE = new CronContainer(); +export default INSTANCE; - getInstance() { - return Singleton.instance; - } -} - -exports.startCron = startCron; -exports.updatetNextDate = updatetNextDate; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js index 3d69560..81cc002 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js @@ -1,23 +1,24 @@ -const fs = require("fs"); +import fs from "fs" +import moment from "moment"; +import stream from "stream" +import { promisify } from "util"; +import got from "got"; +import FormData from "form-data"; +import * as statusTools from "../tools/status.js" +import * as settingsTools from "../tools/settingsTools.js" -const moment = require("moment"); -const stream = require("stream"); -const { promisify } = require("util"); +import logger from "../config/winston.js" const pipeline = promisify(stream.pipeline); -const got = require("got"); -const FormData = require("form-data"); -const statusTools = require("./status"); -const settingsTools = require("./settingsTools"); -const logger = require("../config/winston"); -// Default timout to 90min -const create_snap_timeout = parseInt(process.env.CREATE_BACKUP_TIMEOUT) || ( 90 * 60 * 1000 ); +const token = process.env.SUPERVISOR_TOKEN; + +// Default timeout to 90min +const create_snap_timeout = parseInt(process.env.CREATE_BACKUP_TIMEOUT) || (90 * 60 * 1000); function getVersion() { return new Promise((resolve, reject) => { - let token = process.env.HASSIO_TOKEN; let status = statusTools.getStatus(); let option = { headers: { "Authorization": `Bearer ${token}` }, @@ -36,19 +37,14 @@ function getVersion() { resolve(version); }) .catch((error) => { - status.status = "error"; - status.message = "Fail to fetch HA Version (" + error.message + ")"; - status.error_code = 1; - statusTools.setStatus(status); - logger.error(status.message); - reject(error.message); + statusTools.setError(`Fail to fetch HA Version (${error.message})`, 1); + reject(`Fail to fetch HA Version (${error.message})`); }); }); } function getAddonList() { return new Promise((resolve, reject) => { - let token = process.env.HASSIO_TOKEN; let status = statusTools.getStatus(); let option = { headers: { "Authorization": `Bearer ${token}` }, @@ -78,12 +74,8 @@ function getAddonList() { resolve(installed); }) .catch((error) => { - status.status = "error"; - status.message = "Fail to fetch addons list (" + error.message + ")"; - status.error_code = 1; - statusTools.setStatus(status); - logger.error(status.message); - reject(error.message); + statusTools.setError(`Fail to fetch addons list (${error.message})`, 1); + reject(`Fail to fetch addons list (${error.message})`); }); }); } @@ -146,7 +138,6 @@ function getFolderToBackup() { function getSnapshots() { return new Promise((resolve, reject) => { - let token = process.env.HASSIO_TOKEN; let status = statusTools.getStatus(); let option = { headers: { "Authorization": `Bearer ${token}` }, @@ -165,12 +156,8 @@ function getSnapshots() { resolve(snaps); }) .catch((error) => { - status.status = "error"; - status.message = "Fail to fetch Hassio snapshots (" + error.message + ")"; - status.error_code = 1; - statusTools.setStatus(status); - logger.error(status.message); - reject(error.message); + statusTools.setError(`Fail to fetch Hassio backups (${error.message})`, 1); + reject(`Fail to fetch Hassio backups (${error.message})`); }); }); } @@ -181,7 +168,6 @@ function downloadSnapshot(id) { if (!fs.existsSync("./temp/")) fs.mkdirSync("./temp/"); let tmp_file = `./temp/${id}.tar`; let stream = fs.createWriteStream(tmp_file); - let token = process.env.HASSIO_TOKEN; let status = statusTools.getStatus(); checkSnap(id) .then(() => { @@ -203,29 +189,21 @@ function downloadSnapshot(id) { }), stream ) - .then((res) => { + .then(() => { logger.info("Download success !"); status.progress = 1; statusTools.setStatus(status); logger.debug("Snapshot dl size : " + fs.statSync(tmp_file).size / 1024 / 1024); resolve(); }) - .catch((err) => { + .catch((error) => { fs.unlinkSync(tmp_file); - status.status = "error"; - status.message = "Fail to download Hassio snapshot (" + err.message + ")"; - status.error_code = 7; - statusTools.setStatus(status); - logger.error(status.message); - reject(err.message); + statusTools.setError(`Fail to download Hassio backup (${error.message})`, 7); + reject(`Fail to download Hassio backup (${error.message})`); }); }) - .catch((err) => { - status.status = "error"; - status.message = "Fail to download Hassio snapshot. Not found ?"; - status.error_code = 7; - statusTools.setStatus(status); - logger.error(status.message); + .catch(() => { + statusTools.setError("Fail to download Hassio backup. Not found ?", 7); reject(); }); }); @@ -235,8 +213,6 @@ function dellSnap(id) { return new Promise((resolve, reject) => { checkSnap(id) .then(() => { - let token = process.env.HASSIO_TOKEN; - let option = { headers: { "Authorization": `Bearer ${token}` }, responseType: "json", @@ -257,7 +233,6 @@ function dellSnap(id) { function checkSnap(id) { return new Promise((resolve, reject) => { - let token = process.env.HASSIO_TOKEN; let option = { headers: { "Authorization": `Bearer ${token}` }, responseType: "json", @@ -279,20 +254,23 @@ function createNewBackup(name) { status.progress = -1; statusTools.setStatus(status); logger.info("Creating new snapshot..."); - let token = process.env.HASSIO_TOKEN; getAddonToBackup().then((addons) => { let folders = getFolderToBackup(); let option = { headers: { "Authorization": `Bearer ${token}` }, responseType: "json", - timeout: create_snap_timeout, + timeout: { + response: create_snap_timeout + }, json: { name: name, addons: addons, folders: folders }, }; - if (settingsTools.getSettings().password_protected === "true") { + let password_protected = settingsTools.getSettings().password_protected; + logger.debug(`Is password protected ? ${password_protected}`) + if ( password_protected === "true") { option.json.password = settingsTools.getSettings().password_protect_value } @@ -302,12 +280,8 @@ function createNewBackup(name) { resolve(result.body.data.slug); }) .catch((error) => { - status.status = "error"; - status.message = "Can't create new snapshot (" + error.message + ")"; - status.error_code = 5; - statusTools.setStatus(status); - logger.error(status.message); - reject(status.message); + statusTools.setError(`Can't create new snapshot (${error.message})`, 5); + reject(`Can't create new snapshot (${error.message})`); }); }).catch(reject); @@ -337,8 +311,9 @@ function clean() { logger.info("Local clean done."); resolve(); }) - .catch(() => { - reject(); + .catch((e) => { + statusTools.setError(`Fail to clean backups (${e}) !`, 6); + reject(`Fail to clean backups (${e}) !`); }); }); } @@ -353,15 +328,11 @@ function uploadSnapshot(path) { statusTools.setStatus(status); logger.info("Uploading backup..."); let stream = fs.createReadStream(path); - let token = process.env.HASSIO_TOKEN; - let form = new FormData(); form.append("file", stream); let options = { body: form, - username: this.username, - password: this.password, headers: { "Authorization": `Bearer ${token}` }, }; @@ -399,19 +370,15 @@ function uploadSnapshot(path) { }) .on("error", (err) => { fs.unlinkSync(path); - status.status = "error"; - status.error_code = 4; - status.message = `Fail to upload backup to home assistant (${err}) !`; - statusTools.setStatus(status); - logger.error(status.message); - reject(status.message); + statusTools.setError(`Fail to upload backup to home assistant (${err}) !`, 4); + reject(`Fail to upload backup to home assistant (${err}) !`); }); }); } function stopAddons() { return new Promise(((resolve, reject) => { - logger.info('Stopping addons...') + logger.info('Stopping addons...'); let status = statusTools.getStatus(); status.status = "stopping"; status.progress = -1; @@ -419,7 +386,6 @@ function stopAddons() { status.error_code = null; statusTools.setStatus(status); let promises = []; - let token = process.env.HASSIO_TOKEN; let option = { headers: { "Authorization": `Bearer ${token}` }, responseType: "json", @@ -427,7 +393,7 @@ function stopAddons() { let addons_slug = settingsTools.getSettings().auto_stop_addon for (let addon of addons_slug) { if (addon !== "") { - logger.debug(`... Stopping addon ${addon}`) + logger.debug(`... Stopping addon ${addon}`); promises.push(got.post(`http://hassio/addons/${addon}/stop`, option)); } @@ -439,14 +405,11 @@ function stopAddons() { error = val.reason; if (error) { - status.status = "error"; - status.error_code = 8; - status.message = `Fail to stop addons(${error}) !`; - statusTools.setStatus(status); + statusTools.setError(`Fail to stop addons(${error}) !`, 8); logger.error(status.message); reject(status.message); } else { - logger.info('... Ok') + logger.info('... Ok'); resolve(); } }); @@ -463,7 +426,6 @@ function startAddons() { status.error_code = null; statusTools.setStatus(status); let promises = []; - let token = process.env.HASSIO_TOKEN; let option = { headers: { "Authorization": `Bearer ${token}` }, responseType: "json", @@ -482,12 +444,7 @@ function startAddons() { error = val.reason; if (error) { - let status = statusTools.getStatus(); - status.status = "error"; - status.error_code = 9; - status.message = `Fail to start addons (${error}) !`; - statusTools.setStatus(status); - logger.error(status.message); + statusTools.setError(`Fail to start addons (${error}) !`, 9) reject(status.message); } else { logger.info('... Ok') @@ -502,7 +459,7 @@ function startAddons() { })); } -function publish_state(state){ +function publish_state(state) { // let data_error_sensor = { // state: state.status == "error" ? "on" : "off", @@ -516,7 +473,6 @@ function publish_state(state){ // } - // let token = process.env.HASSIO_TOKEN; // let option = { // headers: { "Authorization": `Bearer ${token}` }, // responseType: "json", @@ -572,14 +528,16 @@ function publish_state(state){ // }); } -exports.getVersion = getVersion; -exports.getAddonList = getAddonList; -exports.getFolderList = getFolderList; -exports.getSnapshots = getSnapshots; -exports.downloadSnapshot = downloadSnapshot; -exports.createNewBackup = createNewBackup; -exports.uploadSnapshot = uploadSnapshot; -exports.stopAddons = stopAddons; -exports.startAddons = startAddons; -exports.clean = clean; -exports.publish_state = publish_state; +export { + getVersion, + getAddonList, + getFolderList, + getSnapshots, + downloadSnapshot, + createNewBackup, + uploadSnapshot, + stopAddons, + startAddons, + clean, + publish_state +} diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/pathTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/pathTools.js index 83e5458..e69637e 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/pathTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/pathTools.js @@ -1,4 +1,4 @@ -let default_root = "/Hassio Backup/"; -exports.default_root = default_root; -exports.manual = "Manual/"; -exports.auto = "Auto/"; +const default_root = "/Hassio Backup/"; +export { default_root }; +export const manual = "Manual/"; +export const auto = "Auto/"; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js index 03a6d96..502dd63 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js @@ -1,7 +1,8 @@ -const fs = require("fs"); -const logger = require("../config/winston"); -const moment = require("moment"); -const CronJob = require("cron").CronJob; +import fs from "fs" +import moment from "moment"; +import { CronJob } from "cron"; + +import logger from "../config/winston.js" const settingsPath = "/data/backup_conf.json"; @@ -24,6 +25,7 @@ function check_cron(conf) { if (conf.cron_base === "4") { if (conf.cron_custom != null) { try { + // TODO Need to be destroy new CronJob(conf.cron_custom, () => {}); return true; } catch(e) { @@ -187,8 +189,4 @@ function setSettings(settings) { fs.writeFileSync(settingsPath, JSON.stringify(settings)); } -exports.getSettings = getSettings; -exports.setSettings = setSettings; -exports.check = check; -exports.check_cron = check_cron; -exports.getFormatedName = getFormatedName; +export { getSettings, setSettings, check, check_cron, getFormatedName }; \ No newline at end of file diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/status.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/status.js index fb3c826..c627c4c 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/status.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/status.js @@ -1,49 +1,38 @@ -const fs = require("fs"); -const hassioApiTools = require("./hassioApiTools"); +import * as hassioApiTools from "./hassioApiTools.js"; +import logger from "../config/winston.js" -const statusPath = "/data/status.json"; -let baseStatus = { +let status = { status: "idle", last_backup: null, next_backup: null, }; -function init() { - if (!fs.existsSync(statusPath)) { - fs.writeFileSync(statusPath, JSON.stringify(baseStatus)); - } else { - let content = getStatus(); - if (content.status !== "idle") { - content.status = "idle"; - content.message = null; - setStatus(content); - } +export function init() { + if (status.status !== "idle") { + status.status = "idle"; + status.message = null; } } -function getStatus() { - if (!fs.existsSync(statusPath)) { - fs.writeFileSync(statusPath, JSON.stringify(baseStatus)); - } - return JSON.parse(fs.readFileSync(statusPath).toString()); +export function getStatus() { + return status; } -function setStatus(state) { - if (fs.existsSync(statusPath)) { - let old_state_str = fs.readFileSync(statusPath).toString(); - if(old_state_str !== JSON.stringify(state)){ - fs.writeFileSync(statusPath, JSON.stringify(state)); - hassioApiTools.publish_state(state); - } - }else{ - fs.writeFileSync(statusPath, JSON.stringify(state)); - hassioApiTools.publish_state(state); +export function setStatus(new_state) { + let old_state_str = JSON.stringify(status); + if(old_state_str !== JSON.stringify(new_state)){ + status = new_state; + hassioApiTools.publish_state(status); } - - } -exports.init = init; -exports.getStatus = getStatus; -exports.setStatus = setStatus; +export function setError(message, error_code){ + // Check if we don't have another error stored + if (status.status != "error") { + status.status = "error" + status.message = message + status.error_code = error_code; + } + logger.error(message); +} diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/toolbox.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/toolbox.js index e9001ef..7def70b 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/toolbox.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/toolbox.js @@ -18,4 +18,4 @@ function humanFileSize(bytes, si = false, dp = 1) { return bytes.toFixed(dp) + " " + units[u]; } -exports.humanFileSize = humanFileSize; +export { humanFileSize } ; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/webdavTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/webdavTools.js index 0633cc8..5b9b46e 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/webdavTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/webdavTools.js @@ -1,20 +1,21 @@ -const { createClient } = require("webdav"); -const fs = require("fs"); -const moment = require("moment"); -const https = require("https"); +import { createClient } from "webdav"; +import fs from "fs" +import moment from "moment"; +import https from "https" +import path from "path"; +import got from "got"; +import stream from "stream"; +import { promisify } from "util"; + +import * as statusTools from "../tools/status.js" +import * as settingsTools from "../tools/settingsTools.js" +import * as pathTools from "../tools/pathTools.js" +import * as hassioApiTools from "../tools/hassioApiTools.js" +import logger from "../config/winston.js" -const statusTools = require("./status"); const endpoint = "/remote.php/webdav"; const configPath = "/data/webdav_conf.json"; -const path = require("path"); -const settingsTools = require("./settingsTools"); -const pathTools = require("./pathTools"); -const hassioApiTools = require("./hassioApiTools"); -const logger = require("../config/winston"); -const got = require("got"); -const stream = require("stream"); -const { promisify } = require("util"); const pipeline = promisify(stream.pipeline); class WebdavTools { @@ -69,12 +70,7 @@ class WebdavTools { }); } __cant_connect_status(err){ - let status = statusTools.getStatus(); - status.status = "error"; - status.error_code = 3; - status.message = "Can't connect to Nextcloud (" + err + ") !"; - statusTools.setStatus(status); - logger.error("Can't connect to Nextcloud (" + err + ") !"); + statusTools.setError(`Can't connect to Nextcloud (${err})`, 3); } async __createRoot() { @@ -427,16 +423,5 @@ function cleanTempFolder() { }); } -class Singleton { - constructor() { - if (!Singleton.instance) { - Singleton.instance = new WebdavTools(); - } - } - - getInstance() { - return Singleton.instance; - } -} - -module.exports = Singleton; +const INSTANCE = new WebdavTools(); +export default INSTANCE;