Merge pull request #969 from WGDashboard/Fix-965
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docker Build and Push / docker_build (push) Has been cancelled
Docker Build and Push / docker_scan (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled

Fix #965
This commit is contained in:
Donald Zou
2025-11-06 06:36:11 +08:00
committed by GitHub
6 changed files with 69 additions and 31 deletions

View File

@@ -194,7 +194,7 @@ with app.app_context():
DashboardConfig = DashboardConfig() DashboardConfig = DashboardConfig()
EmailSender = EmailSender(DashboardConfig) EmailSender = EmailSender(DashboardConfig)
AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig, WireguardConfigurations) AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig, WireguardConfigurations)
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations) AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations, AllPeerShareLinks)
DashboardLogger: DashboardLogger = DashboardLogger() DashboardLogger: DashboardLogger = DashboardLogger()
DashboardPlugins: DashboardPlugins = DashboardPlugins(app, WireguardConfigurations) DashboardPlugins: DashboardPlugins = DashboardPlugins(app, WireguardConfigurations)
DashboardWebHooks: DashboardWebHooks = DashboardWebHooks(DashboardConfig) DashboardWebHooks: DashboardWebHooks = DashboardWebHooks(DashboardConfig)
@@ -223,11 +223,11 @@ def auth_req():
return ResponseObject(True) return ResponseObject(True)
DashboardConfig.APIAccessed = False DashboardConfig.APIAccessed = False
if "api" in request.path: # if "api" in request.path:
if str(request.method) == "GET": # if str(request.method) == "GET":
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=str(request.args)) # DashboardLogger.log(str(request.url), str(request.remote_addr), Message=str(request.args))
elif str(request.method) == "POST": # elif str(request.method) == "POST":
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=f"Request Args: {str(request.args)} Body:{str(request.get_json())}") # DashboardLogger.log(str(request.url), str(request.remote_addr), Message=f"Request Args: {str(request.args)} Body:{str(request.get_json())}")
authenticationRequired = DashboardConfig.GetConfig("Server", "auth_req")[1] authenticationRequired = DashboardConfig.GetConfig("Server", "auth_req")[1]

View File

@@ -174,8 +174,6 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
def getPeers(self): def getPeers(self):
self.Peers.clear() self.Peers.clear()
current_app.logger.info(f"Refreshing {self.Name} peer list")
if self.configurationFileChanged(): if self.configurationFileChanged():
with open(self.configPath, 'r') as configFile: with open(self.configPath, 'r') as configFile:
p = [] p = []

View File

@@ -2,8 +2,12 @@
Peer Job Logger Peer Job Logger
""" """
import uuid import uuid
from typing import Sequence
import sqlalchemy as db import sqlalchemy as db
from flask import current_app from flask import current_app
from sqlalchemy import RowMapping
from .ConnectionString import ConnectionString from .ConnectionString import ConnectionString
from .Log import Log from .Log import Log
@@ -57,3 +61,20 @@ class PeerJobLogger:
current_app.logger.error(f"Getting Peer Job Log Error", e) current_app.logger.error(f"Getting Peer Job Log Error", e)
return logs return logs
return logs return logs
def getFailingJobs(self) -> Sequence[RowMapping]:
with self.engine.connect() as conn:
table = conn.execute(
db.select(
self.jobLogTable.c.JobID
).where(
self.jobLogTable.c.Status == 'false'
).group_by(
self.jobLogTable.c.JobID
).having(
db.func.count(
self.jobLogTable.c.JobID
) > 10
)
).mappings().fetchall()
return table

View File

@@ -1,6 +1,8 @@
""" """
Peer Jobs Peer Jobs
""" """
import sqlalchemy
from .ConnectionString import ConnectionString from .ConnectionString import ConnectionString
from .PeerJob import PeerJob from .PeerJob import PeerJob
from .PeerJobLogger import PeerJobLogger from .PeerJobLogger import PeerJobLogger
@@ -9,7 +11,7 @@ from datetime import datetime
from flask import current_app from flask import current_app
class PeerJobs: class PeerJobs:
def __init__(self, DashboardConfig, WireguardConfigurations): def __init__(self, DashboardConfig, WireguardConfigurations, AllPeerShareLinks):
self.Jobs: list[PeerJob] = [] self.Jobs: list[PeerJob] = []
self.engine = db.create_engine(ConnectionString('wgdashboard_job')) self.engine = db.create_engine(ConnectionString('wgdashboard_job'))
self.metadata = db.MetaData() self.metadata = db.MetaData()
@@ -28,6 +30,7 @@ class PeerJobs:
self.__getJobs() self.__getJobs()
self.JobLogger: PeerJobLogger = PeerJobLogger(self, DashboardConfig) self.JobLogger: PeerJobLogger = PeerJobLogger(self, DashboardConfig)
self.WireguardConfigurations = WireguardConfigurations self.WireguardConfigurations = WireguardConfigurations
self.AllPeerShareLinks = AllPeerShareLinks
def __getJobs(self): def __getJobs(self):
self.Jobs.clear() self.Jobs.clear()
@@ -116,7 +119,7 @@ class PeerJobs:
} }
).where(self.peerJobTable.columns.JobID == Job.JobID) ).where(self.peerJobTable.columns.JobID == Job.JobID)
) )
self.JobLogger.log(Job.JobID, Message=f"Job is removed due to being deleted or finshed.") self.JobLogger.log(Job.JobID, Message=f"Job is removed due to being deleted or finished.")
self.__getJobs() self.__getJobs()
self.WireguardConfigurations.get(Job.Configuration).searchPeer(Job.Peer)[1].getJobs() self.WireguardConfigurations.get(Job.Configuration).searchPeer(Job.Peer)[1].getJobs()
return True, None return True, None
@@ -141,7 +144,7 @@ class PeerJobs:
def runJob(self): def runJob(self):
current_app.logger.info("Running scheduled jobs") self.cleanJob()
needToDelete = [] needToDelete = []
self.__getJobs() self.__getJobs()
for job in self.Jobs: for job in self.Jobs:
@@ -162,7 +165,7 @@ class PeerJobs:
if job.Action == "restrict": if job.Action == "restrict":
s, msg = c.restrictPeers([fp.id]) s, msg = c.restrictPeers([fp.id])
elif job.Action == "delete": elif job.Action == "delete":
s, msg = c.deletePeers([fp.id]) s, msg = c.deletePeers([fp.id], self, self.AllPeerShareLinks)
elif job.Action == "reset_total_data_usage": elif job.Action == "reset_total_data_usage":
s = fp.resetDataUsage("total") s = fp.resetDataUsage("total")
c.restrictPeers([fp.id]) c.restrictPeers([fp.id])
@@ -171,26 +174,35 @@ class PeerJobs:
self.JobLogger.log(job.JobID, s, self.JobLogger.log(job.JobID, s,
f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed." f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed."
) )
current_app.logger.info(f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed.")
needToDelete.append(job) needToDelete.append(job)
else: else:
current_app.logger.info(f"Peer {fp.id} from {c.Name} is failed {job.Action}ed.")
self.JobLogger.log(job.JobID, s, self.JobLogger.log(job.JobID, s,
f"Peer {fp.id} from {c.Name} failed {job.Action}ed." f"Peer {fp.id} from {c.Name} failed {job.Action}ed."
) )
else: else:
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed.")
self.JobLogger.log(job.JobID, False, self.JobLogger.log(job.JobID, False,
f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed." f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed."
) )
else: else:
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed.")
self.JobLogger.log(job.JobID, False, self.JobLogger.log(job.JobID, False,
f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed." f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed."
) )
for j in needToDelete: for j in needToDelete:
self.deleteJob(j) self.deleteJob(j)
def cleanJob(self):
failingJobs = self.JobLogger.getFailingJobs()
with self.engine.begin() as conn:
for job in failingJobs:
conn.execute(
self.peerJobTable.update().values(
{
"ExpireDate": datetime.now()
}
).where(self.peerJobTable.columns.JobID == job.get('JobID'))
)
self.JobLogger.log(job.get('JobID'), Message=f"Job is removed due to being stale.")
def __runJob_Compare(self, x: float | datetime, y: float | datetime, operator: str): def __runJob_Compare(self, x: float | datetime, y: float | datetime, operator: str):
if operator == "eq": if operator == "eq":
return x == y return x == y

View File

@@ -396,8 +396,6 @@ class WireguardConfiguration:
def getPeers(self): def getPeers(self):
tmpList = [] tmpList = []
current_app.logger.info(f"Refreshing {self.Name} peer list")
if self.configurationFileChanged(): if self.configurationFileChanged():
with open(self.configPath, 'r') as configFile: with open(self.configPath, 'r') as configFile:
p = [] p = []
@@ -505,13 +503,22 @@ class WireguardConfiguration:
if tempPeer.status == "running": if tempPeer.status == "running":
endpoint = tempPeer.endpoint.rsplit(":", 1) endpoint = tempPeer.endpoint.rsplit(":", 1)
if len(endpoint) == 2 and len(endpoint[0]) > 0: if len(endpoint) == 2 and len(endpoint[0]) > 0:
conn.execute( exist = conn.execute(
self.peersHistoryEndpointTable.insert().values({ self.peersHistoryEndpointTable.select().where(
"id": tempPeer.id, sqlalchemy.and_(
"endpoint": endpoint[0], self.peersHistoryEndpointTable.c.id == tempPeer.id,
"time": datetime.now() self.peersHistoryEndpointTable.c.endpoint == endpoint[0]
}) )
) )
).mappings().fetchone()
if not exist:
conn.execute(
self.peersHistoryEndpointTable.insert().values({
"id": tempPeer.id,
"endpoint": endpoint[0],
"time": datetime.now()
})
)
def addPeers(self, peers: list) -> tuple[bool, list, str]: def addPeers(self, peers: list) -> tuple[bool, list, str]:
result = { result = {

View File

@@ -146,8 +146,8 @@ export default {
<td v-if="showLogID"><samp class="text-muted">{{log.LogID}}</samp></td> <td v-if="showLogID"><samp class="text-muted">{{log.LogID}}</samp></td>
<td v-if="showJobID"><samp class="text-muted">{{log.JobID}}</samp></td> <td v-if="showJobID"><samp class="text-muted">{{log.JobID}}</samp></td>
<td> <td>
<span class="badge" :class="[log.Status === '1' ? 'text-success-emphasis bg-success-subtle':'text-danger-emphasis bg-danger-subtle']"> <span class="badge" :class="[(log.Status === '1' || log.Status === 'true') ? 'text-success-emphasis bg-success-subtle':'text-danger-emphasis bg-danger-subtle']">
{{log.Status === "1" ? 'Success': 'Failed'}} {{(log.Status === "1" || log.Status === "true") ? 'Success': 'Failed'}}
</span> </span>
</td> </td>
<td>{{log.Message}}</td> <td>{{log.Message}}</td>