diff --git a/src/dashboard.py b/src/dashboard.py index e0036d6..72a47a0 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -288,9 +288,6 @@ def get_transfer(config_name): # {round(cumulative_sent + cumulative_receive, 4)}, '{now_string}') # ''') - - - def get_endpoint(config_name): """ Get endpoint from all peers of a configuration @@ -310,8 +307,6 @@ def get_endpoint(config_name): % (data_usage[count + 1], data_usage[count])) count += 2 - - def get_allowed_ip(conf_peer_data, config_name): """ Get allowed ips from all peers of a configuration @@ -324,8 +319,6 @@ def get_allowed_ip(conf_peer_data, config_name): g.cur.execute("UPDATE " + config_name + " SET allowed_ip = '%s' WHERE id = '%s'" % (i.get('AllowedIPs', '(None)'), i["PublicKey"])) - - def get_all_peers_data(config_name): """ Look for new peers from WireGuard @@ -488,7 +481,6 @@ def get_conf_total_data(config_name): download_total = round(download_total, 4) return [total, upload_total, download_total] - def get_conf_status(config_name): """ Check if the configuration is running or not @@ -690,9 +682,8 @@ def auth_req(): @return: Redirect """ return None - - if getattr(g, 'db', None) is None: + print('hi') g.db = connect_db() g.cur = g.db.cursor() conf = get_dashboard_conf() @@ -781,6 +772,7 @@ def auth(): return jsonify({"status": False, "msg": "Username or Password is incorrect."}) + """ Index Page """ @@ -796,8 +788,8 @@ def index(): if "switch_msg" in session: msg = session["switch_msg"] session.pop("switch_msg") - return render_template('index_new.html') - # return render_template('index.html', conf=get_conf_list(), msg=msg) + # return render_template('index_new.html') + return render_template('index.html', conf=get_conf_list(), msg=msg) # Setting Page @@ -1787,6 +1779,37 @@ def traceroute_ip(): return jsonify(returnjson) except Exception: return "Error" + +### NEW API ROUTES + +@app.route('/api/authenticate', methods=['POST']) +def api_auth(): + """ + Authentication request + @return: json object indicating verifying + """ + data = request.get_json() + config = get_dashboard_conf() + password = hashlib.sha256(data['password'].encode()) + if password.hexdigest() == config["Account"]["password"] \ + and data['username'] == config["Account"]["username"]: + session['username'] = data['username'] + resp = jsonify(ResponseObject(True)) + resp.set_cookie("authToken", hashlib.sha256(f"{data['username']}{datetime.now()}".encode()).hexdigest()) + session.permanent = True + config.clear() + return resp + + config.clear() + return jsonify(ResponseObject(False, "Username or password in incorrect.")) + + +def ResponseObject(status = True, message = None, data = None) -> dict: + return { + "status": status, + "message": message, + "data": data + } import atexit @@ -1911,8 +1934,6 @@ def init_dashboard(): """ Create dashboard default configuration. """ - - # Set Default INI File if not os.path.isfile(DASHBOARD_CONF): open(DASHBOARD_CONF, "w+").close() diff --git a/src/dashboard_new.py b/src/dashboard_new.py new file mode 100644 index 0000000..7a89375 --- /dev/null +++ b/src/dashboard_new.py @@ -0,0 +1,197 @@ +from crypt import methods +import sqlite3 +import configparser +import hashlib +import ipaddress +import json +# Python Built-in Library +import os +import secrets +import subprocess +import time +import re +import urllib.parse +import urllib.request +import urllib.error +from datetime import datetime, timedelta +from operator import itemgetter +# PIP installed library +import ifcfg +from flask import Flask, request, render_template, redirect, url_for, session, jsonify, g +from flask_qrcode import QRcode +from icmplib import ping, traceroute + +# Import other python files +import threading + +from sqlalchemy.orm import mapped_column, declarative_base, Session +from sqlalchemy import FLOAT, INT, VARCHAR, select, MetaData +from sqlalchemy import create_engine + +DASHBOARD_VERSION = 'v3.1' +CONFIGURATION_PATH = os.getenv('CONFIGURATION_PATH', '.') +DB_PATH = os.path.join(CONFIGURATION_PATH, 'db') +if not os.path.isdir(DB_PATH): + os.mkdir(DB_PATH) +DASHBOARD_CONF = os.path.join(CONFIGURATION_PATH, 'wg-dashboard.ini') + +# WireGuard's configuration path +WG_CONF_PATH = None +# Dashboard Config Name +# Upgrade Required +UPDATE = None +# Flask App Configuration +app = Flask("WGDashboard") +app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928 +app.secret_key = secrets.token_urlsafe(32) +# Enable QR Code Generator +QRcode(app) + +''' +Classes +''' +Base = declarative_base() + + +class DashboardConfig: + + def __init__(self): + self.__config = configparser.ConfigParser(strict=False) + self.__config.read(DASHBOARD_CONF) + self.__default = { + "Account": { + "username": "admin", + "password": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" + }, + "Server": { + "wg_conf_path": "/etc/wireguard", + "app_ip": "0.0.0.0", + "app_port": "10086", + "auth_req": "true", + "version": DASHBOARD_VERSION, + "dashboard_refresh_interval": "60000", + "dashboard_sort": "status", + "dashboard_theme": "light" + }, + "Peers": { + "peer_global_DNS": "1.1.1.1", + "peer_endpoint_allowed_ip": "0.0.0.0/0", + "peer_display_mode": "grid", + "remote_endpoint": ifcfg.default_interface()['inet'], + "peer_MTU": "1420", + "peer_keep_alive": "21" + } + } + + for section, keys in self.__default.items(): + for key, value in keys.items(): + exist, currentData = self.GetConfig(section, key) + if not exist: + self.SetConfig(section, key, value) + + def SetConfig(self, section: str, key: str, value: any) -> bool: + if section not in self.__config: + self.__config[section] = {} + self.__config[section][key] = value + return self.SaveConfig() + + def SaveConfig(self) -> bool: + try: + with open(DASHBOARD_CONF, "w+", encoding='utf-8') as configFile: + self.__config.write(configFile) + return True + except Exception as e: + return False + + def GetConfig(self, section, key) -> [any, bool]: + if section not in self.__config: + return False, None + + if key not in self.__config[section]: + return False, None + + return True, self.__config[section][key] + + +def ResponseObject(status=True, message=None, data=None) -> dict: + return { + "status": status, + "message": message, + "data": data + } + + +DashboardConfig = DashboardConfig() + +''' +Private Functions +''' + + +def _createPeerModel(wgConfigName): + class Peer(Base): + __tablename__ = wgConfigName + id = mapped_column(VARCHAR, primary_key=True) + private_key = mapped_column(VARCHAR) + DNS = mapped_column(VARCHAR) + endpoint_allowed_ip = mapped_column(VARCHAR) + name = mapped_column(VARCHAR) + total_receive = mapped_column(FLOAT) + total_sent = mapped_column(FLOAT) + total_data = mapped_column(FLOAT) + endpoint = mapped_column(VARCHAR) + status = mapped_column(VARCHAR) + latest_handshake = mapped_column(VARCHAR) + allowed_ip = mapped_column(VARCHAR) + cumu_receive = mapped_column(FLOAT) + cumu_sent = mapped_column(FLOAT) + cumu_data = mapped_column(FLOAT) + mtu = mapped_column(INT) + keepalive = mapped_column(INT) + remote_endpoint = mapped_column(VARCHAR) + preshared_key = mapped_column(VARCHAR) + + return Peer + + +def _regexMatch(regex, text): + pattern = re.compile(regex) + return pattern.search(text) is not None + + +def _getConfigurationList(): + conf = [] + for i in os.listdir(WG_CONF_PATH): + if _regexMatch("^(.{1,}).(conf)$", i): + i = i.replace('.conf', '') + _createPeerModel(i).__table__.create(engine) + _createPeerModel(i + "_restrict_access").__table__.create(engine) + + +''' +API Routes +''' + + +@app.route('/api/authenticate', methods=['POST']) +def API_AuthenticateLogin(): + data = request.get_json() + password = hashlib.sha256(data['password'].encode()) + print() + if password.hexdigest() == DashboardConfig.GetConfig("Account", "password")[1] \ + and data['username'] == DashboardConfig.GetConfig("Account", "username")[1]: + session['username'] = data['username'] + resp = jsonify(ResponseObject(True)) + resp.set_cookie("authToken", + hashlib.sha256(f"{data['username']}{datetime.now()}".encode()).hexdigest()) + session.permanent = True + return resp + return jsonify(ResponseObject(False, "Username or password is incorrect.")) + + +if __name__ == "__main__": + engine = create_engine("sqlite:///" + os.path.join(CONFIGURATION_PATH, 'db', 'wgdashboard.db')) + _, app_ip = DashboardConfig.GetConfig("Server", "app_ip") + _, app_port = DashboardConfig.GetConfig("Server", "app_port") + _getConfigurationList() + app.run(host=app_ip, debug=False, port=app_port) diff --git a/src/static/app/index.html b/src/static/app/index.html index 456879a..8e026c5 100644 --- a/src/static/app/index.html +++ b/src/static/app/index.html @@ -8,6 +8,6 @@
- +