From 229b9dab9a04b95c2b1ccc894d5c10f0500e0319 Mon Sep 17 00:00:00 2001 From: SebClem Date: Fri, 30 Sep 2022 19:13:39 +0200 Subject: [PATCH] :hammer: Webdav -> add check credential + init folder --- nextcloud_backup/backend/src/postInit.ts | 45 ++++++++--- .../src/services/webdavConfigService.ts | 34 +++++--- .../backend/src/services/webdavService.ts | 79 +++++++++++++++++++ 3 files changed, 138 insertions(+), 20 deletions(-) diff --git a/nextcloud_backup/backend/src/postInit.ts b/nextcloud_backup/backend/src/postInit.ts index b027708..4ec27ac 100644 --- a/nextcloud_backup/backend/src/postInit.ts +++ b/nextcloud_backup/backend/src/postInit.ts @@ -3,8 +3,12 @@ import logger from "./config/winston.js"; import * as homeAssistantService from "./services/homeAssistantService.js"; import * as settingsTools from "./tools/settingsTools.js"; import * as statusTools from "./tools/status.js"; -import kleur from 'kleur'; - +import kleur from "kleur"; +import { checkWebdavLogin, createBackupFolder } from "./services/webdavService.js"; +import { + getWebdavConfig, + validateWebdavConfig, +} from "./services/webdavConfigService.js"; function postInit() { logger.info(`Log level: ${process.env.LOG_LEVEL}`); @@ -31,15 +35,34 @@ function postInit() { } ); - // webdav.confIsValid().then( - // () => { - // newlog.info("Nextcloud connection : \x1b[32mGo !\x1b[0m"); - // }, - // (err) => { - // newlog.error("Nextcloud connection : \x1b[31;1mFAIL !\x1b[0m"); - // newlog.error("... " + err); - // } - // ); + const webdavConf = getWebdavConfig(); + validateWebdavConfig(webdavConf).then( + () => { + logger.info("Webdav config: " + kleur.green().bold("Go !")); + checkWebdavLogin(webdavConf).then( + () => { + logger.info("Webdav : " + kleur.green().bold("Go !")); + createBackupFolder(webdavConf).then( + () => { + logger.info("Webdav fodlers: " + kleur.green().bold("Go !")); + }, + (reason) => { + logger.error("Webdav folders: " + kleur.red().bold("FAIL !")); + logger.error(reason); + } + ); + }, + (reason) => { + logger.error("Webdav : " + kleur.red().bold("FAIL !")); + logger.error(reason); + } + ); + }, + (reason) => { + logger.error("Webdav config: " + kleur.red().bold("FAIL !")); + logger.error(reason); + } + ); settingsTools.check(settingsTools.getSettings(), true); // cronTools.init(); diff --git a/nextcloud_backup/backend/src/services/webdavConfigService.ts b/nextcloud_backup/backend/src/services/webdavConfigService.ts index 060c1aa..c90b383 100644 --- a/nextcloud_backup/backend/src/services/webdavConfigService.ts +++ b/nextcloud_backup/backend/src/services/webdavConfigService.ts @@ -1,26 +1,29 @@ import fs from "fs"; -import Joi from "joi" +import Joi from "joi"; import logger from "../config/winston.js"; import { default_root } from "../tools/pathTools.js"; import WebdavConfigValidation from "../types/services/webdavConfigValidation.js"; -import { WebdavConfig, WebdavEndpointType } from "../types/services/webdavConfig.js" - +import { + WebdavConfig, + WebdavEndpointType, +} from "../types/services/webdavConfig.js"; const webdavConfigPath = "/data/webdavConfigV2.json"; +const NEXTCLOUD_ENDPOINT = "/remote.php/dav/files/$username"; -export function validateWebdavConfig(config: WebdavConfig){ +export function validateWebdavConfig(config: WebdavConfig) { const validator = Joi.object(WebdavConfigValidation); return validator.validateAsync(config); } -export function saveWebdavConfig(config: WebdavConfig){ +export function saveWebdavConfig(config: WebdavConfig) { fs.writeFileSync(webdavConfigPath, JSON.stringify(config, undefined, 2)); } export function getWebdavConfig(): WebdavConfig { if (!fs.existsSync(webdavConfigPath)) { - logger.warn("Webdav Config file not found, creating default one !") + logger.warn("Webdav Config file not found, creating default one !"); const defaultConfig = getWebdavDefaultConfig(); saveWebdavConfig(defaultConfig); return defaultConfig; @@ -29,6 +32,19 @@ export function getWebdavConfig(): WebdavConfig { } } +export function getEndpoint(config: WebdavConfig) { + if (config.webdavEndpoint.type == WebdavEndpointType.NEXTCLOUD) { + return NEXTCLOUD_ENDPOINT.replace("$username", config.username); + } else if (config.webdavEndpoint.customEndpoint) { + return config.webdavEndpoint.customEndpoint.replace( + "$username", + config.username + ); + } else { + return ""; + } +} + export function getWebdavDefaultConfig(): WebdavConfig { return { url: "", @@ -38,6 +54,6 @@ export function getWebdavDefaultConfig(): WebdavConfig { allowSelfSignedCerts: false, webdavEndpoint: { type: WebdavEndpointType.NEXTCLOUD, - } - } -} \ No newline at end of file + }, + }; +} diff --git a/nextcloud_backup/backend/src/services/webdavService.ts b/nextcloud_backup/backend/src/services/webdavService.ts index f79e8d0..cc30c21 100644 --- a/nextcloud_backup/backend/src/services/webdavService.ts +++ b/nextcloud_backup/backend/src/services/webdavService.ts @@ -1,3 +1,82 @@ +import got, { HTTPError, Method } from "got"; +import logger from "../config/winston.js"; +import messageManager from "../tools/messageManager.js"; +import { WebdavConfig } from "../types/services/webdavConfig.js"; +import { getEndpoint } from "./webdavConfigService.js"; +import * as pathTools from "../tools/pathTools.js"; + +export function checkWebdavLogin(config: WebdavConfig) { + const endpoint = getEndpoint(config); + return got(config.url + endpoint, { + method: "OPTIONS", + headers: { + authorization: + "Basic " + + Buffer.from(config.username + ":" + config.password).toString("base64"), + }, + }).then( + (response) => { + return response; + }, + (reason) => { + messageManager.error("Fail to connect to Webdav", reason?.message); + logger.error(`Fail to connect to Webdav`); + logger.error(reason); + return Promise.reject(reason); + } + ); +} + +export async function createBackupFolder(conf: WebdavConfig) { + const root_splited = conf.backupDir.split("/").splice(1); + let path = "/"; + for (const elem of root_splited) { + if (elem != "") { + path = path + elem + "/"; + try { + await createDirectory(path, conf); + logger.debug(`Path ${path} created.`); + } catch (error) { + if (error instanceof HTTPError && error.response.statusCode == 405) + logger.debug(`Path ${path} already exist.`); + else { + messageManager.error("Fail to create webdav root folder"); + logger.error("Fail to create webdav root folder"); + logger.error(error); + return Promise.reject(error); + } + } + } + } + for (const elem of [pathTools.auto, pathTools.manual]) { + try { + await createDirectory(conf.backupDir + elem, conf); + logger.debug(`Path ${conf.backupDir + elem} created.`); + } catch (error) { + if (error instanceof HTTPError && error.response.statusCode == 405) { + logger.debug(`Path ${conf.backupDir + elem} already exist.`); + } else { + messageManager.error("Fail to create webdav root folder"); + logger.error("Fail to create webdav root folder"); + logger.error(error); + return Promise.reject(error); + } + } + } +} + +function createDirectory(path: string, config: WebdavConfig) { + const endpoint = getEndpoint(config); + return got(config.url + endpoint + path, { + method: "MKCOL" as Method, + headers: { + authorization: + "Basic " + + Buffer.from(config.username + ":" + config.password).toString("base64"), + }, + }); +} + // import fs from "fs"; // import got from "got"; // import https from "https";