mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-10-03 15:56:17 +00:00
Compare commits
13 Commits
v4.3.1-dev
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
eb1d52ffba | ||
|
5db7351f8c | ||
|
5ae3a56337 | ||
|
e7068b472e | ||
|
3dc94a35a1 | ||
|
f82abd71a3 | ||
|
602238d794 | ||
|
4d4a15740b | ||
|
524d50ee07 | ||
|
fc591b7fe8 | ||
|
c2f06193d0 | ||
|
f2ead12315 | ||
|
ca8700ac2a |
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@@ -8,24 +8,24 @@ updates:
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/src"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/src/static/app"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/docker"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "docker-compose"
|
||||
directory: "/docker"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,7 +6,6 @@ __pycache__
|
||||
src/test.py
|
||||
*.db
|
||||
src/wg-dashboard.ini
|
||||
src/ssl-tls.ini
|
||||
src/static/pic.xd
|
||||
*.conf
|
||||
private_key.txt
|
||||
|
@@ -104,7 +104,6 @@ ARG wg_port="51820"
|
||||
ENV TZ="Europe/Amsterdam" \
|
||||
global_dns="9.9.9.9" \
|
||||
wgd_port="10086" \
|
||||
log_level="INFO" \
|
||||
public_ip="" \
|
||||
WGDASH=/opt/wgdashboard
|
||||
|
||||
@@ -130,15 +129,6 @@ SaveConfig = true\n\
|
||||
DNS = ${global_dns}" > /configs/wg0.conf.template \
|
||||
&& chmod 600 /configs/wg0.conf.template
|
||||
|
||||
# Replacement of paths with relative ones for namespace handling when using a reverse proxy
|
||||
RUN set -ex && \
|
||||
find ${WGDASH}/src/static/dist -type f \( -name "*.html" -o -name "*.js" \) \
|
||||
-exec sed -i 's|/static/dist|./static/dist|g' {} + && \
|
||||
find ${WGDASH}/src/static/dist -type f -name "*.css" \
|
||||
-exec sed -i 's|/static/dist/WGDashboardClient/assets/|./|g' {} + && \
|
||||
find ${WGDASH}/src/static/dist -type f -name "*.css" \
|
||||
-exec sed -i 's|/static/dist/WGDashboardAdmin/assets/|./|g' {} +
|
||||
|
||||
# Set a healthcheck to determine the container its health
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
|
||||
|
@@ -102,7 +102,6 @@ Updating the WGDashboard container should be through 'The Docker Way' - by pulli
|
||||
| `global_dns` | IPv4 and IPv6 addresses | `9.9.9.9` | `8.8.8.8`, `1.1.1.1` | Default DNS for WireGuard clients. |
|
||||
| `public_ip` | Public IP address | Retrieved automatically | `253.162.134.73` | Used to generate accurate client configs. Needed if container is NAT’d. |
|
||||
| `wgd_port` | Any port that is allowed for the process | `10086` | `443` | This port is used to set the WGDashboard web port. |
|
||||
| `log_level` | `DEBUG`, `INFO`, `WARNING`, `ERROR` and `CRITICAL` | `INFO` | `WARNING` | Sets the severity of the logs being displayed. |
|
||||
| `username` | Any non‐empty string | `-` | `admin` | Username for the WGDashboard web interface account. |
|
||||
| `password` | Any non‐empty string | `-` | `s3cr3tP@ss` | Password for the WGDashboard web interface account (stored hashed). |
|
||||
| `enable_totp` | `true`, `false` | `true` | `false` | Enable TOTP‐based two‐factor authentication for the account. |
|
||||
|
@@ -12,8 +12,7 @@ services:
|
||||
# Environment variables can be used to configure certain values at startup. Without having to configure it from the dashboard.
|
||||
# By default its all disabled, but uncomment the following lines to apply these. (uncommenting is removing the # character)
|
||||
# Refer to the documentation on https://wgdashboard.dev/ for more info on what everything means.
|
||||
environment:
|
||||
- log_level=WARNING
|
||||
#environment:
|
||||
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
|
||||
#- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me.
|
||||
#- wgd_port= # <--- Set the port WGDashboard will use for its web-server.
|
||||
|
@@ -115,7 +115,7 @@ ensure_installation() {
|
||||
|
||||
echo "Done setting template."
|
||||
else
|
||||
echo "Existing Wireguard configuration file found in /etc/wireguard."
|
||||
echo "Existing wg0 configuration file found, using that."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -137,8 +137,7 @@ set_envvars() {
|
||||
|
||||
set_ini Peers remote_endpoint "${public_ip}"
|
||||
set_ini Server app_port "${wgd_port}"
|
||||
set_ini Server log_level "${log_level}"
|
||||
|
||||
|
||||
# Account settings - process all parameters
|
||||
[[ -n "$username" ]] && echo "Configuring user account:"
|
||||
# Basic account variables
|
||||
|
@@ -72,6 +72,7 @@ def ResponseObject(status=True, message=None, data=None, status_code = 200) -> F
|
||||
'''
|
||||
Flask App
|
||||
'''
|
||||
app = Flask("WGDashboard", template_folder=os.path.abspath("./static/dist/WGDashboardAdmin"))
|
||||
|
||||
def peerInformationBackgroundThread():
|
||||
global WireguardConfigurations
|
||||
@@ -119,8 +120,7 @@ def peerJobScheduleBackgroundThread():
|
||||
def gunicornConfig():
|
||||
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||
|
||||
return app_ip, app_port, log_level
|
||||
return app_ip, app_port
|
||||
|
||||
def ProtocolsEnabled() -> list[str]:
|
||||
from shutil import which
|
||||
@@ -172,7 +172,16 @@ def startThreads():
|
||||
scheduleJobThread = threading.Thread(target=peerJobScheduleBackgroundThread, daemon=True)
|
||||
scheduleJobThread.start()
|
||||
|
||||
app = Flask("WGDashboard", template_folder=os.path.abspath("./static/dist/WGDashboardAdmin"))
|
||||
dictConfig({
|
||||
'version': 1,
|
||||
'formatters': {'default': {
|
||||
'format': '[%(asctime)s] [%(levelname)s] in [%(module)s] %(message)s',
|
||||
}},
|
||||
'root': {
|
||||
'level': 'INFO'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
WireguardConfigurations: dict[str, WireguardConfiguration] = {}
|
||||
CONFIGURATION_PATH = os.getenv('CONFIGURATION_PATH', '.')
|
||||
@@ -180,7 +189,6 @@ CONFIGURATION_PATH = os.getenv('CONFIGURATION_PATH', '.')
|
||||
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
||||
app.secret_key = secrets.token_urlsafe(32)
|
||||
app.json = CustomJsonEncoder(app)
|
||||
|
||||
with app.app_context():
|
||||
SystemStatus = SystemStatus()
|
||||
DashboardConfig = DashboardConfig()
|
||||
@@ -191,44 +199,19 @@ with app.app_context():
|
||||
DashboardPlugins: DashboardPlugins = DashboardPlugins(app, WireguardConfigurations)
|
||||
DashboardWebHooks: DashboardWebHooks = DashboardWebHooks(DashboardConfig)
|
||||
NewConfigurationTemplates: NewConfigurationTemplates = NewConfigurationTemplates()
|
||||
|
||||
InitWireguardConfigurationsList(startup=True)
|
||||
|
||||
DashboardClients: DashboardClients = DashboardClients(WireguardConfigurations)
|
||||
app.register_blueprint(
|
||||
createClientBlueprint(WireguardConfigurations, DashboardConfig, DashboardClients)
|
||||
)
|
||||
app.register_blueprint(createClientBlueprint(WireguardConfigurations, DashboardConfig, DashboardClients))
|
||||
|
||||
_, APP_PREFIX = DashboardConfig.GetConfig("Server", "app_prefix")
|
||||
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||
_, WG_CONF_PATH = DashboardConfig.GetConfig("Server", "wg_conf_path")
|
||||
_, log_level = DashboardConfig.GetConfig("Server", "log_level")
|
||||
|
||||
cors = CORS(app, resources={rf"{APP_PREFIX}/api/*": {
|
||||
"origins": "*",
|
||||
"methods": "DELETE, POST, GET, OPTIONS",
|
||||
"allow_headers": ["Content-Type", "wg-dashboard-apikey"]
|
||||
}})
|
||||
|
||||
app.logger.setLevel(getattr(logging, log_level.upper(), logging.INFO))
|
||||
|
||||
dictConfig({
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'default': {
|
||||
'format': '[%(asctime)s] [%(levelname)s] in [%(module)s] %(message)s',
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'wsgi': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'stream': 'ext://flask.logging.wsgi_errors_stream',
|
||||
'formatter': 'default',
|
||||
},
|
||||
}
|
||||
})
|
||||
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||
_, WG_CONF_PATH = DashboardConfig.GetConfig("Server", "wg_conf_path")
|
||||
|
||||
'''
|
||||
API Routes
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import dashboard
|
||||
from datetime import datetime
|
||||
global sqldb, cursor, DashboardConfig, WireguardConfigurations, AllPeerJobs, JobLogger, Dash
|
||||
app_host, app_port, log_level = dashboard.gunicornConfig()
|
||||
app_host, app_port = dashboard.gunicornConfig()
|
||||
date = datetime.today().strftime('%Y_%m_%d_%H_%M_%S')
|
||||
|
||||
def post_worker_init(worker):
|
||||
@@ -16,7 +16,7 @@ daemon = True
|
||||
pidfile = './gunicorn.pid'
|
||||
wsgi_app = "dashboard:app"
|
||||
accesslog = f"./log/access_{date}.log"
|
||||
loglevel = f"{log_level}"
|
||||
loglevel = "info"
|
||||
capture_output = True
|
||||
errorlog = f"./log/error_{date}.log"
|
||||
pythonpath = "., ./modules"
|
||||
|
@@ -174,7 +174,7 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
|
||||
def getPeers(self):
|
||||
self.Peers.clear()
|
||||
current_app.logger.debug(f"Refreshing {self.Name} peer list")
|
||||
current_app.logger.info(f"Refreshing {self.Name} peer list")
|
||||
|
||||
if self.configurationFileChanged():
|
||||
with open(self.configPath, 'r') as configFile:
|
||||
@@ -183,7 +183,7 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
content = configFile.read().split('\n')
|
||||
try:
|
||||
if "[Peer]" not in content:
|
||||
current_app.logger.debug(f"{self.Name} config has no [Peer] section")
|
||||
current_app.logger.info(f"{self.Name} config has no [Peer] section")
|
||||
return
|
||||
|
||||
peerStarts = content.index("[Peer]")
|
||||
|
@@ -1,47 +1,25 @@
|
||||
# ConnectionString.py
|
||||
import configparser
|
||||
import os
|
||||
from sqlalchemy_utils import database_exists, create_database
|
||||
from flask import current_app
|
||||
|
||||
default_db = "wgdashboard"
|
||||
default_log_db = "wgdashboard_log"
|
||||
default_job_db = "wgdashboard_job"
|
||||
sqlite_path = "db"
|
||||
if os.path.exists(sqlite_path):
|
||||
os.makedirs(sqlite_path, exist_ok=True)
|
||||
|
||||
def ConnectionString(database_name: str) -> str:
|
||||
"""
|
||||
Returns a SQLAlchemy-compatible connection string for the chosen database.
|
||||
Creates the database if it doesn't exist.
|
||||
"""
|
||||
|
||||
# Read and parse the INI file once at startup
|
||||
def ConnectionString(database) -> str:
|
||||
parser = configparser.ConfigParser(strict=False)
|
||||
parser.read("wg-dashboard.ini")
|
||||
|
||||
db_type = parser.get("Database", "type")
|
||||
db_prefix = parser.get("Database", "prefix")
|
||||
database_name = f"{db_prefix}{database_name}"
|
||||
|
||||
if db_type == "postgresql":
|
||||
username = parser.get("Database", "username")
|
||||
password = parser.get("Database", "password")
|
||||
host = parser.get("Database", "host")
|
||||
cn = f"postgresql+psycopg://{username}:{password}@{host}/{database_name}"
|
||||
elif db_type == "mysql":
|
||||
username = parser.get("Database", "username")
|
||||
password = parser.get("Database", "password")
|
||||
host = parser.get("Database", "host")
|
||||
cn = f"mysql+pymysql://{username}:{password}@{host}/{database_name}"
|
||||
parser.read_file(open('wg-dashboard.ini', "r+"))
|
||||
sqlitePath = os.path.join("db")
|
||||
if not os.path.isdir(sqlitePath):
|
||||
os.mkdir(sqlitePath)
|
||||
if parser.get("Database", "type") == "postgresql":
|
||||
cn = f'postgresql+psycopg://{parser.get("Database", "username")}:{parser.get("Database", "password")}@{parser.get("Database", "host")}/{database}'
|
||||
elif parser.get("Database", "type") == "mysql":
|
||||
cn = f'mysql+pymysql://{parser.get("Database", "username")}:{parser.get("Database", "password")}@{parser.get("Database", "host")}/{database}'
|
||||
else:
|
||||
cn = f'sqlite:///{os.path.join(sqlite_path, f"{database_name}.db")}'
|
||||
|
||||
cn = f'sqlite:///{os.path.join(sqlitePath, f"{database}.db")}'
|
||||
try:
|
||||
if not database_exists(cn):
|
||||
create_database(cn)
|
||||
except Exception as e:
|
||||
current_app.logger.critical("Database error. Terminating...", e)
|
||||
current_app.logger.error("Database error. Terminating...", e)
|
||||
exit(1)
|
||||
|
||||
|
||||
return cn
|
@@ -8,7 +8,7 @@ import pyotp
|
||||
import sqlalchemy as db
|
||||
import requests
|
||||
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardClientsPeerAssignment import DashboardClientsPeerAssignment
|
||||
from .DashboardClientsTOTP import DashboardClientsTOTP
|
||||
from .DashboardOIDC import DashboardOIDC
|
||||
@@ -20,7 +20,7 @@ from flask import session
|
||||
class DashboardClients:
|
||||
def __init__(self, wireguardConfigurations):
|
||||
self.logger = DashboardLogger()
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.OIDC = DashboardOIDC("Client")
|
||||
|
||||
@@ -32,10 +32,10 @@ class DashboardClients:
|
||||
db.Column('TotpKey', db.String(500)),
|
||||
db.Column('TotpKeyVerified', db.Integer),
|
||||
db.Column('CreatedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('DeletedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP)),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||
extend_existing=True,
|
||||
)
|
||||
|
||||
@@ -46,10 +46,10 @@ class DashboardClients:
|
||||
db.Column('ProviderIssuer', db.String(500), nullable=False, index=True),
|
||||
db.Column('ProviderSubject', db.String(500), nullable=False, index=True),
|
||||
db.Column('CreatedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('DeletedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP)),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||
extend_existing=True,
|
||||
)
|
||||
|
||||
@@ -65,10 +65,10 @@ class DashboardClients:
|
||||
db.Column('ResetToken', db.String(255), nullable=False, primary_key=True),
|
||||
db.Column('ClientID', db.String(255), nullable=False),
|
||||
db.Column('CreatedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('ExpiryDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP)),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||
extend_existing=True
|
||||
)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardLogger import DashboardLogger
|
||||
import sqlalchemy as db
|
||||
from .WireguardConfiguration import WireguardConfiguration
|
||||
@@ -31,7 +31,7 @@ class Assignment:
|
||||
class DashboardClientsPeerAssignment:
|
||||
def __init__(self, wireguardConfigurations: dict[str, WireguardConfiguration]):
|
||||
self.logger = DashboardLogger()
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.wireguardConfigurations = wireguardConfigurations
|
||||
self.dashboardClientsPeerAssignmentTable = db.Table(
|
||||
@@ -41,10 +41,10 @@ class DashboardClientsPeerAssignment:
|
||||
db.Column('ConfigurationName', db.String(255)),
|
||||
db.Column('PeerID', db.String(500)),
|
||||
db.Column('AssignedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('UnassignedDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP)),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)),
|
||||
extend_existing=True
|
||||
)
|
||||
self.metadata.create_all(self.engine)
|
||||
|
@@ -3,19 +3,19 @@ import hashlib
|
||||
import uuid
|
||||
|
||||
import sqlalchemy as db
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
|
||||
|
||||
class DashboardClientsTOTP:
|
||||
def __init__(self):
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.dashboardClientsTOTPTable = db.Table(
|
||||
'DashboardClientsTOTPTokens', self.metadata,
|
||||
db.Column("Token", db.String(500), primary_key=True, index=True),
|
||||
db.Column("ClientID", db.String(500), index=True),
|
||||
db.Column(
|
||||
"ExpireTime", (db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP)
|
||||
"ExpireTime", (db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)
|
||||
)
|
||||
)
|
||||
self.metadata.create_all(self.engine)
|
||||
|
@@ -7,7 +7,7 @@ import sqlalchemy as db
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from flask import current_app
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .Utilities import (
|
||||
GetRemoteEndpoint, ValidateDNSAddress
|
||||
)
|
||||
@@ -47,8 +47,7 @@ class DashboardConfig:
|
||||
"dashboard_sort": "status",
|
||||
"dashboard_theme": "dark",
|
||||
"dashboard_api_key": "false",
|
||||
"dashboard_language": "en-US",
|
||||
"log_level": "INFO"
|
||||
"dashboard_language": "en-US"
|
||||
},
|
||||
"Peers": {
|
||||
"peer_global_DNS": "1.1.1.1",
|
||||
@@ -66,8 +65,7 @@ class DashboardConfig:
|
||||
"host": "",
|
||||
"port": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"prefix": ""
|
||||
"password": ""
|
||||
},
|
||||
"Email":{
|
||||
"server": "",
|
||||
@@ -97,14 +95,28 @@ class DashboardConfig:
|
||||
if not exist:
|
||||
self.SetConfig(section, key, value, True)
|
||||
|
||||
self.SetConfig("Server", "version", DashboardConfig.DashboardVersion)
|
||||
self.SaveConfig()
|
||||
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString('wgdashboard'))
|
||||
self.dbMetadata = db.MetaData()
|
||||
self.__createAPIKeyTable()
|
||||
self.DashboardAPIKeys = self.__getAPIKeys()
|
||||
self.APIAccessed = False
|
||||
self.SetConfig("Server", "version", DashboardConfig.DashboardVersion)
|
||||
|
||||
def getConnectionString(self, database) -> str or None:
|
||||
sqlitePath = os.path.join(DashboardConfig.ConfigurationPath, "db")
|
||||
|
||||
if not os.path.isdir(sqlitePath):
|
||||
os.mkdir(sqlitePath)
|
||||
|
||||
if self.GetConfig("Database", "type")[1] == "postgresql":
|
||||
cn = f'postgresql+psycopg2://{self.GetConfig("Database", "username")[1]}:{self.GetConfig("Database", "password")[1]}@{self.GetConfig("Database", "host")[1]}/{database}'
|
||||
elif self.GetConfig("Database", "type")[1] == "mysql":
|
||||
cn = f'mysql+mysqldb://{self.GetConfig("Database", "username")[1]}:{self.GetConfig("Database", "password")[1]}@{self.GetConfig("Database", "host")[1]}/{database}'
|
||||
else:
|
||||
cn = f'sqlite:///{os.path.join(sqlitePath, f"{database}.db")}'
|
||||
if not database_exists(cn):
|
||||
create_database(cn)
|
||||
return cn
|
||||
|
||||
def __createAPIKeyTable(self):
|
||||
self.apiKeyTable = db.Table('DashboardAPIKeys', self.dbMetadata,
|
||||
|
@@ -4,18 +4,18 @@ Dashboard Logger Class
|
||||
import uuid
|
||||
import sqlalchemy as db
|
||||
from flask import current_app
|
||||
from .ConnectionString import ConnectionString, default_db, default_log_db
|
||||
from .ConnectionString import ConnectionString
|
||||
|
||||
|
||||
class DashboardLogger:
|
||||
def __init__(self):
|
||||
self.engine = db.create_engine(ConnectionString(default_log_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard_log"))
|
||||
self.metadata = db.MetaData()
|
||||
self.dashboardLoggerTable = db.Table('DashboardLog', self.metadata,
|
||||
|
||||
db.Column('LogID', db.String(255), nullable=False, primary_key=True),
|
||||
db.Column('LogDate',
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString(default_db) else db.TIMESTAMP),
|
||||
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
|
||||
server_default=db.func.now()),
|
||||
db.Column('URL', db.String(255)),
|
||||
db.Column('IP', db.String(255)),
|
||||
|
@@ -8,7 +8,7 @@ from datetime import datetime, timedelta
|
||||
import requests
|
||||
from pydantic import BaseModel, field_serializer
|
||||
import sqlalchemy as db
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from flask import current_app
|
||||
|
||||
WebHookActions = ['peer_created', 'peer_deleted', 'peer_updated']
|
||||
@@ -40,7 +40,7 @@ class WebHookSessionLogs(BaseModel):
|
||||
|
||||
class DashboardWebHooks:
|
||||
def __init__(self, DashboardConfig):
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.webHooksTable = db.Table(
|
||||
'DashboardWebHooks', self.metadata,
|
||||
@@ -201,7 +201,7 @@ class DashboardWebHooks:
|
||||
|
||||
class WebHookSession:
|
||||
def __init__(self, webHook: WebHook, data: dict[str, str]):
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.webHookSessionsTable = db.Table('DashboardWebHookSessions', self.metadata, autoload_with=self.engine)
|
||||
self.webHook = webHook
|
||||
|
@@ -2,7 +2,7 @@ import uuid
|
||||
|
||||
from pydantic import BaseModel, field_serializer
|
||||
import sqlalchemy as db
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
|
||||
|
||||
class NewConfigurationTemplate(BaseModel):
|
||||
@@ -14,7 +14,7 @@ class NewConfigurationTemplate(BaseModel):
|
||||
|
||||
class NewConfigurationTemplates:
|
||||
def __init__(self):
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.templatesTable = db.Table(
|
||||
'NewConfigurationTemplates', self.metadata,
|
||||
|
@@ -4,12 +4,12 @@ Peer Job Logger
|
||||
import uuid
|
||||
import sqlalchemy as db
|
||||
from flask import current_app
|
||||
from .ConnectionString import ConnectionString, default_log_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .Log import Log
|
||||
|
||||
class PeerJobLogger:
|
||||
def __init__(self, AllPeerJobs, DashboardConfig):
|
||||
self.engine = db.create_engine(ConnectionString(default_log_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard_log"))
|
||||
self.metadata = db.MetaData()
|
||||
self.jobLogTable = db.Table('JobLog', self.metadata,
|
||||
db.Column('LogID', db.String(255), nullable=False, primary_key=True),
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Peer Jobs
|
||||
"""
|
||||
from .ConnectionString import ConnectionString, default_job_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .PeerJob import PeerJob
|
||||
from .PeerJobLogger import PeerJobLogger
|
||||
import sqlalchemy as db
|
||||
@@ -11,7 +11,7 @@ from flask import current_app
|
||||
class PeerJobs:
|
||||
def __init__(self, DashboardConfig, WireguardConfigurations):
|
||||
self.Jobs: list[PeerJob] = []
|
||||
self.engine = db.create_engine(ConnectionString(default_job_db))
|
||||
self.engine = db.create_engine(ConnectionString('wgdashboard_job'))
|
||||
self.metadata = db.MetaData()
|
||||
self.peerJobTable = db.Table('PeerJobs', self.metadata,
|
||||
db.Column('JobID', db.String(255), nullable=False, primary_key=True),
|
||||
@@ -141,7 +141,7 @@ class PeerJobs:
|
||||
|
||||
|
||||
def runJob(self):
|
||||
current_app.logger.debug("Running scheduled jobs")
|
||||
current_app.logger.info("Running scheduled jobs")
|
||||
needToDelete = []
|
||||
self.__getJobs()
|
||||
for job in self.Jobs:
|
||||
@@ -184,7 +184,7 @@ class PeerJobs:
|
||||
f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed."
|
||||
)
|
||||
else:
|
||||
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed.")
|
||||
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed.")
|
||||
self.JobLogger.log(job.JobID, False,
|
||||
f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed."
|
||||
)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .PeerShareLink import PeerShareLink
|
||||
import sqlalchemy as db
|
||||
from datetime import datetime
|
||||
@@ -10,7 +10,7 @@ Peer Share Links
|
||||
class PeerShareLinks:
|
||||
def __init__(self, DashboardConfig, WireguardConfigurations):
|
||||
self.Links: list[PeerShareLink] = []
|
||||
self.engine = db.create_engine(ConnectionString(default_db))
|
||||
self.engine = db.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata = db.MetaData()
|
||||
self.peerShareLinksTable = db.Table(
|
||||
'PeerShareLinks', self.metadata,
|
||||
|
@@ -10,7 +10,7 @@ from datetime import datetime, timedelta
|
||||
from itertools import islice
|
||||
from flask import current_app
|
||||
|
||||
from .ConnectionString import ConnectionString, default_db
|
||||
from .ConnectionString import ConnectionString
|
||||
from .DashboardConfig import DashboardConfig
|
||||
from .Peer import Peer
|
||||
from .PeerJobs import PeerJobs
|
||||
@@ -64,7 +64,7 @@ class WireguardConfiguration:
|
||||
self.AllPeerShareLinks = AllPeerShareLinks
|
||||
self.DashboardWebHooks = DashboardWebHooks
|
||||
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
|
||||
self.engine: sqlalchemy.Engine = sqlalchemy.create_engine(ConnectionString(default_db))
|
||||
self.engine: sqlalchemy.Engine = sqlalchemy.create_engine(ConnectionString("wgdashboard"))
|
||||
self.metadata: sqlalchemy.MetaData = sqlalchemy.MetaData()
|
||||
self.dbType = self.DashboardConfig.GetConfig("Database", "type")[1]
|
||||
|
||||
@@ -396,7 +396,7 @@ class WireguardConfiguration:
|
||||
|
||||
def getPeers(self):
|
||||
tmpList = []
|
||||
current_app.logger.debug(f"Refreshing {self.Name} peer list")
|
||||
current_app.logger.info(f"Refreshing {self.Name} peer list")
|
||||
|
||||
if self.configurationFileChanged():
|
||||
with open(self.configPath, 'r') as configFile:
|
||||
@@ -405,7 +405,7 @@ class WireguardConfiguration:
|
||||
content = configFile.read().split('\n')
|
||||
try:
|
||||
if "[Peer]" not in content:
|
||||
current_app.logger.debug(f"{self.Name} config has no [Peer] section")
|
||||
current_app.logger.info(f"{self.Name} config has no [Peer] section")
|
||||
return
|
||||
|
||||
peerStarts = content.index("[Peer]")
|
||||
|
1120
src/static/app/package-lock.json
generated
1120
src/static/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@volar/language-server": "2.4.23",
|
||||
"@vue/language-server": "3.0.7",
|
||||
"@vue/language-server": "3.1.0",
|
||||
"@vuepic/vue-datepicker": "^11.0.2",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"@vueuse/shared": "^13.5.0",
|
||||
@@ -26,8 +26,8 @@
|
||||
"electron-builder": "^26.0.12",
|
||||
"fuse.js": "^7.0.0",
|
||||
"i": "^0.3.7",
|
||||
"is-cidr": "^6.0.0",
|
||||
"npm": "^11.6.0",
|
||||
"is-cidr": "^5.0.3",
|
||||
"npm": "^11.6.1",
|
||||
"ol": "^10.2.1",
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.5.0",
|
||||
@@ -35,12 +35,12 @@
|
||||
"qrcodejs": "^1.0.0",
|
||||
"simple-code-editor": "^2.0.9",
|
||||
"uuid": "^13.0.0",
|
||||
"vue": "^3.5.17",
|
||||
"vue": "^3.5.22",
|
||||
"vue-chartjs": "^5.3.0",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"vite": "^7.1.6"
|
||||
"vite": "^7.1.7"
|
||||
}
|
||||
}
|
||||
|
@@ -114,7 +114,7 @@ const data = computed(() => {
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar bg-warning" :style="{width: `${data?.Memory.SwapMemory.percent}%` }"></div>
|
||||
<div class="progress-bar bg-warning" :style="{width: `$ data?.Memory.SwapMemory.percent}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user