mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-30 04:44:54 +01:00
Compare commits
4 Commits
ace8fe7caa
...
2c03791db5
Author | SHA1 | Date | |
---|---|---|---|
2c03791db5 | |||
049beb53b8 | |||
bd0fbe81c2 | |||
a22962902d |
@ -1,8 +1,7 @@
|
|||||||
import cookieParser from "cookie-parser";
|
import cookieParser from "cookie-parser";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import errorHandler from "errorhandler";
|
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import createError from "http-errors";
|
|
||||||
import morgan from "morgan";
|
import morgan from "morgan";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
@ -20,10 +19,11 @@ app.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
app.set("port", process.env.PORT || 3000);
|
app.set("port", process.env.PORT || 3000);
|
||||||
|
if (process.env.ACCESS_LOG == "true") {
|
||||||
// app.use(
|
app.use(
|
||||||
// morgan("dev", { stream: { write: (message) => logger.debug(message) } })
|
morgan("dev", { stream: { write: (message) => logger.debug(message) } })
|
||||||
// );
|
);
|
||||||
|
}
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.urlencoded({ extended: false }));
|
app.use(express.urlencoded({ extended: false }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
@ -36,15 +36,4 @@ app.use("/v2/api/", apiV2Router);
|
|||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// error handler
|
|
||||||
if (app.get("env") == "development") {
|
|
||||||
// catch 404 and forward to error handler
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
next(createError(404));
|
|
||||||
});
|
|
||||||
|
|
||||||
// only use in development
|
|
||||||
app.use(errorHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
import errorHandler from "errorhandler";
|
|
||||||
import "./env.js";
|
import "./env.js";
|
||||||
|
|
||||||
|
import errorHandler from "errorhandler";
|
||||||
|
import figlet from "figlet";
|
||||||
|
import createError from "http-errors";
|
||||||
|
import kleur from "kleur";
|
||||||
import app from "./app.js";
|
import app from "./app.js";
|
||||||
import logger from "./config/winston.js";
|
import logger from "./config/winston.js";
|
||||||
import postInit from "./postInit.js";
|
import postInit from "./postInit.js";
|
||||||
import figlet from "figlet";
|
|
||||||
import kleur from "kleur";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error Handler. Provides full stack
|
* Error Handler. Provides full stack
|
||||||
*/
|
*/
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
app.use(errorHandler());
|
app.use(errorHandler());
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
next(createError(404));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +27,7 @@ const server = app.listen(app.get("port"), () => {
|
|||||||
`App is running at ` +
|
`App is running at ` +
|
||||||
kleur.green().bold(`http://localhost:${app.get("port")}`) +
|
kleur.green().bold(`http://localhost:${app.get("port")}`) +
|
||||||
" in " +
|
" in " +
|
||||||
kleur.green().bold(app.get("env") as string) +
|
kleur.green().bold(process.env.NODE_ENV || "production") +
|
||||||
" mode"
|
" mode"
|
||||||
);
|
);
|
||||||
logger.info(kleur.red().bold("Press CTRL-C to stop"));
|
logger.info(kleur.red().bold("Press CTRL-C to stop"));
|
||||||
|
@ -343,7 +343,7 @@ export async function chunkedUpload(
|
|||||||
const finalDestination = config.url + getEndpoint(config) + webdavPath;
|
const finalDestination = config.url + getEndpoint(config) + webdavPath;
|
||||||
const status = statusTools.getStatus();
|
const status = statusTools.getStatus();
|
||||||
status.status = States.BKUP_UPLOAD_CLOUD;
|
status.status = States.BKUP_UPLOAD_CLOUD;
|
||||||
status.progress = 0;
|
status.progress = -1;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
try {
|
try {
|
||||||
await initChunkedUpload(chunkedUrl, finalDestination, config);
|
await initChunkedUpload(chunkedUrl, finalDestination, config);
|
||||||
@ -365,16 +365,21 @@ export async function chunkedUpload(
|
|||||||
logger.error((err as Error).message);
|
logger.error((err as Error).message);
|
||||||
}
|
}
|
||||||
fs.unlinkSync(localPath);
|
fs.unlinkSync(localPath);
|
||||||
|
const status = statusTools.getStatus();
|
||||||
|
status.status = States.IDLE;
|
||||||
|
status.progress = undefined;
|
||||||
|
statusTools.setStatus(status);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = 0;
|
let start = 0;
|
||||||
let end = fileSize > CHUNK_SIZE ? CHUNK_SIZE : fileSize;
|
let end = Math.min(CHUNK_SIZE - 1, fileSize - 1);
|
||||||
let current_size = end;
|
|
||||||
|
let current_size = end + 1;
|
||||||
// const uploadedBytes = 0;
|
// const uploadedBytes = 0;
|
||||||
|
|
||||||
let i = 0;
|
let i = 1;
|
||||||
while (start < fileSize) {
|
while (start < fileSize - 1) {
|
||||||
const chunk = fs.createReadStream(localPath, { start, end });
|
const chunk = fs.createReadStream(localPath, { start, end });
|
||||||
try {
|
try {
|
||||||
const chunckNumber = i.toString().padStart(CHUNK_NUMBER_SIZE, "0");
|
const chunckNumber = i.toString().padStart(CHUNK_NUMBER_SIZE, "0");
|
||||||
@ -386,9 +391,9 @@ export async function chunkedUpload(
|
|||||||
fileSize,
|
fileSize,
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
start = end;
|
start = end + 1;
|
||||||
end = Math.min(start + CHUNK_SIZE, fileSize - 1);
|
end = Math.min(start + CHUNK_SIZE - 1, fileSize - 1);
|
||||||
current_size = end - start;
|
current_size = end - start + 1;
|
||||||
i++;
|
i++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
@ -408,6 +413,10 @@ export async function chunkedUpload(
|
|||||||
logger.error(`Code: ${(error as PlainResponse).statusCode}`);
|
logger.error(`Code: ${(error as PlainResponse).statusCode}`);
|
||||||
logger.error(`Body: ${(error as PlainResponse).body as string}`);
|
logger.error(`Body: ${(error as PlainResponse).body as string}`);
|
||||||
}
|
}
|
||||||
|
const status = statusTools.getStatus();
|
||||||
|
status.status = States.IDLE;
|
||||||
|
status.progress = undefined;
|
||||||
|
statusTools.setStatus(status);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,6 +444,10 @@ export async function chunkedUpload(
|
|||||||
logger.error((err as Error).message);
|
logger.error((err as Error).message);
|
||||||
}
|
}
|
||||||
fs.unlinkSync(localPath);
|
fs.unlinkSync(localPath);
|
||||||
|
const status = statusTools.getStatus();
|
||||||
|
status.status = States.IDLE;
|
||||||
|
status.progress = undefined;
|
||||||
|
statusTools.setStatus(status);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,6 +465,7 @@ export function uploadChunk(
|
|||||||
logger.debug(`...URI: ${encodeURI(url)}`);
|
logger.debug(`...URI: ${encodeURI(url)}`);
|
||||||
logger.debug(`...Final destination: ${encodeURI(finalDestination)}`);
|
logger.debug(`...Final destination: ${encodeURI(finalDestination)}`);
|
||||||
logger.debug(`...Chunk size: ${contentLength}`);
|
logger.debug(`...Chunk size: ${contentLength}`);
|
||||||
|
logger.debug(`...Total size: ${totalLength}`);
|
||||||
got.stream
|
got.stream
|
||||||
.put(url, {
|
.put(url, {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -1,35 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-fade-transition>
|
<v-fade-transition>
|
||||||
<div id="alertContainer" v-if="alertVisible">
|
<div id="parent" v-if="alertVisible">
|
||||||
<v-slide-x-transition group tag="div">
|
<div id="alertContainer">
|
||||||
<v-alert
|
<v-slide-x-transition group tag="div">
|
||||||
v-for="alert of alertList"
|
<v-alert
|
||||||
v-bind:key="alert.id"
|
v-for="alert of alertList"
|
||||||
elevation="24"
|
v-bind:key="alert.id"
|
||||||
:type="alert.type"
|
elevation="24"
|
||||||
border="start"
|
:type="alert.type"
|
||||||
class="mb-2"
|
border="start"
|
||||||
>
|
class="mb-2"
|
||||||
<v-row dense>
|
>
|
||||||
<v-col v-html="alert.message"></v-col>
|
<v-row dense>
|
||||||
<v-col cols="2">
|
<v-col v-html="alert.message"></v-col>
|
||||||
<v-btn
|
<v-col cols="2">
|
||||||
class="d-inline"
|
<v-btn
|
||||||
size="30"
|
class="d-inline"
|
||||||
variant="text"
|
size="30"
|
||||||
rounded
|
variant="text"
|
||||||
icon="$close"
|
rounded
|
||||||
@click="alertStore.remove(alert.id)"
|
icon="$close"
|
||||||
></v-btn>
|
@click="alertStore.remove(alert.id)"
|
||||||
</v-col>
|
></v-btn>
|
||||||
</v-row>
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<v-progress-linear
|
<v-progress-linear
|
||||||
:max="alertStore.timeOutValue"
|
:max="alertStore.timeOutValue"
|
||||||
:model-value="alert.timeOut"
|
:model-value="alert.timeOut"
|
||||||
></v-progress-linear>
|
></v-progress-linear>
|
||||||
</v-alert>
|
</v-alert>
|
||||||
</v-slide-x-transition>
|
</v-slide-x-transition>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</v-fade-transition>
|
</v-fade-transition>
|
||||||
</template>
|
</template>
|
||||||
@ -45,11 +47,17 @@ const { alertList } = storeToRefs(alertStore);
|
|||||||
const alertVisible = computed(() => alertList.value.length > 0);
|
const alertVisible = computed(() => alertList.value.length > 0);
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
#alertContainer {
|
#parent {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 70px;
|
top: 70px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
|
height: 100vh;
|
||||||
|
#alertContainer {
|
||||||
|
position: sticky;
|
||||||
|
top: 80px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@/store/alert
|
@/store/alert
|
||||||
|
@ -32,9 +32,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useMenuSize } from "@/composable/menuSize";
|
import { useMenuSize } from "@/composable/menuSize";
|
||||||
import { deleteWebdabBackup } from "@/services/webdavService";
|
import { deleteWebdabBackup } from "@/services/webdavService";
|
||||||
|
import { useAlertStore } from "@/store/alert";
|
||||||
import type { WebdavBackup } from "@/types/webdav";
|
import type { WebdavBackup } from "@/types/webdav";
|
||||||
import { computed, ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useDisplay } from "vuetify/dist/vuetify";
|
|
||||||
|
|
||||||
const dialog = ref(false);
|
const dialog = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -42,6 +42,11 @@ const item = ref<WebdavBackup | null>(null);
|
|||||||
|
|
||||||
const { width, isFullScreen } = useMenuSize();
|
const { width, isFullScreen } = useMenuSize();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "deleted"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const alertStore = useAlertStore();
|
||||||
function confirm() {
|
function confirm() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (item.value) {
|
if (item.value) {
|
||||||
@ -49,9 +54,12 @@ function confirm() {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
dialog.value = false;
|
dialog.value = false;
|
||||||
|
alertStore.add("success", "Backup deleted from cloud");
|
||||||
|
emit("deleted");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
alertStore.add("error", "Fail to deleted backup from cloud");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,10 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
<cloud-delete-dialog ref="deleteDialog"></cloud-delete-dialog>
|
<cloud-delete-dialog
|
||||||
|
ref="deleteDialog"
|
||||||
|
@deleted="refreshBackup"
|
||||||
|
></cloud-delete-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -69,4 +69,3 @@ function saved() {
|
|||||||
alertStore.add("success", "Backup settings saved !");
|
alertStore.add("success", "Backup settings saved !");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@/store/dialogStatus@/store/alert
|
|
||||||
|
Loading…
Reference in New Issue
Block a user