Skip to content

Commit d8d829a

Browse files
author
DaanSelen
committed
chore: remnant changes
1 parent 799b8bd commit d8d829a

File tree

7 files changed

+331
-0
lines changed

7 files changed

+331
-0
lines changed

src/config.ini.bak

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
[peers]
2+
remote_endpoint = 89.20.90.254
3+
peer_global_dns = 9.9.9.9
4+
peer_endpoint_allowed_ip = 0.0.0.0/0
5+
peer_display_mode = grid
6+
peer_mtu = 1420
7+
peer_keep_alive = 21
8+
9+
[server]
10+
hostname = 0.0.0.0
11+
port = 10086
12+
debug_enabled = True
13+
wg_conf_path = /etc/wireguard
14+
awg_conf_path = /etc/amnezia/amneziawg
15+
app_prefix =
16+
authentication_required = True
17+
version = v5.0.0
18+
wgdashboard_refresh_interval = 60000
19+
wgdashboard_peer_list_display = grid
20+
wgdashboard_sort = status
21+
wgdashboard_theme = dark
22+
wgdashboard_apikey = true
23+
wgdashboard_language = en-US
24+
log_level = DEBUG
25+
26+
[account]
27+
username = admin
28+
password = $2b$12$1VN62Q7CS/BJcAahHAWsA.3CD6zPqWTmE/HN/AJqwP0zds2l25Fqe
29+
enable_totp = false
30+
totp_verified = false
31+
totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ
32+
33+
[other]
34+
welcome_session = false
35+
36+
[database]
37+
type = sqlite
38+
host =
39+
port =
40+
username =
41+
password =
42+
43+
[email]
44+
server =
45+
port =
46+
encryption =
47+
username =
48+
email_password =
49+
authentication_required = true
50+
send_from =
51+
email_template =
52+
53+
[oidc]
54+
admin_enable = false
55+
client_enable = false
56+
57+
[clients]
58+
enable = true
59+
sign_up = true
60+
61+
[wireguardconfiguration]
62+
autostart =
63+
peer_tracking = false

src/modules/config/config_utils.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/bin/env python3
2+
3+
import logging as log
4+
5+
import configparser as cp
6+
import os
7+
8+
class config_utils():
9+
@staticmethod
10+
def search_known_paths() -> tuple[bool, str]:
11+
'''
12+
Look at predefined paths on the filesystem for a config file
13+
'''
14+
15+
possible_config_locations = [
16+
"./config.ini",
17+
f"{os.getenv('HOME')}/.config/wgdashboard/config.ini",
18+
"/etc/wgdashboard/config.ini",
19+
]
20+
21+
try:
22+
for path in possible_config_locations:
23+
if os.path.exists(path):
24+
return True, path
25+
else:
26+
continue
27+
return False, ''
28+
29+
except Exception as err:
30+
return False, ''
31+
32+
@staticmethod
33+
def read_data(config_path) -> tuple[bool, dict]:
34+
config = cp.ConfigParser()
35+
36+
try:
37+
config.read(config_path)
38+
39+
if len(config.sections()) == 0:
40+
return False, {}
41+
42+
config_dict = {}
43+
for section in config.sections():
44+
new_items = {}
45+
46+
for key, value in config.items(section):
47+
key = key.lower()
48+
val = value.strip().lower()
49+
50+
if val == 'true':
51+
value = True
52+
elif val == 'false':
53+
value = False
54+
55+
new_items[key] = value
56+
57+
config_dict[section.lower()] = new_items
58+
59+
return True, config_dict
60+
61+
except cp.ParsingError as err:
62+
return False, {}
63+
64+
@staticmethod
65+
def find_section(config_data: dict, target_section: str) -> bool:
66+
if target_section not in config_data:
67+
log.error("target section not in the config")
68+
return False
69+
70+
return True
71+
72+
@staticmethod
73+
def find_key(config_data: dict, target_section: str, target_key: str) -> bool:
74+
if target_key not in config_data[target_section]:
75+
log.error("target key not in the config")
76+
return False
77+
78+
return True
79+
80+
@staticmethod
81+
def write_key(config_data: dict, target_section: str, target_key: str, new_value: str) -> bool:
82+
config_data[target_section][target_key] = new_value
83+
84+
config = cp.ConfigParser()
85+
86+
for section, values in config_data.items():
87+
config[section] = {}
88+
for key, value in values.items():
89+
config[section][key] = str(value)
90+
91+
try:
92+
ok, candidate_path = config_utils.search_known_paths()
93+
if not ok:
94+
log.error("failed to retrieve a valid path for the config")
95+
return False
96+
97+
with open(candidate_path, "w") as f:
98+
config.write(f)
99+
100+
return True
101+
102+
except Exception as err:
103+
log.info("exception occured",err)
104+
return False
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/env python3
2+
3+
import logging as log
4+
5+
import os
6+
from urllib.parse import quote_plus
7+
8+
from modules.utilities.utilities import utilities as util
9+
10+
class database_utils():
11+
'''
12+
This class functions as a collection of function to prepare a connection to a database.
13+
'''
14+
15+
@staticmethod
16+
def generate_connection_string(database_config: dict) -> tuple[bool, str]:
17+
if not 'type' in database_config:
18+
return False, ''
19+
20+
username = quote_plus(database_config.get('username', ''))
21+
password = quote_plus(database_config.get('password', ''))
22+
23+
match database_config['type']:
24+
case 'sqlite':
25+
local_database_path = os.path.abspath("./database")
26+
27+
exists = util.ensure_directory(local_database_path)
28+
if exists:
29+
connection_string = f'sqlite:///{local_database_path}/wgdashboard.db'
30+
else:
31+
return False, ''
32+
33+
case 'postgresql' | 'postgres':
34+
connection_string = f'postgresql+psycopg://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '5432')}'
35+
36+
case 'mariadb':
37+
connection_string = f'mariadb+mariadbconnector://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
38+
39+
case 'mysql':
40+
connection_string = f'mysql+pymysql://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
41+
42+
case _:
43+
return False, ''
44+
45+
return True, connection_string

src/modules/routes/routes_utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/env python3
2+
3+
import flask
4+
5+
from ..database.functions import functions
6+
7+
class routes_utils():
8+
@staticmethod
9+
def is_valid_api_key(api_key: str) -> bool:
10+
valid_keys, _ = functions.retrieve_api_keys(flask.current_app.db_session)
11+
valid_key_strings = []
12+
13+
for key in valid_keys:
14+
valid_key_strings.append(key["key"])
15+
16+
return api_key in valid_key_strings
17+
18+
@staticmethod
19+
def is_path_allowed(path: str, white_list: list[str], session_data: dict) -> bool:
20+
# Allow if session has admin role
21+
if session_data.get("role") == "admin" and "username" in session_data:
22+
return True
23+
# Check white list
24+
for p in white_list:
25+
if p in path:
26+
return True
27+
return False
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import logging as log
2+
3+
import bcrypt
4+
import flask
5+
import hashlib
6+
import json
7+
import pyotp
8+
import os
9+
import werkzeug
10+
from datetime import datetime
11+
12+
from .response import make_resp_obj
13+
from .routes_utils import routes_utils
14+
from .locale import localeman
15+
16+
from ..database.functions import functions
17+
from ..config.config import config
18+
19+
routes_welcome = flask.Blueprint("routes_welcome", __name__)
20+
21+
@routes_welcome.route('/api/Welcome_Finish', methods=["POST"])
22+
def api_welcome_finish():
23+
ok, config_other = config.filter(flask.current_app.wgd_config, 'OTHER')
24+
if not ok:
25+
log.error("failed to filter the config in-memory")
26+
return make_resp_obj(False, 'Internal error', {}, 500)
27+
28+
req_data = flask.request.get_json()
29+
if not req_data:
30+
return make_resp_obj(False, "Invalid request body", {}, 400)
31+
32+
if len(req_data["username"]) == 0:
33+
return make_resp_obj(False, "Username cannot be empty", {}, 400)
34+
35+
if len(req_data["newPassword"]) < 7:
36+
return make_resp_obj(False, "Password must be at least 8 characters", {}, 400)
37+
38+
if not config.update('ACCOUNT', 'username', req_data["username"]):
39+
log.error("failed to update the key in the configuration file")
40+
return make_resp_obj(False, 'Internal error', {}, 500)
41+
42+
hashed_password = bcrypt.hashpw(req_data["newPassword"].encode('utf-8'), bcrypt.gensalt())
43+
44+
if not config.update('ACCOUNT', 'password', hashed_password.decode('utf-8')):
45+
log.error("failed to update the key in the configuration file")
46+
return make_resp_obj(False, 'Internal error', {}, 500)
47+
48+
if not config.update('OTHER', 'welcome_session', False):
49+
log.error("failed to update the key in the configuration file")
50+
return make_resp_obj(False, 'Internal error', {}, 500)
51+
52+
# Very important to also refresh the config in-memory
53+
ok, flask.current_app.wgd_config = config.read()
54+
if not ok:
55+
log.error("failed to refresh the in-memory configuration")
56+
return make_resp_obj(False, 'Internal error', {}, 500)
57+
58+
return make_resp_obj()
59+
60+
@routes_welcome.route('/api/Welcome_GetTotpLink')
61+
def api_welcome_get_totp():
62+
ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT')
63+
if not ok:
64+
log.error("failed to filter the config in-memory")
65+
return make_resp_obj(False, 'Internal error', {}, 500)
66+
67+
if "totp_verified" not in config_account or not config_account["totp_verified"]:
68+
totp_key = pyotp.random_base32()
69+
70+
log.debug(totp_key)
71+
ok = config.update('ACCOUNT', 'totp_key', totp_key)
72+
if not ok:
73+
log.error("failed to update the key in the configuration file")
74+
return make_resp_obj(False, 'Internal error', {}, 500)
75+
76+
return make_resp_obj(True, '', pyotp.totp.TOTP(totp_key).provisioning_uri(issuer_name="WGDashboard Admin"))
77+
78+
return make_resp_obj(False, 'Internal error', {}, 500)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/env python3
2+

src/static/build-app.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
echo "Dropping current files..."
4+
5+
rm ./dist -rf
6+
7+
echo "Compiling the new!"
8+
9+
cd ./admin && npm run build && cd ..
10+
cd ./client && npm run build && cd ..
11+
12+
echo "Done!"

0 commit comments

Comments
 (0)