1
0
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:
Donald Zou 2024-10-15 00:30:20 +08:00
parent bb700f3a3d
commit 27de7ddbf8
7 changed files with 128 additions and 37 deletions

View File

@ -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())

View File

@ -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>

View File

@ -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>

View File

@ -145,10 +145,10 @@ export default {
selectedPeer: undefined selectedPeer: undefined
}, },
editConfiguration: { editConfiguration: {
modalOpen: false modalOpen: true
}, },
selectPeers: { selectPeers: {
modalOpen: true modalOpen: false
} }
} }
}, },

View File

@ -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>

View File

@ -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) {

View File

@ -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>