mirror of
https://github.com/WGDashboard/WGDashboard-PRW.git
synced 2026-08-03 22:42:57 +00:00
chore: remnant changes
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
[peers]
|
||||||
|
remote_endpoint = 89.20.90.254
|
||||||
|
peer_global_dns = 9.9.9.9
|
||||||
|
peer_endpoint_allowed_ip = 0.0.0.0/0
|
||||||
|
peer_display_mode = grid
|
||||||
|
peer_mtu = 1420
|
||||||
|
peer_keep_alive = 21
|
||||||
|
|
||||||
|
[server]
|
||||||
|
hostname = 0.0.0.0
|
||||||
|
port = 10086
|
||||||
|
debug_enabled = True
|
||||||
|
wg_conf_path = /etc/wireguard
|
||||||
|
awg_conf_path = /etc/amnezia/amneziawg
|
||||||
|
app_prefix =
|
||||||
|
authentication_required = True
|
||||||
|
version = v5.0.0
|
||||||
|
wgdashboard_refresh_interval = 60000
|
||||||
|
wgdashboard_peer_list_display = grid
|
||||||
|
wgdashboard_sort = status
|
||||||
|
wgdashboard_theme = dark
|
||||||
|
wgdashboard_apikey = true
|
||||||
|
wgdashboard_language = en-US
|
||||||
|
log_level = DEBUG
|
||||||
|
|
||||||
|
[account]
|
||||||
|
username = admin
|
||||||
|
password = $2b$12$1VN62Q7CS/BJcAahHAWsA.3CD6zPqWTmE/HN/AJqwP0zds2l25Fqe
|
||||||
|
enable_totp = false
|
||||||
|
totp_verified = false
|
||||||
|
totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ
|
||||||
|
|
||||||
|
[other]
|
||||||
|
welcome_session = false
|
||||||
|
|
||||||
|
[database]
|
||||||
|
type = sqlite
|
||||||
|
host =
|
||||||
|
port =
|
||||||
|
username =
|
||||||
|
password =
|
||||||
|
|
||||||
|
[email]
|
||||||
|
server =
|
||||||
|
port =
|
||||||
|
encryption =
|
||||||
|
username =
|
||||||
|
email_password =
|
||||||
|
authentication_required = true
|
||||||
|
send_from =
|
||||||
|
email_template =
|
||||||
|
|
||||||
|
[oidc]
|
||||||
|
admin_enable = false
|
||||||
|
client_enable = false
|
||||||
|
|
||||||
|
[clients]
|
||||||
|
enable = true
|
||||||
|
sign_up = true
|
||||||
|
|
||||||
|
[wireguardconfiguration]
|
||||||
|
autostart =
|
||||||
|
peer_tracking = false
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
import configparser as cp
|
||||||
|
import os
|
||||||
|
|
||||||
|
class config_utils():
|
||||||
|
@staticmethod
|
||||||
|
def search_known_paths() -> tuple[bool, str]:
|
||||||
|
'''
|
||||||
|
Look at predefined paths on the filesystem for a config file
|
||||||
|
'''
|
||||||
|
|
||||||
|
possible_config_locations = [
|
||||||
|
"./config.ini",
|
||||||
|
f"{os.getenv('HOME')}/.config/wgdashboard/config.ini",
|
||||||
|
"/etc/wgdashboard/config.ini",
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
for path in possible_config_locations:
|
||||||
|
if os.path.exists(path):
|
||||||
|
return True, path
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read_data(config_path) -> tuple[bool, dict]:
|
||||||
|
config = cp.ConfigParser()
|
||||||
|
|
||||||
|
try:
|
||||||
|
config.read(config_path)
|
||||||
|
|
||||||
|
if len(config.sections()) == 0:
|
||||||
|
return False, {}
|
||||||
|
|
||||||
|
config_dict = {}
|
||||||
|
for section in config.sections():
|
||||||
|
new_items = {}
|
||||||
|
|
||||||
|
for key, value in config.items(section):
|
||||||
|
key = key.lower()
|
||||||
|
val = value.strip().lower()
|
||||||
|
|
||||||
|
if val == 'true':
|
||||||
|
value = True
|
||||||
|
elif val == 'false':
|
||||||
|
value = False
|
||||||
|
|
||||||
|
new_items[key] = value
|
||||||
|
|
||||||
|
config_dict[section.lower()] = new_items
|
||||||
|
|
||||||
|
return True, config_dict
|
||||||
|
|
||||||
|
except cp.ParsingError as err:
|
||||||
|
return False, {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_section(config_data: dict, target_section: str) -> bool:
|
||||||
|
if target_section not in config_data:
|
||||||
|
log.error("target section not in the config")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_key(config_data: dict, target_section: str, target_key: str) -> bool:
|
||||||
|
if target_key not in config_data[target_section]:
|
||||||
|
log.error("target key not in the config")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def write_key(config_data: dict, target_section: str, target_key: str, new_value: str) -> bool:
|
||||||
|
config_data[target_section][target_key] = new_value
|
||||||
|
|
||||||
|
config = cp.ConfigParser()
|
||||||
|
|
||||||
|
for section, values in config_data.items():
|
||||||
|
config[section] = {}
|
||||||
|
for key, value in values.items():
|
||||||
|
config[section][key] = str(value)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ok, candidate_path = config_utils.search_known_paths()
|
||||||
|
if not ok:
|
||||||
|
log.error("failed to retrieve a valid path for the config")
|
||||||
|
return False
|
||||||
|
|
||||||
|
with open(candidate_path, "w") as f:
|
||||||
|
config.write(f)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
log.info("exception occured",err)
|
||||||
|
return False
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
import os
|
||||||
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
|
from modules.utilities.utilities import utilities as util
|
||||||
|
|
||||||
|
class database_utils():
|
||||||
|
'''
|
||||||
|
This class functions as a collection of function to prepare a connection to a database.
|
||||||
|
'''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_connection_string(database_config: dict) -> tuple[bool, str]:
|
||||||
|
if not 'type' in database_config:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
username = quote_plus(database_config.get('username', ''))
|
||||||
|
password = quote_plus(database_config.get('password', ''))
|
||||||
|
|
||||||
|
match database_config['type']:
|
||||||
|
case 'sqlite':
|
||||||
|
local_database_path = os.path.abspath("./database")
|
||||||
|
|
||||||
|
exists = util.ensure_directory(local_database_path)
|
||||||
|
if exists:
|
||||||
|
connection_string = f'sqlite:///{local_database_path}/wgdashboard.db'
|
||||||
|
else:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
case 'postgresql' | 'postgres':
|
||||||
|
connection_string = f'postgresql+psycopg://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '5432')}'
|
||||||
|
|
||||||
|
case 'mariadb':
|
||||||
|
connection_string = f'mariadb+mariadbconnector://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
|
||||||
|
|
||||||
|
case 'mysql':
|
||||||
|
connection_string = f'mysql+pymysql://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
return True, connection_string
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
from ..database.functions import functions
|
||||||
|
|
||||||
|
class routes_utils():
|
||||||
|
@staticmethod
|
||||||
|
def is_valid_api_key(api_key: str) -> bool:
|
||||||
|
valid_keys, _ = functions.retrieve_api_keys(flask.current_app.db_session)
|
||||||
|
valid_key_strings = []
|
||||||
|
|
||||||
|
for key in valid_keys:
|
||||||
|
valid_key_strings.append(key["key"])
|
||||||
|
|
||||||
|
return api_key in valid_key_strings
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_path_allowed(path: str, white_list: list[str], session_data: dict) -> bool:
|
||||||
|
# Allow if session has admin role
|
||||||
|
if session_data.get("role") == "admin" and "username" in session_data:
|
||||||
|
return True
|
||||||
|
# Check white list
|
||||||
|
for p in white_list:
|
||||||
|
if p in path:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import logging as log
|
||||||
|
|
||||||
|
import bcrypt
|
||||||
|
import flask
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import pyotp
|
||||||
|
import os
|
||||||
|
import werkzeug
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from .response import make_resp_obj
|
||||||
|
from .routes_utils import routes_utils
|
||||||
|
from .locale import localeman
|
||||||
|
|
||||||
|
from ..database.functions import functions
|
||||||
|
from ..config.config import config
|
||||||
|
|
||||||
|
routes_welcome = flask.Blueprint("routes_welcome", __name__)
|
||||||
|
|
||||||
|
@routes_welcome.route('/api/Welcome_Finish', methods=["POST"])
|
||||||
|
def api_welcome_finish():
|
||||||
|
ok, config_other = config.filter(flask.current_app.wgd_config, 'OTHER')
|
||||||
|
if not ok:
|
||||||
|
log.error("failed to filter the config in-memory")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
req_data = flask.request.get_json()
|
||||||
|
if not req_data:
|
||||||
|
return make_resp_obj(False, "Invalid request body", {}, 400)
|
||||||
|
|
||||||
|
if len(req_data["username"]) == 0:
|
||||||
|
return make_resp_obj(False, "Username cannot be empty", {}, 400)
|
||||||
|
|
||||||
|
if len(req_data["newPassword"]) < 7:
|
||||||
|
return make_resp_obj(False, "Password must be at least 8 characters", {}, 400)
|
||||||
|
|
||||||
|
if not config.update('ACCOUNT', 'username', req_data["username"]):
|
||||||
|
log.error("failed to update the key in the configuration file")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
hashed_password = bcrypt.hashpw(req_data["newPassword"].encode('utf-8'), bcrypt.gensalt())
|
||||||
|
|
||||||
|
if not config.update('ACCOUNT', 'password', hashed_password.decode('utf-8')):
|
||||||
|
log.error("failed to update the key in the configuration file")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
if not config.update('OTHER', 'welcome_session', False):
|
||||||
|
log.error("failed to update the key in the configuration file")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
# Very important to also refresh the config in-memory
|
||||||
|
ok, flask.current_app.wgd_config = config.read()
|
||||||
|
if not ok:
|
||||||
|
log.error("failed to refresh the in-memory configuration")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
return make_resp_obj()
|
||||||
|
|
||||||
|
@routes_welcome.route('/api/Welcome_GetTotpLink')
|
||||||
|
def api_welcome_get_totp():
|
||||||
|
ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT')
|
||||||
|
if not ok:
|
||||||
|
log.error("failed to filter the config in-memory")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
if "totp_verified" not in config_account or not config_account["totp_verified"]:
|
||||||
|
totp_key = pyotp.random_base32()
|
||||||
|
|
||||||
|
log.debug(totp_key)
|
||||||
|
ok = config.update('ACCOUNT', 'totp_key', totp_key)
|
||||||
|
if not ok:
|
||||||
|
log.error("failed to update the key in the configuration file")
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
|
|
||||||
|
return make_resp_obj(True, '', pyotp.totp.TOTP(totp_key).provisioning_uri(issuer_name="WGDashboard Admin"))
|
||||||
|
|
||||||
|
return make_resp_obj(False, 'Internal error', {}, 500)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Dropping current files..."
|
||||||
|
|
||||||
|
rm ./dist -rf
|
||||||
|
|
||||||
|
echo "Compiling the new!"
|
||||||
|
|
||||||
|
cd ./admin && npm run build && cd ..
|
||||||
|
cd ./client && npm run build && cd ..
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
Reference in New Issue
Block a user