From f5ad7a49ce76f66e56e2c348e080e2e40b8c296c Mon Sep 17 00:00:00 2001 From: Galonza Peter Date: Sun, 26 Dec 2021 02:26:39 +0300 Subject: [PATCH 1/2] general refactoring --- src/dashboard.py | 383 +++++++++++++++++++++++++++++------------------ 1 file changed, 236 insertions(+), 147 deletions(-) diff --git a/src/dashboard.py b/src/dashboard.py index 07959e6..9df79e4 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -3,30 +3,32 @@ Under Apache-2.0 License """ -# Import other python files -from util import * -# Python Built-in Library -import os -from flask import Flask, request, render_template, redirect, url_for, session, abort, jsonify -import subprocess -from datetime import datetime, date, time, timedelta -import time -from operator import itemgetter -import secrets -import hashlib -import json, urllib.request import configparser -import re +import hashlib import ipaddress -import sqlite3 +import json +# Python Built-in Library +import logging +import os +import secrets +import subprocess import threading +import time +import urllib.parse +import urllib.request +from datetime import datetime, time, timedelta +from operator import itemgetter + # PIP installed library import ifcfg +from flask import Flask, request, render_template, redirect, url_for, session, jsonify from flask_qrcode import QRcode +from icmplib import ping, traceroute from tinydb import TinyDB, Query -from tinydb.storages import JSONStorage -from tinydb.middlewares import CachingMiddleware -from icmplib import ping, multiping, traceroute, resolve, Host, Hop + +# Import other python files +from util import * + # Dashboard Version dashboard_version = 'v3.0' # Dashboard Config Name @@ -45,36 +47,44 @@ QRcode(app) sem = threading.RLock() -""" -Dashboard Configuration Related -""" # Read / Write Dashboard Config File def get_dashboard_conf(): + """ + Dashboard Configuration Related + """ + config = configparser.ConfigParser(strict=False) config.read(dashboard_conf) return config + + def set_dashboard_conf(config): config.write(open(dashboard_conf, "w")) -""" -Configuration Related -""" + # Get all keys from a configuration def get_conf_peer_key(config_name): + """ + Configuration Related + """ + try: - peer_key = subprocess.check_output("wg show " + config_name + " peers", shell=True) + peer_key = subprocess.run(f"wg show {config_name} peers", + check=True, shell=True, capture_output=True).stdout peer_key = peer_key.decode("UTF-8").split() return peer_key - except Exception: + except subprocess.CalledProcessError: return config_name + " is not running." + # Get numbers of connected peer of a configuration def get_conf_running_peer_number(config_name): running = 0 # Get latest handshakes try: - data_usage = subprocess.check_output("wg show " + config_name + " latest-handshakes", shell=True) - except Exception: + data_usage = subprocess.run(f"wg show {config_name} latest-handshakes", + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 @@ -87,13 +97,13 @@ def get_conf_running_peer_number(config_name): count += 2 return running + # Read [Interface] section from configuration file def read_conf_file_interface(config_name): conf_location = wg_conf_path + "/" + config_name + ".conf" f = open(conf_location, 'r') file = f.read().split("\n") data = {} - peers_start = 0 for i in range(len(file)): if not regex_match("#(.*)", file[i]): if len(file[i]) > 0: @@ -104,6 +114,7 @@ def read_conf_file_interface(config_name): f.close() return data + # Read the whole configuration file def read_conf_file(config_name): # Read Configuration File Start @@ -143,12 +154,14 @@ def read_conf_file(config_name): # Read Configuration File End return conf_peer_data + # Get latest handshake from all peers of a configuration def get_latest_handshake(config_name, db, peers): # Get latest handshakes try: - data_usage = subprocess.check_output("wg show " + config_name + " latest-handshakes", shell=True) - except Exception: + data_usage = subprocess.run(f"wg show {config_name} latest-handshakes", + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 @@ -167,12 +180,14 @@ def get_latest_handshake(config_name, db, peers): db.update({"latest_handshake": "(None)", "status": status}, peers.id == data_usage[count]) count += 2 + # Get transfer from all peers of a configuration def get_transfer(config_name, db, peers): # Get transfer try: - data_usage = subprocess.check_output("wg show " + config_name + " transfer", shell=True) - except Exception: + data_usage = subprocess.run(f"wg show {config_name} transfer", + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 @@ -202,12 +217,14 @@ def get_transfer(config_name, db, peers): count += 3 + # Get endpoint from all peers of a configuration def get_endpoint(config_name, db, peers): # Get endpoint try: - data_usage = subprocess.check_output("wg show " + config_name + " endpoints", shell=True) - except Exception: + data_usage = subprocess.run(f"wg show {config_name} endpoints", + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 @@ -215,16 +232,18 @@ def get_endpoint(config_name, db, peers): db.update({"endpoint": data_usage[count + 1]}, peers.id == data_usage[count]) count += 2 + # Get allowed ips from all peers of a configuration -def get_allowed_ip(config_name, db, peers, conf_peer_data): +def get_allowed_ip(db, peers, conf_peer_data): # Get allowed ip for i in conf_peer_data["Peers"]: db.update({"allowed_ip": i.get('AllowedIPs', '(None)')}, peers.id == i["PublicKey"]) + # Look for new peers from WireGuard def get_all_peers_data(config_name): sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() @@ -237,7 +256,7 @@ def get_all_peers_data(config_name): "id": i['PublicKey'], "private_key": "", "DNS": config.get("Peers", "peer_global_DNS"), - "endpoint_allowed_ip": config.get("Peers","peer_endpoint_allowed_ip"), + "endpoint_allowed_ip": config.get("Peers", "peer_endpoint_allowed_ip"), "name": "", "total_receive": 0, "total_sent": 0, @@ -248,8 +267,8 @@ def get_all_peers_data(config_name): "allowed_ip": "N/A", "traffic": [], "mtu": config.get("Peers", "peer_mtu"), - "keepalive": config.get("Peers","peer_keep_alive"), - "remote_endpoint":config.get("Peers","remote_endpoint") + "keepalive": config.get("Peers", "peer_keep_alive"), + "remote_endpoint": config.get("Peers", "remote_endpoint") }) else: # Update database since V2.2 @@ -265,9 +284,9 @@ def get_all_peers_data(config_name): if "mtu" not in search[0]: update_db['mtu'] = config.get("Peers", "peer_mtu") if "keepalive" not in search[0]: - update_db['keepalive'] = config.get("Peers","peer_keep_alive") + update_db['keepalive'] = config.get("Peers", "peer_keep_alive") if "remote_endpoint" not in search[0]: - update_db['remote_endpoint'] = config.get("Peers","remote_endpoint") + update_db['remote_endpoint'] = config.get("Peers", "remote_endpoint") db.update(update_db, peers.id == i['PublicKey']) # Remove peers no longer exist in WireGuard configuration file db_key = list(map(lambda a: a['id'], db.all())) @@ -279,20 +298,22 @@ def get_all_peers_data(config_name): get_latest_handshake(config_name, db, peers) get_transfer(config_name, db, peers) get_endpoint(config_name, db, peers) - get_allowed_ip(config_name, db, peers, conf_peer_data) + get_allowed_ip(db, peers, conf_peer_data) toc = time.perf_counter() print(f"Finish fetching data in {toc - tic:0.4f} seconds") db.close() sem.release() -""" -Frontend Related Functions -""" + # Search for peers def get_peers(config_name, search, sort_t): + """ + Frontend Related Functions + """ + get_all_peers_data(config_name) sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peer = Query() if len(search) == 0: @@ -300,7 +321,7 @@ def get_peers(config_name, search, sort_t): else: result = db.search(peer.name.matches('(.*)(' + re.escape(search) + ')(.*)')) if sort_t == "allowed_ip": - result = sorted(result, key = lambda d: ipaddress.ip_network(d[sort_t].split(",")[0])) + result = sorted(result, key=lambda d: ipaddress.ip_network(d[sort_t].split(",")[0])) else: result = sorted(result, key=lambda d: d[sort_t]) db.close() @@ -308,17 +329,16 @@ def get_peers(config_name, search, sort_t): return result - - # Get configuration public key def get_conf_pub_key(config_name): conf = configparser.ConfigParser(strict=False) conf.read(wg_conf_path + "/" + config_name + ".conf") pri = conf.get("Interface", "PrivateKey") - pub = subprocess.check_output("echo '" + pri + "' | wg pubkey", shell=True) + pub = subprocess.run(f"echo '{pri}' | wg pubkey", check=True, shell=True, capture_output=True).stdout conf.clear() return pub.decode().strip("\n") + # Get configuration listen port def get_conf_listen_port(config_name): conf = configparser.ConfigParser(strict=False) @@ -326,17 +346,19 @@ def get_conf_listen_port(config_name): port = "" try: port = conf.get("Interface", "ListenPort") - except: + except (configparser.NoSectionError, configparser.NoOptionError): if get_conf_status(config_name) == "running": - port = subprocess.check_output("wg show "+config_name+" listen-port", shell=True) + port = subprocess.run(f"wg show {config_name} listen-port", + check=True, shell=True, capture_output=True).stdout port = port.decode("UTF-8") conf.clear() return port + # Get configuration total data def get_conf_total_data(config_name): sem.acquire() - + db = TinyDB('db/' + config_name + '.json') upload_total = 0 download_total = 0 @@ -353,6 +375,7 @@ def get_conf_total_data(config_name): sem.release() return [total, upload_total, download_total] + # Get configuration status def get_conf_status(config_name): ifconfig = dict(ifcfg.interfaces().items()) @@ -361,6 +384,7 @@ def get_conf_status(config_name): else: return "stopped" + # Get all configuration as a list def get_conf_list(): conf = [] @@ -377,10 +401,9 @@ def get_conf_list(): conf = sorted(conf, key=itemgetter('conf')) return conf + # Generate private key def gen_private_key(): - gen = subprocess.check_output('wg genkey > private_key.txt && wg pubkey < private_key.txt > public_key.txt', - shell=True) private = open('private_key.txt') private_key = private.readline().strip() public = open('public_key.txt') @@ -392,22 +415,23 @@ def gen_private_key(): os.remove('public_key.txt') return data + # Generate public key def gen_public_key(private_key): pri_key_file = open('private_key.txt', 'w') pri_key_file.write(private_key) pri_key_file.close() try: - check = subprocess.check_output("wg pubkey < private_key.txt > public_key.txt", shell=True) public = open('public_key.txt') public_key = public.readline().strip() os.remove('private_key.txt') os.remove('public_key.txt') return {"status": 'success', "msg": "", "data": public_key} - except subprocess.CalledProcessError as exc: + except subprocess.CalledProcessError: os.remove('private_key.txt') return {"status": 'failed', "msg": "Key is not the correct length or format", "data": ""} + # Check if private key and public key match def checkKeyMatch(private_key, public_key, config_name): result = gen_public_key(private_key) @@ -415,7 +439,7 @@ def checkKeyMatch(private_key, public_key, config_name): return result else: sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() match = db.search(peers.id == result['data']) @@ -428,11 +452,11 @@ def checkKeyMatch(private_key, public_key, config_name): sem.release() return {'status': 'success'} + # Check if there is repeated allowed IP def check_repeat_allowed_IP(public_key, ip, config_name): - sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() peer = db.search(peers.id == public_key) @@ -454,10 +478,10 @@ def check_repeat_allowed_IP(public_key, ip, config_name): Flask Functions """ + # Before request @app.before_request def auth_req(): - conf = configparser.ConfigParser(strict=False) conf.read(dashboard_conf) req = conf.get("Server", "auth_req") @@ -480,10 +504,13 @@ def auth_req(): 'update_app_ip_port', 'update_wg_conf_path']: return redirect(url_for("index")) + """ Sign In / Sign Out """ -#Sign In + + +# Sign In @app.route('/signin', methods=['GET']) def signin(): message = "" @@ -492,7 +519,8 @@ def signin(): session.pop("message") return render_template('signin.html', message=message) -#Sign Out + +# Sign Out @app.route('/signout', methods=['GET']) def signout(): if "username" in session: @@ -500,14 +528,15 @@ def signout(): message = "Sign out successfully!" return render_template('signin.html', message=message) + # Authentication @app.route('/auth', methods=['POST']) def auth(): config = configparser.ConfigParser(strict=False) config.read(dashboard_conf) password = hashlib.sha256(request.form['password'].encode()) - if password.hexdigest() == config["Account"]["password"] and request.form['username'] == config["Account"][ - "username"]: + if password.hexdigest() == config["Account"]["password"] \ + and request.form['username'] == config["Account"]["username"]: session['username'] = request.form['username'] config.clear() return redirect(url_for("index")) @@ -516,20 +545,23 @@ def auth(): config.clear() return redirect(url_for("signin")) -""" -Index Page Related -""" + @app.route('/', methods=['GET']) def index(): - update = check_update() + """ + Index Page Related + """ + return render_template('index.html', conf=get_conf_list()) -""" -Setting Page Related -""" + # Setting Page @app.route('/settings', methods=['GET']) def settings(): + """ + Setting Page Related + """ + message = "" status = "" config = configparser.ConfigParser(strict=False) @@ -546,8 +578,9 @@ def settings(): peer_global_DNS=config.get("Peers", "peer_global_DNS"), peer_endpoint_allowed_ip=config.get("Peers", "peer_endpoint_allowed_ip"), peer_mtu=config.get("Peers", "peer_mtu"), - peer_keepalive=config.get("Peers","peer_keep_alive"), - peer_remote_endpoint=config.get("Peers","remote_endpoint")) + peer_keepalive=config.get("Peers", "peer_keep_alive"), + peer_remote_endpoint=config.get("Peers", "remote_endpoint")) + # Update account username @app.route('/update_acct', methods=['POST']) @@ -566,12 +599,14 @@ def update_acct(): session['username'] = request.form['username'] config.clear() return redirect(url_for("settings")) - except Exception: + except Exception as exc: + logging.error(exc) session['message'] = "Username update failed." session['message_status'] = "danger" config.clear() return redirect(url_for("settings")) + # Update peer default settting @app.route('/update_peer_default_config', methods=['POST']) def update_peer_default_config(): @@ -584,40 +619,45 @@ def update_peer_default_config(): session['message_status'] = "danger" return redirect(url_for("settings")) # Check DNS Format - DNS = request.form['peer_global_DNS'] - if not check_DNS(DNS): + dns_addresses = request.form['peer_global_DNS'] + if not check_DNS(dns_addresses): session['message'] = "Peer DNS Format Incorrect." session['message_status'] = "danger" return redirect(url_for("settings")) - DNS = DNS.replace(" ","").split(',') - DNS = ",".join(DNS) + dns_addresses = dns_addresses.replace(" ", "").split(',') + dns_addresses = ",".join(dns_addresses) # Check Endpoint Allowed IPs ip = request.form['peer_endpoint_allowed_ip'] if not check_Allowed_IPs(ip): - session['message'] = "Peer Endpoint Allowed IPs Format Incorrect. Example: 192.168.1.1/32 or 192.168.1.1/32,192.168.1.2/32" + session['message'] = "Peer Endpoint Allowed IPs Format Incorrect. " \ + "Example: 192.168.1.1/32 or 192.168.1.1/32,192.168.1.2/32" session['message_status'] = "danger" return redirect(url_for("settings")) # Check MTU Format if len(request.form['peer_mtu']) > 0: try: + # TODO need to using mtu = int(request.form['peer_mtu']) - except: + except Exception as exc: + logging.info(exc) session['message'] = "MTU format is incorrect." session['message_status'] = "danger" return redirect(url_for("settings")) # Check keepalive Format if len(request.form['peer_keep_alive']) > 0: try: + # TODO need to using mtu = int(request.form['peer_keep_alive']) - except: + except Exception as exc: + logging.error(exc) session['message'] = "Persistent keepalive format is incorrect." session['message_status'] = "danger" return redirect(url_for("settings")) # Check peer remote endpoint if not check_remote_endpoint(request.form['peer_remote_endpoint']): - session[ - 'message'] = "Peer Remote Endpoint format is incorrect. It can only be a valid IP address or valid domain (without http:// or https://). " + session['message'] = "Peer Remote Endpoint format is incorrect. It can only be a valid " \ + "IP address or valid domain (without http:// or https://). " session['message_status'] = "danger" return redirect(url_for("settings")) @@ -625,8 +665,7 @@ def update_peer_default_config(): config.set("Peers", "peer_keep_alive", request.form['peer_keep_alive']) config.set("Peers", "peer_mtu", request.form['peer_mtu']) config.set("Peers", "peer_endpoint_allowed_ip", ','.join(clean_IP_with_range(ip))) - config.set("Peers", "peer_global_DNS", DNS) - + config.set("Peers", "peer_global_DNS", dns_addresses) try: config.write(open(dashboard_conf, "w")) @@ -634,12 +673,14 @@ def update_peer_default_config(): session['message_status'] = "success" config.clear() return redirect(url_for("settings")) - except Exception: + except Exception as exc: + logging.error(exc) session['message'] = "Peer Default Settings update failed." session['message_status'] = "danger" config.clear() return redirect(url_for("settings")) + # Update dashboard password @app.route('/update_pwd', methods=['POST']) def update_pwd(): @@ -655,7 +696,8 @@ def update_pwd(): session['message_status'] = "success" config.clear() return redirect(url_for("settings")) - except Exception: + except Exception as exc: + logging.error(exc) session['message'] = "Password update failed" session['message_status'] = "danger" config.clear() @@ -671,6 +713,7 @@ def update_pwd(): config.clear() return redirect(url_for("settings")) + # Update dashboard IP and port @app.route('/update_app_ip_port', methods=['POST']) def update_app_ip_port(): @@ -682,6 +725,7 @@ def update_app_ip_port(): config.clear() os.system('bash wgd.sh restart') + # Update WireGuard configuration file path @app.route('/update_wg_conf_path', methods=['POST']) def update_wg_conf_path(): @@ -694,12 +738,14 @@ def update_wg_conf_path(): config.clear() os.system('bash wgd.sh restart') -""" -Configuration Page Related -""" + # Update configuration sorting @app.route('/update_dashboard_sort', methods=['POST']) def update_dashbaord_sort(): + """ + Configuration Page Related + """ + config = configparser.ConfigParser(strict=False) config.read(dashboard_conf) data = request.get_json() @@ -712,6 +758,7 @@ def update_dashbaord_sort(): config.clear() return "true" + # Update configuration refresh interval @app.route('/update_dashboard_refresh_interval', methods=['POST']) def update_dashboard_refresh_interval(): @@ -722,6 +769,7 @@ def update_dashboard_refresh_interval(): config.clear() return "true" + # Configuration Page @app.route('/configuration/', methods=['GET']) def conf(config_name): @@ -746,15 +794,17 @@ def conf(config_name): DNS=config.get("Peers", "peer_global_DNS"), endpoint_allowed_ip=config.get("Peers", "peer_endpoint_allowed_ip"), title=config_name, - mtu=config.get("Peers","peer_MTU"), - keep_alive=config.get("Peers","peer_keep_alive")) + mtu=config.get("Peers", "peer_MTU"), + keep_alive=config.get("Peers", "peer_keep_alive")) + # Get configuration details @app.route('/get_config/', methods=['GET']) def get_conf(config_name): config_interface = read_conf_file_interface(config_name) search = request.args.get('search') - if len(search) == 0: search = "" + if search == 0: + search = "" search = urllib.parse.unquote(search) config = configparser.ConfigParser(strict=False) config.read(dashboard_conf) @@ -778,9 +828,12 @@ def get_conf(config_name): conf_data['checked'] = "nope" else: conf_data['checked'] = "checked" - print(config.get("Peers","remote_endpoint")) - return render_template('get_conf.html', conf_data=conf_data, wg_ip=config.get("Peers","remote_endpoint"), sort_tag=sort, - dashboard_refresh_interval=int(config.get("Server", "dashboard_refresh_interval")), peer_display_mode=peer_display_mode) + print(config.get("Peers", "remote_endpoint")) + return render_template('get_conf.html', conf_data=conf_data, wg_ip=config.get("Peers", "remote_endpoint"), + sort_tag=sort, + dashboard_refresh_interval=int(config.get("Server", "dashboard_refresh_interval")), + peer_display_mode=peer_display_mode) + # Turn on / off a configuration @app.route('/switch/', methods=['GET']) @@ -791,31 +844,34 @@ def switch(config_name): status = get_conf_status(config_name) if status == "running": try: - status = subprocess.check_output("wg-quick down " + config_name, shell=True) - except Exception: + subprocess.run("wg-quick down " + config_name, + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return redirect('/') elif status == "stopped": try: - status = subprocess.check_output("wg-quick up " + config_name, shell=True) - except Exception: + subprocess.run("wg-quick up " + config_name, + check=True, shell=True, capture_output=True).stdout + except subprocess.CalledProcessError: return redirect('/') return redirect(request.referrer) + # Add peer @app.route('/add_peer/', methods=['POST']) def add_peer(config_name): sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() data = request.get_json() public_key = data['public_key'] allowed_ips = data['allowed_ips'] endpoint_allowed_ip = data['endpoint_allowed_ip'] - DNS = data['DNS'] + dns_addresses = data['DNS'] keys = get_conf_peer_key(config_name) - if len(public_key) == 0 or len(DNS) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0: + if len(public_key) == 0 or len(dns_addresses) == 0 or len(allowed_ips) == 0 or len(endpoint_allowed_ip) == 0: db.close() sem.release() return "Please fill in all required box." @@ -831,7 +887,7 @@ def add_peer(config_name): db.close() sem.release() return "Allowed IP already taken by another peer." - if not check_DNS(DNS): + if not check_DNS(dns_addresses): db.close() sem.release() return "DNS formate is incorrect. Example: 1.1.1.1" @@ -841,23 +897,27 @@ def add_peer(config_name): return "Endpoint Allowed IPs format is incorrect." if len(data['MTU']) != 0: try: + # TODO need to using mtu = int(data['MTU']) - except: + except Exception as exc: + logging.error(exc) db.close() sem.release() return "MTU format is not correct." if len(data['keep_alive']) != 0: try: + # TODO need to using keep_alive = int(data['keep_alive']) - except: + except Exception as exc: + logging.error(exc) db.close() sem.release() return "Persistent Keepalive format is not correct." try: - status = subprocess.check_output( - "wg set " + config_name + " peer " + public_key + " allowed-ips " + allowed_ips, shell=True, - stderr=subprocess.STDOUT) - status = subprocess.check_output("wg-quick save " + config_name, shell=True, stderr=subprocess.STDOUT) + subprocess.run(f"wg set {config_name} peer {public_key} allowed-ips {allowed_ips}", + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) + subprocess.run("wg-quick save " + config_name, + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) get_all_peers_data(config_name) db.update({"name": data['name'], "private_key": data['private_key'], "DNS": data['DNS'], "endpoint_allowed_ip": endpoint_allowed_ip}, @@ -870,13 +930,14 @@ def add_peer(config_name): sem.release() return exc.output.strip() + # Remove peer @app.route('/remove_peer/', methods=['POST']) def remove_peer(config_name): if get_conf_status(config_name) == "stopped": return "Your need to turn on " + config_name + " first." sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() data = request.get_json() @@ -889,9 +950,10 @@ def remove_peer(config_name): return "This key does not exist" else: try: - status = subprocess.check_output("wg set " + config_name + " peer " + delete_key + " remove", shell=True, - stderr=subprocess.STDOUT) - status = subprocess.check_output("wg-quick save " + config_name, shell=True, stderr=subprocess.STDOUT) + subprocess.run(f"wg set {config_name} peer {delete_key} remove", + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) + subprocess.run("wg-quick save " + config_name, + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) db.remove(peers.id == delete_key) db.close() sem.release() @@ -901,6 +963,7 @@ def remove_peer(config_name): sem.release() return exc.output.strip() + # Save peer settings @app.route('/save_peer_setting/', methods=['POST']) def save_peer_setting(config_name): @@ -908,11 +971,11 @@ def save_peer_setting(config_name): id = data['id'] name = data['name'] private_key = data['private_key'] - DNS = data['DNS'] + dns_addresses = data['DNS'] allowed_ip = data['allowed_ip'] endpoint_allowed_ip = data['endpoint_allowed_ip'] sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() if len(db.search(peers.id == id)) == 1: @@ -921,21 +984,25 @@ def save_peer_setting(config_name): db.close() sem.release() return jsonify({"status": "failed", "msg": "Endpoint Allowed IPs format is incorrect."}) - if not check_DNS(DNS): + if not check_DNS(dns_addresses): db.close() sem.release() return jsonify({"status": "failed", "msg": "DNS format is incorrect."}) if len(data['MTU']) != 0: try: + # TODO need to use mtu = int(data['MTU']) - except: + except Exception as exc: + logging.error(exc) db.close() sem.release() return jsonify({"status": "failed", "msg": "MTU format is not correct."}) if len(data['keep_alive']) != 0: try: + # TODO need to using keep_alive = int(data['keep_alive']) - except: + except Exception as exc: + logging.error(exc) db.close() sem.release() return jsonify({"status": "failed", "msg": "Persistent Keepalive format is not correct."}) @@ -953,19 +1020,19 @@ def save_peer_setting(config_name): if allowed_ip == "": allowed_ip = '""' allowed_ip = allowed_ip.replace(" ", "") - change_ip = subprocess.check_output('wg set ' + config_name + " peer " + id + " allowed-ips " + allowed_ip, - shell=True, stderr=subprocess.STDOUT) - save_change_ip = subprocess.check_output('wg-quick save ' + config_name, shell=True, - stderr=subprocess.STDOUT) + change_ip = subprocess.run('wg set ' + config_name + " peer " + id + " allowed-ips " + allowed_ip, + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT).stdout + subprocess.run('wg-quick save ' + config_name, + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) if change_ip.decode("UTF-8") != "": db.close() sem.release() return jsonify({"status": "failed", "msg": change_ip.decode("UTF-8")}) db.update( {"name": name, "private_key": private_key, - "DNS": DNS, "endpoint_allowed_ip": endpoint_allowed_ip, + "DNS": dns_addresses, "endpoint_allowed_ip": endpoint_allowed_ip, "mtu": data['MTU'], - "keepalive":data['keep_alive']}, + "keepalive": data['keep_alive']}, peers.id == id) db.close() sem.release() @@ -979,13 +1046,14 @@ def save_peer_setting(config_name): sem.release() return jsonify({"status": "failed", "msg": "This peer does not exist."}) + # Get peer settings @app.route('/get_peer_data/', methods=['POST']) def get_peer_name(config_name): data = request.get_json() id = data['id'] sem.acquire() - + db = TinyDB('db/' + config_name + '.json') peers = Query() result = db.search(peers.id == id) @@ -996,11 +1064,13 @@ def get_peer_name(config_name): sem.release() return jsonify(data) + # Generate a private key @app.route('/generate_peer', methods=['GET']) def generate_peer(): return jsonify(gen_private_key()) + # Generate a public key from a private key @app.route('/generate_public_key', methods=['POST']) def generate_public_key(): @@ -1008,6 +1078,7 @@ def generate_public_key(): private_key = data['private_key'] return jsonify(gen_public_key(private_key)) + # Check if both key match @app.route('/check_key_match/', methods=['POST']) def check_key_match(config_name): @@ -1033,8 +1104,8 @@ def generate_qrcode(config_name): endpoint = config.get("Peers", "remote_endpoint") + ":" + listen_port private_key = peer['private_key'] allowed_ip = peer['allowed_ip'] - DNS = peer['DNS'] - MTU = peer['mtu'] + dns_addresses = peer['DNS'] + mtu_value = peer['mtu'] endpoint_allowed_ip = peer['endpoint_allowed_ip'] keepalive = peer['keepalive'] conf = { @@ -1043,8 +1114,8 @@ def generate_qrcode(config_name): "endpoint": endpoint, "private_key": private_key, "allowed_ip": allowed_ip, - "DNS": DNS, - "mtu": MTU, + "DNS": dns_addresses, + "mtu": mtu_value, "endpoint_allowed_ip": endpoint_allowed_ip, "keepalive": keepalive, } @@ -1055,6 +1126,8 @@ def generate_qrcode(config_name): db.close() sem.release() return redirect("/configuration/" + config_name) + + # Download configuration file @app.route('/', methods=['GET']) def download(config_name): @@ -1070,11 +1143,11 @@ def download(config_name): if peer['private_key'] != "": public_key = get_conf_pub_key(config_name) listen_port = get_conf_listen_port(config_name) - endpoint = config.get("Peers","remote_endpoint") + ":" + listen_port + endpoint = config.get("Peers", "remote_endpoint") + ":" + listen_port private_key = peer['private_key'] allowed_ip = peer['allowed_ip'] - DNS = peer['DNS'] - MTU = peer['mtu'] + dns_addresses = peer['DNS'] + mtu_value = peer['mtu'] endpoint_allowed_ip = peer['endpoint_allowed_ip'] keepalive = peer['keepalive'] filename = peer['name'] @@ -1093,21 +1166,25 @@ def download(config_name): filename = "".join(filename.split(' ')) filename = filename + "_" + config_name - def generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive): - yield "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + DNS + "\nMTU = " + MTU + "\n\n[Peer]\nPublicKey = " + public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + endpoint+ "\nPersistentKeepalive = " + keepalive db.close() sem.release() - return app.response_class(generate(private_key, allowed_ip, DNS, MTU, public_key, endpoint, keepalive), + result = "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \ + dns_addresses + "\nMTU = " + mtu_value + "\n\n[Peer]\nPublicKey = " + \ + public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \ + endpoint + "\nPersistentKeepalive = " + keepalive + + return app.response_class((yield result), mimetype='text/conf', headers={"Content-Disposition": "attachment;filename=" + filename + ".conf"}) else: db.close() return redirect("/configuration/" + config_name) + # Switch peer displate mode @app.route('/switch_display_mode/', methods=['GET']) def switch_display_mode(mode): - if mode in ['list','grid']: + if mode in ['list', 'grid']: config.read(dashboard_conf) config.set("Peers", "peer_display_mode", mode) config.write(open(dashboard_conf, "w")) @@ -1119,6 +1196,8 @@ def switch_display_mode(mode): """ Dashboard Tools Related """ + + # Get all IP for ping @app.route('/get_ping_ip', methods=['POST']) def get_ping_ip(): @@ -1141,6 +1220,7 @@ def get_ping_ip(): sem.release() return html + # Ping IP @app.route('/ping_ip', methods=['POST']) def ping_ip(): @@ -1159,9 +1239,11 @@ def ping_ip(): if returnjson['package_loss'] == 1.0: returnjson['package_loss'] = returnjson['package_sent'] return jsonify(returnjson) - except Exception: + except Exception as exc: + logging.error(exc) return "Error" + # Traceroute IP @app.route('/traceroute_ip', methods=['POST']) def traceroute_ip(): @@ -1176,16 +1258,20 @@ def traceroute_ip(): "max_rtt": hop.max_rtt}) last_distance = hop.distance return jsonify(returnjson) - except Exception: + except Exception as exc: + logging.error(exc) return "Error" + """ Dashboard Initialization """ + + def init_dashboard(): # Set Default INI File if not os.path.isfile("wg-dashboard.ini"): - conf_file = open("wg-dashboard.ini", "w+") + open("wg-dashboard.ini", "w") config = configparser.ConfigParser(strict=False) config.read(dashboard_conf) # Defualt dashboard account setting @@ -1231,17 +1317,20 @@ def init_dashboard(): config.write(open(dashboard_conf, "w")) config.clear() -""" -Dashboard check update -""" + def check_update(): + """ + Dashboard check update + """ + conf = configparser.ConfigParser(strict=False) conf.read(dashboard_conf) data = urllib.request.urlopen("https://api.github.com/repos/donaldzou/WGDashboard/releases").read() output = json.loads(data) release = [] for i in output: - if i["prerelease"] == False: release.append(i) + if not i["prerelease"]: + release.append(i) if conf.get("Server", "version") == release[0]["tag_name"]: return "false" else: @@ -1254,7 +1343,7 @@ if __name__ == "__main__": config = configparser.ConfigParser(strict=False) config.read('wg-dashboard.ini') app_ip = config.get("Server", "app_ip") - app_port = config.get("Server", "app_port") + app_port = int(config.get("Server", "app_port")) wg_conf_path = config.get("Server", "wg_conf_path") config.clear() app.run(host=app_ip, debug=False, port=app_port) @@ -1266,4 +1355,4 @@ else: app_ip = config.get("Server", "app_ip") app_port = config.get("Server", "app_port") wg_conf_path = config.get("Server", "wg_conf_path") - config.clear() \ No newline at end of file + config.clear() From c7bf30e18eaf194caa8adbf99165995fbed38095 Mon Sep 17 00:00:00 2001 From: Galonza Peter Date: Tue, 28 Dec 2021 22:53:51 +0300 Subject: [PATCH 2/2] pylint warnings --- src/dashboard.py | 299 ++++++++++++++++++++++++----------------------- 1 file changed, 155 insertions(+), 144 deletions(-) diff --git a/src/dashboard.py b/src/dashboard.py index 5c85a0a..49eca8d 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -13,9 +13,10 @@ import secrets import subprocess import threading import time +import re import urllib.parse import urllib.request -from datetime import datetime, time, timedelta +from datetime import datetime, timedelta from operator import itemgetter # PIP installed library @@ -26,14 +27,15 @@ from icmplib import ping, traceroute from tinydb import TinyDB, Query # Import other python files -from util import * +from util import regex_match, check_DNS, check_Allowed_IPs, check_remote_endpoint,\ + check_IP_with_range, clean_IP_with_range # Dashboard Version -dashboard_version = 'v3.0' +DASHBOARD_VERSION = 'v3.0' # Dashboard Config Name -dashboard_conf = 'wg-dashboard.ini' +DASHBOARD_CONF = 'wg-dashboard.ini' # Upgrade Required -update = "" +UPDATE = None # Flask App Configuration app = Flask("WGDashboard") app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928 @@ -53,12 +55,12 @@ def get_dashboard_conf(): """ config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) return config def set_dashboard_conf(config): - with open(dashboard_conf, "w") as conf_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as conf_object: config.write(conf_object) @@ -89,10 +91,10 @@ def get_conf_running_peer_number(config_name): data_usage = data_usage.decode("UTF-8").split() count = 0 now = datetime.now() - b = timedelta(minutes=2) - for i in range(int(len(data_usage) / 2)): + time_delta = timedelta(minutes=2) + for _ in range(int(len(data_usage) / 2)): minus = now - datetime.fromtimestamp(int(data_usage[count + 1])) - if minus < b: + if minus < time_delta: running += 1 count += 2 return running @@ -101,14 +103,14 @@ def get_conf_running_peer_number(config_name): # Read [Interface] section from configuration file def read_conf_file_interface(config_name): conf_location = wg_conf_path + "/" + config_name + ".conf" - with open(conf_location, 'r') as file_object: + with open(conf_location, 'r', encoding='utf-8') as file_object: file = file_object.read().split("\n") data = {} - for i in range(len(file)): - if not regex_match("#(.*)", file[i]): - if len(file[i]) > 0: - if file[i] != "[Interface]": - tmp = re.split(r'\s*=\s*', file[i], 1) + for i in file: + if not regex_match("#(.*)", i): + if len(i) > 0: + if i != "[Interface]": + tmp = re.split(r'\s*=\s*', i, 1) if len(tmp) == 2: data[tmp[0]] = tmp[1] return data @@ -118,24 +120,24 @@ def read_conf_file_interface(config_name): def read_conf_file(config_name): # Read Configuration File Start conf_location = wg_conf_path + "/" + config_name + ".conf" - with open(conf_location, 'r') as file_object: + with open(conf_location, 'r', encoding='utf-8') as file_object: file = file_object.read().split("\n") conf_peer_data = { "Interface": {}, "Peers": [] } peers_start = 0 - for i in range(len(file)): - if not regex_match("#(.*)", file[i]): - if file[i] == "[Peer]": + for i in file: + if not regex_match("#(.*)", i): + if i == "[Peer]": peers_start = i break - else: - if len(file[i]) > 0: - if file[i] != "[Interface]": - tmp = re.split(r'\s*=\s*', file[i], 1) - if len(tmp) == 2: - conf_peer_data['Interface'][tmp[0]] = tmp[1] + + if len(i) > 0: + if i != "[Interface]": + tmp = re.split(r'\s*=\s*', i, 1) + if len(tmp) == 2: + conf_peer_data['Interface'][tmp[0]] = tmp[1] conf_peers = file[peers_start:] peer = -1 for i in conf_peers: @@ -145,7 +147,7 @@ def read_conf_file(config_name): conf_peer_data["Peers"].append({}) elif peer > -1: if len(i) > 0: - tmp = re.split('\s*=\s*', i, 1) + tmp = re.split(r'\s*=\s*', i, 1) if len(tmp) == 2: conf_peer_data["Peers"][peer][tmp[0]] = tmp[1] @@ -164,20 +166,22 @@ def get_latest_handshake(config_name, db, peers): data_usage = data_usage.decode("UTF-8").split() count = 0 now = datetime.now() - b = timedelta(minutes=2) - for i in range(int(len(data_usage) / 2)): + time_delta = timedelta(minutes=2) + for _ in range(int(len(data_usage) / 2)): minus = now - datetime.fromtimestamp(int(data_usage[count + 1])) - if minus < b: + if minus < time_delta: status = "running" else: status = "stopped" if int(data_usage[count + 1]) > 0: - db.update({"latest_handshake": str(minus).split(".")[0], "status": status}, + db.update({"latest_handshake": str(minus).split(".", maxsplit=1)[0], "status": status}, peers.id == data_usage[count]) else: db.update({"latest_handshake": "(None)", "status": status}, peers.id == data_usage[count]) count += 2 + return None + # Get transfer from all peers of a configuration def get_transfer(config_name, db, peers): @@ -189,7 +193,7 @@ def get_transfer(config_name, db, peers): return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 - for i in range(int(len(data_usage) / 3)): + for _ in range(int(len(data_usage) / 3)): cur_i = db.search(peers.id == data_usage[count]) total_sent = cur_i[0]['total_sent'] total_receive = cur_i[0]['total_receive'] @@ -215,6 +219,8 @@ def get_transfer(config_name, db, peers): count += 3 + return None + # Get endpoint from all peers of a configuration def get_endpoint(config_name, db, peers): @@ -226,10 +232,12 @@ def get_endpoint(config_name, db, peers): return "stopped" data_usage = data_usage.decode("UTF-8").split() count = 0 - for i in range(int(len(data_usage) / 2)): + for _ in range(int(len(data_usage) / 2)): db.update({"endpoint": data_usage[count + 1]}, peers.id == data_usage[count]) count += 2 + return None + # Get allowed ips from all peers of a configuration def get_allowed_ip(db, peers, conf_peer_data): @@ -377,10 +385,8 @@ def get_conf_total_data(config_name): # Get configuration status def get_conf_status(config_name): ifconfig = dict(ifcfg.interfaces().items()) - if config_name in ifconfig.keys(): - return "running" - else: - return "stopped" + + return "running" if config_name in ifconfig.keys() else "stopped" # Get all configuration as a list @@ -402,9 +408,9 @@ def get_conf_list(): # Generate private key def gen_private_key(): - with open('private_key.txt') as file_object: + with open('private_key.txt', encoding='utf-8') as file_object: private_key = file_object.readline().strip() - with open('public_key.txt') as file_object: + with open('public_key.txt', encoding='utf-8') as file_object: public_key = file_object.readline().strip() data = {"private_key": private_key, "public_key": public_key} os.remove('private_key.txt') @@ -414,10 +420,10 @@ def gen_private_key(): # Generate public key def gen_public_key(private_key): - with open('private_key.txt', 'w') as file_object: + with open('private_key.txt', 'w', encoding='utf-8') as file_object: file_object.write(private_key) try: - with open('public_key.txt') as file_object: + with open('public_key.txt', encoding='utf-8') as file_object: public_key = file_object.readline().strip() os.remove('private_key.txt') os.remove('public_key.txt') @@ -428,28 +434,28 @@ def gen_public_key(private_key): # Check if private key and public key match -def checkKeyMatch(private_key, public_key, config_name): +def f_check_key_match(private_key, public_key, config_name): result = gen_public_key(private_key) if result['status'] == 'failed': return result - else: - sem.acquire() - db = TinyDB('db/' + config_name + '.json') - peers = Query() - match = db.search(peers.id == result['data']) - if len(match) != 1 or result['data'] != public_key: - db.close() - sem.release() - return {'status': 'failed', 'msg': 'Please check your private key, it does not match with the public key.'} - else: - db.close() - sem.release() - return {'status': 'success'} + sem.acquire() + + db = TinyDB('db/' + config_name + '.json') + peers = Query() + match = db.search(peers.id == result['data']) + if len(match) != 1 or result['data'] != public_key: + db.close() + sem.release() + return {'status': 'failed', 'msg': 'Please check your private key, it does not match with the public key.'} + + db.close() + sem.release() + return {'status': 'success'} # Check if there is repeated allowed IP -def check_repeat_allowed_IP(public_key, ip, config_name): +def check_repeat_allowed_ip(public_key, ip, config_name): sem.acquire() db = TinyDB('db/' + config_name + '.json') @@ -457,16 +463,16 @@ def check_repeat_allowed_IP(public_key, ip, config_name): peer = db.search(peers.id == public_key) if len(peer) != 1: return {'status': 'failed', 'msg': 'Peer does not exist'} - else: - existed_ip = db.search((peers.id != public_key) & (peers.allowed_ip == ip)) - if len(existed_ip) != 0: - db.close() - sem.release() - return {'status': 'failed', 'msg': "Allowed IP already taken by another peer."} - else: - db.close() - sem.release() - return {'status': 'success'} + + existed_ip = db.search((peers.id != public_key) & (peers.allowed_ip == ip)) + if len(existed_ip) != 0: + db.close() + sem.release() + return {'status': 'failed', 'msg': "Allowed IP already taken by another peer."} + + db.close() + sem.release() + return {'status': 'success'} """ @@ -478,10 +484,10 @@ Flask Functions @app.before_request def auth_req(): conf = configparser.ConfigParser(strict=False) - conf.read(dashboard_conf) + conf.read(DASHBOARD_CONF) req = conf.get("Server", "auth_req") - session['update'] = update - session['dashboard_version'] = dashboard_version + session['update'] = UPDATE + session['dashboard_version'] = DASHBOARD_VERSION if req == "true": if '/static/' not in request.path and \ request.endpoint != "signin" and \ @@ -499,6 +505,8 @@ def auth_req(): 'update_app_ip_port', 'update_wg_conf_path']: return redirect(url_for("index")) + return None + """ Sign In / Sign Out @@ -528,17 +536,17 @@ def signout(): @app.route('/auth', methods=['POST']) def auth(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) password = hashlib.sha256(request.form['password'].encode()) if password.hexdigest() == config["Account"]["password"] \ and request.form['username'] == config["Account"]["username"]: session['username'] = request.form['username'] config.clear() return redirect(url_for("index")) - else: - session['message'] = "Username or Password is incorrect." - config.clear() - return redirect(url_for("signin")) + + session['message'] = "Username or Password is incorrect." + config.clear() + return redirect(url_for("signin")) @app.route('/', methods=['GET']) @@ -560,7 +568,7 @@ def settings(): message = "" status = "" config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) if "message" in session and "message_status" in session: message = session['message'] status = session['message_status'] @@ -585,10 +593,10 @@ def update_acct(): session['message_status'] = "danger" return redirect(url_for("settings")) config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) config.set("Account", "username", request.form['username']) try: - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() session['message'] = "Username update successfully!" @@ -606,7 +614,7 @@ def update_acct(): @app.route('/update_peer_default_config', methods=['POST']) def update_peer_default_config(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) if len(request.form['peer_endpoint_allowed_ip']) == 0 or \ len(request.form['peer_global_DNS']) == 0 or \ len(request.form['peer_remote_endpoint']) == 0: @@ -653,7 +661,7 @@ def update_peer_default_config(): config.set("Peers", "peer_global_DNS", dns_addresses) try: - with open(dashboard_conf, "w") as conf_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as conf_object: config.write(conf_object) session['message'] = "Peer Default Settings update successfully!" session['message_status'] = "success" @@ -670,13 +678,13 @@ def update_peer_default_config(): @app.route('/update_pwd', methods=['POST']) def update_pwd(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) if hashlib.sha256(request.form['currentpass'].encode()).hexdigest() == config.get("Account", "password"): if hashlib.sha256(request.form['newpass'].encode()).hexdigest() == hashlib.sha256( request.form['repnewpass'].encode()).hexdigest(): config.set("Account", "password", hashlib.sha256(request.form['repnewpass'].encode()).hexdigest()) try: - with open(dashboard_conf, "w") as conf_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as conf_object: config.write(conf_object) session['message'] = "Password update successfully!" session['message_status'] = "success" @@ -703,10 +711,10 @@ def update_pwd(): @app.route('/update_app_ip_port', methods=['POST']) def update_app_ip_port(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) config.set("Server", "app_ip", request.form['app_ip']) config.set("Server", "app_port", request.form['app_port']) - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() os.system('bash wgd.sh restart') @@ -716,9 +724,9 @@ def update_app_ip_port(): @app.route('/update_wg_conf_path', methods=['POST']) def update_wg_conf_path(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) config.set("Server", "wg_conf_path", request.form['wg_conf_path']) - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() session['message'] = "WireGuard Configuration Path Update Successfully!" @@ -734,14 +742,14 @@ def update_dashbaord_sort(): """ config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) data = request.get_json() sort_tag = ['name', 'status', 'allowed_ip'] if data['sort'] in sort_tag: config.set("Server", "dashboard_sort", data['sort']) else: config.set("Server", "dashboard_sort", 'status') - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() return "true" @@ -751,9 +759,9 @@ def update_dashbaord_sort(): @app.route('/update_dashboard_refresh_interval', methods=['POST']) def update_dashboard_refresh_interval(): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) config.set("Server", "dashboard_refresh_interval", str(request.form['interval'])) - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() return "true" @@ -761,9 +769,9 @@ def update_dashboard_refresh_interval(): # Configuration Page @app.route('/configuration/', methods=['GET']) -def conf(config_name): +def configuration(config_name): config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) conf_data = { "name": config_name, "status": get_conf_status(config_name), @@ -774,7 +782,7 @@ def conf(config_name): else: conf_data['checked'] = "checked" config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) config_list = get_conf_list() if config_name not in [conf['conf'] for conf in config_list]: return render_template('index.html', conf=get_conf_list()) @@ -796,10 +804,10 @@ def get_conf(config_name): search = "" search = urllib.parse.unquote(search) config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) sort = config.get("Server", "dashboard_sort") peer_display_mode = config.get("Peers", "peer_display_mode") - if "Address" not in config_interface.keys(): + if "Address" not in config_interface: conf_address = "N/A" else: conf_address = config_interface['Address'] @@ -864,7 +872,7 @@ def add_peer(config_name): db.close() sem.release() return "Please fill in all required box." - if type(keys) != list: + if not isinstance(keys, list): db.close() sem.release() return config_name + " is not running." @@ -922,25 +930,25 @@ def remove_peer(config_name): data = request.get_json() delete_key = data['peer_id'] keys = get_conf_peer_key(config_name) - if type(keys) != list: + if not isinstance(keys, list): return config_name + " is not running." if delete_key not in keys: db.close() return "This key does not exist" - else: - try: - subprocess.run(f"wg set {config_name} peer {delete_key} remove", - check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) - subprocess.run("wg-quick save " + config_name, - check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) - db.remove(peers.id == delete_key) - db.close() - sem.release() - return "true" - except subprocess.CalledProcessError as exc: - db.close() - sem.release() - return exc.output.strip() + + try: + subprocess.run(f"wg set {config_name} peer {delete_key} remove", + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) + subprocess.run("wg-quick save " + config_name, + check=True, shell=True, capture_output=True, stderr=subprocess.STDOUT) + db.remove(peers.id == delete_key) + db.close() + sem.release() + return "true" + except subprocess.CalledProcessError as exc: + db.close() + sem.release() + return exc.output.strip() # Save peer settings @@ -958,7 +966,7 @@ def save_peer_setting(config_name): db = TinyDB('db/' + config_name + '.json') peers = Query() if len(db.search(peers.id == id)) == 1: - check_ip = check_repeat_allowed_IP(id, allowed_ip, config_name) + check_ip = check_repeat_allowed_ip(id, allowed_ip, config_name) if not check_IP_with_range(endpoint_allowed_ip): db.close() sem.release() @@ -976,7 +984,7 @@ def save_peer_setting(config_name): sem.release() return jsonify({"status": "failed", "msg": "Persistent Keepalive format is not correct."}) if private_key != "": - check_key = checkKeyMatch(private_key, id, config_name) + check_key = f_check_key_match(private_key, id, config_name) if check_key['status'] == "failed": db.close() sem.release() @@ -1054,7 +1062,7 @@ def check_key_match(config_name): data = request.get_json() private_key = data['private_key'] public_key = data['public_key'] - return jsonify(checkKeyMatch(private_key, public_key, config_name)) + return jsonify(f_check_key_match(private_key, public_key, config_name)) @app.route("/qrcode/", methods=['GET']) @@ -1145,22 +1153,23 @@ def download(config_name): return app.response_class((yield result), mimetype='text/conf', headers={"Content-Disposition": "attachment;filename=" + filename + ".conf"}) - else: - db.close() - return redirect("/configuration/" + config_name) + + db.close() + return redirect("/configuration/" + config_name) # Switch peer displate mode @app.route('/switch_display_mode/', methods=['GET']) def switch_display_mode(mode): if mode in ['list', 'grid']: - config.read(dashboard_conf) + config = configparser.ConfigParser(strict=False) + config.read(DASHBOARD_CONF) config.set("Peers", "peer_display_mode", mode) - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) return "true" - else: - return "false" + + return "false" """ @@ -1239,9 +1248,9 @@ Dashboard Initialization def init_dashboard(): # Set Default INI File if not os.path.isfile("wg-dashboard.ini"): - open("wg-dashboard.ini", "w") + open("wg-dashboard.ini", "w", encoding='utf-8') config = configparser.ConfigParser(strict=False) - config.read(dashboard_conf) + config.read(DASHBOARD_CONF) # Defualt dashboard account setting if "Account" not in config: config['Account'] = {} @@ -1261,8 +1270,8 @@ def init_dashboard(): config['Server']['app_port'] = '10086' if 'auth_req' not in config['Server']: config['Server']['auth_req'] = 'true' - if 'version' not in config['Server'] or config['Server']['version'] != dashboard_version: - config['Server']['version'] = dashboard_version + if 'version' not in config['Server'] or config['Server']['version'] != DASHBOARD_VERSION: + config['Server']['version'] = DASHBOARD_VERSION if 'dashboard_refresh_interval' not in config['Server']: config['Server']['dashboard_refresh_interval'] = '60000' if 'dashboard_sort' not in config['Server']: @@ -1282,7 +1291,7 @@ def init_dashboard(): config['Peers']['peer_MTU'] = "1420" if 'peer_keep_alive' not in config['Peers']: config['Peers']['peer_keep_alive'] = "21" - with open(dashboard_conf, "w") as config_object: + with open(DASHBOARD_CONF, "w", encoding='utf-8') as config_object: config.write(config_object) config.clear() @@ -1292,36 +1301,38 @@ def check_update(): Dashboard check update """ - conf = configparser.ConfigParser(strict=False) - conf.read(dashboard_conf) + config = configparser.ConfigParser(strict=False) + config.read(DASHBOARD_CONF) data = urllib.request.urlopen("https://api.github.com/repos/donaldzou/WGDashboard/releases").read() output = json.loads(data) release = [] for i in output: if not i["prerelease"]: release.append(i) - if conf.get("Server", "version") == release[0]["tag_name"]: - return "false" + if config.get("Server", "version") == release[0]["tag_name"]: + result = "false" else: - return "true" + result = "true" + + return result if __name__ == "__main__": init_dashboard() - update = check_update() - config = configparser.ConfigParser(strict=False) - config.read('wg-dashboard.ini') - app_ip = config.get("Server", "app_ip") - app_port = int(config.get("Server", "app_port")) - wg_conf_path = config.get("Server", "wg_conf_path") - config.clear() + UPDATE = check_update() + configuration_settings = configparser.ConfigParser(strict=False) + configuration_settings.read('wg-dashboard.ini') + app_ip = configuration_settings.get("Server", "app_ip") + app_port = int(configuration_settings.get("Server", "app_port")) + wg_conf_path = configuration_settings.get("Server", "wg_conf_path") + configuration_settings.clear() app.run(host=app_ip, debug=False, port=app_port) else: init_dashboard() - update = check_update() - config = configparser.ConfigParser(strict=False) - config.read('wg-dashboard.ini') - app_ip = config.get("Server", "app_ip") - app_port = config.get("Server", "app_port") - wg_conf_path = config.get("Server", "wg_conf_path") - config.clear() + UPDATE = check_update() + configuration_settings = configparser.ConfigParser(strict=False) + configuration_settings.read('wg-dashboard.ini') + app_ip = configuration_settings.get("Server", "app_ip") + app_port = configuration_settings.get("Server", "app_port") + wg_conf_path = configuration_settings.get("Server", "wg_conf_path") + configuration_settings.clear()