' +
From b8b721f2bdf633b40e93632febe658a9472648c4 Mon Sep 17 00:00:00 2001
From: Donald Cheng Hong Zou
Date: Sun, 2 Jan 2022 14:45:24 -0500
Subject: [PATCH 16/28] Delete wgdashboard.db
---
src/db/wgdashboard.db | Bin 28672 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 src/db/wgdashboard.db
diff --git a/src/db/wgdashboard.db b/src/db/wgdashboard.db
deleted file mode 100644
index e6936e0cf90b70f4909a344b31fd8b1e34d89a51..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 28672
zcmeI4OONAN6@ZiO>Pk&_r>dc+HEIepk?0mZ3gh_t?Le!>c~xGO_Zy_biEo^TW4mIz
zoJ0u7%%X*a1RI3duwjFQSj=n&BvxpaERa~S7zu$`u;dqj>ouuL9Cfu?no&2`sVL61
zE9czrT;H7IoO8>?Y~O@|t~MTtW`OkE^LV|U_W}WrXY;2XkH_acFSbo*XXE0H^Xk2{
zzh>9@3~cXje&^`s#xFhFU%3lzXSU$x51lt?Lj({3L|`3(4?3H^x9;EfK6}>`+X}R0
z+WGTEOL3tR4^)ImHXd*q0#Euq9#QBgD-N{4-Y=?qmI!KEfsGezZa3_GxY3#KR?%!%)^&X3P^=8vi)gMlhklG(gmP$+xE^y;zNL>^1kNDxwFC|FY!B`CzN
zr87;hD*gS<%aY$cmzGrM5(l2ZkAN8wMGXgtIzI6~Che%Fp7LS-vy9ITjRHR$cL?c4Sd&O>bU=x$dfJ|uBkW%i5d^r_0@P7wpig=v5j
z%z3@Tlboi)cbt-kizI%RRQkDpky#EF3e`%$ie~H?KAn4}jOC(UI!=|3k5o9tKj1Fv=>Sd(Du(^`y
z4{(5SG)9vc3BokV64W|-@GklPx3@gEePNF;eCN|U4|cTePq#Dv-}@iEk=bfrYs90I
z5CKF05kLeGf!CJ6?Je)Ompk|VW5<($yKjHP=kw9KyFus0DP@Jp7bs3@9=&b~Fje!y;g7<-Snwb<|b2a9|l`;ABzAzAEqS{q_ex`|mFvnR_4q
znJr@#E`d%}-dKoJ-K6h;sLqvA
z{}BS;-TTAW-u&ku|N5Q1PrScYu@664DyE$(JuaVVWg*FR3EApa`&o?#*+xfqieACK
zJ!=QmU`*=N1^MZ`d;65rN&V=<-G`wwml)=WVJJxSRMMIbBdJIN-w#QX#%RJrt(@V9
z(iAq>G-p(rg7(x(51N!3$qO^75tN*@C-)TacXW;j
z5F~h_p7_gd&e5p@4P2^*~OGo`Pd1jgUXgn7q4kWp*Wbr&sWaLD83}}_jP+ht-YRaWbA1^*-@_Hzu+53Yo
zQLQp&Lh0fat6|wHAIp=Ks$3ou-QzI}&BkhF@AW&%yZC{3e&an&1zjHH|CjIQ_ZCqc
zy9kp*IsFTGQ-ibJPhF{kcmk7}5#YZpPlP~li=3m3^PR)4MSn9^%0-TH4win_5r7QAf)>I$>hcV98NYNO}gc;!6ky)pa%l#pg|Nn(f
hEl4;bfCwN0hyWsh2p|H803v`0AOeU0BJjBo_#Z}c(*ytj
From 77a82cb84b5377abfa9b7cdbae09452b58669f4c Mon Sep 17 00:00:00 2001
From: Donald Cheng Hong Zou
Date: Tue, 4 Jan 2022 16:32:23 -0500
Subject: [PATCH 17/28] Finished adding available IP and related UI adjustment
---
src/dashboard.py | 73 ++++++++---
src/static/css/dashboard.css | 12 ++
src/static/css/dashboard.min.css | 2 +-
src/static/js/configuration.js | 190 +++++++++++++++++++++++++----
src/static/js/configuration.min.js | 2 +-
src/templates/configuration.html | 48 +++++++-
src/util.py | 1 +
7 files changed, 279 insertions(+), 49 deletions(-)
diff --git a/src/dashboard.py b/src/dashboard.py
index a3d07a3..a7ba139 100644
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -13,20 +13,17 @@ import json
import os
import secrets
import subprocess
-import threading
import time
import re
import urllib.parse
import urllib.request
from datetime import datetime, timedelta
from operator import itemgetter
-import signal
# 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
# Import other python files
from util import regex_match, check_DNS, check_Allowed_IPs, check_remote_endpoint, \
@@ -325,7 +322,7 @@ def get_peers(config_name, search, sort_t):
data = g.cur.execute("SELECT * FROM " + config_name).fetchall()
result = [{col[i]: data[k][i] for i in range(len(col))} for k in range(len(data))]
else:
- sql = "SELECT * FROM " + config_name + " WHERE name LIKE '%"+search+"%'"
+ sql = "SELECT * FROM " + config_name + " WHERE name LIKE '%" + search + "%'"
data = g.cur.execute(sql).fetchall()
result = [{col[i]: data[k][i] for i in range(len(col))} for k in range(len(data))]
if sort_t == "allowed_ip":
@@ -395,8 +392,18 @@ def get_conf_list():
for i in os.listdir(wg_conf_path):
if regex_match("^(.{1,}).(conf)$", i):
i = i.replace('.conf', '')
- g.cur.execute(
- "CREATE TABLE IF NOT EXISTS " + i + " (id VARCHAR NULL, private_key VARCHAR NULL, DNS VARCHAR NULL, endpoint_allowed_ip VARCHAR NULL, name VARCHAR NULL, total_receive FLOAT NULL, total_sent FLOAT NULL, total_data FLOAT NULL, endpoint VARCHAR NULL, status VARCHAR NULL, latest_handshake VARCHAR NULL, allowed_ip VARCHAR NULL, cumu_receive FLOAT NULL, cumu_sent FLOAT NULL, cumu_data FLOAT NULL, mtu INT NULL, keepalive INT NULL, remote_endpoint VARCHAR NULL, preshared_key VARCHAR NULL)")
+ create_table = f"""
+ CREATE TABLE IF NOT EXISTS {i} (
+ id VARCHAR NOT NULL, private_key VARCHAR NULL, DNS VARCHAR NULL,
+ endpoint_allowed_ip VARCHAR NULL, name VARCHAR NULL, total_receive FLOAT NULL,
+ total_sent FLOAT NULL, total_data FLOAT NULL, endpoint VARCHAR NULL,
+ status VARCHAR NULL, latest_handshake VARCHAR NULL, allowed_ip VARCHAR NULL,
+ cumu_receive FLOAT NULL, cumu_sent FLOAT NULL, cumu_data FLOAT NULL, mtu INT NULL,
+ keepalive INT NULL, remote_endpoint VARCHAR NULL, preshared_key VARCHAR NULL,
+ PRIMARY KEY (id)
+ )
+ """
+ g.cur.execute(create_table)
temp = {"conf": i, "status": get_conf_status(i), "public_key": get_conf_pub_key(i)}
if temp['status'] == "running":
temp['checked'] = 'checked'
@@ -412,13 +419,11 @@ def get_conf_list():
def gen_private_key():
gen = subprocess.check_output('wg genkey > private_key.txt && wg pubkey < private_key.txt > public_key.txt',
shell=True)
- gen_psk = subprocess.check_output('wg genpsk', shell=True)
- preshare_key = gen_psk.decode("UTF-8").strip()
with open('private_key.txt', encoding='utf-8') as file_object:
private_key = file_object.readline().strip()
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, "preshared_key": preshare_key}
+ data = {"private_key": private_key, "public_key": public_key}
return data
@@ -867,8 +872,9 @@ def add_peer(config_name):
return config_name + " is not running."
if public_key in keys:
return "Public key already exist."
- check_dup_ip = g.cur.execute("SELECT COUNT(*) FROM " + config_name + " WHERE allowed_ip = ?",
- (allowed_ips,)).fetchone()
+ check_dup_ip = g.cur.execute(
+ "SELECT COUNT(*) FROM " + config_name + " WHERE allowed_ip LIKE '" + allowed_ips + "%'", ) \
+ .fetchone()
if check_dup_ip[0] != 0:
return "Allowed IP already taken by another peer."
if not check_DNS(dns_addresses):
@@ -890,7 +896,6 @@ def add_peer(config_name):
status = subprocess.check_output(f"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)
-
get_all_peers_data(config_name)
sql = "UPDATE " + config_name + " SET name = ?, private_key = ?, DNS = ?, endpoint_allowed_ip = ? WHERE id = ?"
g.cur.execute(sql, (data['name'], data['private_key'], data['DNS'], endpoint_allowed_ip, public_key))
@@ -992,6 +997,35 @@ def get_peer_name(config_name):
return jsonify(data)
+# Return available IPs
+@app.route('/available_ips/', methods=['GET'])
+def available_ips(config_name):
+ config_interface = read_conf_file_interface(config_name)
+ if "Address" in config_interface:
+ existed = []
+ conf_address = config_interface['Address']
+ address = conf_address.split(',')
+ for i in address:
+ add, sub = i.split("/")
+ existed.append(ipaddress.ip_address(add))
+ peers = g.cur.execute("SELECT allowed_ip FROM " + config_name).fetchall()
+ for i in peers:
+ add = i[0].split(",")
+ for k in add:
+ a, s = k.split("/")
+ existed.append(ipaddress.ip_address(a))
+ available = list(ipaddress.ip_network(address[0], False).hosts())
+ for i in existed:
+ try:
+ available.remove(i)
+ except ValueError as e:
+ pass
+ available = [str(i) for i in available]
+ return jsonify(available)
+ else:
+ return jsonify([])
+
+
# Generate a private key
@app.route('/generate_peer', methods=['GET'])
def generate_peer():
@@ -1018,8 +1052,9 @@ def check_key_match(config_name):
@app.route("/qrcode/", methods=['GET'])
def generate_qrcode(config_name):
peer_id = request.args.get('id')
- get_peer = g.cur.execute("SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key FROM "
- + config_name + " WHERE id = ?", (peer_id,)).fetchall()
+ get_peer = g.cur.execute(
+ "SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key FROM "
+ + config_name + " WHERE id = ?", (peer_id,)).fetchall()
config = get_dashboard_conf()
if len(get_peer) == 1:
peer = get_peer[0]
@@ -1041,7 +1076,6 @@ def generate_qrcode(config_name):
+ str(keepalive) + "\nEndpoint = " + endpoint
if preshared_key != "":
result += "\nPresharedKey = " + preshared_key
-
return render_template("qrcode.html", i=result)
else:
return redirect("/configuration/" + config_name)
@@ -1054,7 +1088,7 @@ def download(config_name):
peer_id = request.args.get('id')
get_peer = g.cur.execute(
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key, name FROM "
- + config_name + " WHERE id = ?", (peer_id,)).fetchall()
+ + config_name + " WHERE id = ?", (peer_id,)).fetchall()
config = get_dashboard_conf()
if len(get_peer) == 1:
peer = get_peer[0]
@@ -1090,9 +1124,10 @@ def download(config_name):
def generate():
yield "[Interface]\nPrivateKey = " + private_key + "\nAddress = " + allowed_ip + "\nDNS = " + \
- dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
- public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
- endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
+ dns_addresses + "\nMTU = " + str(mtu_value) + "\n\n[Peer]\nPublicKey = " + \
+ public_key + "\nAllowedIPs = " + endpoint_allowed_ip + "\nEndpoint = " + \
+ endpoint + "\nPersistentKeepalive = " + str(keepalive) + psk
+
return app.response_class(generate(), mimetype='text/conf',
headers={"Content-Disposition": "attachment;filename=" + filename + ".conf"})
return redirect("/configuration/" + config_name)
diff --git a/src/static/css/dashboard.css b/src/static/css/dashboard.css
index e89cf5e..f7f8377 100644
--- a/src/static/css/dashboard.css
+++ b/src/static/css/dashboard.css
@@ -382,3 +382,15 @@ main{
animation: loading 3s infinite ease-in-out;
}
+#qrcode_img img{
+ width: 100%;
+}
+
+#selected_ip_list .badge{
+ margin: 0.1rem
+}
+
+#add_modal.ip_modal_open{
+ transition: filter 0.2s ease-in-out;
+ filter: brightness(0.5);
+}
\ No newline at end of file
diff --git a/src/static/css/dashboard.min.css b/src/static/css/dashboard.min.css
index 8df3ac2..fff2c94 100644
--- a/src/static/css/dashboard.min.css
+++ b/src/static/css/dashboard.min.css
@@ -1 +1 @@
-@-webkit-keyframes rotating{0%{-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotating{0%{-ms-transform:rotate(0deg);-moz-transform:rotate(0deg);-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-ms-transform:rotate(360deg);-moz-transform:rotate(360deg);-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading{0%,to{background-color:#dfdfdf}50%{background-color:#adadad}}@-moz-keyframes loading{0%,to{background-color:#dfdfdf}50%{background-color:#adadad}}body{font-size:.875rem}.feather{width:16px;height:16px;vertical-align:text-bottom}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:48px 0 0;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:calc(100vh - 48px);padding-top:.5rem;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:500;color:#333;transition:.2s cubic-bezier(.82,-.07,0,1.01)}.nav-link:hover{padding-left:30px}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active{color:#007bff}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.navbar-brand{padding-top:.75rem;padding-bottom:.75rem;font-size:1rem;background-color:rgba(0,0,0,.25);box-shadow:inset -1px 0 0 rgba(0,0,0,.25)}.navbar .navbar-toggler{top:.25rem;right:1rem}.navbar .form-control{padding:.75rem 1rem;border-width:0;border-radius:0}.form-control-dark{color:#fff;background-color:rgba(255,255,255,.1);border-color:rgba(255,255,255,.1)}.form-control-dark:focus{border-color:transparent;box-shadow:0 0 0 3px rgba(255,255,255,.25)}.dot{width:10px;height:10px;border-radius:50px;display:inline-block;margin-left:10px}.dot-running{background-color:#28a745!important;box-shadow:0 0 0 .2rem #28a74545}.h6-dot-running{margin-left:.3rem}.dot-stopped{background-color:#6c757d!important}.card-running{border-color:#28a745}.info h6{line-break:anywhere;transition:.2s ease-in-out}.info .row .col-sm{display:flex;flex-direction:column}.info .row .col-sm small{display:flex}.info .row .col-sm small strong:last-child(1){margin-left:auto!important}.btn-control{border:0!important;padding:0 1rem 0 0}.btn-control:active,.btn-control:focus{background-color:transparent!important;border:0!important;box-shadow:none}.share_peer_btn_group .btn-control{padding:0 0 0 1rem}.btn-control:hover{background:#fff}.btn-delete-peer:hover{color:#dc3545}.btn-setting-peer:hover{color:#007bff}.btn-download-peer:hover{color:#17a2b8}.login-container{padding:2rem}@media (max-width:992px){.card-col{margin-bottom:1rem}}.switch{font-size:2rem}.switch:hover{text-decoration:none}.btn-group-label:hover{color:#007bff;border-color:#007bff;background:#fff}@media (max-width:768px){.peer_data_group{text-align:left}}.index-switch{text-align:right}main{margin-bottom:3rem}.peer_list{margin-bottom:7rem}@media (max-width:768px){.add_btn{bottom:1.5rem!important}.peer_list{margin-bottom:4rem!important}}.add_btn{position:fixed;bottom:3rem;right:2rem;z-index:99;border-radius:100px!important;padding:10px 20px;box-shadow:0 10px 20px rgba(0,0,0,.19),0 6px 6px rgba(0,0,0,.23)}.rotating::before{-webkit-animation:rotating .75s linear infinite;-moz-animation:rotating .75s linear infinite;-ms-animation:rotating .75s linear infinite;-o-animation:rotating .75s linear infinite;animation:rotating .75s linear infinite}.peer_private_key_textbox_switch{position:absolute;right:2rem;transform:translateY(-28px);font-size:1.2rem;cursor:pointer}#peer_private_key_textbox,#private_key,#public_key{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.progress-bar{transition:.3s ease-in-out}.key{transition:.2s ease-in-out;cursor:pointer}.key:hover{color:#007bff}.card,.form-control{border-radius:10px}.peer_list .card .button-group{height:22px}.btn{border-radius:8px}.modal-content{border-radius:10px}.tooltip-inner{font-size:.8rem}#conf_status_btn,.conf_card{transition:.2s ease-in-out}.conf_card:hover{border-color:#007bff;cursor:pointer}.info_loading{animation:loading 2s infinite ease-in-out;border-radius:5px;height:19px;transition:.3s ease-in-out}#conf_status_btn.info_loading{height:38px;border-radius:5px;animation:loading 3s infinite ease-in-out}
\ No newline at end of file
+@-webkit-keyframes rotating{0%{-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotating{0%{-ms-transform:rotate(0deg);-moz-transform:rotate(0deg);-webkit-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-ms-transform:rotate(360deg);-moz-transform:rotate(360deg);-webkit-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading{0%,to{background-color:#dfdfdf}50%{background-color:#adadad}}@-moz-keyframes loading{0%,to{background-color:#dfdfdf}50%{background-color:#adadad}}body{font-size:.875rem}.feather{width:16px;height:16px;vertical-align:text-bottom}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:48px 0 0;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:calc(100vh - 48px);padding-top:.5rem;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:500;color:#333;transition:.2s cubic-bezier(.82,-.07,0,1.01)}.nav-link:hover{padding-left:30px}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active{color:#007bff}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.navbar-brand{padding-top:.75rem;padding-bottom:.75rem;font-size:1rem;background-color:rgba(0,0,0,.25);box-shadow:inset -1px 0 0 rgba(0,0,0,.25)}.navbar .navbar-toggler{top:.25rem;right:1rem}.navbar .form-control{padding:.75rem 1rem;border-width:0;border-radius:0}.form-control-dark{color:#fff;background-color:rgba(255,255,255,.1);border-color:rgba(255,255,255,.1)}.form-control-dark:focus{border-color:transparent;box-shadow:0 0 0 3px rgba(255,255,255,.25)}.dot{width:10px;height:10px;border-radius:50px;display:inline-block;margin-left:10px}.dot-running{background-color:#28a745!important;box-shadow:0 0 0 .2rem #28a74545}.h6-dot-running{margin-left:.3rem}.dot-stopped{background-color:#6c757d!important}.card-running{border-color:#28a745}.info h6{line-break:anywhere;transition:.2s ease-in-out}.info .row .col-sm{display:flex;flex-direction:column}.info .row .col-sm small{display:flex}.info .row .col-sm small strong:last-child(1){margin-left:auto!important}.btn-control{border:0!important;padding:0 1rem 0 0}.btn-control:active,.btn-control:focus{background-color:transparent!important;border:0!important;box-shadow:none}.share_peer_btn_group .btn-control{padding:0 0 0 1rem}.btn-control:hover{background:#fff}.btn-delete-peer:hover{color:#dc3545}.btn-setting-peer:hover{color:#007bff}.btn-download-peer:hover{color:#17a2b8}.login-container{padding:2rem}@media (max-width:992px){.card-col{margin-bottom:1rem}}.switch{font-size:2rem}.switch:hover{text-decoration:none}.btn-group-label:hover{color:#007bff;border-color:#007bff;background:#fff}@media (max-width:768px){.peer_data_group{text-align:left}}.index-switch{text-align:right}main{margin-bottom:3rem}.peer_list{margin-bottom:7rem}@media (max-width:768px){.add_btn{bottom:1.5rem!important}.peer_list{margin-bottom:4rem!important}}.add_btn{position:fixed;bottom:3rem;right:2rem;z-index:99;border-radius:100px!important;padding:10px 20px;box-shadow:0 10px 20px rgba(0,0,0,.19),0 6px 6px rgba(0,0,0,.23)}.rotating::before{-webkit-animation:rotating .75s linear infinite;-moz-animation:rotating .75s linear infinite;-ms-animation:rotating .75s linear infinite;-o-animation:rotating .75s linear infinite;animation:rotating .75s linear infinite}.peer_private_key_textbox_switch{position:absolute;right:2rem;transform:translateY(-28px);font-size:1.2rem;cursor:pointer}#peer_private_key_textbox,#private_key,#public_key{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.progress-bar{transition:.3s ease-in-out}.key{transition:.2s ease-in-out;cursor:pointer}.key:hover{color:#007bff}.card,.form-control{border-radius:10px}.peer_list .card .button-group{height:22px}.btn{border-radius:8px}.modal-content{border-radius:10px}.tooltip-inner{font-size:.8rem}#conf_status_btn,.conf_card{transition:.2s ease-in-out}.conf_card:hover{border-color:#007bff;cursor:pointer}.info_loading{animation:loading 2s infinite ease-in-out;border-radius:5px;height:19px;transition:.3s ease-in-out}#conf_status_btn.info_loading{height:38px;border-radius:5px;animation:loading 3s infinite ease-in-out}#qrcode_img img{width:100%}#selected_ip_list .badge{margin:.1rem}#add_modal.ip_modal_open{transition:filter .2s ease-in-out;filter:brightness(.5)}
\ No newline at end of file
diff --git a/src/static/js/configuration.js b/src/static/js/configuration.js
index 7d85ef1..3e02930 100644
--- a/src/static/js/configuration.js
+++ b/src/static/js/configuration.js
@@ -1,12 +1,27 @@
+$("[data-toggle='tooltip']").tooltip()
let $body = $("body");
+let $progress_bar = $(".progress-bar");
+let available_ips = [];
+let $save_peer = $("#save_peer");
+$(".add_btn").on("click", function(){
+ addModal.toggle();
+});
+
+/**
+ * Round Transfer number into 4 digits
+ * @param value
+ * @param digits
+ * @returns {number}
+ */
function roundN(value, digits) {
let tenToN = 10 ** digits;
return (Math.round(value * tenToN)) / tenToN;
}
-// Progress Bar
-let $progress_bar = $(".progress-bar");
+/**
+ * Start Progress Bar
+ */
function startProgressBar(){
$progress_bar.css("width","0%")
.css("opacity", "100")
@@ -19,10 +34,16 @@ function startProgressBar(){
},300);
}
+/**
+ * Still Loading Progress Bar
+ */
function stillLoadingProgressBar(){
$progress_bar.css("transition", "3s ease-in-out").css("width", "75%");
}
+/**
+ * End Progress Bae
+ */
function endProgressBar(){
$progress_bar.css("transition", "0.3s ease-in-out").css("width","100%");
setTimeout(function(){
@@ -31,20 +52,27 @@ function endProgressBar(){
}
+/**
+ * Show toast
+ * @param msg
+ */
function showToast(msg) {
$('#alertToast').toast('show');
$('#alertToast .toast-body').html(msg);
}
-
-// Config Toggle
+/**
+ * When configuration switch got click
+ */
$body.on("click", ".switch", function (){
$(this).siblings($(".spinner-border")).css("display", "inline-block");
$(this).remove();
location.replace("/switch/"+$(this).attr('id'));
});
-// Generating Keys
+/**
+ * Generate Private and Public key for a new peer
+ */
function generate_key(){
$.ajax({
"url": "/generate_peer",
@@ -52,11 +80,14 @@ function generate_key(){
}).done(function(res){
$("#private_key").val(res.private_key);
$("#public_key").val(res.public_key);
- $("#preshare_key").val(res.preshared_key);
$("#add_peer_alert").addClass("d-none");
$("#re_generate_key i").removeClass("rotating");
});
}
+
+/**
+ * Generate public for existing peer
+ */
function generate_public_key(){
$.ajax({
"url": "/generate_public_key",
@@ -70,11 +101,13 @@ function generate_public_key(){
$("#add_peer_alert").addClass("d-none");
}
$("#public_key").val(res.data);
- $("#re_generate_key i").removeClass("rotating");
+ $("#re_generate_key i").removeClass("rotating");
});
}
-// Add Peer
+/**
+ * Generate Public key when private got change
+ */
$("#private_key").on("change",function(){
if ($(this).val().length > 0){
$("#re_generate_key i").addClass("rotating");
@@ -84,33 +117,144 @@ $("#private_key").on("change",function(){
}
});
+/**
+ * Trigger IP badge and item
+ * @param ip
+ */
+function trigger_ip(ip){
+ let $ip_ele = $(".available-ip-item[data-ip='"+ip+"']");
+ if ($ip_ele.html()){
+ if ($ip_ele.hasClass("active")){
+ $ip_ele.removeClass("active");
+ $("#selected_ip_list .badge[data-ip='"+ip+"']").remove();
+ }else{
+ $ip_ele.addClass("active");
+ $("#selected_ip_list").append(''+ip+'')
+ }
+ }
+}
+
+/**
+ * Get all available IP for this configuration
+ */
+function get_available_ip(){
+ $.ajax({
+ "url": "/available_ips/"+$save_peer.attr("conf_id"),
+ "method": "GET",
+ }).done(function (res) {
+ available_ips = res;
+ let $list_group = $("#available_ip_modal .modal-body .list-group");
+ $list_group.html("");
+ $("#allowed_ips").val(available_ips[0]);
+ available_ips.forEach((ip) =>
+ $list_group.append(''+ip+''));
+ });
+}
+
+$("#available_ip_modal").on("show.bs.modal", () => {
+ $('#add_modal').addClass("ip_modal_open");
+}).on("hidden.bs.modal", function () {
+ $('#add_modal').removeClass("ip_modal_open");
+ let ips = [];
+ let $selected_ip_list = $("#selected_ip_list");
+ $selected_ip_list.children().each(function(){
+ ips.push($(this).data("ip"));
+ });
+ ips.forEach((ele) => trigger_ip(ele));
+})
+
+/**
+ * When IP Badge got click
+ */
+$body.on("click", ".available-ip-badge", function(){
+ $(".available-ip-item[data-ip='"+$(this).data("ip")+"']").removeClass("active");
+ $(this).remove();
+})
+
+/**
+ * When available ip item got click
+ */
+$body.on("click", ".available-ip-item", function () {
+ trigger_ip($(this).data("ip"));
+});
+
+let $ipModal = new bootstrap.Modal(document.getElementById('available_ip_modal'), {
+ keyboard: false
+});
+
+$("#search_available_ip").on("click", function () {
+ $ipModal.toggle();
+ let $allowed_ips = $("#allowed_ips");
+ if ($allowed_ips.val().length > 0){
+ let s = $allowed_ips.val().split(",");
+ for (let i = 0; i < s.length; i++){
+ s[i] = s[i].trim();
+ trigger_ip(s[i]);
+ }
+ }
+}).tooltip();
+
+$("#confirm_ip").on("click", () => {
+ $ipModal.toggle();
+ let ips = [];
+ let $selected_ip_list = $("#selected_ip_list");
+ $selected_ip_list.children().each(function(){
+ ips.push($(this).data("ip"));
+ });
+ $("#allowed_ips").val(ips.join(", "));
+ ips.forEach((ele) => trigger_ip(ele));
+});
+
+$("#allowed_ips").on("keyup", function(){
+ let s = clean_ip($(this).val());
+ s = s.split(",");
+ if (available_ips.includes(s[s.length - 1])){
+ $("#allowed_ips_indicator").removeClass().addClass("text-success")
+ .html('');
+ }else{
+ $("#allowed_ips_indicator").removeClass().addClass("text-warning")
+ .html('');
+ }
+})
+
+
$('#add_modal').on('show.bs.modal', function (event) {
generate_key();
+ get_available_ip();
+}).on('hide.bs.modal', function(){
+ $("#allowed_ips_indicator").html('');
});
+
$("#re_generate_key").on("click",function (){
$("#public_key").attr("disabled","disabled");
$("#re_generate_key i").addClass("rotating");
generate_key();
});
+
let addModal = new bootstrap.Modal(document.getElementById('add_modal'), {
keyboard: false
});
-$(".add_btn").on("click", function(){
- addModal.toggle();
-});
+function clean_ip(val){
+ let clean_ip = val.split(',');
+ for (let i = 0; i < clean_ip.length; i++) clean_ip[i] = clean_ip[i].trim(' ');
+ return clean_ip.filter(Boolean).join(",");
+}
-$("#save_peer").on("click",function(){
+$save_peer.on("click",function(){
let $public_key = $("#public_key");
let $private_key = $("#private_key");
let $allowed_ips = $("#allowed_ips");
+ $allowed_ips.val(clean_ip($allowed_ips.val()));
let $new_add_DNS = $("#new_add_DNS");
+ $new_add_DNS.val(clean_ip($new_add_DNS.val()));
let $new_add_endpoint_allowed_ip = $("#new_add_endpoint_allowed_ip");
+ $new_add_endpoint_allowed_ip.val(clean_ip($new_add_endpoint_allowed_ip.val()));
let $new_add_name = $("#new_add_name");
let $new_add_MTU = $("#new_add_MTU");
let $new_add_keep_alive = $("#new_add_keep_alive");
let $enable_preshare_key = $("#enable_preshare_key");
-
+ let p_key = $public_key.val()
$(this).attr("disabled","disabled");
$(this).html("Saving...");
if ($allowed_ips.val() !== "" && $public_key.val() !== "" && $new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
@@ -138,10 +282,14 @@ $("#save_peer").on("click",function(){
if(response !== "true"){
$("#add_peer_alert").html(response).removeClass("d-none");
data_list.forEach((ele) => ele.removeAttr("disabled"));
- $("#save_peer").removeAttr("disabled").html("Save");
+ $save_peer.removeAttr("disabled").html("Save");
}
else{
load_data("");
+ data_list.forEach((ele) => ele.removeAttr("disabled"));
+ $("#add_peer_form").trigger("reset");
+ $save_peer.removeAttr("disabled").html("Save");
+ showToast("Add peer successful!");
addModal.toggle();
}
}
@@ -159,6 +307,8 @@ let qrcodeModal = new bootstrap.Modal(document.getElementById('qrcode_modal'), {
});
// QR Code
$body.on("click", ".btn-qrcode-peer", function (){
+
+
let src = $(this).attr('img_src');
$.ajax({
"url": src,
@@ -326,7 +476,6 @@ $(".peer_private_key_textbox_switch").on("click",function (){
$(".peer_private_key_textbox_switch i").removeClass().addClass(icon);
});
-
// Search Peer
let typingTimer;
let doneTypingInterval = 200;
@@ -335,14 +484,15 @@ $input.on('keyup', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
+
$input.on('keydown', function () {
clearTimeout(typingTimer);
});
+
function doneTyping () {
load_data($input.val());
}
-
// Sorting
$body.on("change", "#sort_by_dropdown", function (){
$.ajax({
@@ -360,16 +510,13 @@ $body.on("change", "#sort_by_dropdown", function (){
$body.on("mouseenter", ".key", function(){
let label = $(this).parent().siblings().children()[1];
label.style.opacity = "100";
-})
-$body.on("mouseout", ".key", function(){
+}).on("mouseout", ".key", function(){
let label = $(this).parent().siblings().children()[1];
label.style.opacity = "0";
setTimeout(function (){
label.innerHTML = "CLICK TO COPY";
},200);
-});
-
-$body.on("click", ".key", function(){
+}).on("click", ".key", function(){
var label = $(this).parent().siblings().children()[1];
copyToClipboard($(this));
label.innerHTML = "COPIED!";
@@ -420,7 +567,6 @@ $body.on("click", ".refresh", function (){
load_data($('#search_peer_textbox').val());
});
-
// Switch display mode
$body.on("click", ".display_mode", function(){
$(".display-btn-group button").removeClass("active");
diff --git a/src/static/js/configuration.min.js b/src/static/js/configuration.min.js
index 2d4032c..cf30794 100644
--- a/src/static/js/configuration.min.js
+++ b/src/static/js/configuration.min.js
@@ -1 +1 @@
-let $body=$("body");function roundN(value,digits){let tenToN=10**digits;return Math.round(value*tenToN)/tenToN}let $progress_bar=$(".progress-bar");function startProgressBar(){$progress_bar.css("width","0%").css("opacity","100").css("background","rgb(255,69,69)").css("background","linear-gradient(145deg, rgba(255,69,69,1) 0%, rgba(0,115,186,1) 100%)").css("width","25%");setTimeout(function(){stillLoadingProgressBar()},300)}function stillLoadingProgressBar(){$progress_bar.css("transition","3s ease-in-out").css("width","75%")}function endProgressBar(){$progress_bar.css("transition","0.3s ease-in-out").css("width","100%");setTimeout(function(){$progress_bar.css("opacity","0")},250)}function showToast(msg){$("#alertToast").toast("show");$("#alertToast .toast-body").html(msg)}$body.on("click",".switch",function(){$(this).siblings($(".spinner-border")).css("display","inline-block");$(this).remove();location.replace("/switch/"+$(this).attr("id"))});function generate_key(){$.ajax({url:"/generate_peer",method:"GET"}).done(function(res){$("#private_key").val(res.private_key);$("#public_key").val(res.public_key);$("#preshare_key").val(res.preshared_key);$("#add_peer_alert").addClass("d-none");$("#re_generate_key i").removeClass("rotating")})}function generate_public_key(){$.ajax({url:"/generate_public_key",method:"POST",headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$("#private_key").val()})}).done(function(res){if(res.status==="failed"){$("#add_peer_alert").html(res.msg).removeClass("d-none")}else{$("#add_peer_alert").addClass("d-none")}$("#public_key").val(res.data);$("#re_generate_key i").removeClass("rotating")})}$("#private_key").on("change",function(){if($(this).val().length>0){$("#re_generate_key i").addClass("rotating");generate_public_key()}else{$("#public_key").removeAttr("disabled").val("")}});$("#add_modal").on("show.bs.modal",function(event){generate_key()});$("#re_generate_key").on("click",function(){$("#public_key").attr("disabled","disabled");$("#re_generate_key i").addClass("rotating");generate_key()});let addModal=new bootstrap.Modal(document.getElementById("add_modal"),{keyboard:false});$(".add_btn").on("click",function(){addModal.toggle()});$("#save_peer").on("click",function(){let $public_key=$("#public_key");let $private_key=$("#private_key");let $allowed_ips=$("#allowed_ips");let $new_add_DNS=$("#new_add_DNS");let $new_add_endpoint_allowed_ip=$("#new_add_endpoint_allowed_ip");let $new_add_name=$("#new_add_name");let $new_add_MTU=$("#new_add_MTU");let $new_add_keep_alive=$("#new_add_keep_alive");let $enable_preshare_key=$("#enable_preshare_key");$(this).attr("disabled","disabled");$(this).html("Saving...");if($allowed_ips.val()!==""&&$public_key.val()!==""&&$new_add_DNS.val()!==""&&$new_add_endpoint_allowed_ip.val()!==""){let conf=$(this).attr("conf_id");let data_list=[$private_key,$allowed_ips,$new_add_name,$new_add_DNS,$new_add_endpoint_allowed_ip,$new_add_MTU,$new_add_keep_alive];data_list.forEach(ele=>ele.attr("disabled","disabled"));$.ajax({method:"POST",url:"/add_peer/"+conf,headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$private_key.val(),public_key:$public_key.val(),allowed_ips:$allowed_ips.val(),name:$new_add_name.val(),DNS:$new_add_DNS.val(),endpoint_allowed_ip:$new_add_endpoint_allowed_ip.val(),MTU:$new_add_MTU.val(),keep_alive:$new_add_keep_alive.val(),enable_preshared_key:$enable_preshare_key.prop("checked")}),success:function(response){if(response!=="true"){$("#add_peer_alert").html(response).removeClass("d-none");data_list.forEach(ele=>ele.removeAttr("disabled"));$("#save_peer").removeAttr("disabled").html("Save")}else{load_data("");addModal.toggle()}}})}else{$("#add_peer_alert").html("Please fill in all required box.").removeClass("d-none");$(this).removeAttr("disabled");$(this).html("Save")}});let qrcodeModal=new bootstrap.Modal(document.getElementById("qrcode_modal"),{keyboard:false});$body.on("click",".btn-qrcode-peer",function(){let src=$(this).attr("img_src");$.ajax({url:src,method:"GET"}).done(function(res){$("#qrcode_img").attr("src",res);qrcodeModal.toggle()})});let deleteModal=new bootstrap.Modal(document.getElementById("delete_modal"),{keyboard:false});$body.on("click",".btn-delete-peer",function(){let peer_id=$(this).attr("id");$("#delete_peer").attr("peer_id",peer_id);deleteModal.toggle()});$("#delete_peer").on("click",function(){$(this).attr("disabled","disabled");$(this).html("Deleting...");let peer_id=$(this).attr("peer_id");let config=$(this).attr("conf_id");$.ajax({method:"POST",url:"/remove_peer/"+config,headers:{"Content-Type":"application/json"},data:JSON.stringify({action:"delete",peer_id:peer_id}),success:function(response){if(response!=="true"){$("#remove_peer_alert").html(response+$("#add_peer_alert").html()).removeClass("d-none")}else{deleteModal.toggle();load_data($("#search_peer_textbox").val());$("#alertToast").toast("show");$("#alertToast .toast-body").html("Peer deleted!");$("#delete_peer").removeAttr("disabled").html("Delete")}}})});let settingModal=new bootstrap.Modal(document.getElementById("setting_modal"),{keyboard:false});$body.on("click",".btn-setting-peer",function(){startProgressBar();let peer_id=$(this).attr("id");$("#save_peer_setting").attr("peer_id",peer_id);$.ajax({method:"POST",url:"/get_peer_data/"+$("#setting_modal").attr("conf_id"),headers:{"Content-Type":"application/json"},data:JSON.stringify({id:peer_id}),success:function(response){let peer_name=response.name===""?"Untitled Peer":response.name;$("#setting_modal .peer_name").html(peer_name);$("#setting_modal #peer_name_textbox").val(response.name);$("#setting_modal #peer_private_key_textbox").val(response.private_key);$("#setting_modal #peer_DNS_textbox").val(response.DNS);$("#setting_modal #peer_allowed_ip_textbox").val(response.allowed_ip);$("#setting_modal #peer_endpoint_allowed_ips").val(response.endpoint_allowed_ip);$("#setting_modal #peer_mtu").val(response.mtu);$("#setting_modal #peer_keep_alive").val(response.keep_alive);$("#setting_modal #peer_preshared_key_textbox").val(response.preshared_key);settingModal.toggle();endProgressBar()}})});$("#setting_modal").on("hidden.bs.modal",function(event){$("#setting_peer_alert").addClass("d-none")});$("#peer_private_key_textbox").on("change",function(){let $save_peer_setting=$("#save_peer_setting");if($(this).val().length>0){$.ajax({url:"/check_key_match/"+$save_peer_setting.attr("conf_id"),method:"POST",headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$("#peer_private_key_textbox").val(),public_key:$save_peer_setting.attr("peer_id")})}).done(function(res){if(res.status==="failed"){$("#setting_peer_alert").html(res.status).removeClass("d-none")}else{$("#setting_peer_alert").addClass("d-none")}})}});$("#save_peer_setting").on("click",function(){$(this).attr("disabled","disabled");$(this).html("Saving...");let $peer_DNS_textbox=$("#peer_DNS_textbox");let $peer_allowed_ip_textbox=$("#peer_allowed_ip_textbox");let $peer_endpoint_allowed_ips=$("#peer_endpoint_allowed_ips");let $peer_name_textbox=$("#peer_name_textbox");let $peer_private_key_textbox=$("#peer_private_key_textbox");let $peer_preshared_key_textbox=$("#peer_preshared_key_textbox");let $peer_mtu=$("#peer_mtu");let $peer_keep_alive=$("#peer_keep_alive");if($peer_DNS_textbox.val()!==""&&$peer_allowed_ip_textbox.val()!==""&&$peer_endpoint_allowed_ips.val()!==""){let peer_id=$(this).attr("peer_id");let conf_id=$(this).attr("conf_id");let data_list=[$peer_name_textbox,$peer_DNS_textbox,$peer_private_key_textbox,$peer_preshared_key_textbox,$peer_allowed_ip_textbox,$peer_endpoint_allowed_ips,$peer_mtu,$peer_keep_alive];data_list.forEach(ele=>ele.attr("disabled","disabled"));$.ajax({method:"POST",url:"/save_peer_setting/"+conf_id,headers:{"Content-Type":"application/json"},data:JSON.stringify({id:peer_id,name:$peer_name_textbox.val(),DNS:$peer_DNS_textbox.val(),private_key:$peer_private_key_textbox.val(),allowed_ip:$peer_allowed_ip_textbox.val(),endpoint_allowed_ip:$peer_endpoint_allowed_ips.val(),MTU:$peer_mtu.val(),keep_alive:$peer_keep_alive.val(),preshared_key:$peer_preshared_key_textbox.val()}),success:function(response){if(response.status==="failed"){$("#setting_peer_alert").html(response.msg).removeClass("d-none")}else{settingModal.toggle();load_data($("#search_peer_textbox").val());$("#alertToast").toast("show");$("#alertToast .toast-body").html("Peer Saved!")}$("#save_peer_setting").removeAttr("disabled").html("Save");data_list.forEach(ele=>ele.removeAttr("disabled"))}})}else{$("#setting_peer_alert").html("Please fill in all required box.").removeClass("d-none");$("#save_peer_setting").removeAttr("disabled").html("Save")}});$(".peer_private_key_textbox_switch").on("click",function(){let $peer_private_key_textbox=$("#peer_private_key_textbox");let mode=$peer_private_key_textbox.attr("type")==="password"?"text":"password";let icon=$peer_private_key_textbox.attr("type")==="password"?"bi bi-eye-slash-fill":"bi bi-eye-fill";$peer_private_key_textbox.attr("type",mode);$(".peer_private_key_textbox_switch i").removeClass().addClass(icon)});let typingTimer;let doneTypingInterval=200;let $input=$("#search_peer_textbox");$input.on("keyup",function(){clearTimeout(typingTimer);typingTimer=setTimeout(doneTyping,doneTypingInterval)});$input.on("keydown",function(){clearTimeout(typingTimer)});function doneTyping(){load_data($input.val())}$body.on("change","#sort_by_dropdown",function(){$.ajax({method:"POST",data:JSON.stringify({sort:$("#sort_by_dropdown option:selected").val()}),headers:{"Content-Type":"application/json"},url:"/update_dashboard_sort",success:function(res){load_data($("#search_peer_textbox").val())}})});$body.on("mouseenter",".key",function(){let label=$(this).parent().siblings().children()[1];label.style.opacity="100"});$body.on("mouseout",".key",function(){let label=$(this).parent().siblings().children()[1];label.style.opacity="0";setTimeout(function(){label.innerHTML="CLICK TO COPY"},200)});$body.on("click",".key",function(){var label=$(this).parent().siblings().children()[1];copyToClipboard($(this));label.innerHTML="COPIED!"});function copyToClipboard(element){let $temp=$("");$body.append($temp);$temp.val($(element).text()).trigger("select");document.execCommand("copy");$temp.remove()}$body.on("click",".update_interval",function(){let prev=$(".interval-btn-group.active button");$(".interval-btn-group button").removeClass("active");let _new=$(this);_new.addClass("active");let interval=$(this).data("refresh-interval");$.ajax({method:"POST",data:"interval="+$(this).data("refresh-interval"),url:"/update_dashboard_refresh_interval",success:function(res){if(res==="true"){load_interval=interval;clearInterval(load_timeout);load_timeout=setInterval(function(){load_data($("#search_peer_textbox").val())},interval);showToast("Refresh Interval set to "+Math.round(interval/1e3)+" seconds")}else{$(".interval-btn-group button").removeClass("active");$('.interval-btn-group button[data-refresh-interval="'+load_interval+'"]').addClass("active");showToast("Refresh Interval set unsuccessful")}}})});$body.on("click",".refresh",function(){load_data($("#search_peer_textbox").val())});$body.on("click",".display_mode",function(){$(".display-btn-group button").removeClass("active");$(this).addClass("active");let display_mode=$(this).data("display-mode");$.ajax({method:"GET",url:"/switch_display_mode/"+$(this).data("display-mode"),success:function(res){if(res==="true"){if(display_mode==="list"){Array($(".peer_list").children()).forEach(function(child){$(child).removeClass().addClass("col-12")});showToast("Displaying as List")}else{Array($(".peer_list").children()).forEach(function(child){$(child).removeClass().addClass("col-sm-6 col-lg-4")});showToast("Displaying as Grids")}}}})});
\ No newline at end of file
+$("[data-toggle='tooltip']").tooltip();let $body=$("body");let $progress_bar=$(".progress-bar");let available_ips=[];let $save_peer=$("#save_peer");$(".add_btn").on("click",function(){addModal.toggle()});function roundN(value,digits){let tenToN=10**digits;return Math.round(value*tenToN)/tenToN}function startProgressBar(){$progress_bar.css("width","0%").css("opacity","100").css("background","rgb(255,69,69)").css("background","linear-gradient(145deg, rgba(255,69,69,1) 0%, rgba(0,115,186,1) 100%)").css("width","25%");setTimeout(function(){stillLoadingProgressBar()},300)}function stillLoadingProgressBar(){$progress_bar.css("transition","3s ease-in-out").css("width","75%")}function endProgressBar(){$progress_bar.css("transition","0.3s ease-in-out").css("width","100%");setTimeout(function(){$progress_bar.css("opacity","0")},250)}function showToast(msg){$("#alertToast").toast("show");$("#alertToast .toast-body").html(msg)}$body.on("click",".switch",function(){$(this).siblings($(".spinner-border")).css("display","inline-block");$(this).remove();location.replace("/switch/"+$(this).attr("id"))});function generate_key(){$.ajax({url:"/generate_peer",method:"GET"}).done(function(res){$("#private_key").val(res.private_key);$("#public_key").val(res.public_key);$("#add_peer_alert").addClass("d-none");$("#re_generate_key i").removeClass("rotating")})}function generate_public_key(){$.ajax({url:"/generate_public_key",method:"POST",headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$("#private_key").val()})}).done(function(res){if(res.status==="failed"){$("#add_peer_alert").html(res.msg).removeClass("d-none")}else{$("#add_peer_alert").addClass("d-none")}$("#public_key").val(res.data);$("#re_generate_key i").removeClass("rotating")})}$("#private_key").on("change",function(){if($(this).val().length>0){$("#re_generate_key i").addClass("rotating");generate_public_key()}else{$("#public_key").removeAttr("disabled").val("")}});function trigger_ip(ip){let $ip_ele=$(".available-ip-item[data-ip='"+ip+"']");if($ip_ele.html()){if($ip_ele.hasClass("active")){$ip_ele.removeClass("active");$("#selected_ip_list .badge[data-ip='"+ip+"']").remove()}else{$ip_ele.addClass("active");$("#selected_ip_list").append(''+ip+"")}}}function get_available_ip(){$.ajax({url:"/available_ips/"+$save_peer.attr("conf_id"),method:"GET"}).done(function(res){available_ips=res;let $list_group=$("#available_ip_modal .modal-body .list-group");$list_group.html("");$("#allowed_ips").val(available_ips[0]);available_ips.forEach(ip=>$list_group.append(''+ip+""))})}$("#available_ip_modal").on("show.bs.modal",()=>{$("#add_modal").addClass("ip_modal_open")}).on("hidden.bs.modal",function(){$("#add_modal").removeClass("ip_modal_open");let ips=[];let $selected_ip_list=$("#selected_ip_list");$selected_ip_list.children().each(function(){ips.push($(this).data("ip"))});ips.forEach(ele=>trigger_ip(ele))});$body.on("click",".available-ip-badge",function(){$(".available-ip-item[data-ip='"+$(this).data("ip")+"']").removeClass("active");$(this).remove()});$body.on("click",".available-ip-item",function(){trigger_ip($(this).data("ip"))});let $ipModal=new bootstrap.Modal(document.getElementById("available_ip_modal"),{keyboard:false});$("#search_available_ip").on("click",function(){$ipModal.toggle();let $allowed_ips=$("#allowed_ips");if($allowed_ips.val().length>0){let s=$allowed_ips.val().split(",");for(let i=0;i{$ipModal.toggle();let ips=[];let $selected_ip_list=$("#selected_ip_list");$selected_ip_list.children().each(function(){ips.push($(this).data("ip"))});$("#allowed_ips").val(ips.join(", "));ips.forEach(ele=>trigger_ip(ele))});$("#allowed_ips").on("keyup",function(){let s=clean_ip($(this).val());s=s.split(",");if(available_ips.includes(s[s.length-1])){$("#allowed_ips_indicator").removeClass().addClass("text-success").html('')}else{$("#allowed_ips_indicator").removeClass().addClass("text-warning").html('')}});$("#add_modal").on("show.bs.modal",function(event){generate_key();get_available_ip()}).on("hide.bs.modal",function(){$("#allowed_ips_indicator").html("")});$("#re_generate_key").on("click",function(){$("#public_key").attr("disabled","disabled");$("#re_generate_key i").addClass("rotating");generate_key()});let addModal=new bootstrap.Modal(document.getElementById("add_modal"),{keyboard:false});function clean_ip(val){let clean_ip=val.split(",");for(let i=0;iele.attr("disabled","disabled"));$.ajax({method:"POST",url:"/add_peer/"+conf,headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$private_key.val(),public_key:$public_key.val(),allowed_ips:$allowed_ips.val(),name:$new_add_name.val(),DNS:$new_add_DNS.val(),endpoint_allowed_ip:$new_add_endpoint_allowed_ip.val(),MTU:$new_add_MTU.val(),keep_alive:$new_add_keep_alive.val(),enable_preshared_key:$enable_preshare_key.prop("checked")}),success:function(response){if(response!=="true"){$("#add_peer_alert").html(response).removeClass("d-none");data_list.forEach(ele=>ele.removeAttr("disabled"));$save_peer.removeAttr("disabled").html("Save")}else{load_data("");data_list.forEach(ele=>ele.removeAttr("disabled"));$("#add_peer_form").trigger("reset");$save_peer.removeAttr("disabled").html("Save");showToast("Add peer successful!");addModal.toggle()}}})}else{$("#add_peer_alert").html("Please fill in all required box.").removeClass("d-none");$(this).removeAttr("disabled");$(this).html("Save")}});let qrcodeModal=new bootstrap.Modal(document.getElementById("qrcode_modal"),{keyboard:false});$body.on("click",".btn-qrcode-peer",function(){let src=$(this).attr("img_src");$.ajax({url:src,method:"GET"}).done(function(res){$("#qrcode_img").attr("src",res);qrcodeModal.toggle()})});let deleteModal=new bootstrap.Modal(document.getElementById("delete_modal"),{keyboard:false});$body.on("click",".btn-delete-peer",function(){let peer_id=$(this).attr("id");$("#delete_peer").attr("peer_id",peer_id);deleteModal.toggle()});$("#delete_peer").on("click",function(){$(this).attr("disabled","disabled");$(this).html("Deleting...");let peer_id=$(this).attr("peer_id");let config=$(this).attr("conf_id");$.ajax({method:"POST",url:"/remove_peer/"+config,headers:{"Content-Type":"application/json"},data:JSON.stringify({action:"delete",peer_id:peer_id}),success:function(response){if(response!=="true"){$("#remove_peer_alert").html(response+$("#add_peer_alert").html()).removeClass("d-none")}else{deleteModal.toggle();load_data($("#search_peer_textbox").val());$("#alertToast").toast("show");$("#alertToast .toast-body").html("Peer deleted!");$("#delete_peer").removeAttr("disabled").html("Delete")}}})});let settingModal=new bootstrap.Modal(document.getElementById("setting_modal"),{keyboard:false});$body.on("click",".btn-setting-peer",function(){startProgressBar();let peer_id=$(this).attr("id");$("#save_peer_setting").attr("peer_id",peer_id);$.ajax({method:"POST",url:"/get_peer_data/"+$("#setting_modal").attr("conf_id"),headers:{"Content-Type":"application/json"},data:JSON.stringify({id:peer_id}),success:function(response){let peer_name=response.name===""?"Untitled Peer":response.name;$("#setting_modal .peer_name").html(peer_name);$("#setting_modal #peer_name_textbox").val(response.name);$("#setting_modal #peer_private_key_textbox").val(response.private_key);$("#setting_modal #peer_DNS_textbox").val(response.DNS);$("#setting_modal #peer_allowed_ip_textbox").val(response.allowed_ip);$("#setting_modal #peer_endpoint_allowed_ips").val(response.endpoint_allowed_ip);$("#setting_modal #peer_mtu").val(response.mtu);$("#setting_modal #peer_keep_alive").val(response.keep_alive);$("#setting_modal #peer_preshared_key_textbox").val(response.preshared_key);settingModal.toggle();endProgressBar()}})});$("#setting_modal").on("hidden.bs.modal",function(event){$("#setting_peer_alert").addClass("d-none")});$("#peer_private_key_textbox").on("change",function(){let $save_peer_setting=$("#save_peer_setting");if($(this).val().length>0){$.ajax({url:"/check_key_match/"+$save_peer_setting.attr("conf_id"),method:"POST",headers:{"Content-Type":"application/json"},data:JSON.stringify({private_key:$("#peer_private_key_textbox").val(),public_key:$save_peer_setting.attr("peer_id")})}).done(function(res){if(res.status==="failed"){$("#setting_peer_alert").html(res.status).removeClass("d-none")}else{$("#setting_peer_alert").addClass("d-none")}})}});$("#save_peer_setting").on("click",function(){$(this).attr("disabled","disabled");$(this).html("Saving...");let $peer_DNS_textbox=$("#peer_DNS_textbox");let $peer_allowed_ip_textbox=$("#peer_allowed_ip_textbox");let $peer_endpoint_allowed_ips=$("#peer_endpoint_allowed_ips");let $peer_name_textbox=$("#peer_name_textbox");let $peer_private_key_textbox=$("#peer_private_key_textbox");let $peer_preshared_key_textbox=$("#peer_preshared_key_textbox");let $peer_mtu=$("#peer_mtu");let $peer_keep_alive=$("#peer_keep_alive");if($peer_DNS_textbox.val()!==""&&$peer_allowed_ip_textbox.val()!==""&&$peer_endpoint_allowed_ips.val()!==""){let peer_id=$(this).attr("peer_id");let conf_id=$(this).attr("conf_id");let data_list=[$peer_name_textbox,$peer_DNS_textbox,$peer_private_key_textbox,$peer_preshared_key_textbox,$peer_allowed_ip_textbox,$peer_endpoint_allowed_ips,$peer_mtu,$peer_keep_alive];data_list.forEach(ele=>ele.attr("disabled","disabled"));$.ajax({method:"POST",url:"/save_peer_setting/"+conf_id,headers:{"Content-Type":"application/json"},data:JSON.stringify({id:peer_id,name:$peer_name_textbox.val(),DNS:$peer_DNS_textbox.val(),private_key:$peer_private_key_textbox.val(),allowed_ip:$peer_allowed_ip_textbox.val(),endpoint_allowed_ip:$peer_endpoint_allowed_ips.val(),MTU:$peer_mtu.val(),keep_alive:$peer_keep_alive.val(),preshared_key:$peer_preshared_key_textbox.val()}),success:function(response){if(response.status==="failed"){$("#setting_peer_alert").html(response.msg).removeClass("d-none")}else{settingModal.toggle();load_data($("#search_peer_textbox").val());$("#alertToast").toast("show");$("#alertToast .toast-body").html("Peer Saved!")}$("#save_peer_setting").removeAttr("disabled").html("Save");data_list.forEach(ele=>ele.removeAttr("disabled"))}})}else{$("#setting_peer_alert").html("Please fill in all required box.").removeClass("d-none");$("#save_peer_setting").removeAttr("disabled").html("Save")}});$(".peer_private_key_textbox_switch").on("click",function(){let $peer_private_key_textbox=$("#peer_private_key_textbox");let mode=$peer_private_key_textbox.attr("type")==="password"?"text":"password";let icon=$peer_private_key_textbox.attr("type")==="password"?"bi bi-eye-slash-fill":"bi bi-eye-fill";$peer_private_key_textbox.attr("type",mode);$(".peer_private_key_textbox_switch i").removeClass().addClass(icon)});let typingTimer;let doneTypingInterval=200;let $input=$("#search_peer_textbox");$input.on("keyup",function(){clearTimeout(typingTimer);typingTimer=setTimeout(doneTyping,doneTypingInterval)});$input.on("keydown",function(){clearTimeout(typingTimer)});function doneTyping(){load_data($input.val())}$body.on("change","#sort_by_dropdown",function(){$.ajax({method:"POST",data:JSON.stringify({sort:$("#sort_by_dropdown option:selected").val()}),headers:{"Content-Type":"application/json"},url:"/update_dashboard_sort",success:function(res){load_data($("#search_peer_textbox").val())}})});$body.on("mouseenter",".key",function(){let label=$(this).parent().siblings().children()[1];label.style.opacity="100"}).on("mouseout",".key",function(){let label=$(this).parent().siblings().children()[1];label.style.opacity="0";setTimeout(function(){label.innerHTML="CLICK TO COPY"},200)}).on("click",".key",function(){var label=$(this).parent().siblings().children()[1];copyToClipboard($(this));label.innerHTML="COPIED!"});function copyToClipboard(element){let $temp=$("");$body.append($temp);$temp.val($(element).text()).trigger("select");document.execCommand("copy");$temp.remove()}$body.on("click",".update_interval",function(){let prev=$(".interval-btn-group.active button");$(".interval-btn-group button").removeClass("active");let _new=$(this);_new.addClass("active");let interval=$(this).data("refresh-interval");$.ajax({method:"POST",data:"interval="+$(this).data("refresh-interval"),url:"/update_dashboard_refresh_interval",success:function(res){if(res==="true"){load_interval=interval;clearInterval(load_timeout);load_timeout=setInterval(function(){load_data($("#search_peer_textbox").val())},interval);showToast("Refresh Interval set to "+Math.round(interval/1e3)+" seconds")}else{$(".interval-btn-group button").removeClass("active");$('.interval-btn-group button[data-refresh-interval="'+load_interval+'"]').addClass("active");showToast("Refresh Interval set unsuccessful")}}})});$body.on("click",".refresh",function(){load_data($("#search_peer_textbox").val())});$body.on("click",".display_mode",function(){$(".display-btn-group button").removeClass("active");$(this).addClass("active");let display_mode=$(this).data("display-mode");$.ajax({method:"GET",url:"/switch_display_mode/"+$(this).data("display-mode"),success:function(res){if(res==="true"){if(display_mode==="list"){Array($(".peer_list").children()).forEach(function(child){$(child).removeClass().addClass("col-12")});showToast("Displaying as List")}else{Array($(".peer_list").children()).forEach(function(child){$(child).removeClass().addClass("col-sm-6 col-lg-4")});showToast("Displaying as Grids")}}}})});
\ No newline at end of file
diff --git a/src/templates/configuration.html b/src/templates/configuration.html
index f50b7f1..83e3f6b 100644
--- a/src/templates/configuration.html
+++ b/src/templates/configuration.html
@@ -83,7 +83,7 @@
+
@@ -154,7 +155,15 @@
@@ -296,6 +305,31 @@
+