mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-07-15 09:36:59 +00:00
Peer assignment to client is done
This commit is contained in:
parent
af045447e6
commit
68e757aafc
@ -26,12 +26,8 @@ def login_required(f):
|
|||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration], dashboardConfig: DashboardConfig):
|
from modules.DashboardClients import DashboardClients
|
||||||
from modules.DashboardClients import DashboardClients
|
def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration], dashboardConfig: DashboardConfig, dashboardClients: DashboardClients):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DashboardClients = DashboardClients(wireguardConfigurations)
|
|
||||||
|
|
||||||
client = Blueprint('client', __name__, template_folder=os.path.abspath("./static/client/dist"))
|
client = Blueprint('client', __name__, template_folder=os.path.abspath("./static/client/dist"))
|
||||||
prefix = f'{dashboardConfig.GetConfig("Server", "app_prefix")[1]}/client'
|
prefix = f'{dashboardConfig.GetConfig("Server", "app_prefix")[1]}/client'
|
||||||
@ -45,17 +41,17 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
@client.post(f'{prefix}/api/signup')
|
@client.post(f'{prefix}/api/signup')
|
||||||
def ClientAPI_SignUp():
|
def ClientAPI_SignUp():
|
||||||
data = request.json
|
data = request.json
|
||||||
status, msg = DashboardClients.SignUp(**data)
|
status, msg = dashboardClients.SignUp(**data)
|
||||||
return ResponseObject(status, msg)
|
return ResponseObject(status, msg)
|
||||||
|
|
||||||
@client.get(f'{prefix}/api/signin/oidc/providers')
|
@client.get(f'{prefix}/api/signin/oidc/providers')
|
||||||
def ClientAPI_SignIn_OIDC_GetProviders():
|
def ClientAPI_SignIn_OIDC_GetProviders():
|
||||||
return ResponseObject(data=DashboardClients.OIDC.GetProviders())
|
return ResponseObject(data=dashboardClients.OIDC.GetProviders())
|
||||||
|
|
||||||
@client.post(f'{prefix}/api/signin/oidc')
|
@client.post(f'{prefix}/api/signin/oidc')
|
||||||
def ClientAPI_SignIn_OIDC():
|
def ClientAPI_SignIn_OIDC():
|
||||||
data = request.json
|
data = request.json
|
||||||
status, oidcData = DashboardClients.SignIn_OIDC(**data)
|
status, oidcData = dashboardClients.SignIn_OIDC(**data)
|
||||||
if not status:
|
if not status:
|
||||||
return ResponseObject(status, oidcData)
|
return ResponseObject(status, oidcData)
|
||||||
|
|
||||||
@ -68,7 +64,7 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
@client.post(f'{prefix}/api/signin')
|
@client.post(f'{prefix}/api/signin')
|
||||||
def ClientAPI_SignIn():
|
def ClientAPI_SignIn():
|
||||||
data = request.json
|
data = request.json
|
||||||
status, msg = DashboardClients.SignIn(**data)
|
status, msg = dashboardClients.SignIn(**data)
|
||||||
if status:
|
if status:
|
||||||
session['Email'] = data.get('Email')
|
session['Email'] = data.get('Email')
|
||||||
session['Role'] = 'client'
|
session['Role'] = 'client'
|
||||||
@ -78,7 +74,7 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
@client.get(f'{prefix}/api/signout')
|
@client.get(f'{prefix}/api/signout')
|
||||||
def ClientAPI_SignOut():
|
def ClientAPI_SignOut():
|
||||||
if session.get("SignInMethod") == "OIDC":
|
if session.get("SignInMethod") == "OIDC":
|
||||||
DashboardClients.SignOut_OIDC()
|
dashboardClients.SignOut_OIDC()
|
||||||
session.clear()
|
session.clear()
|
||||||
return ResponseObject(True)
|
return ResponseObject(True)
|
||||||
|
|
||||||
@ -88,7 +84,7 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
if not token:
|
if not token:
|
||||||
return ResponseObject(False, "Please provide TOTP token")
|
return ResponseObject(False, "Please provide TOTP token")
|
||||||
|
|
||||||
status, msg = DashboardClients.SignIn_GetTotp(token)
|
status, msg = dashboardClients.SignIn_GetTotp(token)
|
||||||
return ResponseObject(status, msg)
|
return ResponseObject(status, msg)
|
||||||
|
|
||||||
@client.post(f'{prefix}/api/signin/totp')
|
@client.post(f'{prefix}/api/signin/totp')
|
||||||
@ -98,14 +94,14 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
userProvidedTotp = data.get('UserProvidedTOTP', None)
|
userProvidedTotp = data.get('UserProvidedTOTP', None)
|
||||||
if not all([token, userProvidedTotp]):
|
if not all([token, userProvidedTotp]):
|
||||||
return ResponseObject(False, "Please fill in all fields")
|
return ResponseObject(False, "Please fill in all fields")
|
||||||
status, msg = DashboardClients.SignIn_GetTotp(token, userProvidedTotp)
|
status, msg = dashboardClients.SignIn_GetTotp(token, userProvidedTotp)
|
||||||
if status:
|
if status:
|
||||||
if session.get('Email') is None:
|
if session.get('Email') is None:
|
||||||
return ResponseObject(False, "Sign in status is invalid", status_code=401)
|
return ResponseObject(False, "Sign in status is invalid", status_code=401)
|
||||||
session['TotpVerified'] = True
|
session['TotpVerified'] = True
|
||||||
return ResponseObject(True, data={
|
return ResponseObject(True, data={
|
||||||
"Email": session.get('Email'),
|
"Email": session.get('Email'),
|
||||||
"Profile": DashboardClients.GetClientProfile(session.get("ClientID"))
|
"Profile": dashboardClients.GetClientProfile(session.get("ClientID"))
|
||||||
})
|
})
|
||||||
return ResponseObject(status, msg)
|
return ResponseObject(status, msg)
|
||||||
|
|
||||||
@ -127,7 +123,7 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
@client.get(f'{prefix}/api/configurations')
|
@client.get(f'{prefix}/api/configurations')
|
||||||
@login_required
|
@login_required
|
||||||
def ClientAPI_Configurations():
|
def ClientAPI_Configurations():
|
||||||
return ResponseObject(True, data=DashboardClients.GetClientAssignedPeers(session['ClientID']))
|
return ResponseObject(True, data=dashboardClients.GetClientAssignedPeers(session['ClientID']))
|
||||||
|
|
||||||
@client.get(f'{prefix}/api/settings/getClientProfile')
|
@client.get(f'{prefix}/api/settings/getClientProfile')
|
||||||
@login_required
|
@login_required
|
||||||
@ -135,14 +131,14 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
return ResponseObject(data={
|
return ResponseObject(data={
|
||||||
"Email": session.get("Email"),
|
"Email": session.get("Email"),
|
||||||
"SignInMethod": session.get("SignInMethod"),
|
"SignInMethod": session.get("SignInMethod"),
|
||||||
"Profile": DashboardClients.GetClientProfile(session.get("ClientID"))
|
"Profile": dashboardClients.GetClientProfile(session.get("ClientID"))
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.post(f'{prefix}/api/settings/updatePassword')
|
@client.post(f'{prefix}/api/settings/updatePassword')
|
||||||
@login_required
|
@login_required
|
||||||
def ClientAPI_Settings_UpdatePassword():
|
def ClientAPI_Settings_UpdatePassword():
|
||||||
data = request.json
|
data = request.json
|
||||||
status, message = DashboardClients.UpdateClientPassword(session['Email'], **data)
|
status, message = dashboardClients.UpdateClientPassword(session['Email'], **data)
|
||||||
|
|
||||||
return ResponseObject(status, message)
|
return ResponseObject(status, message)
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@ from flask_cors import CORS
|
|||||||
from icmplib import ping, traceroute
|
from icmplib import ping, traceroute
|
||||||
from flask.json.provider import DefaultJSONProvider
|
from flask.json.provider import DefaultJSONProvider
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
|
|
||||||
|
from sqlalchemy import RowMapping
|
||||||
|
|
||||||
from modules.Utilities import (
|
from modules.Utilities import (
|
||||||
RegexMatch, StringToBoolean,
|
RegexMatch, StringToBoolean,
|
||||||
ValidateIPAddressesWithRange, ValidateDNSAddress,
|
ValidateIPAddressesWithRange, ValidateDNSAddress,
|
||||||
@ -33,6 +36,8 @@ from client import createClientBlueprint
|
|||||||
|
|
||||||
from logging.config import dictConfig
|
from logging.config import dictConfig
|
||||||
|
|
||||||
|
from modules.DashboardClients import DashboardClients
|
||||||
|
|
||||||
dictConfig({
|
dictConfig({
|
||||||
'version': 1,
|
'version': 1,
|
||||||
'formatters': {'default': {
|
'formatters': {'default': {
|
||||||
@ -57,6 +62,8 @@ class CustomJsonEncoder(DefaultJSONProvider):
|
|||||||
def default(self, o):
|
def default(self, o):
|
||||||
if callable(getattr(o, "toJson", None)):
|
if callable(getattr(o, "toJson", None)):
|
||||||
return o.toJson()
|
return o.toJson()
|
||||||
|
if type(o) is RowMapping:
|
||||||
|
return dict(o)
|
||||||
return super().default(self)
|
return super().default(self)
|
||||||
app.json = CustomJsonEncoder(app)
|
app.json = CustomJsonEncoder(app)
|
||||||
|
|
||||||
@ -1195,6 +1202,52 @@ def API_SystemStatus():
|
|||||||
def API_ProtocolsEnabled():
|
def API_ProtocolsEnabled():
|
||||||
return ResponseObject(data=ProtocolsEnabled())
|
return ResponseObject(data=ProtocolsEnabled())
|
||||||
|
|
||||||
|
'''
|
||||||
|
Client Controller
|
||||||
|
'''
|
||||||
|
@app.get(f'{APP_PREFIX}/api/clients/allClients')
|
||||||
|
def API_Clients_AllClients():
|
||||||
|
return ResponseObject(data=DashboardClients.GetAllClients())
|
||||||
|
|
||||||
|
@app.post(f'{APP_PREFIX}/api/clients/assignClient')
|
||||||
|
def API_Clients_AssignClient():
|
||||||
|
data = request.get_json()
|
||||||
|
configurationName = data.get('ConfigurationName')
|
||||||
|
id = data.get('Peer')
|
||||||
|
client = data.get('ClientID')
|
||||||
|
if not all([configurationName, id, client]):
|
||||||
|
return ResponseObject(False, "Please provide all required fields")
|
||||||
|
|
||||||
|
status, data = DashboardClients.AssignClient(configurationName, id, client)
|
||||||
|
if not status:
|
||||||
|
return ResponseObject(status, message="Client already assiged to this peer")
|
||||||
|
|
||||||
|
return ResponseObject(data=data)
|
||||||
|
|
||||||
|
@app.post(f'{APP_PREFIX}/api/clients/unassignClient')
|
||||||
|
def API_Clients_UnassignClient():
|
||||||
|
data = request.get_json()
|
||||||
|
assignmentID = data.get('AssignmentID')
|
||||||
|
if not assignmentID:
|
||||||
|
return ResponseObject(False, "Please provide AssignmentID")
|
||||||
|
return ResponseObject(status=DashboardClients.UnassignClient(assignmentID))
|
||||||
|
|
||||||
|
@app.get(f'{APP_PREFIX}/api/clients/assignedClients')
|
||||||
|
def API_Clients_AssignedClients():
|
||||||
|
data = request.args
|
||||||
|
configurationName = data.get('ConfigurationName')
|
||||||
|
peerID = data.get('Peer')
|
||||||
|
if not all([configurationName, id]):
|
||||||
|
return ResponseObject(False, "Please provide all required fields")
|
||||||
|
return ResponseObject(
|
||||||
|
data=DashboardClients.GetAssignedPeerClients(configurationName, peerID))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Index Page
|
||||||
|
'''
|
||||||
|
|
||||||
@app.get(f'{APP_PREFIX}/')
|
@app.get(f'{APP_PREFIX}/')
|
||||||
def index():
|
def index():
|
||||||
app.logger.info('hi')
|
app.logger.info('hi')
|
||||||
@ -1282,10 +1335,13 @@ AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig)
|
|||||||
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations)
|
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations)
|
||||||
DashboardLogger: DashboardLogger = DashboardLogger()
|
DashboardLogger: DashboardLogger = DashboardLogger()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InitWireguardConfigurationsList(startup=True)
|
InitWireguardConfigurationsList(startup=True)
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
app.register_blueprint(createClientBlueprint(WireguardConfigurations, DashboardConfig))
|
DashboardClients: DashboardClients = DashboardClients(WireguardConfigurations)
|
||||||
|
app.register_blueprint(createClientBlueprint(WireguardConfigurations, DashboardConfig, DashboardClients))
|
||||||
|
|
||||||
def startThreads():
|
def startThreads():
|
||||||
bgThread = threading.Thread(target=peerInformationBackgroundThread, daemon=True)
|
bgThread = threading.Thread(target=peerInformationBackgroundThread, daemon=True)
|
||||||
|
@ -46,6 +46,8 @@ class DashboardClients:
|
|||||||
db.Column('CreatedDate',
|
db.Column('CreatedDate',
|
||||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||||
server_default=db.func.now()),
|
server_default=db.func.now()),
|
||||||
|
db.Column('DeletedDate',
|
||||||
|
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||||
extend_existing=True,
|
extend_existing=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,21 +59,61 @@ class DashboardClients:
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.metadata.create_all(self.engine)
|
self.metadata.create_all(self.engine)
|
||||||
self.Clients = []
|
self.Clients = {}
|
||||||
|
self.ClientsRaw = []
|
||||||
self.__getClients()
|
self.__getClients()
|
||||||
self.DashboardClientsTOTP = DashboardClientsTOTP()
|
self.DashboardClientsTOTP = DashboardClientsTOTP()
|
||||||
self.DashboardClientsPeerAssignment = DashboardClientsPeerAssignment(wireguardConfigurations)
|
self.DashboardClientsPeerAssignment = DashboardClientsPeerAssignment(wireguardConfigurations)
|
||||||
|
|
||||||
def __getClients(self):
|
def __getClients(self):
|
||||||
with self.engine.connect() as conn:
|
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(
|
db.select(
|
||||||
self.dashboardClientsTable.c.ClientID,
|
union,
|
||||||
self.dashboardClientsTable.c.Email,
|
self.dashboardClientsInfoTable.c.Name
|
||||||
self.dashboardClientsTable.c.CreatedDate
|
).outerjoin(self.dashboardClientsInfoTable,
|
||||||
).where(
|
union.c.ClientID == self.dashboardClientsInfoTable.c.ClientID)
|
||||||
self.dashboardClientsTable.c.DeletedDate is None)
|
).mappings().fetchall()
|
||||||
).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):
|
def GetClientProfile(self, ClientID):
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
@ -227,9 +269,7 @@ class DashboardClients:
|
|||||||
"ClientID": newClientUUID,
|
"ClientID": newClientUUID,
|
||||||
"Email": Email,
|
"Email": Email,
|
||||||
"Password": bcrypt.hashpw(encodePassword, bcrypt.gensalt()).decode("utf-8"),
|
"Password": bcrypt.hashpw(encodePassword, bcrypt.gensalt()).decode("utf-8"),
|
||||||
"TotpKey": totpKey,
|
"TotpKey": totpKey
|
||||||
"AuthType": "local",
|
|
||||||
"AuthSrc": "local"
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
conn.execute(
|
conn.execute(
|
||||||
@ -240,13 +280,13 @@ class DashboardClients:
|
|||||||
self.logger.log(Message=f"User {Email} signed up")
|
self.logger.log(Message=f"User {Email} signed up")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(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
|
return True, None
|
||||||
|
|
||||||
def GetClientAssignedPeers(self, ClientID):
|
def GetClientAssignedPeers(self, ClientID):
|
||||||
return self.DashboardClientsPeerAssignment.GetAssignedPeers(ClientID)
|
return self.DashboardClientsPeerAssignment.GetAssignedPeers(ClientID)
|
||||||
|
|
||||||
def UpdateClientPassword(self, Email, CurrentPassword, NewPassword, ConfirmNewPassword):
|
def UpdateClientPassword(self, Email, CurrentPassword, NewPassword, ConfirmNewPassword):
|
||||||
if not all([CurrentPassword, NewPassword, ConfirmNewPassword]):
|
if not all([CurrentPassword, NewPassword, ConfirmNewPassword]):
|
||||||
return False, "Please fill in all fields"
|
return False, "Please fill in all fields"
|
||||||
@ -273,4 +313,22 @@ class DashboardClients:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(e)}")
|
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(e)}")
|
||||||
return False, "Signed up failed."
|
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)
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
import datetime
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from .ConnectionString import ConnectionString
|
from .ConnectionString import ConnectionString
|
||||||
@ -5,7 +6,28 @@ from .DashboardLogger import DashboardLogger
|
|||||||
import sqlalchemy as db
|
import sqlalchemy as db
|
||||||
from .WireguardConfiguration import WireguardConfiguration
|
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:
|
class DashboardClientsPeerAssignment:
|
||||||
def __init__(self, wireguardConfigurations: dict[str, WireguardConfiguration]):
|
def __init__(self, wireguardConfigurations: dict[str, WireguardConfiguration]):
|
||||||
self.logger = DashboardLogger()
|
self.logger = DashboardLogger()
|
||||||
@ -26,26 +48,28 @@ class DashboardClientsPeerAssignment:
|
|||||||
extend_existing=True
|
extend_existing=True
|
||||||
)
|
)
|
||||||
self.metadata.create_all(self.engine)
|
self.metadata.create_all(self.engine)
|
||||||
self.assignments = []
|
self.assignments: list[Assignment] = []
|
||||||
self.__getAssignments()
|
self.__getAssignments()
|
||||||
|
|
||||||
self.AssignClient("0117a895-bd8b-4ba2-9116-6658372417fb", "wg0", "3kv6Bo46u7ULT07B3I1VHw/rYomVnrCD5TFU369jRSc=")
|
|
||||||
self.GetAssignedPeers("0117a895-bd8b-4ba2-9116-6658372417fb")
|
|
||||||
|
|
||||||
def __getAssignments(self):
|
def __getAssignments(self):
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
self.assignments = conn.execute(
|
assignments = []
|
||||||
|
get = conn.execute(
|
||||||
self.dashboardClientsPeerAssignmentTable.select().where(
|
self.dashboardClientsPeerAssignmentTable.select().where(
|
||||||
self.dashboardClientsPeerAssignmentTable.c.UnassignedDate == db.null()
|
self.dashboardClientsPeerAssignmentTable.c.UnassignedDate.is_(None)
|
||||||
)
|
)
|
||||||
).mappings().fetchall()
|
).mappings().fetchall()
|
||||||
|
for a in get:
|
||||||
|
assignments.append(Assignment(**a))
|
||||||
|
self.assignments = assignments
|
||||||
|
|
||||||
|
|
||||||
def AssignClient(self, ClientID, ConfigurationName, PeerID):
|
def AssignClient(self, ClientID, ConfigurationName, PeerID):
|
||||||
existing = list(
|
existing = list(
|
||||||
filter(lambda e:
|
filter(lambda e:
|
||||||
e['ClientID'] == ClientID and
|
e.ClientID == ClientID and
|
||||||
e['ConfigurationName'] == ConfigurationName and
|
e.ConfigurationName == ConfigurationName and
|
||||||
e['PeerID'] == PeerID, self.assignments)
|
e.PeerID == PeerID, self.assignments)
|
||||||
)
|
)
|
||||||
if len(existing) == 0:
|
if len(existing) == 0:
|
||||||
if ConfigurationName in self.wireguardConfigurations.keys():
|
if ConfigurationName in self.wireguardConfigurations.keys():
|
||||||
@ -66,25 +90,44 @@ class DashboardClientsPeerAssignment:
|
|||||||
return True, data
|
return True, data
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
def UnassignClient(self, AssignmentID):
|
def UnassignClients(self, AssignmentID):
|
||||||
pass
|
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):
|
def GetAssignedClients(self, ConfigurationName, PeerID) -> list[Assignment]:
|
||||||
pass
|
self.__getAssignments()
|
||||||
|
return list(filter(
|
||||||
|
lambda c : c.ConfigurationName == ConfigurationName and
|
||||||
|
c.PeerID == PeerID, self.assignments))
|
||||||
|
|
||||||
def GetAssignedPeers(self, ClientID):
|
def GetAssignedPeers(self, ClientID):
|
||||||
self.__getAssignments()
|
self.__getAssignments()
|
||||||
|
|
||||||
peers = []
|
peers = []
|
||||||
assigned = filter(lambda e:
|
assigned = filter(lambda e:
|
||||||
e['ClientID'] == ClientID, self.assignments)
|
e.ClientID == ClientID, self.assignments)
|
||||||
|
|
||||||
for a in assigned:
|
for a in assigned:
|
||||||
peer = filter(lambda e : e.id == a['PeerID'],
|
peer = filter(lambda e : e.id == a.PeerID,
|
||||||
self.wireguardConfigurations[a['ConfigurationName']].Peers)
|
self.wireguardConfigurations[a.ConfigurationName].Peers)
|
||||||
for p in peer:
|
for p in peer:
|
||||||
peers.append({
|
peers.append({
|
||||||
'protocol': self.wireguardConfigurations[a['ConfigurationName']].Protocol,
|
'protocol': self.wireguardConfigurations[a.ConfigurationName].Protocol,
|
||||||
'id': p.id,
|
'id': p.id,
|
||||||
'private_key': p.private_key,
|
'private_key': p.private_key,
|
||||||
'name': p.name,
|
'name': p.name,
|
||||||
@ -95,7 +138,7 @@ class DashboardClientsPeerAssignment:
|
|||||||
'latest_handshake': p.latest_handshake,
|
'latest_handshake': p.latest_handshake,
|
||||||
'allowed_ip': p.allowed_ip,
|
'allowed_ip': p.allowed_ip,
|
||||||
'jobs': p.jobs,
|
'jobs': p.jobs,
|
||||||
'configuration_name': a['ConfigurationName'],
|
'configuration_name': a.ConfigurationName,
|
||||||
'peer_configuration_data': p.downloadPeer()
|
'peer_configuration_data': p.downloadPeer()
|
||||||
})
|
})
|
||||||
return peers
|
return peers
|
@ -129,7 +129,7 @@ class DashboardConfig:
|
|||||||
try:
|
try:
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
keys = conn.execute(self.apiKeyTable.select().where(
|
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()
|
)).fetchall()
|
||||||
fKeys = []
|
fKeys = []
|
||||||
for k in keys:
|
for k in keys:
|
||||||
|
@ -29,6 +29,11 @@ class DashboardOIDC:
|
|||||||
def GetProviders(self):
|
def GetProviders(self):
|
||||||
return self.providers
|
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):
|
def VerifyToken(self, provider, code, redirect_uri):
|
||||||
try:
|
try:
|
||||||
if not all([provider, code, redirect_uri]):
|
if not all([provider, code, redirect_uri]):
|
||||||
|
@ -32,7 +32,7 @@ class PeerJobs:
|
|||||||
self.Jobs.clear()
|
self.Jobs.clear()
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
jobs = conn.execute(self.peerJobTable.select().where(
|
jobs = conn.execute(self.peerJobTable.select().where(
|
||||||
self.peerJobTable.columns.ExpireDate == None
|
self.peerJobTable.columns.ExpireDate.is_(None)
|
||||||
)).mappings().fetchall()
|
)).mappings().fetchall()
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
self.Jobs.append(PeerJob(
|
self.Jobs.append(PeerJob(
|
||||||
|
@ -28,7 +28,7 @@ class PeerShareLinks:
|
|||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
allLinks = conn.execute(
|
allLinks = conn.execute(
|
||||||
self.peerShareLinksTable.select().where(
|
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()
|
).mappings().fetchall()
|
||||||
for link in allLinks:
|
for link in allLinks:
|
||||||
|
@ -1 +1 @@
|
|||||||
import{_ as r,c as i,d as o,w as e,k as l,a as t,j as _,i as a,l as d,S as u}from"./index-AzYVPyhh.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(k,x,h,w,$,v){const n=l("RouterView");return t(),i("div",p,[o(n,null,{default:e(({Component:s,route:c})=>[o(_,{name:"fade2",mode:"out-in"},{default:e(()=>[(t(),a(u,null,{default:e(()=>[(t(),a(d(s),{key:c.path}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
import{_ as r,c as i,d as o,w as e,k as l,a as t,j as _,i as a,l as d,S as u}from"./index-DcxvUQLx.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(k,x,h,w,$,v){const n=l("RouterView");return t(),i("div",p,[o(n,null,{default:e(({Component:s,route:c})=>[o(_,{name:"fade2",mode:"out-in"},{default:e(()=>[(t(),a(u,null,{default:e(()=>[(t(),a(d(s),{key:c.path}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
src/static/app/dist/assets/editConfiguration-CStW59Wh.js
vendored
Normal file
7
src/static/app/dist/assets/editConfiguration-CStW59Wh.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/editConfiguration-D2Cid4Hl.css
vendored
Normal file
1
src/static/app/dist/assets/editConfiguration-D2Cid4Hl.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
import{P as Ws,Q as Vs,R as Ue,U as Hn,r as Wn,o as Vn,V as Nn,H as jn,X as Xe,Y as $n,Z as Ns}from"./index-AzYVPyhh.js";/*!
|
import{P as Ws,Q as Vs,R as Ue,U as Hn,r as Wn,o as Vn,V as Nn,H as jn,X as Xe,Y as $n,Z as Ns}from"./index-DcxvUQLx.js";/*!
|
||||||
* @kurkle/color v0.3.2
|
* @kurkle/color v0.3.2
|
||||||
* https://github.com/kurkle/color#readme
|
* https://github.com/kurkle/color#readme
|
||||||
* (c) 2023 Jukka Kurkela
|
* (c) 2023 Jukka Kurkela
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{_ as e,G as t,a as o,c as a,t as c}from"./index-AzYVPyhh.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return o(),a("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
import{_ as e,G as t,a as o,c as a,t as c}from"./index-DcxvUQLx.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return o(),a("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
@ -1 +1 @@
|
|||||||
import{L as l}from"./localeText-qJNpKS91.js";import{d as c}from"./dayjs.min-DO3nadR-.js";import{_ as h,a as o,c as a,b as e,d as i,w as u,f as p,t as n,j as g,n as f,k as _}from"./index-AzYVPyhh.js";const x={name:"message",methods:{dayjs:c,hide(){this.ct(),this.message.show=!1},show(){this.timeout=setTimeout(()=>{this.message.show=!1},5e3)},ct(){clearTimeout(this.timeout)}},components:{LocaleText:l},props:{message:Object},mounted(){this.show()},data(){return{dismiss:!1,timeout:null}}},v=["id"],b={key:0,class:"d-flex"},w={class:"fw-bold d-block",style:{"text-transform":"uppercase"}},y={class:"ms-auto"},k={key:1},T={class:"card-body d-flex align-items-center gap-3"};function M(j,s,C,L,t,m){const d=_("LocaleText");return o(),a("div",{onMouseenter:s[1]||(s[1]=r=>{t.dismiss=!0,this.ct()}),onMouseleave:s[2]||(s[2]=r=>{t.dismiss=!1,this.show()}),class:"card shadow rounded-3 position-relative message ms-auto",id:this.message.id},[e("div",{class:f([{"text-bg-danger":this.message.type==="danger","text-bg-success":this.message.type==="success","text-bg-warning":this.message.type==="warning"},"card-header pos"])},[i(g,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(o(),a("div",k,[e("small",{onClick:s[0]||(s[0]=r=>m.hide()),class:"d-block mx-auto w-100 text-center",style:{cursor:"pointer"}},[s[3]||(s[3]=e("i",{class:"bi bi-x-lg me-2"},null,-1)),i(d,{t:"Dismiss"})])])):(o(),a("div",b,[e("small",w,[i(d,{t:"FROM "}),p(" "+n(this.message.from),1)]),e("small",y,n(m.dayjs().format("hh:mm A")),1)]))]),_:1})],2),e("div",T,[e("div",null,n(this.message.content),1)])],40,v)}const z=h(x,[["render",M],["__scopeId","data-v-94c76b54"]]);export{z as M};
|
import{L as l}from"./localeText-BZk4B_3P.js";import{d as c}from"./dayjs.min-C-HzUJel.js";import{_ as h,a as o,c as a,b as e,d as i,w as u,f as p,t as n,j as g,n as f,k as _}from"./index-DcxvUQLx.js";const x={name:"message",methods:{dayjs:c,hide(){this.ct(),this.message.show=!1},show(){this.timeout=setTimeout(()=>{this.message.show=!1},5e3)},ct(){clearTimeout(this.timeout)}},components:{LocaleText:l},props:{message:Object},mounted(){this.show()},data(){return{dismiss:!1,timeout:null}}},v=["id"],b={key:0,class:"d-flex"},w={class:"fw-bold d-block",style:{"text-transform":"uppercase"}},y={class:"ms-auto"},k={key:1},T={class:"card-body d-flex align-items-center gap-3"};function M(j,s,C,L,t,m){const d=_("LocaleText");return o(),a("div",{onMouseenter:s[1]||(s[1]=r=>{t.dismiss=!0,this.ct()}),onMouseleave:s[2]||(s[2]=r=>{t.dismiss=!1,this.show()}),class:"card shadow rounded-3 position-relative message ms-auto",id:this.message.id},[e("div",{class:f([{"text-bg-danger":this.message.type==="danger","text-bg-success":this.message.type==="success","text-bg-warning":this.message.type==="warning"},"card-header pos"])},[i(g,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(o(),a("div",k,[e("small",{onClick:s[0]||(s[0]=r=>m.hide()),class:"d-block mx-auto w-100 text-center",style:{cursor:"pointer"}},[s[3]||(s[3]=e("i",{class:"bi bi-x-lg me-2"},null,-1)),i(d,{t:"Dismiss"})])])):(o(),a("div",b,[e("small",w,[i(d,{t:"FROM "}),p(" "+n(this.message.from),1)]),e("small",y,n(m.dayjs().format("hh:mm A")),1)]))]),_:1})],2),e("div",T,[e("div",null,n(this.message.content),1)])],40,v)}const z=h(x,[["render",M],["__scopeId","data-v-94c76b54"]]);export{z as M};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerAssignModal-Bft8pleA.js
vendored
Normal file
1
src/static/app/dist/assets/peerAssignModal-Bft8pleA.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerAssignModal-D9tSJfEI.css
vendored
Normal file
1
src/static/app/dist/assets/peerAssignModal-D9tSJfEI.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.list-move[data-v-c72df947],.list-enter-active[data-v-c72df947],.list-leave-active[data-v-c72df947]{transition:all .5s ease}.list-enter-from[data-v-c72df947],.list-leave-to[data-v-c72df947]{opacity:0;transform:scale(.9)}.list-leave-active[data-v-c72df947]{position:absolute;width:100%}.assignment[data-v-c72df947]:last-child{margin-bottom:0!important}[data-v-db8c10f7]:focus{outline:none}
|
@ -1 +1 @@
|
|||||||
import{_ as v,D as g,r as o,o as h,J as x,g as y,a as i,c as n,b as s,d as c,n as w,e as C,w as k,j as F}from"./index-AzYVPyhh.js";import{L as T}from"./localeText-qJNpKS91.js";import"./browser-CjSdxGTc.js";const M={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},S={class:"container d-flex h-100 w-100"},D={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},P={class:"card rounded-3 shadow w-100"},j={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},B={class:"mb-0"},G={class:"card-body p-4 d-flex flex-column gap-3"},L={style:{height:"300px"},class:"d-flex"},N=["value"],V={key:0,class:"spinner-border m-auto",role:"status"},I={class:"d-flex"},W=["disabled"],$={key:0,class:"d-block"},q={key:1,class:"d-block",id:"check"},z={__name:"peerConfigurationFile",props:{selectedPeer:Object},emits:["close"],setup(u,{emit:p}){const m=p,f=u,r=g(),t=o(!1),l=o(""),a=o(!0);o({error:!1,message:void 0}),h(()=>{const d=x();y("/api/downloadPeer/"+d.params.id,{id:f.selectedPeer.id},e=>{e.status?(l.value=e.data.file,a.value=!1):this.dashboardStore.newMessage("Server",e.message,"danger")})});const b=async()=>{navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l.value).then(()=>{t.value=!0,setTimeout(()=>{t.value=!1},3e3)}).catch(()=>{r.newMessage("WGDashboard","Failed to copy","danger")}):(document.querySelector("#peerConfigurationFile").select(),document.execCommand("copy")?(t.value=!0,setTimeout(()=>{t.value=!1},3e3)):r.newMessage("WGDashboard","Failed to copy","danger"))};return(d,e)=>(i(),n("div",M,[s("div",S,[s("div",D,[s("div",P,[s("div",j,[s("h4",B,[c(T,{t:"Peer Configuration File"})]),s("button",{type:"button",class:"btn-close ms-auto",onClick:e[0]||(e[0]=_=>m("close"))})]),s("div",G,[s("div",L,[s("textarea",{style:{height:"300px"},class:w(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,N),a.value?(i(),n("div",V,e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)]))):C("",!0)]),s("div",I,[s("button",{onClick:e[1]||(e[1]=_=>b()),disabled:t.value||a.value,class:"ms-auto btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 position-relative"},[c(F,{name:"slide-up",mode:"out-in"},{default:k(()=>[t.value?(i(),n("span",q,e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)]))):(i(),n("span",$,e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])))]),_:1})],8,W)])])])])])]))}},R=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{R as default};
|
import{_ as v,D as g,r as o,o as h,J as x,g as y,a as i,c as n,b as s,d as c,n as w,e as C,w as k,j as F}from"./index-DcxvUQLx.js";import{L as T}from"./localeText-BZk4B_3P.js";import"./browser-CjSdxGTc.js";const M={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},S={class:"container d-flex h-100 w-100"},D={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},P={class:"card rounded-3 shadow w-100"},j={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},B={class:"mb-0"},G={class:"card-body p-4 d-flex flex-column gap-3"},L={style:{height:"300px"},class:"d-flex"},N=["value"],V={key:0,class:"spinner-border m-auto",role:"status"},I={class:"d-flex"},W=["disabled"],$={key:0,class:"d-block"},q={key:1,class:"d-block",id:"check"},z={__name:"peerConfigurationFile",props:{selectedPeer:Object},emits:["close"],setup(u,{emit:p}){const m=p,f=u,r=g(),t=o(!1),l=o(""),a=o(!0);o({error:!1,message:void 0}),h(()=>{const d=x();y("/api/downloadPeer/"+d.params.id,{id:f.selectedPeer.id},e=>{e.status?(l.value=e.data.file,a.value=!1):this.dashboardStore.newMessage("Server",e.message,"danger")})});const b=async()=>{navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l.value).then(()=>{t.value=!0,setTimeout(()=>{t.value=!1},3e3)}).catch(()=>{r.newMessage("WGDashboard","Failed to copy","danger")}):(document.querySelector("#peerConfigurationFile").select(),document.execCommand("copy")?(t.value=!0,setTimeout(()=>{t.value=!1},3e3)):r.newMessage("WGDashboard","Failed to copy","danger"))};return(d,e)=>(i(),n("div",M,[s("div",S,[s("div",D,[s("div",P,[s("div",j,[s("h4",B,[c(T,{t:"Peer Configuration File"})]),s("button",{type:"button",class:"btn-close ms-auto",onClick:e[0]||(e[0]=_=>m("close"))})]),s("div",G,[s("div",L,[s("textarea",{style:{height:"300px"},class:w(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,N),a.value?(i(),n("div",V,e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)]))):C("",!0)]),s("div",I,[s("button",{onClick:e[1]||(e[1]=_=>b()),disabled:t.value||a.value,class:"ms-auto btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 position-relative"},[c(F,{name:"slide-up",mode:"out-in"},{default:k(()=>[t.value?(i(),n("span",q,e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)]))):(i(),n("span",$,e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])))]),_:1})],8,W)])])])])])]))}},R=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{R as default};
|
@ -1 +1 @@
|
|||||||
import{S as p,a as b}from"./schedulePeerJob-Cy0v4heL.js";import{_ as h,W as u,z as m,k as i,a as o,c as a,b as e,d as r,w as _,F as v,h as f,i as J,e as x,T as g}from"./index-AzYVPyhh.js";import{L as w}from"./localeText-qJNpKS91.js";import"./vue-datepicker-Co-zpMN6.js";import"./dayjs.min-DO3nadR-.js";const P={name:"peerJobs",setup(){return{store:u()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:p,ScheduleDropdown:b},data(){return{}},methods:{deleteJob(d){this.selectedPeer.jobs=this.selectedPeer.jobs.filter(t=>t.JobID!==d.JobID)},addJob(){this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({JobID:m().toString(),Configuration:this.selectedPeer.configuration.Name,Peer:this.selectedPeer.id,Field:this.store.PeerScheduleJobs.dropdowns.Field[0].value,Operator:this.store.PeerScheduleJobs.dropdowns.Operator[0].value,Value:"",CreationDate:"",ExpireDate:"",Action:this.store.PeerScheduleJobs.dropdowns.Action[0].value})))}}},S={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},y={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},C={class:"card rounded-3 shadow",style:{width:"700px"}},D={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},k={class:"mb-0 fw-normal"},j={class:"card-body px-4 pb-4 pt-2 position-relative"},T={class:"d-flex align-items-center mb-3"},N={class:"card shadow-sm",key:"none",style:{height:"153px"}},I={class:"card-body text-muted text-center d-flex"},L={class:"m-auto"};function O(d,t,B,F,V,A){const n=i("LocaleText"),l=i("SchedulePeerJob");return o(),a("div",S,[e("div",y,[e("div",$,[e("div",C,[e("div",D,[e("h4",k,[r(n,{t:"Schedule Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=s=>this.$emit("close"))})]),e("div",j,[e("div",T,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow",onClick:t[1]||(t[1]=s=>this.addJob())},[t[3]||(t[3]=e("i",{class:"bi bi-plus-lg me-2"},null,-1)),r(n,{t:"Job"})])]),r(g,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:_(()=>[(o(!0),a(v,null,f(this.selectedPeer.jobs,(s,E)=>(o(),J(l,{onRefresh:t[2]||(t[2]=c=>this.$emit("refresh")),onDelete:c=>this.deleteJob(s),dropdowns:this.store.PeerScheduleJobs.dropdowns,key:s.JobID,pjob:s},null,8,["onDelete","dropdowns","pjob"]))),128)),this.selectedPeer.jobs.length===0?(o(),a("div",N,[e("div",I,[e("h6",L,[r(n,{t:"This peer does not have any job yet."})])])])):x("",!0)]),_:1})])])])])])}const q=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{q as default};
|
import{S as p,a as b}from"./schedulePeerJob-4q3NRUJn.js";import{_ as h,W as u,z as m,k as i,a as o,c as a,b as e,d as r,w as _,F as v,h as f,i as J,e as x,T as g}from"./index-DcxvUQLx.js";import{L as w}from"./localeText-BZk4B_3P.js";import"./vue-datepicker-4raVR3Z0.js";import"./dayjs.min-C-HzUJel.js";const P={name:"peerJobs",setup(){return{store:u()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:p,ScheduleDropdown:b},data(){return{}},methods:{deleteJob(d){this.selectedPeer.jobs=this.selectedPeer.jobs.filter(t=>t.JobID!==d.JobID)},addJob(){this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({JobID:m().toString(),Configuration:this.selectedPeer.configuration.Name,Peer:this.selectedPeer.id,Field:this.store.PeerScheduleJobs.dropdowns.Field[0].value,Operator:this.store.PeerScheduleJobs.dropdowns.Operator[0].value,Value:"",CreationDate:"",ExpireDate:"",Action:this.store.PeerScheduleJobs.dropdowns.Action[0].value})))}}},S={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},y={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},C={class:"card rounded-3 shadow",style:{width:"700px"}},D={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},k={class:"mb-0 fw-normal"},j={class:"card-body px-4 pb-4 pt-2 position-relative"},T={class:"d-flex align-items-center mb-3"},N={class:"card shadow-sm",key:"none",style:{height:"153px"}},I={class:"card-body text-muted text-center d-flex"},L={class:"m-auto"};function O(d,t,B,F,V,A){const n=i("LocaleText"),l=i("SchedulePeerJob");return o(),a("div",S,[e("div",y,[e("div",$,[e("div",C,[e("div",D,[e("h4",k,[r(n,{t:"Schedule Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=s=>this.$emit("close"))})]),e("div",j,[e("div",T,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow",onClick:t[1]||(t[1]=s=>this.addJob())},[t[3]||(t[3]=e("i",{class:"bi bi-plus-lg me-2"},null,-1)),r(n,{t:"Job"})])]),r(g,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:_(()=>[(o(!0),a(v,null,f(this.selectedPeer.jobs,(s,E)=>(o(),J(l,{onRefresh:t[2]||(t[2]=c=>this.$emit("refresh")),onDelete:c=>this.deleteJob(s),dropdowns:this.store.PeerScheduleJobs.dropdowns,key:s.JobID,pjob:s},null,8,["onDelete","dropdowns","pjob"]))),128)),this.selectedPeer.jobs.length===0?(o(),a("div",N,[e("div",I,[e("h6",L,[r(n,{t:"This peer does not have any job yet."})])])])):x("",!0)]),_:1})])])])])])}const q=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{q as default};
|
@ -1 +1 @@
|
|||||||
import{S as _}from"./schedulePeerJob-Cy0v4heL.js";import{_ as g,W as v,k as c,a as t,c as r,b as e,d as l,F as p,h as b,t as m,e as f,i as y}from"./index-AzYVPyhh.js";import{L as x}from"./localeText-qJNpKS91.js";import"./vue-datepicker-Co-zpMN6.js";import"./dayjs.min-DO3nadR-.js";const J={name:"peerJobsAllModal",setup(){return{store:v()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},k={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},w={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},A={class:"card rounded-3 shadow",style:{width:"900px"}},L={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},S={class:"mb-0 fw-normal"},C={class:"card-body px-4 pb-4 pt-2"},P={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},j={class:"accordion-header"},M=["data-bs-target"],B={key:0},N={class:"text-muted"},D=["id"],T={class:"accordion-body"},V={key:1,class:"card shadow-sm",style:{height:"153px"}},F={class:"card-body text-muted text-center d-flex"},O={class:"m-auto"};function W(a,o,E,I,R,q){const n=c("LocaleText"),u=c("SchedulePeerJob");return t(),r("div",k,[e("div",w,[e("div",$,[e("div",A,[e("div",L,[e("h4",S,[l(n,{t:"All Active Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:o[0]||(o[0]=s=>this.$emit("close"))})]),e("div",C,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow mb-2",onClick:o[1]||(o[1]=s=>this.$emit("allLogs"))},[o[4]||(o[4]=e("i",{class:"bi bi-clock me-2"},null,-1)),l(n,{t:"Logs"})]),this.getAllJobs.length>0?(t(),r("div",P,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",j,[e("button",{class:"accordion-button collapsed",type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse_"+d},[e("small",null,[e("strong",null,[s.name?(t(),r("span",B,m(s.name)+" • ",1)):f("",!0),e("samp",N,m(s.id),1)])])],8,M)]),e("div",{id:"collapse_"+d,class:"accordion-collapse collapse","data-bs-parent":"#peerJobsLogsModalAccordion"},[e("div",T,[(t(!0),r(p,null,b(s.jobs,i=>(t(),y(u,{onDelete:o[2]||(o[2]=h=>this.$emit("refresh")),onRefresh:o[3]||(o[3]=h=>this.$emit("refresh")),dropdowns:this.store.PeerScheduleJobs.dropdowns,viewOnly:!0,key:i.JobID,pjob:i},null,8,["dropdowns","pjob"]))),128))])],8,D)]))),128))])):(t(),r("div",V,[e("div",F,[e("span",O,[l(n,{t:"No active job at the moment."})])])]))])])])])])}const U=g(J,[["render",W]]);export{U as default};
|
import{S as _}from"./schedulePeerJob-4q3NRUJn.js";import{_ as g,W as v,k as c,a as t,c as r,b as e,d as l,F as p,h as b,t as m,e as f,i as y}from"./index-DcxvUQLx.js";import{L as x}from"./localeText-BZk4B_3P.js";import"./vue-datepicker-4raVR3Z0.js";import"./dayjs.min-C-HzUJel.js";const J={name:"peerJobsAllModal",setup(){return{store:v()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},k={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},w={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},A={class:"card rounded-3 shadow",style:{width:"900px"}},L={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},S={class:"mb-0 fw-normal"},C={class:"card-body px-4 pb-4 pt-2"},P={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},j={class:"accordion-header"},M=["data-bs-target"],B={key:0},N={class:"text-muted"},D=["id"],T={class:"accordion-body"},V={key:1,class:"card shadow-sm",style:{height:"153px"}},F={class:"card-body text-muted text-center d-flex"},O={class:"m-auto"};function W(a,o,E,I,R,q){const n=c("LocaleText"),u=c("SchedulePeerJob");return t(),r("div",k,[e("div",w,[e("div",$,[e("div",A,[e("div",L,[e("h4",S,[l(n,{t:"All Active Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:o[0]||(o[0]=s=>this.$emit("close"))})]),e("div",C,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow mb-2",onClick:o[1]||(o[1]=s=>this.$emit("allLogs"))},[o[4]||(o[4]=e("i",{class:"bi bi-clock me-2"},null,-1)),l(n,{t:"Logs"})]),this.getAllJobs.length>0?(t(),r("div",P,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",j,[e("button",{class:"accordion-button collapsed",type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse_"+d},[e("small",null,[e("strong",null,[s.name?(t(),r("span",B,m(s.name)+" • ",1)):f("",!0),e("samp",N,m(s.id),1)])])],8,M)]),e("div",{id:"collapse_"+d,class:"accordion-collapse collapse","data-bs-parent":"#peerJobsLogsModalAccordion"},[e("div",T,[(t(!0),r(p,null,b(s.jobs,i=>(t(),y(u,{onDelete:o[2]||(o[2]=h=>this.$emit("refresh")),onRefresh:o[3]||(o[3]=h=>this.$emit("refresh")),dropdowns:this.store.PeerScheduleJobs.dropdowns,viewOnly:!0,key:i.JobID,pjob:i},null,8,["dropdowns","pjob"]))),128))])],8,D)]))),128))])):(t(),r("div",V,[e("div",F,[e("span",O,[l(n,{t:"No active job at the moment."})])])]))])])])])])}const U=g(J,[["render",W]]);export{U as default};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
src/static/app/dist/assets/peerList-DCgdfrOh.js
vendored
Normal file
2
src/static/app/dist/assets/peerList-DCgdfrOh.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{b as i}from"./browser-CjSdxGTc.js";import{L as c}from"./localeText-qJNpKS91.js";import{_ as l,D as p,g as _,k as m,a as n,c as r,b as e,d as u,n as h,e as f}from"./index-AzYVPyhh.js";const g={name:"peerQRCode",components:{LocaleText:c},props:{selectedPeer:Object},setup(){return{dashboardStore:p()}},data(){return{loading:!0}},mounted(){_("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},o=>{if(this.loading=!1,o.status){let t="";if(this.selectedPeer.configuration.Protocol==="awg"){let a={containers:[{awg:{isThirdPartyConfig:!0,last_config:o.data.file,port:this.selectedPeer.configuration.ListenPort,transport_proto:"udp"},container:"amnezia-awg"}],defaultContainer:"amnezia-awg",description:this.selectedPeer.name,hostName:this.dashboardStore.Configuration.Peers.remote_endpoint};t=JSON.stringify(a)}else t=o.data.file;i.toCanvas(document.querySelector("#qrcode"),t,a=>{a&&console.error(a)})}else this.dashboardStore.newMessage("Server",o.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},v={class:"container d-flex h-100 w-100"},C={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},w={class:"card rounded-3 shadow"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},x={class:"mb-0"},S={class:"card-body p-4"},y={class:"d-flex"},L={key:0,class:"spinner-border m-auto",role:"status"};function k(o,t,a,N,s,$){const d=m("LocaleText");return n(),r("div",b,[e("div",v,[e("div",C,[e("div",w,[e("div",P,[e("h4",x,[u(d,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=Q=>this.$emit("close"))})]),e("div",S,[e("div",y,[e("canvas",{id:"qrcode",class:h(["rounded-3 shadow animate__animated animate__fadeIn animate__faster",{"d-none":s.loading}])},null,2),s.loading?(n(),r("div",L,t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)]))):f("",!0)])])])])])])}const q=l(g,[["render",k],["__scopeId","data-v-5816a147"]]);export{q as default};
|
import{b as i}from"./browser-CjSdxGTc.js";import{L as c}from"./localeText-BZk4B_3P.js";import{_ as l,D as p,g as _,k as m,a as n,c as r,b as e,d as u,n as h,e as f}from"./index-DcxvUQLx.js";const g={name:"peerQRCode",components:{LocaleText:c},props:{selectedPeer:Object},setup(){return{dashboardStore:p()}},data(){return{loading:!0}},mounted(){_("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},o=>{if(this.loading=!1,o.status){let t="";if(this.selectedPeer.configuration.Protocol==="awg"){let a={containers:[{awg:{isThirdPartyConfig:!0,last_config:o.data.file,port:this.selectedPeer.configuration.ListenPort,transport_proto:"udp"},container:"amnezia-awg"}],defaultContainer:"amnezia-awg",description:this.selectedPeer.name,hostName:this.dashboardStore.Configuration.Peers.remote_endpoint};t=JSON.stringify(a)}else t=o.data.file;i.toCanvas(document.querySelector("#qrcode"),t,a=>{a&&console.error(a)})}else this.dashboardStore.newMessage("Server",o.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},v={class:"container d-flex h-100 w-100"},C={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},w={class:"card rounded-3 shadow"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},x={class:"mb-0"},S={class:"card-body p-4"},y={class:"d-flex"},L={key:0,class:"spinner-border m-auto",role:"status"};function k(o,t,a,N,s,$){const d=m("LocaleText");return n(),r("div",b,[e("div",v,[e("div",C,[e("div",w,[e("div",P,[e("h4",x,[u(d,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=Q=>this.$emit("close"))})]),e("div",S,[e("div",y,[e("canvas",{id:"qrcode",class:h(["rounded-3 shadow animate__animated animate__fadeIn animate__faster",{"d-none":s.loading}])},null,2),s.loading?(n(),r("div",L,t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)]))):f("",!0)])])])])])])}const q=l(g,[["render",k],["__scopeId","data-v-5816a147"]]);export{q as default};
|
@ -1 +1 @@
|
|||||||
import{_ as u,q as m,G as p,r as b,W as f,a2 as h,o as g,a as v,i as y,w as _,b as e,m as x,y as w,d as S,j as B}from"./index-AzYVPyhh.js";import{L as T}from"./localeText-qJNpKS91.js";const C={class:"fixed-bottom w-100 bottom-0 z-2",style:{"z-index":"1"}},P={class:"container-fluid"},k={class:"row g-0"},L={class:"col-md-9 col-lg-10 d-flex justify-content-center py-2"},V={class:"rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary"},j={class:"d-flex gap-1 align-items-center px-2"},z=["placeholder"],D={__name:"peerSearchBar",emits:["close"],setup(G,{emit:n}){const l=m(()=>p("Search Peers..."));let t;const o=b(""),r=f(),i=()=>{t?(clearTimeout(t),t=setTimeout(()=>{r.searchString=o.value},300)):t=setTimeout(()=>{r.searchString=o.value},300)},d=n,c=h("searchBar");return g(()=>{c.value.focus()}),(M,s)=>(v(),y(B,{name:"slideUp",appear:"",type:"animation",style:{"animation-delay":"1s"}},{default:_(()=>[e("div",C,[e("div",P,[e("div",k,[s[5]||(s[5]=e("div",{class:"col-md-3 col-lg-2"},null,-1)),e("div",L,[e("div",V,[e("div",j,[s[4]||(s[4]=e("h6",{class:"mb-0 me-2"},[e("label",{for:"searchPeers"},[e("i",{class:"bi bi-search"})])],-1)),x(e("input",{ref:"searchBar",class:"flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:s[0]||(s[0]=a=>i()),"onUpdate:modelValue":s[1]||(s[1]=a=>o.value=a)},null,40,z),[[w,o.value]]),e("button",{onClick:s[2]||(s[2]=a=>d("close")),style:{"white-space":"nowrap"},class:"btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center"},[e("span",null,[s[3]||(s[3]=e("i",{class:"bi bi-x-circle-fill me-2"},null,-1)),S(T,{t:"Done"})])])])])])])])])]),_:1}))}},W=u(D,[["__scopeId","data-v-b741afe7"]]);export{W as default};
|
import{_ as u,q as m,G as p,r as b,W as f,a2 as h,o as g,a as v,i as y,w as _,b as e,m as x,y as w,d as S,j as B}from"./index-DcxvUQLx.js";import{L as T}from"./localeText-BZk4B_3P.js";const C={class:"fixed-bottom w-100 bottom-0 z-2",style:{"z-index":"1"}},P={class:"container-fluid"},k={class:"row g-0"},L={class:"col-md-9 col-lg-10 d-flex justify-content-center py-2"},V={class:"rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary"},j={class:"d-flex gap-1 align-items-center px-2"},z=["placeholder"],D={__name:"peerSearchBar",emits:["close"],setup(G,{emit:n}){const l=m(()=>p("Search Peers..."));let t;const o=b(""),r=f(),i=()=>{t?(clearTimeout(t),t=setTimeout(()=>{r.searchString=o.value},300)):t=setTimeout(()=>{r.searchString=o.value},300)},d=n,c=h("searchBar");return g(()=>{c.value.focus()}),(M,s)=>(v(),y(B,{name:"slideUp",appear:"",type:"animation",style:{"animation-delay":"1s"}},{default:_(()=>[e("div",C,[e("div",P,[e("div",k,[s[5]||(s[5]=e("div",{class:"col-md-3 col-lg-2"},null,-1)),e("div",L,[e("div",V,[e("div",j,[s[4]||(s[4]=e("h6",{class:"mb-0 me-2"},[e("label",{for:"searchPeers"},[e("i",{class:"bi bi-search"})])],-1)),x(e("input",{ref:"searchBar",class:"flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:s[0]||(s[0]=a=>i()),"onUpdate:modelValue":s[1]||(s[1]=a=>o.value=a)},null,40,z),[[w,o.value]]),e("button",{onClick:s[2]||(s[2]=a=>d("close")),style:{"white-space":"nowrap"},class:"btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center"},[e("span",null,[s[3]||(s[3]=e("i",{class:"bi bi-x-circle-fill me-2"},null,-1)),S(T,{t:"Done"})])])])])])])])])]),_:1}))}},W=u(D,[["__scopeId","data-v-b741afe7"]]);export{W as default};
|
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerShareLinkModal-APm3lCa1.js
vendored
Normal file
1
src/static/app/dist/assets/peerShareLinkModal-APm3lCa1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
.card[data-v-8cfb4d4d]{border-color:var(--bs-border-color)!important}textarea[data-v-6e705c87]:focus,input[data-v-6e705c87]:focus{box-shadow:none;border-color:var(--bs-border-color)!important}textarea[data-v-6e705c87]{padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x)}
|
.card[data-v-8cfb4d4d]{border-color:var(--bs-border-color)!important}textarea[data-v-913bd64b]:focus,input[data-v-913bd64b]:focus{box-shadow:none;border-color:var(--bs-border-color)!important}textarea[data-v-913bd64b]{padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x)}
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{L as r}from"./localeText-qJNpKS91.js";import{a as t,c as n,f as i,i as s,e as a}from"./index-AzYVPyhh.js";const d={key:0,class:"badge wireguardBg rounded-3 shadow"},c={key:1,class:"badge amneziawgBg rounded-3 shadow"},u={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(e){return(m,o)=>e.protocol==="wg"?(t(),n("span",d,[o[0]||(o[0]=i(" WireGuard ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):e.protocol==="awg"?(t(),n("span",c,[o[1]||(o[1]=i(" AmneziaWG ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):a("",!0)}};export{u as _};
|
import{L as r}from"./localeText-BZk4B_3P.js";import{a as t,c as n,f as i,i as s,e as a}from"./index-DcxvUQLx.js";const d={key:0,class:"badge wireguardBg rounded-3 shadow"},c={key:1,class:"badge amneziawgBg rounded-3 shadow"},u={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(e){return(m,o)=>e.protocol==="wg"?(t(),n("span",d,[o[0]||(o[0]=i(" WireGuard ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):e.protocol==="awg"?(t(),n("span",c,[o[1]||(o[1]=i(" AmneziaWG ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):a("",!0)}};export{u as _};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{_ as u,D as m,A as p,c as r,b as e,d as o,f as c,t as h,e as f,m as l,y as d,a as i,k as w}from"./index-AzYVPyhh.js";import{L as g}from"./localeText-qJNpKS91.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:m()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,p("/api/Welcome_Finish",this.setup,n=>{n.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(s=>s.classList.add("is-invalid")),this.errorMessage=n.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},_=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},v={class:"dashboardLogo display-4"},y={class:"mb-5"},P={key:0,class:"alert alert-danger"},N={class:"d-flex flex-column gap-3"},k={id:"createAccount",class:"d-flex flex-column gap-2"},S={class:"form-group text-body"},T={for:"username",class:"mb-1 text-muted"},C={class:"form-group text-body"},L={for:"password",class:"mb-1 text-muted"},V={class:"form-group text-body"},A={for:"confirmPassword",class:"mb-1 text-muted"},$=["disabled"],q={key:0,class:"d-flex align-items-center w-100"},M={key:1,class:"d-flex align-items-center w-100"};function B(n,s,D,E,U,F){const t=w("LocaleText");return i(),r("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[e("div",x,[e("span",v,[o(t,{t:"Nice to meet you!"})]),e("p",y,[o(t,{t:"Please fill in the following fields to finish setup"}),s[4]||(s[4]=c(" 😊"))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):f("",!0),e("div",N,[e("form",k,[e("div",S,[e("label",T,[e("small",null,[o(t,{t:"Enter an username you like"})])]),l(e("input",{type:"text",autocomplete:"username","onUpdate:modelValue":s[0]||(s[0]=a=>this.setup.username=a),class:"form-control",id:"username",name:"username",required:""},null,512),[[d,this.setup.username]])]),e("div",C,[e("label",L,[e("small",null,[o(t,{t:"Enter a password"}),e("code",null,[o(t,{t:"(At least 8 characters and make sure is strong enough!)"})])])]),l(e("input",{type:"password",autocomplete:"new-password","onUpdate:modelValue":s[1]||(s[1]=a=>this.setup.newPassword=a),class:"form-control",id:"password",name:"password",required:""},null,512),[[d,this.setup.newPassword]])]),e("div",V,[e("label",A,[e("small",null,[o(t,{t:"Confirm password"})])]),l(e("input",{type:"password",autocomplete:"confirm-new-password","onUpdate:modelValue":s[2]||(s[2]=a=>this.setup.repeatNewPassword=a),class:"form-control",id:"confirmPassword",name:"confirmPassword",required:""},null,512),[[d,this.setup.repeatNewPassword]])])]),e("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:s[3]||(s[3]=a=>this.submit())},[!this.loading&&!this.done?(i(),r("span",q,[o(t,{t:"Next"}),s[5]||(s[5]=e("i",{class:"bi bi-chevron-right ms-auto"},null,-1))])):(i(),r("span",M,[o(t,{t:"Saving..."}),s[6]||(s[6]=e("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[e("span",{class:"visually-hidden"},"Loading...")],-1))]))],8,$)])])])],8,_)}const j=u(b,[["render",B]]);export{j as default};
|
import{_ as u,D as m,A as p,c as r,b as e,d as o,f as c,t as h,e as f,m as l,y as d,a as i,k as w}from"./index-DcxvUQLx.js";import{L as g}from"./localeText-BZk4B_3P.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:m()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,p("/api/Welcome_Finish",this.setup,n=>{n.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(s=>s.classList.add("is-invalid")),this.errorMessage=n.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},_=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},v={class:"dashboardLogo display-4"},y={class:"mb-5"},P={key:0,class:"alert alert-danger"},N={class:"d-flex flex-column gap-3"},k={id:"createAccount",class:"d-flex flex-column gap-2"},S={class:"form-group text-body"},T={for:"username",class:"mb-1 text-muted"},C={class:"form-group text-body"},L={for:"password",class:"mb-1 text-muted"},V={class:"form-group text-body"},A={for:"confirmPassword",class:"mb-1 text-muted"},$=["disabled"],q={key:0,class:"d-flex align-items-center w-100"},M={key:1,class:"d-flex align-items-center w-100"};function B(n,s,D,E,U,F){const t=w("LocaleText");return i(),r("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[e("div",x,[e("span",v,[o(t,{t:"Nice to meet you!"})]),e("p",y,[o(t,{t:"Please fill in the following fields to finish setup"}),s[4]||(s[4]=c(" 😊"))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):f("",!0),e("div",N,[e("form",k,[e("div",S,[e("label",T,[e("small",null,[o(t,{t:"Enter an username you like"})])]),l(e("input",{type:"text",autocomplete:"username","onUpdate:modelValue":s[0]||(s[0]=a=>this.setup.username=a),class:"form-control",id:"username",name:"username",required:""},null,512),[[d,this.setup.username]])]),e("div",C,[e("label",L,[e("small",null,[o(t,{t:"Enter a password"}),e("code",null,[o(t,{t:"(At least 8 characters and make sure is strong enough!)"})])])]),l(e("input",{type:"password",autocomplete:"new-password","onUpdate:modelValue":s[1]||(s[1]=a=>this.setup.newPassword=a),class:"form-control",id:"password",name:"password",required:""},null,512),[[d,this.setup.newPassword]])]),e("div",V,[e("label",A,[e("small",null,[o(t,{t:"Confirm password"})])]),l(e("input",{type:"password",autocomplete:"confirm-new-password","onUpdate:modelValue":s[2]||(s[2]=a=>this.setup.repeatNewPassword=a),class:"form-control",id:"confirmPassword",name:"confirmPassword",required:""},null,512),[[d,this.setup.repeatNewPassword]])])]),e("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:s[3]||(s[3]=a=>this.submit())},[!this.loading&&!this.done?(i(),r("span",q,[o(t,{t:"Next"}),s[5]||(s[5]=e("i",{class:"bi bi-chevron-right ms-auto"},null,-1))])):(i(),r("span",M,[o(t,{t:"Saving..."}),s[6]||(s[6]=e("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[e("span",{class:"visually-hidden"},"Loading...")],-1))]))],8,$)])])])],8,_)}const j=u(b,[["render",B]]);export{j as default};
|
@ -1 +1 @@
|
|||||||
import{_,r,D as p,g as u,c as m,b as t,d as c,J as h,a as f,k as b}from"./index-AzYVPyhh.js";import{b as v}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-qJNpKS91.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=h(),e=r(!1),i=p(),n=r(""),s=r(void 0),l=r(new Blob);await u("/api/getDashboardTheme",{},d=>{n.value=d.data});const a=o.query.ShareID;return a===void 0||a.length===0?(s.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},d=>{d.status?(s.value=d.data,l.value=new Blob([s.value.file],{type:"text/plain"})):s.value=void 0,e.value=!0}),{store:i,theme:n,peerConfiguration:s,blob:l}},mounted(){this.peerConfiguration&&v.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,o=>{o&&console.error(o)})},methods:{download(){const o=new Blob([this.peerConfiguration.file],{type:"text/plain"}),e=URL.createObjectURL(o),i=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=i,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},w=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},C={key:0,class:"text-center position-relative",style:{}},U={class:"position-absolute w-100 h-100 top-0 start-0 d-flex animate__animated animate__fadeInUp",style:{"animation-delay":"0.1s"}},I={class:"m-auto"},L={key:1,class:"d-flex align-items-center flex-column gap-3"},k={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},B={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},D={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},R=["download","href"];function q(o,e,i,n,s,l){const a=b("LocaleText");return f(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.theme},[t("div",x,[this.peerConfiguration?(f(),m("div",L,[t("div",k,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),c(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",B,null,512),t("p",D,[c(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),c(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:l.getBlob,class:"btn btn-lg bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle animate__animated animate__fadeInUp shadow-sm",style:{"animation-delay":"0.25s"}},e[3]||(e[3]=[t("i",{class:"bi bi-download"},null,-1)]),8,R)])):(f(),m("div",C,[e[0]||(e[0]=t("div",{class:"animate__animated animate__fadeInUp"},[t("h1",{style:{"font-size":"20rem",filter:"blur(1rem)","animation-duration":"7s"},class:"animate__animated animate__flash animate__infinite"},[t("i",{class:"bi bi-file-binary"})])],-1)),t("div",U,[t("h3",I,[c(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,w)}const N=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{N as default};
|
import{_,r,D as p,g as u,c as m,b as t,d as c,J as h,a as f,k as b}from"./index-DcxvUQLx.js";import{b as v}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-BZk4B_3P.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=h(),e=r(!1),i=p(),n=r(""),s=r(void 0),l=r(new Blob);await u("/api/getDashboardTheme",{},d=>{n.value=d.data});const a=o.query.ShareID;return a===void 0||a.length===0?(s.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},d=>{d.status?(s.value=d.data,l.value=new Blob([s.value.file],{type:"text/plain"})):s.value=void 0,e.value=!0}),{store:i,theme:n,peerConfiguration:s,blob:l}},mounted(){this.peerConfiguration&&v.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,o=>{o&&console.error(o)})},methods:{download(){const o=new Blob([this.peerConfiguration.file],{type:"text/plain"}),e=URL.createObjectURL(o),i=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=i,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},w=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},C={key:0,class:"text-center position-relative",style:{}},U={class:"position-absolute w-100 h-100 top-0 start-0 d-flex animate__animated animate__fadeInUp",style:{"animation-delay":"0.1s"}},I={class:"m-auto"},L={key:1,class:"d-flex align-items-center flex-column gap-3"},k={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},B={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},D={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},R=["download","href"];function q(o,e,i,n,s,l){const a=b("LocaleText");return f(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.theme},[t("div",x,[this.peerConfiguration?(f(),m("div",L,[t("div",k,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),c(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",B,null,512),t("p",D,[c(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),c(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:l.getBlob,class:"btn btn-lg bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle animate__animated animate__fadeInUp shadow-sm",style:{"animation-delay":"0.25s"}},e[3]||(e[3]=[t("i",{class:"bi bi-download"},null,-1)]),8,R)])):(f(),m("div",C,[e[0]||(e[0]=t("div",{class:"animate__animated animate__fadeInUp"},[t("h1",{style:{"font-size":"20rem",filter:"blur(1rem)","animation-duration":"7s"},class:"animate__animated animate__flash animate__infinite"},[t("i",{class:"bi bi-file-binary"})])],-1)),t("div",U,[t("h3",I,[c(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,w)}const N=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{N as default};
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{_ as b,p as m,r as p,q as v,a as t,c as r,d as g,w as x,s as n,n as f,b as l,t as d,e as C,j as w}from"./index-AzYVPyhh.js";const y={class:"text-muted me-2"},_={class:"fw-bold"},k={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){m(c=>({"2ec4d3bc":o.value}));const u=e,s=p(!1),o=v(()=>u.square?"40px":"25px");return(c,a)=>(t(),r("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=i=>s.value=!0),onMouseleave:a[1]||(a[1]=i=>s.value=!1),style:n({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[g(w,{name:"zoomReversed"},{default:x(()=>[s.value?(t(),r("div",{key:0,style:n([{"white-space":"nowrap"},{top:o.value}]),class:f(["floatingLabel z-3 border position-absolute d-block p-1 px-2 bg-body text-body rounded-3 border shadow d-flex",[e.align?"end-0":"start-0"]])},[l("small",y," Core #"+d(e.core_number+1),1),l("small",_,d(e.percentage)+"% ",1)],6)):C("",!0)]),_:1})],36))}},B=b(k,[["__scopeId","data-v-2ad535bb"]]);export{B as C};
|
import{_ as b,p as m,r as p,q as v,a as t,c as r,d as g,w as x,s as n,n as f,b as l,t as d,e as C,j as w}from"./index-DcxvUQLx.js";const y={class:"text-muted me-2"},_={class:"fw-bold"},k={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){m(c=>({"2ec4d3bc":o.value}));const u=e,s=p(!1),o=v(()=>u.square?"40px":"25px");return(c,a)=>(t(),r("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=i=>s.value=!0),onMouseleave:a[1]||(a[1]=i=>s.value=!1),style:n({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[g(w,{name:"zoomReversed"},{default:x(()=>[s.value?(t(),r("div",{key:0,style:n([{"white-space":"nowrap"},{top:o.value}]),class:f(["floatingLabel z-3 border position-absolute d-block p-1 px-2 bg-body text-body rounded-3 border shadow d-flex",[e.align?"end-0":"start-0"]])},[l("small",y," Core #"+d(e.core_number+1),1),l("small",_,d(e.percentage)+"% ",1)],6)):C("",!0)]),_:1})],36))}},B=b(k,[["__scopeId","data-v-2ad535bb"]]);export{B as C};
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{_ as h,D as m,g as p,A as f,c as b,b as t,d as i,t as _,m as v,y as g,i as d,w as r,k as c,a as n}from"./index-AzYVPyhh.js";import{b as x}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-qJNpKS91.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=m();let e="";return await p("/api/Welcome_GetTotpLink",{},a=>{a.status&&(e=a.data)}),{l:e,store:s}},mounted(){this.l&&x.toCanvas(document.getElementById("qrcode"),this.l,function(s){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(s){const e=document.querySelector("#totp");e.classList.remove("is-invalid","is-valid"),s.length===6&&(console.log(s),/[0-9]{6}/.test(s)?f("/api/Welcome_VerifyTotpLink",{totp:s},a=>{a.status?(this.verified=!0,e.classList.add("is-valid"),this.$emit("verified")):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},k=["data-bs-theme"],w={class:"m-auto text-body",style:{width:"500px"}},L={class:"d-flex flex-column"},M={class:"dashboardLogo display-4"},C={class:"mb-2"},P={class:"text-muted"},I={class:"p-3 bg-body-secondary rounded-3 border mb-3"},O={class:"text-muted mb-0"},B=["href"],$={style:{"line-break":"anywhere"}},A={for:"totp",class:"mb-2"},D={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],E={class:"invalid-feedback"},F={class:"valid-feedback"},R={class:"d-flex gap-3 mt-5 flex-column"};function G(s,e,a,N,W,Q){const o=c("LocaleText"),l=c("RouterLink");return n(),b("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[t("div",w,[t("div",L,[t("div",null,[t("h1",M,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",C,[t("small",P,[i(o,{t:"1. Please scan the following QR Code to generate TOTP with your choice of authenticator"})])]),e[1]||(e[1]=t("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1)),t("div",I,[t("p",O,[t("small",null,[i(o,{t:"Or you can click the link below:"})])]),t("a",{href:this.l},[t("code",$,_(this.l),1)],8,B)]),t("label",A,[t("small",D,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[v(t("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":e[0]||(e[0]=u=>this.totp=u),disabled:this.verified},null,8,q),[[g,this.totp]]),t("div",E,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",F,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",R,[this.verified?(n(),d(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:r(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),d(l,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:r(()=>[i(o,{t:"I don't need MFA"}),e[2]||(e[2]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1}))])])])],8,k)}const z=h(T,[["render",G]]);export{z as default};
|
import{_ as h,D as m,g as p,A as f,c as b,b as t,d as i,t as _,m as v,y as g,i as d,w as r,k as c,a as n}from"./index-DcxvUQLx.js";import{b as x}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-BZk4B_3P.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=m();let e="";return await p("/api/Welcome_GetTotpLink",{},a=>{a.status&&(e=a.data)}),{l:e,store:s}},mounted(){this.l&&x.toCanvas(document.getElementById("qrcode"),this.l,function(s){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(s){const e=document.querySelector("#totp");e.classList.remove("is-invalid","is-valid"),s.length===6&&(console.log(s),/[0-9]{6}/.test(s)?f("/api/Welcome_VerifyTotpLink",{totp:s},a=>{a.status?(this.verified=!0,e.classList.add("is-valid"),this.$emit("verified")):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},k=["data-bs-theme"],w={class:"m-auto text-body",style:{width:"500px"}},L={class:"d-flex flex-column"},M={class:"dashboardLogo display-4"},C={class:"mb-2"},P={class:"text-muted"},I={class:"p-3 bg-body-secondary rounded-3 border mb-3"},O={class:"text-muted mb-0"},B=["href"],$={style:{"line-break":"anywhere"}},A={for:"totp",class:"mb-2"},D={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],E={class:"invalid-feedback"},F={class:"valid-feedback"},R={class:"d-flex gap-3 mt-5 flex-column"};function G(s,e,a,N,W,Q){const o=c("LocaleText"),l=c("RouterLink");return n(),b("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[t("div",w,[t("div",L,[t("div",null,[t("h1",M,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",C,[t("small",P,[i(o,{t:"1. Please scan the following QR Code to generate TOTP with your choice of authenticator"})])]),e[1]||(e[1]=t("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1)),t("div",I,[t("p",O,[t("small",null,[i(o,{t:"Or you can click the link below:"})])]),t("a",{href:this.l},[t("code",$,_(this.l),1)],8,B)]),t("label",A,[t("small",D,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[v(t("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":e[0]||(e[0]=u=>this.totp=u),disabled:this.verified},null,8,q),[[g,this.totp]]),t("div",E,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",F,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",R,[this.verified?(n(),d(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:r(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),d(l,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:r(()=>[i(o,{t:"I don't need MFA"}),e[2]||(e[2]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1}))])])])],8,k)}const z=h(T,[["render",G]]);export{z as default};
|
@ -1 +1 @@
|
|||||||
import{_ as h,W as g,g as b,c as o,b as t,d as n,m as y,y as f,C as x,w as r,j as c,a as l,f as v,F as u,h as m,n as k,s as T,t as i,k as _}from"./index-AzYVPyhh.js";import{O as A}from"./osmap-iyZf8b7y.js";import{L as w}from"./localeText-qJNpKS91.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:g()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,b("/api/traceroute/execute",{ipAddress:this.ipAddress},d=>{d.status?this.tracerouteResult=d.data:this.store.newMessage("Server",d.message,"danger"),this.tracing=!1}))}}},M={class:"mt-md-5 mt-3 text-body"},S={class:"container-md"},$={class:"mb-3 text-body"},C={class:"d-flex gap-2 mb-3 flex-column"},L={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},I={key:1,class:"d-block"},N={class:"position-relative"},z={key:"pingPlaceholder"},D={key:1},E={key:"table",class:"w-100 mt-2"},F={class:"table table-sm rounded-3 w-100"},G={scope:"col"},H={scope:"col"},K={scope:"col"},W={scope:"col"},j={scope:"col"},U={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=_("LocaleText"),p=_("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",C,[t("div",L,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),y(t("input",{disabled:this.tracing,id:"ipAddress",class:"form-control rounded-3","onUpdate:modelValue":s[0]||(s[0]=e=>this.ipAddress=e),onKeyup:s[1]||(s[1]=x(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[f,this.ipAddress]])]),t("button",{class:"btn btn-primary rounded-3 position-relative flex-grow-1",disabled:this.tracing||!this.ipAddress,onClick:s[2]||(s[2]=e=>this.execute())},[n(c,{name:"slide"},{default:r(()=>[this.tracing?(l(),o("span",I,s[4]||(s[4]=[t("span",{class:"spinner-border spinner-border-sm","aria-hidden":"true"},null,-1),t("span",{class:"visually-hidden",role:"status"},"Loading...",-1)]))):(l(),o("span",B,s[3]||(s[3]=[t("i",{class:"bi bi-person-walking me-2"},null,-1),v("Trace! ")])))]),_:1})],8,V)]),t("div",N,[n(c,{name:"ping"},{default:r(()=>[this.tracerouteResult?(l(),o("div",D,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",E,[t("table",F,[t("thead",null,[t("tr",null,[t("th",G,[n(a,{t:"Hop"})]),t("th",H,[n(a,{t:"IP Address"})]),t("th",K,[n(a,{t:"Average RTT (ms)"})]),t("th",W,[n(a,{t:"Min RTT (ms)"})]),t("th",j,[n(a,{t:"Max RTT (ms)"})]),t("th",U,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(u,null,m(this.tracerouteResult,(e,et)=>(l(),o("tr",null,[t("td",null,[t("small",null,i(e.hop),1)]),t("td",null,[t("small",null,[t("samp",null,i(e.ip),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.avg_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.min_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.max_rtt),1)])]),t("td",null,[e.geo.city&&e.geo.country?(l(),o("span",q,[t("small",null,i(e.geo.city)+", "+i(e.geo.country),1)])):(l(),o("span",J," - "))])]))),256))])])])])):(l(),o("div",z,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(u,null,m(5,e=>t("div",{class:k(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:T({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const lt=h(R,[["render",Q],["__scopeId","data-v-3e75b4d4"]]);export{lt as default};
|
import{_ as h,W as g,g as b,c as o,b as t,d as n,m as y,y as f,C as x,w as r,j as c,a as l,f as v,F as u,h as m,n as k,s as T,t as i,k as _}from"./index-DcxvUQLx.js";import{O as A}from"./osmap-rsVUm9vk.js";import{L as w}from"./localeText-BZk4B_3P.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:g()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,b("/api/traceroute/execute",{ipAddress:this.ipAddress},d=>{d.status?this.tracerouteResult=d.data:this.store.newMessage("Server",d.message,"danger"),this.tracing=!1}))}}},M={class:"mt-md-5 mt-3 text-body"},S={class:"container-md"},$={class:"mb-3 text-body"},C={class:"d-flex gap-2 mb-3 flex-column"},L={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},I={key:1,class:"d-block"},N={class:"position-relative"},z={key:"pingPlaceholder"},D={key:1},E={key:"table",class:"w-100 mt-2"},F={class:"table table-sm rounded-3 w-100"},G={scope:"col"},H={scope:"col"},K={scope:"col"},W={scope:"col"},j={scope:"col"},U={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=_("LocaleText"),p=_("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",C,[t("div",L,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),y(t("input",{disabled:this.tracing,id:"ipAddress",class:"form-control rounded-3","onUpdate:modelValue":s[0]||(s[0]=e=>this.ipAddress=e),onKeyup:s[1]||(s[1]=x(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[f,this.ipAddress]])]),t("button",{class:"btn btn-primary rounded-3 position-relative flex-grow-1",disabled:this.tracing||!this.ipAddress,onClick:s[2]||(s[2]=e=>this.execute())},[n(c,{name:"slide"},{default:r(()=>[this.tracing?(l(),o("span",I,s[4]||(s[4]=[t("span",{class:"spinner-border spinner-border-sm","aria-hidden":"true"},null,-1),t("span",{class:"visually-hidden",role:"status"},"Loading...",-1)]))):(l(),o("span",B,s[3]||(s[3]=[t("i",{class:"bi bi-person-walking me-2"},null,-1),v("Trace! ")])))]),_:1})],8,V)]),t("div",N,[n(c,{name:"ping"},{default:r(()=>[this.tracerouteResult?(l(),o("div",D,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",E,[t("table",F,[t("thead",null,[t("tr",null,[t("th",G,[n(a,{t:"Hop"})]),t("th",H,[n(a,{t:"IP Address"})]),t("th",K,[n(a,{t:"Average RTT (ms)"})]),t("th",W,[n(a,{t:"Min RTT (ms)"})]),t("th",j,[n(a,{t:"Max RTT (ms)"})]),t("th",U,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(u,null,m(this.tracerouteResult,(e,et)=>(l(),o("tr",null,[t("td",null,[t("small",null,i(e.hop),1)]),t("td",null,[t("small",null,[t("samp",null,i(e.ip),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.avg_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.min_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.max_rtt),1)])]),t("td",null,[e.geo.city&&e.geo.country?(l(),o("span",q,[t("small",null,i(e.geo.city)+", "+i(e.geo.country),1)])):(l(),o("span",J," - "))])]))),256))])])])])):(l(),o("div",z,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(u,null,m(5,e=>t("div",{class:k(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:T({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const lt=h(R,[["render",Q],["__scopeId","data-v-3e75b4d4"]]);export{lt as default};
|
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
@ -10,7 +10,7 @@
|
|||||||
<link rel="icon" href="/static/app/dist/img/Logo-2-512x512.png">
|
<link rel="icon" href="/static/app/dist/img/Logo-2-512x512.png">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>WGDashboard</title>
|
<title>WGDashboard</title>
|
||||||
<script type="module" crossorigin src="/static/app/dist/assets/index-AzYVPyhh.js"></script>
|
<script type="module" crossorigin src="/static/app/dist/assets/index-DcxvUQLx.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/static/app/dist/assets/index-DFl-XeJT.css">
|
<link rel="stylesheet" crossorigin href="/static/app/dist/assets/index-DFl-XeJT.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -115,6 +115,7 @@ export default {
|
|||||||
@jobs="this.$emit('jobs')"
|
@jobs="this.$emit('jobs')"
|
||||||
@refresh="this.$emit('refresh')"
|
@refresh="this.$emit('refresh')"
|
||||||
@share="this.$emit('share')"
|
@share="this.$emit('share')"
|
||||||
|
@assign="this.$emit('assign')"
|
||||||
:Peer="Peer"
|
:Peer="Peer"
|
||||||
v-if="this.subMenuOpened"
|
v-if="this.subMenuOpened"
|
||||||
ref="target"
|
ref="target"
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
<script setup async>
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import {GetLocale} from "@/utilities/locale.js";
|
||||||
|
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import SearchClients from "@/components/configurationComponents/peerAssignModalComponents/searchClients.vue";
|
||||||
|
import AssignedClients from "@/components/configurationComponents/peerAssignModalComponents/assignedClients.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
selectedPeer: Object
|
||||||
|
})
|
||||||
|
const emits = defineEmits([
|
||||||
|
'close'
|
||||||
|
])
|
||||||
|
const assignments = ref([])
|
||||||
|
const clients = ref([])
|
||||||
|
await fetchGet('/api/clients/allClients', {},(res) => {
|
||||||
|
clients.value = res.data;
|
||||||
|
console.log(clients.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const getAssignedClients = async () => {
|
||||||
|
await fetchGet('/api/clients/assignedClients', {
|
||||||
|
ConfigurationName: props.selectedPeer.configuration.Name,
|
||||||
|
Peer: props.selectedPeer.id
|
||||||
|
}, (res) => {
|
||||||
|
assignments.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await getAssignedClients()
|
||||||
|
|
||||||
|
const assignClient = async (clientID) => {
|
||||||
|
await fetchPost('/api/clients/assignClient', {
|
||||||
|
ConfigurationName: props.selectedPeer.configuration.Name,
|
||||||
|
Peer: props.selectedPeer.id,
|
||||||
|
ClientID: clientID
|
||||||
|
}, async (res) => {
|
||||||
|
if (res.status){
|
||||||
|
await getAssignedClients()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const unassignClient = async (assignmentID) => {
|
||||||
|
await fetchPost('/api/clients/unassignClient', {
|
||||||
|
AssignmentID: assignmentID
|
||||||
|
}, async (res) => {
|
||||||
|
if (res.status){
|
||||||
|
await getAssignedClients()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
|
||||||
|
<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="Assign Peer to Client"></LocaleText>
|
||||||
|
</h4>
|
||||||
|
<button type="button" class="btn-close ms-auto" @click="emits('close')"></button>
|
||||||
|
</div>
|
||||||
|
<div class="card-body px-4 pb-4 d-flex gap-2 flex-column">
|
||||||
|
<AssignedClients
|
||||||
|
@unassign="args => unassignClient(args)"
|
||||||
|
:assignments="assignments"></AssignedClients>
|
||||||
|
<SearchClients
|
||||||
|
:assignments="assignments"
|
||||||
|
@assign="args => assignClient(args)"
|
||||||
|
:clients="clients"></SearchClients>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,63 @@
|
|||||||
|
<script setup>
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
const props = defineProps(['assignments'])
|
||||||
|
const emits = defineEmits(['unassign'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-3 bg-body-tertiary rounded-3 d-flex flex-column gap-2">
|
||||||
|
<h6 class="mb-0">
|
||||||
|
<LocaleText t="Assigned Clients"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
<TransitionGroup name="list" tag="div" class="position-relative">
|
||||||
|
<div class="bg-body-secondary rounded-3 text-start p-2 d-flex mb-2 assignment"
|
||||||
|
:key="a.AssignmentID"
|
||||||
|
v-for="a in assignments">
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small>
|
||||||
|
{{ a.Client.Email }}
|
||||||
|
</small>
|
||||||
|
<small class="text-muted">
|
||||||
|
{{ a.Client.Name ? a.Client.Name + ' | ' : '' }}{{ a.Client.ClientGroup ? a.Client.ClientGroup : 'Local' }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
@click="emits('unassign', a.AssignmentID)"
|
||||||
|
aria-label="Delete Assignment"
|
||||||
|
class="btn bg-danger-subtle text-danger-emphasis ms-auto">
|
||||||
|
<i class="bi bi-trash-fill"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
|
<div class="text-center" v-if="assignments.length === 0">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="No client assigned to this peer yet"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-move, /* apply transition to moving elements */
|
||||||
|
.list-enter-active,
|
||||||
|
.list-leave-active {
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-enter-from,
|
||||||
|
.list-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure leaving items are taken out of layout flow so that moving
|
||||||
|
animations can be calculated correctly. */
|
||||||
|
.list-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assignment:last-child{
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,77 @@
|
|||||||
|
<script setup>
|
||||||
|
import {GetLocale} from "@/utilities/locale.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {computed, reactive, ref} from "vue";
|
||||||
|
import SearchClientsGroup from "@/components/configurationComponents/peerAssignModalComponents/searchClientsGroup.vue";
|
||||||
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
|
||||||
|
const props = defineProps(['clients', 'newAssignClients', 'assignments'])
|
||||||
|
|
||||||
|
const selectedGroup = ref("")
|
||||||
|
const searchString = ref("")
|
||||||
|
const getSelectedGroup = computed(() => {
|
||||||
|
if (selectedGroup.value){
|
||||||
|
return {
|
||||||
|
[selectedGroup.value] : props.clients[selectedGroup.value]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props.clients
|
||||||
|
})
|
||||||
|
const groupCount = reactive({})
|
||||||
|
Object.keys(props.clients).forEach(
|
||||||
|
x => groupCount[x] = props.clients[x].length
|
||||||
|
)
|
||||||
|
|
||||||
|
const emits = defineEmits(['assign'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-3 bg-body-tertiary rounded-3 position-relative">
|
||||||
|
<h6>
|
||||||
|
<LocaleText t="Assign to Clients"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
<label for="SearchClient" class="form-label">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Enter Email or Name to Search"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input class="form-control rounded-3 mb-2"
|
||||||
|
id="SearchClient"
|
||||||
|
v-model="searchString" type="email">
|
||||||
|
<div class="w-100 rounded-3 d-flex flex-column gap-2 ">
|
||||||
|
<div>
|
||||||
|
<small class="text-muted">Groups</small>
|
||||||
|
<div class="mt-1">
|
||||||
|
<button
|
||||||
|
:class="{'active': !selectedGroup}"
|
||||||
|
@click="selectedGroup = ''"
|
||||||
|
class="btn bg-primary-subtle text-primary-emphasis btn-sm me-2 rounded-3">
|
||||||
|
<LocaleText t="All"></LocaleText>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="selectedGroup = groupName"
|
||||||
|
:class="{'active': selectedGroup === groupName}"
|
||||||
|
class="btn bg-primary-subtle text-primary-emphasis btn-sm me-2 rounded-3"
|
||||||
|
v-for="(_, groupName) in clients">
|
||||||
|
{{ groupName }}
|
||||||
|
<span class="ms-1 badge" :class="[ groupCount[groupName] > 0 ? 'bg-primary' : 'bg-secondary' ]">
|
||||||
|
{{ groupCount[groupName] }}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-3 border rounded-3 d-flex flex-column gap-2 overflow-y-scroll" style="height: 400px">
|
||||||
|
<SearchClientsGroup
|
||||||
|
:assignments="assignments"
|
||||||
|
@assign="(args) => emits('assign', args)"
|
||||||
|
@count="(args) => groupCount[groupName] = args"
|
||||||
|
:searchString="searchString"
|
||||||
|
:group="group" :groupName="groupName" v-for="(group, groupName) in getSelectedGroup"></SearchClientsGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,49 @@
|
|||||||
|
<script setup>
|
||||||
|
import {computed} from "vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
|
const props = defineProps(['group', 'groupName', 'searchString', 'assignments'])
|
||||||
|
const emits = defineEmits(['count', 'assign'])
|
||||||
|
|
||||||
|
const filterGroup = computed(() => {
|
||||||
|
let g = props.group.filter(x =>
|
||||||
|
!props.assignments.map(a => a.Client.ClientID).includes(x.ClientID))
|
||||||
|
|
||||||
|
if (props.searchString){
|
||||||
|
let v = g.filter(
|
||||||
|
x => (x.Name && x.Name.includes(props.searchString)) || (x.Email && x.Email.includes(props.searchString))
|
||||||
|
)
|
||||||
|
emits('count', v.length)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
emits('count', g.length)
|
||||||
|
return g
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="d-flex flex-column gap-2">
|
||||||
|
<h6 class="mb-0">
|
||||||
|
<small>{{groupName}}</small>
|
||||||
|
</h6>
|
||||||
|
<div v-if="filterGroup.length > 0" class="d-flex flex-column gap-2">
|
||||||
|
<div class="bg-body-secondary rounded-3 text-start p-2 d-flex p-1" role="button"
|
||||||
|
@click="emits('assign', client.ClientID)"
|
||||||
|
v-for="client in filterGroup">
|
||||||
|
<small class="mb-0">
|
||||||
|
{{ client.Email }}
|
||||||
|
</small>
|
||||||
|
<small class="text-muted ms-auto">{{ client.Name }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="No result"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -70,6 +70,9 @@ const configurationModals = ref({
|
|||||||
},
|
},
|
||||||
editRawConfigurationFile: {
|
editRawConfigurationFile: {
|
||||||
modalOpen: false
|
modalOpen: false
|
||||||
|
},
|
||||||
|
assignPeer: {
|
||||||
|
modalOpen: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const peerSearchBar = ref(false)
|
const peerSearchBar = ref(false)
|
||||||
@ -361,6 +364,7 @@ const searchPeers = computed(() => {
|
|||||||
@setting="configurationModals.peerSetting.modalOpen = true; configurationModalSelectedPeer = peer"
|
@setting="configurationModals.peerSetting.modalOpen = true; configurationModalSelectedPeer = peer"
|
||||||
@qrcode="configurationModalSelectedPeer = peer; configurationModals.peerQRCode.modalOpen = true;"
|
@qrcode="configurationModalSelectedPeer = peer; configurationModals.peerQRCode.modalOpen = true;"
|
||||||
@configurationFile="configurationModalSelectedPeer = peer; configurationModals.peerConfigurationFile.modalOpen = true;"
|
@configurationFile="configurationModalSelectedPeer = peer; configurationModals.peerConfigurationFile.modalOpen = true;"
|
||||||
|
@assign="configurationModalSelectedPeer = peer; configurationModals.assignPeer.modalOpen = true;"
|
||||||
></Peer>
|
></Peer>
|
||||||
</div>
|
</div>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
|
@ -6,14 +6,8 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
const emits = defineEmits(["refresh"])
|
const emits = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
const PeerAssignModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerAssignModal.vue"))
|
||||||
const DeleteConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/deleteConfiguration.vue"))
|
|
||||||
const ConfigurationBackupRestoreModal = defineAsyncComponent(() => import("@/components/configurationComponents/configurationBackupRestore.vue"))
|
|
||||||
const SelectPeersModal = defineAsyncComponent(() => import("@/components/configurationComponents/selectPeers.vue"))
|
|
||||||
const EditConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/editConfiguration.vue"))
|
|
||||||
const PeerShareLinkModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerShareLinkModal.vue"))
|
const PeerShareLinkModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerShareLinkModal.vue"))
|
||||||
const PeerJobsLogsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobsLogsModal.vue"))
|
|
||||||
const PeerJobsAllModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobsAllModal.vue"))
|
|
||||||
const PeerJobsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobs.vue"))
|
const PeerJobsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobs.vue"))
|
||||||
const PeerQRCodeModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerQRCode.vue"))
|
const PeerQRCodeModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerQRCode.vue"))
|
||||||
const PeerConfigurationFileModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerConfigurationFile.vue"))
|
const PeerConfigurationFileModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerConfigurationFile.vue"))
|
||||||
@ -53,6 +47,10 @@ const PeerSettingsModal = defineAsyncComponent(() => import("@/components/config
|
|||||||
v-if="configurationModals.peerConfigurationFile.modalOpen"
|
v-if="configurationModals.peerConfigurationFile.modalOpen"
|
||||||
:selectedPeer="configurationModalSelectedPeer"
|
:selectedPeer="configurationModalSelectedPeer"
|
||||||
></PeerConfigurationFileModal>
|
></PeerConfigurationFileModal>
|
||||||
|
<PeerAssignModal
|
||||||
|
:selectedPeer="configurationModalSelectedPeer"
|
||||||
|
@close="configurationModals.assignPeer.modalOpen = false"
|
||||||
|
v-if="configurationModals.assignPeer.modalOpen"></PeerAssignModal>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -147,6 +147,13 @@ export default {
|
|||||||
<i class="me-auto bi bi-app-indicator"></i> <LocaleText t="Schedule Jobs"></LocaleText>
|
<i class="me-auto bi bi-app-indicator"></i> <LocaleText t="Schedule Jobs"></LocaleText>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item d-flex" role="button"
|
||||||
|
@click="this.$emit('assign')"
|
||||||
|
>
|
||||||
|
<i class="me-auto bi bi-diagram-2"></i> <LocaleText t="Assign Peer"></LocaleText>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item d-flex text-warning"
|
<a class="dropdown-item d-flex text-warning"
|
||||||
|
@ -38,7 +38,7 @@ const sendEmail = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const emits = defineEmits(['fullscreen'])
|
const emits = defineEmits(['fullscreen', 'hide'])
|
||||||
watch(livePreview, () => {
|
watch(livePreview, () => {
|
||||||
emits('fullscreen', livePreview.value)
|
emits('fullscreen', livePreview.value)
|
||||||
})
|
})
|
||||||
@ -47,9 +47,14 @@ watch(livePreview, () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="emailIsReady">
|
<div v-if="emailIsReady">
|
||||||
<h6 class="mb-3">
|
<div class="d-flex mb-3 align-items-center">
|
||||||
<LocaleText t="Share with Email"></LocaleText>
|
<a role="button" class="d-flex text-decoration-none text-body text-muted" @click="emits('hide')">
|
||||||
</h6>
|
<i class="bi bi-chevron-left me-2"></i> Back
|
||||||
|
</a>
|
||||||
|
<h6 class="mb-0 ms-auto">
|
||||||
|
<LocaleText t="Share with Email"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
<form class="d-flex gap-3 flex-column"
|
<form class="d-flex gap-3 flex-column"
|
||||||
@submit="(e) => {e.preventDefault(); sendEmail()}"
|
@submit="(e) => {e.preventDefault(); sendEmail()}"
|
||||||
>
|
>
|
||||||
|
@ -22,7 +22,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
dataCopy: undefined,
|
dataCopy: undefined,
|
||||||
loading: false,
|
loading: false,
|
||||||
fullscreen: false
|
fullscreen: false,
|
||||||
|
shareWithEmail: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(){
|
setup(){
|
||||||
@ -133,42 +134,53 @@ export default {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="d-flex gap-2 mb-4">
|
<div v-if="!shareWithEmail">
|
||||||
<i class="bi bi-link-45deg"></i>
|
<div class="d-flex gap-2 mb-4">
|
||||||
<a :href="this.getUrl"
|
<i class="bi bi-link-45deg"></i>
|
||||||
class="text-decoration-none" target="_blank">
|
<a :href="this.getUrl"
|
||||||
{{ getUrl }}
|
class="text-decoration-none" target="_blank">
|
||||||
</a>
|
{{ getUrl }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column gap-2 mb-3">
|
||||||
|
<small>
|
||||||
|
<i class="bi bi-calendar me-2"></i>
|
||||||
|
<LocaleText t="Expire At"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<VueDatePicker
|
||||||
|
:is24="true"
|
||||||
|
:min-date="new Date()"
|
||||||
|
:model-value="this.dataCopy.ExpireDate"
|
||||||
|
@update:model-value="this.parseTime" time-picker-inline
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
preview-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
|
||||||
|
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2 flex-column flex-sm-row">
|
||||||
|
<button
|
||||||
|
style="flex: 1 1 0"
|
||||||
|
@click="this.stopSharing()"
|
||||||
|
:disabled="this.loading"
|
||||||
|
class="w-100 btn bg-danger-subtle text-danger-emphasis border-1 border-danger-subtle rounded-3 shadow-sm">
|
||||||
|
<span :class="{'animate__animated animate__flash animate__infinite animate__slower': this.loading}">
|
||||||
|
<i class="bi bi-send-slash-fill me-2" ></i>
|
||||||
|
</span>
|
||||||
|
<LocaleText t="Stop Sharing..." v-if="this.loading"></LocaleText>
|
||||||
|
<LocaleText t="Stop Sharing" v-else></LocaleText>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
style="flex: 1 1 0"
|
||||||
|
@click="shareWithEmail = true"
|
||||||
|
class="btn bg-primary-subtle text-primary-emphasis border-primary-subtle rounded-3">
|
||||||
|
<i class="bi bi-envelope me-2"></i><LocaleText t="Share with Email"></LocaleText>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column gap-2 mb-3">
|
<Suspense v-else>
|
||||||
<small>
|
|
||||||
<i class="bi bi-calendar me-2"></i>
|
|
||||||
<LocaleText t="Expire At"></LocaleText>
|
|
||||||
</small>
|
|
||||||
<VueDatePicker
|
|
||||||
:is24="true"
|
|
||||||
:min-date="new Date()"
|
|
||||||
:model-value="this.dataCopy.ExpireDate"
|
|
||||||
@update:model-value="this.parseTime" time-picker-inline
|
|
||||||
format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
preview-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
|
|
||||||
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
@click="this.stopSharing()"
|
|
||||||
:disabled="this.loading"
|
|
||||||
class="w-100 btn bg-danger-subtle text-danger-emphasis border-1 border-danger-subtle rounded-3 shadow-sm">
|
|
||||||
<span :class="{'animate__animated animate__flash animate__infinite animate__slower': this.loading}">
|
|
||||||
<i class="bi bi-send-slash-fill me-2" ></i>
|
|
||||||
</span>
|
|
||||||
<LocaleText t="Stop Sharing..." v-if="this.loading"></LocaleText>
|
|
||||||
<LocaleText t="Stop Sharing" v-else></LocaleText>
|
|
||||||
</button>
|
|
||||||
<hr>
|
|
||||||
<Suspense>
|
|
||||||
<PeerShareWithEmail
|
<PeerShareWithEmail
|
||||||
|
@hide="shareWithEmail = false"
|
||||||
@fullscreen="(f) => { this.fullscreen = f; }"
|
@fullscreen="(f) => { this.fullscreen = f; }"
|
||||||
:selectedPeer="selectedPeer" :dataCopy="dataCopy"></PeerShareWithEmail>
|
:selectedPeer="selectedPeer" :dataCopy="dataCopy"></PeerShareWithEmail>
|
||||||
<template #fallback>
|
<template #fallback>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user