mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
Still working on backup & restore
This commit is contained in:
parent
bb700f3a3d
commit
27de7ddbf8
@ -136,17 +136,17 @@ class DashboardLogger:
|
|||||||
|
|
||||||
def log(self, URL: str = "", IP: str = "", Status: str = "true", Message: str = "") -> bool:
|
def log(self, URL: str = "", IP: str = "", Status: str = "true", Message: str = "") -> bool:
|
||||||
pass
|
pass
|
||||||
# try:
|
try:
|
||||||
# with self.loggerdb:
|
with self.loggerdb:
|
||||||
# loggerdbCursor = self.loggerdb.cursor()
|
loggerdbCursor = self.loggerdb.cursor()
|
||||||
# loggerdbCursor.execute(
|
loggerdbCursor.execute(
|
||||||
# "INSERT INTO DashboardLog (LogID, URL, IP, Status, Message) VALUES (?, ?, ?, ?, ?)", (str(uuid.uuid4()), URL, IP, Status, Message,))
|
"INSERT INTO DashboardLog (LogID, URL, IP, Status, Message) VALUES (?, ?, ?, ?, ?)", (str(uuid.uuid4()), URL, IP, Status, Message,))
|
||||||
# if self.loggerdb.in_transaction:
|
if self.loggerdb.in_transaction:
|
||||||
# self.loggerdb.commit()
|
self.loggerdb.commit()
|
||||||
# return True
|
return True
|
||||||
# except Exception as e:
|
except Exception as e:
|
||||||
# print(f"[WGDashboard] Access Log Error: {str(e)}")
|
print(f"[WGDashboard] Access Log Error: {str(e)}")
|
||||||
# return False
|
return False
|
||||||
|
|
||||||
class PeerJobLogger:
|
class PeerJobLogger:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -587,7 +587,6 @@ class WireguardConfiguration:
|
|||||||
return changed
|
return changed
|
||||||
|
|
||||||
def __getPeers(self):
|
def __getPeers(self):
|
||||||
|
|
||||||
if self.configurationFileChanged():
|
if self.configurationFileChanged():
|
||||||
self.Peers = []
|
self.Peers = []
|
||||||
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'r') as configFile:
|
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'r') as configFile:
|
||||||
@ -663,7 +662,6 @@ class WireguardConfiguration:
|
|||||||
checkIfExist = sqlSelect("SELECT * FROM '%s'" % self.Name).fetchall()
|
checkIfExist = sqlSelect("SELECT * FROM '%s'" % self.Name).fetchall()
|
||||||
for i in checkIfExist:
|
for i in checkIfExist:
|
||||||
self.Peers.append(Peer(i, self))
|
self.Peers.append(Peer(i, self))
|
||||||
|
|
||||||
|
|
||||||
def addPeers(self, peers: list):
|
def addPeers(self, peers: list):
|
||||||
for p in peers:
|
for p in peers:
|
||||||
@ -918,6 +916,39 @@ class WireguardConfiguration:
|
|||||||
"TotalPeers": len(self.Peers)
|
"TotalPeers": len(self.Peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def backupConfigurationFile(self):
|
||||||
|
if not os.path.exists(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup')):
|
||||||
|
os.mkdir(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup'))
|
||||||
|
shutil.copy(
|
||||||
|
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'),
|
||||||
|
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup', f'{self.Name}_{datetime.now().strftime("%Y%m%d%H%M%S")}.conf')
|
||||||
|
)
|
||||||
|
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'w') as f:
|
||||||
|
f.write("\n".join(original))
|
||||||
|
|
||||||
|
def getBackups(self):
|
||||||
|
backups = []
|
||||||
|
|
||||||
|
directory = os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup')
|
||||||
|
files = [(file, os.path.getctime(os.path.join(directory, file)))
|
||||||
|
for file in os.listdir(directory) if os.path.isfile(os.path.join(directory, file))]
|
||||||
|
files.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
|
||||||
|
for f, ct in files:
|
||||||
|
if _regexMatch(f"^({self.Name})_(.*)\.(conf)$", f):
|
||||||
|
s = re.search(f"^({self.Name})_(.*)\.(conf)$", f)
|
||||||
|
date = s.group(2)
|
||||||
|
backups.append({
|
||||||
|
"filename": f,
|
||||||
|
"backupDate": date,
|
||||||
|
"content": open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup', f), 'r').read()
|
||||||
|
})
|
||||||
|
|
||||||
|
return backups
|
||||||
|
|
||||||
|
def restoreBackup(self, backupFileName: str):
|
||||||
|
pass
|
||||||
|
|
||||||
def updateConfigurationSettings(self, newData: dict) -> tuple[bool, str]:
|
def updateConfigurationSettings(self, newData: dict) -> tuple[bool, str]:
|
||||||
if self.Status:
|
if self.Status:
|
||||||
self.toggleConfiguration()
|
self.toggleConfiguration()
|
||||||
@ -927,8 +958,6 @@ class WireguardConfiguration:
|
|||||||
original = f.readlines()
|
original = f.readlines()
|
||||||
original = [l.rstrip("\n") for l in original]
|
original = [l.rstrip("\n") for l in original]
|
||||||
allowEdit = ["Address", "PreUp", "PostUp", "PreDown", "PostDown", "ListenPost", "PrivateKey"]
|
allowEdit = ["Address", "PreUp", "PostUp", "PreDown", "PostDown", "ListenPost", "PrivateKey"]
|
||||||
|
|
||||||
|
|
||||||
start = original.index("[Interface]")
|
start = original.index("[Interface]")
|
||||||
for line in range(start+1, len(original)):
|
for line in range(start+1, len(original)):
|
||||||
if original[line] == "[Peer]":
|
if original[line] == "[Peer]":
|
||||||
@ -947,15 +976,7 @@ class WireguardConfiguration:
|
|||||||
dataChanged = True
|
dataChanged = True
|
||||||
print(original[line])
|
print(original[line])
|
||||||
if dataChanged:
|
if dataChanged:
|
||||||
|
self.backupConfigurationFile()
|
||||||
if not os.path.exists(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup')):
|
|
||||||
os.mkdir(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup'))
|
|
||||||
shutil.copy(
|
|
||||||
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'),
|
|
||||||
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup', f'{self.Name}_{datetime.now().strftime("%Y%m%d%H%M%S")}.conf')
|
|
||||||
)
|
|
||||||
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'w') as f:
|
|
||||||
f.write("\n".join(original))
|
|
||||||
|
|
||||||
|
|
||||||
status, msg = self.toggleConfiguration()
|
status, msg = self.toggleConfiguration()
|
||||||
@ -1663,6 +1684,13 @@ def API_updateWireguardConfiguration():
|
|||||||
|
|
||||||
return ResponseObject(status, message=msg, data=WireguardConfigurations[name])
|
return ResponseObject(status, message=msg, data=WireguardConfigurations[name])
|
||||||
|
|
||||||
|
@app.get(f'{APP_PREFIX}/api/getWireguardConfigurationBackup')
|
||||||
|
def API_getWireguardConfigurationBackup():
|
||||||
|
configurationName = request.args.get('configurationName')
|
||||||
|
if configurationName is None or configurationName not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
return ResponseObject(data=WireguardConfigurations[configurationName].getBackups())
|
||||||
|
|
||||||
@app.get(f'{APP_PREFIX}/api/getDashboardConfiguration')
|
@app.get(f'{APP_PREFIX}/api/getDashboardConfiguration')
|
||||||
def API_getDashboardConfiguration():
|
def API_getDashboardConfiguration():
|
||||||
return ResponseObject(data=DashboardConfig.toJson())
|
return ResponseObject(data=DashboardConfig.toJson())
|
||||||
|
@ -5,6 +5,8 @@ import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStor
|
|||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import router from "@/router/index.js";
|
import router from "@/router/index.js";
|
||||||
|
import ConfigurationBackupRestore
|
||||||
|
from "@/components/configurationComponents/editConfigurationComponents/configurationBackupRestore.vue";
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
configurationInfo: Object
|
configurationInfo: Object
|
||||||
})
|
})
|
||||||
@ -177,13 +179,17 @@ watch(data, () => {
|
|||||||
:disabled="!dataChanged || saving">
|
:disabled="!dataChanged || saving">
|
||||||
<i class="bi bi-arrow-clockwise"></i>
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 px-3 py-2 shadow"
|
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 px-3 py-2 shadow"
|
||||||
:disabled="!dataChanged || saving"
|
:disabled="!dataChanged || saving"
|
||||||
@click="saveForm()"
|
@click="saveForm()"
|
||||||
>
|
>
|
||||||
<i class="bi bi-save-fill"></i></button>
|
<i class="bi bi-save-fill"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
|
<h6>
|
||||||
|
<LocaleText t="Backup & Restore"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
<ConfigurationBackupRestore></ConfigurationBackupRestore>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
<script setup>
|
||||||
|
import {onMounted, reactive, ref} from "vue";
|
||||||
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const backups = ref([])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchGet("/api/getWireguardConfigurationBackup", {
|
||||||
|
configurationName: route.params.id
|
||||||
|
}, (res) => {
|
||||||
|
backups.value = res.data;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="card rounded-3" style="height: 400px; overflow-y: scroll">
|
||||||
|
<div class="card-body d-flex gap-2 flex-column">
|
||||||
|
<div class="card" v-for="b in backups">
|
||||||
|
<div class="card-body p-2 px-3">
|
||||||
|
<div class="d-flex gap-3 align-items-center">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small class="text-muted">
|
||||||
|
Filename
|
||||||
|
</small>
|
||||||
|
<small>
|
||||||
|
{{b.filename}}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small class="text-muted">
|
||||||
|
Backup Date
|
||||||
|
</small>
|
||||||
|
<small>
|
||||||
|
{{dayjs(b.backupDate, "YYYYMMDDHHmmss").format("YYYY-MM-DD HH:mm:ss")}}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2 align-items-center ms-auto">
|
||||||
|
<button class="btn bg-info-subtle text-info-emphasis border-info-subtle rounded-3 btn-sm">
|
||||||
|
<i class="bi bi-eye-fill"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn bg-warning-subtle text-warning-emphasis border-warning-subtle rounded-3 btn-sm">
|
||||||
|
<i class="bi bi-clock-history"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn bg-danger-subtle text-danger-emphasis border-danger-subtle rounded-3 btn-sm">
|
||||||
|
<i class="bi bi-trash-fill"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -145,10 +145,10 @@ export default {
|
|||||||
selectedPeer: undefined
|
selectedPeer: undefined
|
||||||
},
|
},
|
||||||
editConfiguration: {
|
editConfiguration: {
|
||||||
modalOpen: false
|
modalOpen: true
|
||||||
},
|
},
|
||||||
selectPeers: {
|
selectPeers: {
|
||||||
modalOpen: true
|
modalOpen: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -231,19 +231,17 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<button class="btn btn-secondary rounded-3 shadow"
|
<button class="btn bg-secondary-subtle border-secondary-subtle text-secondary-emphasis rounded-3 shadow ms-auto px-3 py-2"
|
||||||
@click="this.reset()"
|
@click="this.reset()"
|
||||||
:disabled="!this.dataChanged || this.saving">
|
:disabled="!this.dataChanged || this.saving">
|
||||||
<LocaleText t="Revert"></LocaleText>
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
<i class="bi bi-arrow-clockwise ms-2"></i>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="ms-auto btn btn-dark btn-brand rounded-3 px-3 py-2 shadow"
|
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 px-3 py-2 shadow"
|
||||||
:disabled="!this.dataChanged || this.saving"
|
:disabled="!this.dataChanged || this.saving"
|
||||||
@click="this.savePeer()"
|
@click="this.savePeer()"
|
||||||
>
|
>
|
||||||
<LocaleText t="Save Peer"></LocaleText>
|
<i class="bi bi-save-fill"></i></button>
|
||||||
<i class="bi bi-save-fill ms-2"></i></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,9 +66,7 @@ const downloaded = reactive({
|
|||||||
failed: []
|
failed: []
|
||||||
})
|
})
|
||||||
const cardBody = useTemplateRef('card-body');
|
const cardBody = useTemplateRef('card-body');
|
||||||
const sleep = m => new Promise(resolve => setTimeout(resolve, m))
|
|
||||||
const el = useTemplateRef("sp")
|
const el = useTemplateRef("sp")
|
||||||
console.log(el.value)
|
|
||||||
const submitDownload = async () => {
|
const submitDownload = async () => {
|
||||||
downloadConfirmation.value = true
|
downloadConfirmation.value = true
|
||||||
for (const x of selectedPeers.value) {
|
for (const x of selectedPeers.value) {
|
||||||
|
@ -66,10 +66,10 @@ export default {
|
|||||||
<LocaleText t="WireGuard Configurations"></LocaleText>
|
<LocaleText t="WireGuard Configurations"></LocaleText>
|
||||||
</h6>
|
</h6>
|
||||||
<ul class="nav flex-column px-2">
|
<ul class="nav flex-column px-2">
|
||||||
<li class="nav-item">
|
<li class="nav-item" v-for="c in this.wireguardConfigurationsStore.Configurations">
|
||||||
<RouterLink :to="'/configuration/'+c.Name + '/peers'" class="nav-link nav-conf-link rounded-3"
|
<RouterLink :to="'/configuration/'+c.Name + '/peers'" class="nav-link nav-conf-link rounded-3"
|
||||||
active-class="active"
|
active-class="active"
|
||||||
v-for="c in this.wireguardConfigurationsStore.Configurations">
|
>
|
||||||
<span class="dot me-2" :class="{active: c.Status}"></span>
|
<span class="dot me-2" :class="{active: c.Status}"></span>
|
||||||
{{c.Name}}
|
{{c.Name}}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
Loading…
Reference in New Issue
Block a user