mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-10-03 07:46:18 +00:00
Webhooks feature is done #669
This commit is contained in:
@@ -270,11 +270,11 @@ def API_addWireguardConfiguration():
|
||||
)
|
||||
WireguardConfigurations[data['ConfigurationName']] = (
|
||||
WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data=data, name=data['ConfigurationName'])) if protocol == 'wg' else (
|
||||
AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data=data, name=data['ConfigurationName']))
|
||||
AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, data=data, name=data['ConfigurationName']))
|
||||
else:
|
||||
WireguardConfigurations[data['ConfigurationName']] = (
|
||||
WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data=data)) if data.get('Protocol') == 'wg' else (
|
||||
AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data=data))
|
||||
WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, data=data)) if data.get('Protocol') == 'wg' else (
|
||||
AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, DashboardWebHooks, data=data))
|
||||
return ResponseObject()
|
||||
|
||||
@app.get(f'{APP_PREFIX}/api/toggleWireguardConfiguration')
|
||||
@@ -371,7 +371,7 @@ def API_renameWireguardConfiguration():
|
||||
|
||||
status, message = rc.renameConfiguration(data.get("NewConfigurationName"))
|
||||
if status:
|
||||
WireguardConfigurations[data.get("NewConfigurationName")] = (WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data.get("NewConfigurationName")) if rc.Protocol == 'wg' else AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, data.get("NewConfigurationName")))
|
||||
WireguardConfigurations[data.get("NewConfigurationName")] = (WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, data.get("NewConfigurationName")) if rc.Protocol == 'wg' else AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, data.get("NewConfigurationName")))
|
||||
else:
|
||||
WireguardConfigurations[data.get("ConfigurationName")] = rc
|
||||
return ResponseObject(status, message)
|
||||
@@ -552,9 +552,13 @@ def API_updatePeerSettings(configName):
|
||||
if wireguardConfig.Protocol == 'wg':
|
||||
status, msg = peer.updatePeer(name, private_key, preshared_key, dns_addresses,
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive)
|
||||
return ResponseObject(status, msg)
|
||||
status, msg = peer.updatePeer(name, private_key, preshared_key, dns_addresses,
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive, "off")
|
||||
else:
|
||||
status, msg = peer.updatePeer(name, private_key, preshared_key, dns_addresses,
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive, "off")
|
||||
DashboardWebHooks.RunWebHook('peer_updated', {
|
||||
"configuration": wireguardConfig.Name,
|
||||
"peers": [id]
|
||||
})
|
||||
return ResponseObject(status, msg)
|
||||
|
||||
return ResponseObject(False, "Peer does not exist")
|
||||
@@ -749,10 +753,10 @@ def API_addPeers(configName):
|
||||
if len(keyPairs) == 0 or (bulkAdd and len(keyPairs) != bulkAddAmount):
|
||||
return ResponseObject(False, "Generating key pairs by bulk failed")
|
||||
status, result = config.addPeers(keyPairs)
|
||||
DashboardWebHooks.RunWebHook('peer_created', {
|
||||
"configuration": config.Name,
|
||||
"peers": list(map(lambda p : p['id'], keyPairs))
|
||||
})
|
||||
# DashboardWebHooks.RunWebHook('peer_created', {
|
||||
# "configuration": config.Name,
|
||||
# "peers": list(map(lambda p : p['id'], keyPairs))
|
||||
# })
|
||||
return ResponseObject(status=status, message=result['message'], data=result['peers'])
|
||||
|
||||
else:
|
||||
@@ -817,10 +821,10 @@ def API_addPeers(configName):
|
||||
"advanced_security": "off"
|
||||
}]
|
||||
)
|
||||
DashboardWebHooks.RunWebHook('peer_created', {
|
||||
"configuration": config.Name,
|
||||
"peers": [{"id": public_key}]
|
||||
})
|
||||
# DashboardWebHooks.RunWebHook('peer_created', {
|
||||
# "configuration": config.Name,
|
||||
# "peers": [{"id": public_key}]
|
||||
# })
|
||||
return ResponseObject(status=status, message=result['message'], data=result['peers'])
|
||||
except Exception as e:
|
||||
app.logger.error("Add peers failed", data, exc_info=e)
|
||||
@@ -1473,9 +1477,9 @@ def InitWireguardConfigurationsList(startup: bool = False):
|
||||
try:
|
||||
if i in WireguardConfigurations.keys():
|
||||
if WireguardConfigurations[i].configurationFileChanged():
|
||||
WireguardConfigurations[i] = WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i)
|
||||
WireguardConfigurations[i] = WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, i)
|
||||
else:
|
||||
WireguardConfigurations[i] = WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i, startup=startup)
|
||||
WireguardConfigurations[i] = WireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, i, startup=startup)
|
||||
except WireguardConfiguration.InvalidConfigurationFileException as e:
|
||||
print(f"{i} have an invalid configuration file.")
|
||||
|
||||
@@ -1488,9 +1492,9 @@ def InitWireguardConfigurationsList(startup: bool = False):
|
||||
try:
|
||||
if i in WireguardConfigurations.keys():
|
||||
if WireguardConfigurations[i].configurationFileChanged():
|
||||
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i)
|
||||
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, i)
|
||||
else:
|
||||
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, i, startup=startup)
|
||||
WireguardConfigurations[i] = AmneziaWireguardConfiguration(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, i, startup=startup)
|
||||
except WireguardConfiguration.InvalidConfigurationFileException as e:
|
||||
print(f"{i} have an invalid configuration file.")
|
||||
|
||||
|
@@ -8,12 +8,14 @@ from .AmneziaWGPeer import AmneziaWGPeer
|
||||
from .PeerShareLinks import PeerShareLinks
|
||||
from .Utilities import RegexMatch
|
||||
from .WireguardConfiguration import WireguardConfiguration
|
||||
from .DashboardWebHooks import DashboardWebHooks
|
||||
|
||||
|
||||
class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
def __init__(self, DashboardConfig,
|
||||
AllPeerJobs: PeerJobs,
|
||||
AllPeerShareLinks: PeerShareLinks,
|
||||
DashboardWebHooks: DashboardWebHooks,
|
||||
name: str = None, data: dict = None, backup: dict = None, startup: bool = False):
|
||||
self.Jc = 0
|
||||
self.Jmin = 0
|
||||
@@ -25,7 +27,7 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
self.H3 = 3
|
||||
self.H4 = 4
|
||||
|
||||
super().__init__(DashboardConfig, AllPeerJobs, AllPeerShareLinks, name, data, backup, startup, wg=False)
|
||||
super().__init__(DashboardConfig, AllPeerJobs, AllPeerShareLinks, DashboardWebHooks, name, data, backup, startup, wg=False)
|
||||
|
||||
def toJson(self):
|
||||
self.Status = self.getStatus()
|
||||
@@ -301,6 +303,10 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
p = self.searchPeer(p['id'])
|
||||
if p[0]:
|
||||
result['peers'].append(p[1])
|
||||
self.DashboardWebHooks.RunWebHook("peer_created", {
|
||||
"configuration": self.Name,
|
||||
"peers": list(map(lambda k : k['id'], peers))
|
||||
})
|
||||
return True, result
|
||||
except Exception as e:
|
||||
result['message'] = str(e)
|
||||
|
@@ -168,19 +168,23 @@ class DashboardWebHooks:
|
||||
return False, str(e)
|
||||
return True, None
|
||||
|
||||
def RunWebHook(self, action: str, data: dict[str, str]):
|
||||
if action not in WebHookActions:
|
||||
return False
|
||||
self.__getWebHooks()
|
||||
subscribedWebHooks = filter(lambda webhook: action in webhook.SubscribedActions, self.WebHooks)
|
||||
data['action'] = action
|
||||
for i in subscribedWebHooks:
|
||||
try:
|
||||
t = threading.Thread(target=WebHookSession, args=(i,data), daemon=True)
|
||||
t.start()
|
||||
print("Spinning threads...")
|
||||
except Exception as e:
|
||||
pass
|
||||
def RunWebHook(self, action: str, data):
|
||||
try:
|
||||
if action not in WebHookActions:
|
||||
return False
|
||||
self.__getWebHooks()
|
||||
subscribedWebHooks = filter(lambda webhook: action in webhook.SubscribedActions, self.WebHooks)
|
||||
data['action'] = action
|
||||
for i in subscribedWebHooks:
|
||||
try:
|
||||
ws = WebHookSession(i, data)
|
||||
t = threading.Thread(target=ws.Execute, daemon=True)
|
||||
t.start()
|
||||
print("Spinning threads...")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return True
|
||||
|
||||
class WebHookSession:
|
||||
@@ -197,7 +201,6 @@ class WebHookSession:
|
||||
data['webhook_session'] = self.sessionID
|
||||
self.data = data
|
||||
self.Prepare()
|
||||
self.Execute(data)
|
||||
|
||||
def Prepare(self):
|
||||
with self.engine.begin() as conn:
|
||||
@@ -235,7 +238,7 @@ class WebHookSession:
|
||||
)
|
||||
)
|
||||
|
||||
def Execute(self, data: dict[str, str]):
|
||||
def Execute(self):
|
||||
success = False
|
||||
|
||||
for i in range(5):
|
||||
@@ -247,15 +250,15 @@ class WebHookSession:
|
||||
headerDictionary[header['key']] = header['value']
|
||||
|
||||
if self.webHook.ContentType == "application/json":
|
||||
reqData = json.dumps(data)
|
||||
reqData = json.dumps(self.data)
|
||||
else:
|
||||
for (key, val) in data.items():
|
||||
if type(data[key]) not in [str, int]:
|
||||
data[key] = json.dumps(data[key])
|
||||
reqData = urllib.parse.urlencode(data)
|
||||
for (key, val) in self.data.items():
|
||||
if type(self.data[key]) not in [str, int]:
|
||||
self.data[key] = json.dumps(self.data[key])
|
||||
reqData = urllib.parse.urlencode(self.data)
|
||||
try:
|
||||
req = requests.post(
|
||||
self.webHook.PayloadURL, headers=headerDictionary, timeout=10, data=reqData
|
||||
self.webHook.PayloadURL, headers=headerDictionary, timeout=10, data=reqData, verify=self.webHook.VerifySSL
|
||||
)
|
||||
req.raise_for_status()
|
||||
success = True
|
||||
|
@@ -11,12 +11,14 @@ from itertools import islice
|
||||
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardConfig import DashboardConfig
|
||||
from .DashboardWebHooks import DashboardWebHooks
|
||||
from .Peer import Peer
|
||||
from .PeerJobs import PeerJobs
|
||||
from .PeerShareLinks import PeerShareLinks
|
||||
from .Utilities import StringToBoolean, GenerateWireguardPublicKey, RegexMatch, ValidateDNSAddress, \
|
||||
ValidateEndpointAllowedIPs
|
||||
from .WireguardConfigurationInfo import WireguardConfigurationInfo, PeerGroupsClass
|
||||
from .DashboardWebHooks import DashboardWebHooks
|
||||
|
||||
|
||||
class WireguardConfiguration:
|
||||
@@ -30,6 +32,7 @@ class WireguardConfiguration:
|
||||
def __init__(self, DashboardConfig: DashboardConfig,
|
||||
AllPeerJobs: PeerJobs,
|
||||
AllPeerShareLinks: PeerShareLinks,
|
||||
DashboardWebHooks: DashboardWebHooks,
|
||||
name: str = None,
|
||||
data: dict = None,
|
||||
backup: dict = None,
|
||||
@@ -61,6 +64,7 @@ class WireguardConfiguration:
|
||||
self.AllPeerJobs = AllPeerJobs
|
||||
self.DashboardConfig = DashboardConfig
|
||||
self.AllPeerShareLinks = AllPeerShareLinks
|
||||
self.DashboardWebHooks = DashboardWebHooks
|
||||
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
|
||||
self.engine: sqlalchemy.engine = sqlalchemy.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata: sqlalchemy.MetaData = sqlalchemy.MetaData()
|
||||
@@ -497,6 +501,10 @@ class WireguardConfiguration:
|
||||
p = self.searchPeer(p['id'])
|
||||
if p[0]:
|
||||
result['peers'].append(p[1])
|
||||
self.DashboardWebHooks.RunWebHook("peer_created", {
|
||||
"configuration": self.Name,
|
||||
"peers": list(map(lambda k : k['id'], peers))
|
||||
})
|
||||
return True, result
|
||||
except Exception as e:
|
||||
result['message'] = str(e)
|
||||
@@ -598,6 +606,7 @@ class WireguardConfiguration:
|
||||
def deletePeers(self, listOfPublicKeys, AllPeerJobs: PeerJobs, AllPeerShareLinks: PeerShareLinks) -> tuple[bool, str]:
|
||||
numOfDeletedPeers = 0
|
||||
numOfFailedToDeletePeers = 0
|
||||
deleted = []
|
||||
if not self.getStatus():
|
||||
self.toggleConfiguration()
|
||||
with self.engine.begin() as conn:
|
||||
@@ -616,6 +625,7 @@ class WireguardConfiguration:
|
||||
self.peersTable.columns.id == pf.id
|
||||
)
|
||||
)
|
||||
deleted.append(pf.id)
|
||||
numOfDeletedPeers += 1
|
||||
except Exception as e:
|
||||
numOfFailedToDeletePeers += 1
|
||||
@@ -624,12 +634,17 @@ class WireguardConfiguration:
|
||||
return False, "Failed to save configuration through WireGuard"
|
||||
|
||||
self.getPeers()
|
||||
|
||||
|
||||
if numOfDeletedPeers == 0 and numOfFailedToDeletePeers == 0:
|
||||
return False, "No peer(s) to delete found"
|
||||
|
||||
|
||||
if numOfDeletedPeers == len(listOfPublicKeys):
|
||||
self.DashboardWebHooks.RunWebHook("peer_deleted", {
|
||||
"configuration": self.Name,
|
||||
"peers": deleted
|
||||
})
|
||||
return True, f"Deleted {numOfDeletedPeers} peer(s)"
|
||||
|
||||
return False, f"Deleted {numOfDeletedPeers} peer(s) successfully. Failed to delete {numOfFailedToDeletePeers} peer(s)"
|
||||
|
||||
def __wgSave(self) -> tuple[bool, str] | tuple[bool, None]:
|
||||
|
@@ -4,8 +4,6 @@ import { fetchGet } from "@/utilities/fetch.js"
|
||||
import {onMounted, ref} from "vue";
|
||||
import AddWebHook from "@/components/settingsComponent/dashboardWebHooksComponents/addWebHook.vue";
|
||||
import WebHookSessions from "@/components/settingsComponent/dashboardWebHooksComponents/webHookSessions.vue";
|
||||
import ClientGroup from "@/components/clientComponents/clientGroup.vue";
|
||||
import ClientSettings from "@/components/clientComponents/clientSettings.vue";
|
||||
const webHooks = ref([])
|
||||
const webHooksLoaded = ref(false)
|
||||
|
||||
@@ -34,14 +32,14 @@ const view = ref("edit")
|
||||
<i class="bi bi-plug-fill me-2"></i>
|
||||
<LocaleText t="Webhooks"></LocaleText>
|
||||
</h6>
|
||||
<button class="btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle rounded-3 shadow-sm ms-auto"
|
||||
<button class="btn btn-sm bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle rounded-3 shadow-sm ms-auto"
|
||||
@click="addWebHook = true; selectedWebHook = undefined"
|
||||
v-if="!addWebHook"
|
||||
>
|
||||
<i class="bi bi-plus-circle-fill me-2"></i>
|
||||
<LocaleText t="Webhook"></LocaleText>
|
||||
</button>
|
||||
<button class="btn bg-secondary-subtle text-secondary-emphasis border-1 border-secondary-subtle rounded-3 shadow-sm ms-auto"
|
||||
<button class="btn btn-sm bg-secondary-subtle text-secondary-emphasis border-1 border-secondary-subtle rounded-3 shadow-sm ms-auto"
|
||||
@click="addWebHook = false"
|
||||
v-else
|
||||
>
|
||||
@@ -105,7 +103,6 @@ const view = ref("edit")
|
||||
:webHook="selectedWebHook" @refresh="getWebHooks()" ></AddWebHook>
|
||||
<Suspense v-else-if="view === 'sessions'">
|
||||
<WebHookSessions
|
||||
|
||||
:key="selectedWebHook"
|
||||
:webHook="selectedWebHook"></WebHookSessions>
|
||||
<template #fallback>
|
||||
|
@@ -31,7 +31,8 @@ const Actions = ref({
|
||||
'peer_updated': "Peer Updated"
|
||||
})
|
||||
const emits = defineEmits(['refresh', 'delete'])
|
||||
|
||||
import { DashboardConfigurationStore } from "@/stores/DashboardConfigurationStore"
|
||||
const store = DashboardConfigurationStore()
|
||||
const alert = ref(false)
|
||||
const alertMsg = ref("")
|
||||
const submitting = ref(false)
|
||||
@@ -41,9 +42,11 @@ const submitWebHook = async (e) => {
|
||||
await fetchPost("/api/webHooks/updateWebHook", newWebHook.value, (res) => {
|
||||
if (res.status){
|
||||
emits('refresh')
|
||||
store.newMessage("Server", "Webhook saved", "success")
|
||||
}else{
|
||||
alert.value = true
|
||||
alertMsg.value = res.message
|
||||
store.newMessage("Server", "Webhook failed to save", "danger")
|
||||
}
|
||||
submitting.value = false
|
||||
})
|
||||
@@ -54,9 +57,11 @@ const deleteWebHook = async () => {
|
||||
await fetchPost("/api/webHooks/deleteWebHook", newWebHook.value, (res) => {
|
||||
if (res.status){
|
||||
emits('delete')
|
||||
store.newMessage("Server", "Webhook deleted", "success")
|
||||
}else{
|
||||
alert.value = true
|
||||
alertMsg.value = res.message
|
||||
store.newMessage("Server", "Webhook failed to delete", "danger")
|
||||
}
|
||||
submitting.value = false
|
||||
})
|
||||
|
@@ -1,8 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import LocaleText from "@/components/text/localeText.vue";
|
||||
import {computed} from "vue";
|
||||
const props = defineProps(['session'])
|
||||
|
||||
const formattedBody = computed(() => {
|
||||
return JSON.stringify(props.session.Data, null, 4)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -94,7 +97,7 @@ const props = defineProps(['session'])
|
||||
<LocaleText t="Data"></LocaleText>
|
||||
</h6>
|
||||
<div class="bg-body-tertiary p-3 rounded-3">
|
||||
<pre class="mb-0"><code>{{ JSON.stringify(session.Data, null, 4) }}</code></pre>
|
||||
<pre class="mb-0"><code>{{ formattedBody }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -27,13 +27,6 @@ const latestSession = computed(() => {
|
||||
return sessions.value[0]
|
||||
})
|
||||
|
||||
// watch(() => latestSession.value.Status, () => {
|
||||
// if (latestSession.value.Status > -1) clearInterval(refreshInterval.value)
|
||||
// })
|
||||
|
||||
// if (latestSession.value.Status === -1){
|
||||
//
|
||||
// }
|
||||
refreshInterval.value = setInterval(() => {
|
||||
getSessions()
|
||||
}, 5000)
|
||||
@@ -48,7 +41,8 @@ onBeforeUnmount(() => {
|
||||
<h6 class="mb-3">
|
||||
<LocaleText t="Latest Session"></LocaleText>
|
||||
</h6>
|
||||
<WebHookSession :session="latestSession" :key="latestSession.WebHookSessionID"></WebHookSession>
|
||||
<WebHookSession :session="latestSession"
|
||||
:key="latestSession.WebHookID"></WebHookSession>
|
||||
</div>
|
||||
<div class="border-top p-3" v-if="sessions.length > 1">
|
||||
<h6>
|
||||
|
Reference in New Issue
Block a user