1
0
mirror of https://github.com/donaldzou/WGDashboard.git synced 2024-11-22 07:10:09 +01:00
This commit is contained in:
Donald Zou 2024-10-29 14:57:29 +08:00
parent d7e5e2f381
commit 01c0175e8f
13 changed files with 299 additions and 225 deletions

View File

@ -441,7 +441,7 @@ class WireguardConfiguration:
return self.message
def __init__(self, name: str = None, data: dict = None, backup: dict = None):
print(f"[WGDashboard] Initialized Configuration: {name}")
self.__parser: configparser.ConfigParser = configparser.ConfigParser(strict=False)
self.__parser.optionxform = str
@ -505,7 +505,10 @@ class WireguardConfiguration:
self.__parser.write(configFile)
self.__initPeersList()
print(f"[WGDashboard] Initialized Configuration: {name}")
if self.getAutostartStatus() and not self.getStatus():
self.toggleConfiguration()
print(f"[WGDashboard] Autostart Configuration: {name}")
def __initPeersList(self):
@ -622,6 +625,10 @@ class WireguardConfiguration:
self.Status = self.Name in psutil.net_if_addrs().keys()
return self.Status
def getAutostartStatus(self):
s, d = DashboardConfig.GetConfig("WireGuardConfiguration", "autostart")
return self.Name in d
def __getRestrictedPeers(self):
self.RestrictedPeers = []
restricted = sqlSelect("SELECT * FROM '%s_restrict_access'" % self.Name).fetchall()
@ -1078,7 +1085,6 @@ class WireguardConfiguration:
self.__dropDatabase()
return True
class Peer:
def __init__(self, tableData, configuration: WireguardConfiguration):
self.configuration = configuration
@ -1225,17 +1231,11 @@ PersistentKeepalive = {str(self.keepalive)}
except Exception as e:
return False
return True
# Regex Match
def regex_match(regex, text):
pattern = re.compile(regex)
return pattern.search(text) is not None
def iPv46RegexCheck(ip):
return re.match(
r'((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))',
ip)
class DashboardAPIKey:
def __init__(self, Key: str, CreatedAt: str, ExpiredAt: str):
self.Key = Key
@ -1287,6 +1287,9 @@ class DashboardConfig:
},
"Database":{
"type": "sqlite"
},
"WireGuardConfiguration": {
"autostart": ""
}
}
@ -1324,8 +1327,6 @@ class DashboardConfig:
sqlUpdate("UPDATE DashboardAPIKeys SET ExpiredAt = datetime('now', 'localtime') WHERE Key = ?", (key, ))
self.DashboardAPIKeys = self.__getAPIKeys()
def __configValidation(self, key, value: Any) -> [bool, str]:
if type(value) is str and len(value) == 0:
return False, "Field cannot be empty!"
@ -1384,8 +1385,10 @@ class DashboardConfig:
self.__config[section][key] = "true"
else:
self.__config[section][key] = "false"
if type(value) in [int, float]:
elif type(value) in [int, float]:
self.__config[section][key] = str(value)
elif type(value) is list:
self.__config[section][key] = "||".join(value)
else:
self.__config[section][key] = value
return self.SaveConfig(), ""
@ -1412,6 +1415,9 @@ class DashboardConfig:
if self.__config[section][key] in ["0", "no", "false", "off"]:
return True, False
if section == "WireGuardConfiguration" and key == "autostart":
return True, self.__config[section][key].split("||")
return True, self.__config[section][key]
def toJson(self) -> dict[str, dict[Any, Any]]:
@ -1421,12 +1427,7 @@ class DashboardConfig:
the_dict[section] = {}
for key, val in self.__config.items(section):
if key not in self.hiddenAttribute:
if val in ["1", "yes", "true", "on"]:
the_dict[section][key] = True
elif val in ["0", "no", "false", "off"]:
the_dict[section][key] = False
else:
the_dict[section][key] = val
the_dict[section][key] = self.GetConfig(section, key)[1]
return the_dict

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -159,7 +159,7 @@ export default {
modalOpen: false
},
deleteConfiguration: {
modalOpen: true
modalOpen: false
}
}
},

View File

@ -58,7 +58,16 @@ export default {
exact-active-class="active">
<i class="bi bi-gear me-2"></i>
<LocaleText t="Settings"></LocaleText>
</RouterLink></li>
</RouterLink>
</li>
<li class="nav-item">
<a class="nav-link rounded-3"
target="_blank"
href="https://donaldzou.github.io/WGDashboard-Documentation/user-guides.html">
<i class="bi bi-question-circle me-2"></i>
<LocaleText t="Help"></LocaleText>
</a>
</li>
</ul>
<hr class="text-body">
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">

View File

@ -78,16 +78,16 @@ export default {
</script>
<template>
<div class="d-flex flex-column">
<div class="row">
<div class="d-flex flex-column gap-2">
<div class="row g-2">
<div class="col-sm">
<div class="form-group mb-2">
<div class="form-group">
<label :for="'currentPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>
<LocaleText t="Current Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
<input type="password" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
v-model="this.value.currentPassword"
:id="'currentPassword_' + this.uuid">
@ -95,13 +95,13 @@ export default {
</div>
</div>
<div class="col-sm">
<div class="form-group mb-2">
<div class="form-group">
<label :for="'newPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>
<LocaleText t="New Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
<input type="password" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
v-model="this.value.newPassword"
:id="'newPassword_' + this.uuid">
@ -109,13 +109,13 @@ export default {
</div>
</div>
<div class="col-sm">
<div class="form-group mb-2">
<div class="form-group">
<label :for="'repeatNewPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>
<LocaleText t="Repeat New Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
<input type="password" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
v-model="this.value.repeatNewPassword"
:id="'repeatNewPassword_' + this.uuid">

View File

@ -44,14 +44,19 @@ export default {
<template>
<div>
<div class="d-flex align-items-center">
<strong>
<h6>
<LocaleText t="Multi-Factor Authentication (MFA)"></LocaleText>
</strong>
<div class="form-check form-switch ms-3">
</h6>
<div class="d-flex align-items-center">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox"
v-model="this.status"
role="switch" id="allowMFAKeysSwitch">
<label for="allowMFAKeysSwitch">
<LocaleText t="Enabled" v-if="this.status"></LocaleText>
<LocaleText t="Disabled" v-else></LocaleText>
</label>
</div>
<button class="btn bg-warning-subtle text-warning-emphasis border-1 border-warning-subtle ms-auto rounded-3 shadow-sm"
v-if="this.status" @click="this.resetMFA()">

View File

@ -63,9 +63,12 @@ export default {
</script>
<template>
<div class="card mb-4 shadow rounded-3">
<div class="card-header d-flex">
<div class="card rounded-3">
<div class="card-body position-relative d-flex flex-column gap-2" >
<div class="d-flex align-items-center">
<h5 class="mb-0">
<LocaleText t="API Keys"></LocaleText>
</h5>
<div class="form-check form-switch ms-auto" v-if="!this.store.getActiveCrossServer()" >
<input class="form-check-input" type="checkbox"
v-model="this.value"
@ -74,13 +77,11 @@ export default {
<label class="form-check-label" for="allowAPIKeysSwitch">
<LocaleText t="Enabled" v-if="this.value"></LocaleText>
<LocaleText t="Disabled" v-else></LocaleText>
</label>
</div>
</div>
<div class="card-body position-relative d-flex flex-column gap-2" v-if="this.value">
<button class="ms-auto btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle rounded-3 shadow-sm"
<div v-if="this.value" class="d-flex flex-column gap-2">
<button class="btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle rounded-3 shadow-sm"
@click="this.newDashboardAPIKey = true"
v-if="!this.store.getActiveCrossServer()"
>
@ -107,6 +108,7 @@ export default {
@close="this.newDashboardAPIKey = false"
></NewDashboardAPIKey>
</Transition>
</div>
</div>
</div>

View File

@ -58,15 +58,13 @@ export default {
</script>
<template>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<div>
<h5>
<LocaleText t="Dashboard IP Address & Listen Port"></LocaleText>
</p>
<div class="card-body">
<div class="row gx-3">
</h5>
<div class="row g-2">
<div class="col-sm">
<div class="form-group mb-2">
<div class="form-group">
<label for="input_dashboard_ip" class="text-muted mb-1">
<strong><small>
<LocaleText t="IP Address / Hostname"></LocaleText>
@ -84,7 +82,7 @@ export default {
</div>
</div>
<div class="col-sm">
<div class="form-group mb-2">
<div class="form-group">
<label for="input_dashboard_ip" class="text-muted mb-1">
<strong><small>
<LocaleText t="Listen Port"></LocaleText>
@ -102,13 +100,13 @@ export default {
</div>
</div>
</div>
<div class="px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1 mb-2">
<div
class="px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mb-2 mt-2">
<small><i class="bi bi-exclamation-triangle-fill me-2"></i>
<LocaleText t="Manual restart of WGDashboard is needed to apply changes on IP Address and Listen Port"></LocaleText>
</small>
</div>
</div>
</div>
</template>
<style scoped>

View File

@ -44,11 +44,11 @@ export default {
</script>
<template>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<LocaleText t="Dashboard Language"></LocaleText>
</p>
<div class="card-body d-flex gap-2">
<div>
<small class="text-muted d-block mb-1">
<strong><LocaleText t="Language"></LocaleText></strong>
</small>
<div class="d-flex gap-2">
<div class="dropdown w-100">
<button class="btn bg-primary-subtle text-primary-emphasis dropdown-toggle w-100 rounded-3"
:disabled="!this.languages"

View File

@ -0,0 +1,30 @@
<script setup>
import LocaleText from "@/components/text/localeText.vue";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {computed, ref} from "vue";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
const store = DashboardConfigurationStore()
const wireguardConfigurationStore = WireguardConfigurationsStore()
const data = ref(store.Configuration.WireGuardConfiguration.autostart)
const configurations = computed(() => {
return wireguardConfigurationStore.Configurations.map(x => x.Name)
})
</script>
<template>
<div class="">
<h5>
<LocaleText t="Autostart"></LocaleText>
</h5>
<div class="d-flex gap-2">
<button class="btn btn-outline-primary" v-for="c in configurations">
<i class="bi-circle me-2"></i> {{c}}
</button>
</div>
</div>
</template>
<style scoped>
</style>

View File

@ -27,11 +27,13 @@ export default {
</script>
<template>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<LocaleText t="Dashboard Theme"></LocaleText>
</p>
<div class="card-body d-flex gap-2">
<div >
<small class="text-muted mb-1 d-block">
<strong>
<LocaleText t="Theme"></LocaleText>
</strong>
</small>
<div class="d-flex gap-1">
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
@click="this.switchTheme('light')"
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'light'}">

View File

@ -14,11 +14,14 @@ import AccountSettingsMFA from "@/components/settingsComponent/accountSettingsMF
import LocaleText from "@/components/text/localeText.vue";
import DashboardLanguage from "@/components/settingsComponent/dashboardLanguage.vue";
import DashboardIPPortInput from "@/components/settingsComponent/dashboardIPPortInput.vue";
import DashboardSettingsWireguardConfigurationAutostart
from "@/components/settingsComponent/dashboardSettingsWireguardConfigurationAutostart.vue";
export default {
name: "settings",
methods: {ipV46RegexCheck},
components: {
DashboardSettingsWireguardConfigurationAutostart,
DashboardIPPortInput,
DashboardLanguage,
LocaleText,
@ -36,17 +39,35 @@ export default {
</script>
<template>
<div class="mt-md-5 mt-3">
<div class="container-md">
<h2 class="mb-4 text-body">
<LocaleText t="Settings"></LocaleText>
<div class="mt-md-5 mt-3 text-body mb-3">
<div class="container-md d-flex flex-column gap-4">
<div>
<h2>
<LocaleText t="WireGuard Configuration Settings"></LocaleText>
</h2>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<LocaleText t="Peers Default Settings"></LocaleText>
</p>
<hr>
<div class="card rounded-3 mb-3">
<div class="card-body">
<DashboardSettingsInputWireguardConfigurationPath
targetData="wg_conf_path"
title="Configurations Directory"
:warning="true"
warning-text="Remember to remove / at the end of your path. e.g /etc/wireguard"
>
</DashboardSettingsInputWireguardConfigurationPath>
</div>
</div>
<div class="card rounded-3 mb-3">
<div class="card-body">
<DashboardSettingsWireguardConfigurationAutostart></DashboardSettingsWireguardConfigurationAutostart>
</div>
</div>
<div class="card rounded-3 mb-3">
<div class="card-body">
<h5>
<LocaleText t="Peer Default Settings"></LocaleText>
</h5>
<div>
<PeersDefaultSettingsInput
targetData="peer_global_dns" title="DNS"></PeersDefaultSettingsInput>
<PeersDefaultSettingsInput
@ -61,52 +82,58 @@ export default {
></PeersDefaultSettingsInput>
</div>
</div>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<LocaleText t="WireGuard Configurations Settings"></LocaleText>
</p>
</div>
</div>
<div>
<h2>
<LocaleText t="WGDashboard Settings"></LocaleText>
</h2>
<hr>
<div class="d-flex flex-column gap-3">
<div class="card rounded-3">
<div class="card-body">
<DashboardSettingsInputWireguardConfigurationPath
targetData="wg_conf_path"
title="Configurations Directory"
:warning="true"
warning-text="Remember to remove / at the end of your path. e.g /etc/wireguard"
>
</DashboardSettingsInputWireguardConfigurationPath>
</div>
</div>
<hr class="mb-4">
<div class="row gx-4">
<div class="row g-2">
<div class="col-sm">
<DashboardTheme></DashboardTheme>
</div>
<div class="col-sm">
<DashboardLanguage></DashboardLanguage>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<DashboardIPPortInput></DashboardIPPortInput>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">
<LocaleText t="WGDashboard Account Settings"></LocaleText>
</p>
<div class="card-body d-flex gap-4 flex-column">
</div>
</div>
<div class="card">
<div class="card-body d-flex flex-column gap-3">
<div>
<h5>
<LocaleText t="Account Settings"></LocaleText>
</h5>
<AccountSettingsInputUsername targetData="username"
title="Username"
></AccountSettingsInputUsername>
<hr class="m-0">
</div>
<div>
<h6>
<LocaleText t="Update Password"></LocaleText>
</h6>
<AccountSettingsInputPassword
targetData="password">
</AccountSettingsInputPassword>
<hr class="m-0" v-if="!this.dashboardConfigurationStore.getActiveCrossServer()">
</div>
<AccountSettingsMFA v-if="!this.dashboardConfigurationStore.getActiveCrossServer()"></AccountSettingsMFA>
</div>
</div>
<DashboardAPIKeys></DashboardAPIKeys>
</div>
</div>
</div>
</div>
</template>
<style scoped>