Peer assignment to client is done

This commit is contained in:
Donald Zou
2025-07-10 23:39:21 +08:00
parent 2c73dc1df8
commit 1839645360
63 changed files with 609 additions and 147 deletions

View File

@@ -46,6 +46,8 @@ class DashboardClients:
db.Column('CreatedDate',
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
server_default=db.func.now()),
db.Column('DeletedDate',
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
extend_existing=True,
)
@@ -57,21 +59,61 @@ class DashboardClients:
)
self.metadata.create_all(self.engine)
self.Clients = []
self.Clients = {}
self.ClientsRaw = []
self.__getClients()
self.DashboardClientsTOTP = DashboardClientsTOTP()
self.DashboardClientsPeerAssignment = DashboardClientsPeerAssignment(wireguardConfigurations)
def __getClients(self):
with self.engine.connect() as conn:
self.Clients = conn.execute(
localClients = db.select(
self.dashboardClientsTable.c.ClientID,
self.dashboardClientsTable.c.Email,
db.literal_column("'Local'").label("ClientGroup")
).where(
self.dashboardClientsTable.c.DeletedDate.is_(None)
)
oidcClients = db.select(
self.dashboardOIDCClientsTable.c.ClientID,
self.dashboardOIDCClientsTable.c.Email,
self.dashboardOIDCClientsTable.c.ProviderIssuer.label("ClientGroup"),
).where(
self.dashboardOIDCClientsTable.c.DeletedDate.is_(None)
)
union = db.union(localClients, oidcClients).alias("U")
self.ClientsRaw = conn.execute(
db.select(
self.dashboardClientsTable.c.ClientID,
self.dashboardClientsTable.c.Email,
self.dashboardClientsTable.c.CreatedDate
).where(
self.dashboardClientsTable.c.DeletedDate is None)
).mappings().fetchall()
union,
self.dashboardClientsInfoTable.c.Name
).outerjoin(self.dashboardClientsInfoTable,
union.c.ClientID == self.dashboardClientsInfoTable.c.ClientID)
).mappings().fetchall()
groups = set(map(lambda c: c.get('ClientGroup'), self.ClientsRaw))
gr = {}
for g in groups:
gr[(g if g == 'Local' else self.OIDC.GetProviderNameByIssuer(g))] = [
dict(x) for x in list(
filter(lambda c: c.get('ClientGroup') == g, self.ClientsRaw)
)
]
self.Clients = gr
def GetAllClients(self):
self.__getClients()
return self.Clients
def GetClient(self, ClientID) -> dict[str, str] | None:
self.__getClients()
c = filter(lambda x: x['ClientID'] == ClientID, self.ClientsRaw)
client = next((dict(client) for client in c), None)
if client is not None:
client['ClientGroup'] = self.OIDC.GetProviderNameByIssuer(client['ClientGroup'])
return client
def GetClientProfile(self, ClientID):
with self.engine.connect() as conn:
@@ -227,9 +269,7 @@ class DashboardClients:
"ClientID": newClientUUID,
"Email": Email,
"Password": bcrypt.hashpw(encodePassword, bcrypt.gensalt()).decode("utf-8"),
"TotpKey": totpKey,
"AuthType": "local",
"AuthSrc": "local"
"TotpKey": totpKey
})
)
conn.execute(
@@ -240,13 +280,13 @@ class DashboardClients:
self.logger.log(Message=f"User {Email} signed up")
except Exception as e:
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(e)}")
return False, "Signed up failed."
return False, "Signe up failed."
return True, None
def GetClientAssignedPeers(self, ClientID):
return self.DashboardClientsPeerAssignment.GetAssignedPeers(ClientID)
def UpdateClientPassword(self, Email, CurrentPassword, NewPassword, ConfirmNewPassword):
if not all([CurrentPassword, NewPassword, ConfirmNewPassword]):
return False, "Please fill in all fields"
@@ -273,4 +313,22 @@ class DashboardClients:
except Exception as e:
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(e)}")
return False, "Signed up failed."
return True, None
return True, None
'''
For WGDashboard Admin to Manage Clients
'''
def GetAssignedPeerClients(self, ConfigurationName, PeerID):
c = self.DashboardClientsPeerAssignment.GetAssignedClients(ConfigurationName, PeerID)
for a in c:
client = self.GetClient(a.ClientID)
if client is not None:
a.Client = self.GetClient(a.ClientID)
return c
def AssignClient(self, ConfigurationName, PeerID, ClientID) -> tuple[bool, dict[str, str]] | tuple[bool, None]:
return self.DashboardClientsPeerAssignment.AssignClient(ClientID, ConfigurationName, PeerID)
def UnassignClient(self, AssignmentID):
return self.DashboardClientsPeerAssignment.UnassignClients(AssignmentID)

View File

@@ -1,3 +1,4 @@
import datetime
import uuid
from .ConnectionString import ConnectionString
@@ -5,7 +6,28 @@ from .DashboardLogger import DashboardLogger
import sqlalchemy as db
from .WireguardConfiguration import WireguardConfiguration
class Assignment:
def __init__(self, **kwargs):
self.AssignmentID: str = kwargs.get('AssignmentID')
self.ClientID: str = kwargs.get('ClientID')
self.ConfigurationName: str = kwargs.get('ConfigurationName')
self.PeerID: str = kwargs.get('PeerID')
self.AssignedDate: datetime.datetime = kwargs.get('AssignedDate')
self.UnassignedDate: datetime.datetime = kwargs.get('UnassignedDate')
self.Client: dict = {
"ClientID": self.ClientID
}
def toJson(self):
return {
"AssignmentID": self.AssignmentID,
"Client": self.Client,
"ConfigurationName": self.ConfigurationName,
"PeerID": self.PeerID,
"AssignedDate": self.AssignedDate.strftime("%Y-%m-%d %H:%M:%S"),
"UnassignedDate": self.UnassignedDate.strftime("%Y-%m-%d %H:%M:%S") if self.UnassignedDate is not None else self.UnassignedDate
}
class DashboardClientsPeerAssignment:
def __init__(self, wireguardConfigurations: dict[str, WireguardConfiguration]):
self.logger = DashboardLogger()
@@ -26,26 +48,28 @@ class DashboardClientsPeerAssignment:
extend_existing=True
)
self.metadata.create_all(self.engine)
self.assignments = []
self.assignments: list[Assignment] = []
self.__getAssignments()
self.AssignClient("0117a895-bd8b-4ba2-9116-6658372417fb", "wg0", "3kv6Bo46u7ULT07B3I1VHw/rYomVnrCD5TFU369jRSc=")
self.GetAssignedPeers("0117a895-bd8b-4ba2-9116-6658372417fb")
def __getAssignments(self):
with self.engine.connect() as conn:
self.assignments = conn.execute(
assignments = []
get = conn.execute(
self.dashboardClientsPeerAssignmentTable.select().where(
self.dashboardClientsPeerAssignmentTable.c.UnassignedDate == db.null()
self.dashboardClientsPeerAssignmentTable.c.UnassignedDate.is_(None)
)
).mappings().fetchall()
for a in get:
assignments.append(Assignment(**a))
self.assignments = assignments
def AssignClient(self, ClientID, ConfigurationName, PeerID):
existing = list(
filter(lambda e:
e['ClientID'] == ClientID and
e['ConfigurationName'] == ConfigurationName and
e['PeerID'] == PeerID, self.assignments)
e.ClientID == ClientID and
e.ConfigurationName == ConfigurationName and
e.PeerID == PeerID, self.assignments)
)
if len(existing) == 0:
if ConfigurationName in self.wireguardConfigurations.keys():
@@ -66,25 +90,44 @@ class DashboardClientsPeerAssignment:
return True, data
return False, None
def UnassignClient(self, AssignmentID):
pass
def UnassignClients(self, AssignmentID):
existing = list(
filter(lambda e:
e.AssignmentID == AssignmentID, self.assignments)
)
if not existing:
return False
with self.engine.begin() as conn:
conn.execute(
self.dashboardClientsPeerAssignmentTable.update().values({
"UnassignedDate": datetime.datetime.now()
}).where(
self.dashboardClientsPeerAssignmentTable.c.AssignmentID == AssignmentID
)
)
self.__getAssignments()
return True
def GetAssignedClient(self, ConfigurationName, PeerID):
pass
def GetAssignedClients(self, ConfigurationName, PeerID) -> list[Assignment]:
self.__getAssignments()
return list(filter(
lambda c : c.ConfigurationName == ConfigurationName and
c.PeerID == PeerID, self.assignments))
def GetAssignedPeers(self, ClientID):
self.__getAssignments()
peers = []
assigned = filter(lambda e:
e['ClientID'] == ClientID, self.assignments)
e.ClientID == ClientID, self.assignments)
for a in assigned:
peer = filter(lambda e : e.id == a['PeerID'],
self.wireguardConfigurations[a['ConfigurationName']].Peers)
peer = filter(lambda e : e.id == a.PeerID,
self.wireguardConfigurations[a.ConfigurationName].Peers)
for p in peer:
peers.append({
'protocol': self.wireguardConfigurations[a['ConfigurationName']].Protocol,
'protocol': self.wireguardConfigurations[a.ConfigurationName].Protocol,
'id': p.id,
'private_key': p.private_key,
'name': p.name,
@@ -95,7 +138,7 @@ class DashboardClientsPeerAssignment:
'latest_handshake': p.latest_handshake,
'allowed_ip': p.allowed_ip,
'jobs': p.jobs,
'configuration_name': a['ConfigurationName'],
'configuration_name': a.ConfigurationName,
'peer_configuration_data': p.downloadPeer()
})
return peers

View File

@@ -129,7 +129,7 @@ class DashboardConfig:
try:
with self.engine.connect() as conn:
keys = conn.execute(self.apiKeyTable.select().where(
db.or_(self.apiKeyTable.columns.ExpiredAt == None, self.apiKeyTable.columns.ExpiredAt > datetime.now())
db.or_(self.apiKeyTable.columns.ExpiredAt.is_(None), self.apiKeyTable.columns.ExpiredAt > datetime.now())
)).fetchall()
fKeys = []
for k in keys:

View File

@@ -29,6 +29,11 @@ class DashboardOIDC:
def GetProviders(self):
return self.providers
def GetProviderNameByIssuer(self, issuer):
for (key, val) in self.providers.items():
if val.get('openid_configuration').get('issuer') == issuer:
return key
def VerifyToken(self, provider, code, redirect_uri):
try:
if not all([provider, code, redirect_uri]):

View File

@@ -32,7 +32,7 @@ class PeerJobs:
self.Jobs.clear()
with self.engine.connect() as conn:
jobs = conn.execute(self.peerJobTable.select().where(
self.peerJobTable.columns.ExpireDate == None
self.peerJobTable.columns.ExpireDate.is_(None)
)).mappings().fetchall()
for job in jobs:
self.Jobs.append(PeerJob(

View File

@@ -28,7 +28,7 @@ class PeerShareLinks:
with self.engine.connect() as conn:
allLinks = conn.execute(
self.peerShareLinksTable.select().where(
db.or_(self.peerShareLinksTable.columns.ExpireDate == None, self.peerShareLinksTable.columns.ExpireDate > datetime.now())
db.or_(self.peerShareLinksTable.columns.ExpireDate.is_(None), self.peerShareLinksTable.columns.ExpireDate > datetime.now())
)
).mappings().fetchall()
for link in allLinks: