mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
Configuration Settings done
This commit is contained in:
parent
5f46f54dfd
commit
4a2f3e0372
@ -1,5 +1,6 @@
|
|||||||
import itertools
|
import itertools
|
||||||
import random
|
import random
|
||||||
|
import shutil
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import configparser
|
import configparser
|
||||||
import hashlib
|
import hashlib
|
||||||
@ -488,8 +489,6 @@ class WireguardConfiguration:
|
|||||||
setattr(self, i, _strToBool(data[i]))
|
setattr(self, i, _strToBool(data[i]))
|
||||||
else:
|
else:
|
||||||
setattr(self, i, str(data[i]))
|
setattr(self, i, str(data[i]))
|
||||||
|
|
||||||
# self.__createDatabase()
|
|
||||||
self.__parser["Interface"] = {
|
self.__parser["Interface"] = {
|
||||||
"PrivateKey": self.PrivateKey,
|
"PrivateKey": self.PrivateKey,
|
||||||
"Address": self.Address,
|
"Address": self.Address,
|
||||||
@ -506,7 +505,6 @@ class WireguardConfiguration:
|
|||||||
self.__parser.write(configFile)
|
self.__parser.write(configFile)
|
||||||
|
|
||||||
self.Peers: list[Peer] = []
|
self.Peers: list[Peer] = []
|
||||||
# Create tables in database
|
|
||||||
self.__createDatabase()
|
self.__createDatabase()
|
||||||
self.getPeersList()
|
self.getPeersList()
|
||||||
self.getRestrictedPeersList()
|
self.getRestrictedPeersList()
|
||||||
@ -815,7 +813,6 @@ class WireguardConfiguration:
|
|||||||
, (status, latestHandshake[count],))
|
, (status, latestHandshake[count],))
|
||||||
count += 2
|
count += 2
|
||||||
|
|
||||||
|
|
||||||
def getPeersTransfer(self):
|
def getPeersTransfer(self):
|
||||||
if not self.getStatus():
|
if not self.getStatus():
|
||||||
self.toggleConfiguration()
|
self.toggleConfiguration()
|
||||||
@ -919,6 +916,51 @@ class WireguardConfiguration:
|
|||||||
"ConnectedPeers": len(list(filter(lambda x: x.status == "running", self.Peers)))
|
"ConnectedPeers": len(list(filter(lambda x: x.status == "running", self.Peers)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def updateConfigurationSettings(self, newData: dict) -> tuple[bool, str]:
|
||||||
|
if self.Status:
|
||||||
|
self.toggleConfiguration()
|
||||||
|
original = []
|
||||||
|
dataChanged = False
|
||||||
|
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'r') as f:
|
||||||
|
original = f.readlines()
|
||||||
|
original = [l.rstrip("\n") for l in original]
|
||||||
|
allowEdit = ["Address", "PreUp", "PostUp", "PreDown", "PostDown", "ListenPost", "PrivateKey"]
|
||||||
|
|
||||||
|
|
||||||
|
start = original.index("[Interface]")
|
||||||
|
for line in range(start+1, len(original)):
|
||||||
|
if original[line] == "[Peer]":
|
||||||
|
break
|
||||||
|
split = re.split(r'\s*=\s*', original[line], 1)
|
||||||
|
if len(split) == 2:
|
||||||
|
key = split[0]
|
||||||
|
value = split[1]
|
||||||
|
if key in allowEdit and key in newData.keys() and value != newData[key]:
|
||||||
|
split[1] = newData[key]
|
||||||
|
original[line] = " = ".join(split)
|
||||||
|
if isinstance(getattr(self, key), bool):
|
||||||
|
setattr(self, key, _strToBool(newData[key]))
|
||||||
|
else:
|
||||||
|
setattr(self, key, str(newData[key]))
|
||||||
|
dataChanged = True
|
||||||
|
print(original[line])
|
||||||
|
if dataChanged:
|
||||||
|
|
||||||
|
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()
|
||||||
|
if not status:
|
||||||
|
return False, msg
|
||||||
|
return True, ""
|
||||||
|
|
||||||
class Peer:
|
class Peer:
|
||||||
def __init__(self, tableData, configuration: WireguardConfiguration):
|
def __init__(self, tableData, configuration: WireguardConfiguration):
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
@ -1607,6 +1649,21 @@ def API_toggleWireguardConfiguration():
|
|||||||
toggleStatus, msg = WireguardConfigurations[configurationName].toggleConfiguration()
|
toggleStatus, msg = WireguardConfigurations[configurationName].toggleConfiguration()
|
||||||
return ResponseObject(toggleStatus, msg, WireguardConfigurations[configurationName].Status)
|
return ResponseObject(toggleStatus, msg, WireguardConfigurations[configurationName].Status)
|
||||||
|
|
||||||
|
@app.post(f'{APP_PREFIX}/api/updateWireguardConfiguration')
|
||||||
|
def API_updateWireguardConfiguration():
|
||||||
|
data = request.get_json()
|
||||||
|
requiredKeys = ["Name"]
|
||||||
|
for i in requiredKeys:
|
||||||
|
if i not in data.keys():
|
||||||
|
return ResponseObject(False, "Please provide these following field: " + ", ".join(requiredKeys))
|
||||||
|
|
||||||
|
name = data.get("Name")
|
||||||
|
if name not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
|
||||||
|
status, msg = WireguardConfigurations[name].updateConfigurationSettings(data)
|
||||||
|
|
||||||
|
return ResponseObject(status, message=msg, data=WireguardConfigurations[name])
|
||||||
|
|
||||||
@app.get(f'{APP_PREFIX}/api/getDashboardConfiguration')
|
@app.get(f'{APP_PREFIX}/api/getDashboardConfiguration')
|
||||||
def API_getDashboardConfiguration():
|
def API_getDashboardConfiguration():
|
||||||
|
12
src/static/app/dist/assets/index.css
vendored
12
src/static/app/dist/assets/index.css
vendored
File diff suppressed because one or more lines are too long
98
src/static/app/dist/assets/index.js
vendored
98
src/static/app/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
2
src/static/app/dist/index.html
vendored
2
src/static/app/dist/index.html
vendored
@ -9,6 +9,6 @@
|
|||||||
<link rel="stylesheet" crossorigin href="/static/app/dist/assets/index.css">
|
<link rel="stylesheet" crossorigin href="/static/app/dist/assets/index.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app" class="w-100 vh-100"></div>
|
<div id="app"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
3192
src/static/app/package-lock.json
generated
3192
src/static/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,7 @@ const getActiveCrossServer = computed(() => {
|
|||||||
</nav>
|
</nav>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<RouterView v-slot="{ Component }">
|
<RouterView v-slot="{ Component }">
|
||||||
<Transition name="app" mode="out-in">
|
<Transition name="app" mode="out-in" type="transition">
|
||||||
<Component :is="Component"></Component>
|
<Component :is="Component"></Component>
|
||||||
</Transition>
|
</Transition>
|
||||||
</RouterView>
|
</RouterView>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import "@/utilities/wireguard.js"
|
import "@/utilities/wireguard.js"
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
export default {
|
export default {
|
||||||
name: "privatePublicKeyInput",
|
name: "privatePublicKeyInput",
|
||||||
components: {LocaleText},
|
components: {LocaleText},
|
||||||
@ -12,7 +13,8 @@ export default {
|
|||||||
},
|
},
|
||||||
setup(){
|
setup(){
|
||||||
const dashboardStore = DashboardConfigurationStore();
|
const dashboardStore = DashboardConfigurationStore();
|
||||||
return {dashboardStore}
|
const wgStore = WireguardConfigurationsStore()
|
||||||
|
return {dashboardStore, wgStore}
|
||||||
},
|
},
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
@ -39,7 +41,7 @@ export default {
|
|||||||
checkMatching(){
|
checkMatching(){
|
||||||
try{
|
try{
|
||||||
if(this.keypair.privateKey){
|
if(this.keypair.privateKey){
|
||||||
if(this.testKey(this.keypair.privateKey)){
|
if(this.wgStore.checkWGKeyLength(this.keypair.privateKey)){
|
||||||
this.keypair.publicKey = window.wireguard.generatePublicKey(this.keypair.privateKey)
|
this.keypair.publicKey = window.wireguard.generatePublicKey(this.keypair.privateKey)
|
||||||
if (window.wireguard.generatePublicKey(this.keypair.privateKey)
|
if (window.wireguard.generatePublicKey(this.keypair.privateKey)
|
||||||
!== this.keypair.publicKey){
|
!== this.keypair.publicKey){
|
||||||
|
@ -42,6 +42,7 @@ import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogs
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
|
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import EditConfiguration from "@/components/configurationComponents/peerScheduleJobsComponents/editConfiguration.vue";
|
||||||
|
|
||||||
Chart.register(
|
Chart.register(
|
||||||
ArcElement,
|
ArcElement,
|
||||||
@ -72,6 +73,7 @@ Chart.register(
|
|||||||
export default {
|
export default {
|
||||||
name: "peerList",
|
name: "peerList",
|
||||||
components: {
|
components: {
|
||||||
|
EditConfiguration,
|
||||||
LocaleText,
|
LocaleText,
|
||||||
PeerShareLinkModal,
|
PeerShareLinkModal,
|
||||||
PeerJobsLogsModal,
|
PeerJobsLogsModal,
|
||||||
@ -139,6 +141,9 @@ export default {
|
|||||||
peerShare:{
|
peerShare:{
|
||||||
modalOpen: false,
|
modalOpen: false,
|
||||||
selectedPeer: undefined
|
selectedPeer: undefined
|
||||||
|
},
|
||||||
|
editConfiguration: {
|
||||||
|
modalOpen: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -584,6 +589,7 @@ export default {
|
|||||||
<PeerSearch
|
<PeerSearch
|
||||||
@jobsAll="this.peerScheduleJobsAll.modalOpen = true"
|
@jobsAll="this.peerScheduleJobsAll.modalOpen = true"
|
||||||
@jobLogs="this.peerScheduleJobsLogs.modalOpen = true"
|
@jobLogs="this.peerScheduleJobsLogs.modalOpen = true"
|
||||||
|
@editConfiguration="this.editConfiguration.modalOpen = true"
|
||||||
:configuration="this.configurationInfo"></PeerSearch>
|
:configuration="this.configurationInfo"></PeerSearch>
|
||||||
<TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0">
|
<TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0">
|
||||||
<div class="col-12 col-lg-6 col-xl-4"
|
<div class="col-12 col-lg-6 col-xl-4"
|
||||||
@ -643,6 +649,13 @@ export default {
|
|||||||
@close="this.peerShare.modalOpen = false; this.peerShare.selectedPeer = undefined;"
|
@close="this.peerShare.modalOpen = false; this.peerShare.selectedPeer = undefined;"
|
||||||
:peer="this.configurationPeers.find(x => x.id === this.peerShare.selectedPeer)"></PeerShareLinkModal>
|
:peer="this.configurationPeers.find(x => x.id === this.peerShare.selectedPeer)"></PeerShareLinkModal>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
<Transition name="zoom">
|
||||||
|
<EditConfiguration
|
||||||
|
@close="this.editConfiguration.modalOpen = false"
|
||||||
|
@dataChanged="(d) => this.configurationInfo = d"
|
||||||
|
:configurationInfo="this.configurationInfo"
|
||||||
|
v-if="this.editConfiguration.modalOpen"></EditConfiguration>
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -0,0 +1,197 @@
|
|||||||
|
<script setup>
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {onMounted, reactive, ref, useTemplateRef, watch} from "vue";
|
||||||
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import router from "@/router/index.js";
|
||||||
|
const props = defineProps({
|
||||||
|
configurationInfo: Object
|
||||||
|
})
|
||||||
|
const wgStore = WireguardConfigurationsStore()
|
||||||
|
const store = DashboardConfigurationStore()
|
||||||
|
const saving = ref(false)
|
||||||
|
const data = reactive(JSON.parse(JSON.stringify(props.configurationInfo)))
|
||||||
|
const editPrivateKey = ref(false)
|
||||||
|
const dataChanged = ref(false)
|
||||||
|
const confirmChanges = ref(false)
|
||||||
|
const reqField = reactive({
|
||||||
|
PrivateKey: true,
|
||||||
|
IPAddress: true,
|
||||||
|
ListenPort: true
|
||||||
|
})
|
||||||
|
const editConfigurationContainer = useTemplateRef("editConfigurationContainer")
|
||||||
|
const genKey = () => {
|
||||||
|
if (wgStore.checkWGKeyLength(data.PrivateKey)){
|
||||||
|
reqField.PrivateKey = true;
|
||||||
|
data.PublicKey = window.wireguard.generatePublicKey(data.PrivateKey)
|
||||||
|
}else{
|
||||||
|
reqField.PrivateKey = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resetForm = () => {
|
||||||
|
dataChanged.value = false;
|
||||||
|
Object.assign(data, JSON.parse(JSON.stringify(props.configurationInfo)))
|
||||||
|
}
|
||||||
|
const emit = defineEmits(["changed"])
|
||||||
|
const saveForm = () => {
|
||||||
|
saving.value = true
|
||||||
|
fetchPost("/api/updateWireguardConfiguration", data, (res) => {
|
||||||
|
saving.value = false
|
||||||
|
if (res.status){
|
||||||
|
store.newMessage("Server", "Configuration saved", "success")
|
||||||
|
dataChanged.value = false
|
||||||
|
emit("dataChanged", res.data)
|
||||||
|
|
||||||
|
}else{
|
||||||
|
store.newMessage("Server", res.message, "danger")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
watch(data, () => {
|
||||||
|
dataChanged.value = JSON.stringify(data) !== JSON.stringify(props.configurationInfo);
|
||||||
|
}, {
|
||||||
|
deep: true
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll" ref="editConfigurationContainer">
|
||||||
|
<div class="container d-flex h-100 w-100">
|
||||||
|
<div class="m-auto modal-dialog-centered dashboardModal" style="width: 700px">
|
||||||
|
<div class="card rounded-3 shadow flex-grow-1">
|
||||||
|
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4">
|
||||||
|
<h4 class="mb-0">
|
||||||
|
<LocaleText t="Configuration Settings"></LocaleText>
|
||||||
|
</h4>
|
||||||
|
<button type="button" class="btn-close ms-auto" @click="$emit('close')"></button>
|
||||||
|
</div>
|
||||||
|
<div class="card-body px-4 pb-4">
|
||||||
|
<div class="d-flex gap-2 flex-column">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Name"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<small class="ms-auto"><samp>{{data.Name}}</samp></small>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Public Key"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<small class="ms-auto"><samp>{{data.PublicKey}}</samp></small>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_private_key" class="form-label d-flex">
|
||||||
|
<small class="text-muted d-block">
|
||||||
|
<LocaleText t="Private Key"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<div class="form-check form-switch ms-auto">
|
||||||
|
<input class="form-check-input"
|
||||||
|
type="checkbox" role="switch" id="editPrivateKeySwitch"
|
||||||
|
v-model="editPrivateKey"
|
||||||
|
>
|
||||||
|
<label class="form-check-label" for="editPrivateKeySwitch">
|
||||||
|
<small>Edit</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving || !editPrivateKey"
|
||||||
|
:class="{'is-invalid': !reqField.PrivateKey}"
|
||||||
|
@keyup="genKey()"
|
||||||
|
v-model="data.PrivateKey"
|
||||||
|
id="configuration_private_key">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_ipaddress_cidr" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="IP Address/CIDR"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.Address"
|
||||||
|
id="configuration_ipaddress_cidr">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_listen_port" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Listen Port"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="number" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.ListenPort"
|
||||||
|
id="configuration_listen_port">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_preup" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="PreUp"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.PreUp"
|
||||||
|
id="configuration_preup">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_predown" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="PreDown"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.PreDown"
|
||||||
|
id="configuration_predown">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_postup" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="PostUp"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.PostUp"
|
||||||
|
id="configuration_postup">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="configuration_postdown" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="PostDown"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="form-control form-control-sm rounded-3"
|
||||||
|
:disabled="saving"
|
||||||
|
v-model="data.PostDown"
|
||||||
|
id="configuration_postdown">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center gap-2 mt-4">
|
||||||
|
<button class="btn bg-secondary-subtle border-secondary-subtle text-secondary-emphasis rounded-3 shadow ms-auto px-3 py-2"
|
||||||
|
@click="resetForm()"
|
||||||
|
:disabled="!dataChanged || saving">
|
||||||
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 px-3 py-2 shadow"
|
||||||
|
:disabled="!dataChanged || saving"
|
||||||
|
@click="saveForm()"
|
||||||
|
>
|
||||||
|
<i class="bi bi-save-fill"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -182,6 +182,13 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column">
|
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column">
|
||||||
<div>
|
<div>
|
||||||
|
<div class="list-group">
|
||||||
|
<a class="list-group-item list-group-item-action d-flex" role="button"
|
||||||
|
@click="this.$emit('editConfiguration')">
|
||||||
|
<LocaleText t="Configuration Settings"></LocaleText>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
<p class="text-muted fw-bold mb-2"><small>
|
<p class="text-muted fw-bold mb-2"><small>
|
||||||
<LocaleText t="Peer Jobs"></LocaleText>
|
<LocaleText t="Peer Jobs"></LocaleText>
|
||||||
</small></p>
|
</small></p>
|
||||||
|
@ -79,6 +79,10 @@ export const WireguardConfigurationsStore = defineStore('WireguardConfigurations
|
|||||||
checkCIDR(ip){
|
checkCIDR(ip){
|
||||||
return isCidr(ip) !== 0
|
return isCidr(ip) !== 0
|
||||||
},
|
},
|
||||||
|
checkWGKeyLength(key){
|
||||||
|
console.log(key)
|
||||||
|
const reg = /^[A-Za-z0-9+/]{43}=?=?$/;
|
||||||
|
return reg.test(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -24,12 +24,6 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme="dark"]{
|
|
||||||
hr{
|
|
||||||
border-color: #efefef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#app{
|
#app{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@ -1071,7 +1065,13 @@ pre.index-alert {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.login-container-fluid{
|
.login-container-fluid{
|
||||||
height: calc(100% - 50px) !important;
|
height: calc(100% - 50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 576px) {
|
||||||
|
.login-container-fluid{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.totp{
|
.totp{
|
||||||
@ -1204,3 +1204,30 @@ pre.index-alert {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(50px) !important;
|
transform: translateX(50px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@property --bgdegree{
|
||||||
|
syntax: '<angle>';
|
||||||
|
initial-value: 234deg;
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container-fluid{
|
||||||
|
background: linear-gradient(var(--bgdegree), #009fff1a var(--distance2), #ff4b001a 100%);
|
||||||
|
animation: login 8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container-fluid[data-bs-theme="dark"]{
|
||||||
|
background: linear-gradient(var(--bgdegree), #003555 var(--distance2), #521800 100%);
|
||||||
|
animation: login 8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes login {
|
||||||
|
0%{
|
||||||
|
--bgdegree: 234deg;
|
||||||
|
}
|
||||||
|
100%{
|
||||||
|
--bgdegree: 594deg;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user