mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-23 07:30:11 +01:00
Updated documentation, minor fixes
This commit is contained in:
parent
305c23190c
commit
9e16619e56
@ -286,9 +286,9 @@ def update_peer_default_config():
|
|||||||
|
|
||||||
config = g.conf
|
config = g.conf
|
||||||
if (
|
if (
|
||||||
len(request.form["peer_endpoint_allowed_ips"]) == 0
|
not (request.form["peer_endpoint_allowed_ips"])
|
||||||
or len(request.form["peer_global_DNS"]) == 0
|
or not (request.form["peer_global_DNS"])
|
||||||
or len(request.form["peer_remote_endpoint"]) == 0
|
or not (request.form["peer_remote_endpoint"])
|
||||||
):
|
):
|
||||||
session["message"] = "Please fill in all required boxes."
|
session["message"] = "Please fill in all required boxes."
|
||||||
session["message_status"] = "danger"
|
session["message_status"] = "danger"
|
||||||
|
61
src/db.py
61
src/db.py
@ -3,7 +3,10 @@ from __main__ import app
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
def get_net_stats(interface_name: str) -> list:
|
def get_net_stats(interface_name: str) -> list[sqlite3.Row]:
|
||||||
|
"""
|
||||||
|
Gets net stats for all peers of `interface_name` and returns a list of dicts
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.get_net_stats({interface_name})")
|
app.logger.debug(f"db.get_net_stats({interface_name})")
|
||||||
data = g.cur.execute(
|
data = g.cur.execute(
|
||||||
f"SELECT total_sent, total_receive, cumu_sent, cumu_receive FROM {interface_name}"
|
f"SELECT total_sent, total_receive, cumu_sent, cumu_receive FROM {interface_name}"
|
||||||
@ -12,6 +15,9 @@ def get_net_stats(interface_name: str) -> list:
|
|||||||
|
|
||||||
|
|
||||||
def get_net_stats_and_peer_status(interface_name: str, id: str) -> sqlite3.Row | None:
|
def get_net_stats_and_peer_status(interface_name: str, id: str) -> sqlite3.Row | None:
|
||||||
|
"""
|
||||||
|
Gets net stats for a given peer of `interface_name` and the data as `dict`, `None` if not found.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.get_net_stats_and_peer_status({interface_name})")
|
app.logger.debug(f"db.get_net_stats_and_peer_status({interface_name})")
|
||||||
data = g.cur.execute(
|
data = g.cur.execute(
|
||||||
"""SELECT total_receive, total_sent, cumu_receive, cumu_sent, status
|
"""SELECT total_receive, total_sent, cumu_receive, cumu_sent, status
|
||||||
@ -21,7 +27,12 @@ def get_net_stats_and_peer_status(interface_name: str, id: str) -> sqlite3.Row |
|
|||||||
return data.fetchone()
|
return data.fetchone()
|
||||||
|
|
||||||
|
|
||||||
def get_peer_count_by_allowed_ips(interface_name: str, ip: str, id: str):
|
def get_peer_count_by_allowed_ips(
|
||||||
|
interface_name: str, ip: str, id: str
|
||||||
|
) -> sqlite3.Row | None:
|
||||||
|
"""
|
||||||
|
Gets and returns the number of peers of `interface_name` that have allowed_ips similar to `ip`.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.get_peer_count_by_allowed_ips({interface_name}, {ip}, {id})")
|
app.logger.debug(f"db.get_peer_count_by_allowed_ips({interface_name}, {ip}, {id})")
|
||||||
data = g.cur.execute(
|
data = g.cur.execute(
|
||||||
f"""SELECT COUNT(*) FROM {interface_name}
|
f"""SELECT COUNT(*) FROM {interface_name}
|
||||||
@ -31,7 +42,7 @@ def get_peer_count_by_allowed_ips(interface_name: str, ip: str, id: str):
|
|||||||
return data.fetchone()
|
return data.fetchone()
|
||||||
|
|
||||||
|
|
||||||
def get_peers(interface_name: str, search: str = None) -> list:
|
def get_peers(interface_name: str, search: str = None) -> list[sqlite3.Row]:
|
||||||
"""Returns the list of records which name matches the search string, or all if no search is provided"""
|
"""Returns the list of records which name matches the search string, or all if no search is provided"""
|
||||||
|
|
||||||
app.logger.debug(f"db.get_peers({interface_name}, {search})")
|
app.logger.debug(f"db.get_peers({interface_name}, {search})")
|
||||||
@ -44,8 +55,10 @@ def get_peers(interface_name: str, search: str = None) -> list:
|
|||||||
return data.fetchall()
|
return data.fetchall()
|
||||||
|
|
||||||
|
|
||||||
def get_peer_by_id(interface_name: str, id: str) -> list:
|
def get_peer_by_id(interface_name: str, id: str) -> sqlite3.Row | None:
|
||||||
"""Returns the record matching the pass id or None."""
|
"""
|
||||||
|
Returns the peer of `interface_name` matching `id` or None.
|
||||||
|
"""
|
||||||
|
|
||||||
app.logger.debug(f"db.get_peer_by_id({interface_name}, {id})")
|
app.logger.debug(f"db.get_peer_by_id({interface_name}, {id})")
|
||||||
sql = "SELECT * FROM %s WHERE id='%s'" % (interface_name, id)
|
sql = "SELECT * FROM %s WHERE id='%s'" % (interface_name, id)
|
||||||
@ -53,21 +66,29 @@ def get_peer_by_id(interface_name: str, id: str) -> list:
|
|||||||
return data.fetchone()
|
return data.fetchone()
|
||||||
|
|
||||||
|
|
||||||
def get_peer_allowed_ips(interface_name: str) -> list:
|
def get_peer_allowed_ips(interface_name: str) -> list[sqlite3.Row]:
|
||||||
|
"""
|
||||||
|
Returns the `allowed_ips` of all peers of `interface_name`.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.get_peer_allowed_ips({interface_name})")
|
app.logger.debug(f"db.get_peer_allowed_ips({interface_name})")
|
||||||
sql = f"SELECT allowed_ips FROM {interface_name}"
|
sql = f"SELECT allowed_ips FROM {interface_name}"
|
||||||
data = g.cur.execute(sql)
|
data = g.cur.execute(sql)
|
||||||
return data.fetchall()
|
return data.fetchall()
|
||||||
|
|
||||||
|
|
||||||
def get_peer_ids(interface_name: str):
|
def get_peer_ids(interface_name: str) -> list[sqlite3.Row]:
|
||||||
|
"""
|
||||||
|
Returns the `id`s of all peers of `interface_name`.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.get_peer_ids({interface_name})")
|
app.logger.debug(f"db.get_peer_ids({interface_name})")
|
||||||
data = g.cur.execute("SELECT id FROM %s" % interface_name)
|
data = g.cur.execute("SELECT id FROM %s" % interface_name)
|
||||||
return data.fetchall()
|
return data.fetchall()
|
||||||
|
|
||||||
|
|
||||||
def remove_stale_peers(interface_name: str, peer_data: str):
|
def remove_stale_peers(interface_name: str, peer_data: dict):
|
||||||
"""Removes entries that which id is present in the db, but not in peer_data"""
|
"""
|
||||||
|
Removes from the DB entries that are present there, but not in `peer_data`
|
||||||
|
"""
|
||||||
|
|
||||||
app.logger.debug(f"db.remove_stale_peers({interface_name}, peer_data)")
|
app.logger.debug(f"db.remove_stale_peers({interface_name}, peer_data)")
|
||||||
db_key = set(map(lambda a: a[0], get_peer_ids(interface_name)))
|
db_key = set(map(lambda a: a[0], get_peer_ids(interface_name)))
|
||||||
@ -79,12 +100,18 @@ def remove_stale_peers(interface_name: str, peer_data: str):
|
|||||||
|
|
||||||
|
|
||||||
def delete_peer(interface_name: str, id: str):
|
def delete_peer(interface_name: str, id: str):
|
||||||
|
"""
|
||||||
|
Removes a peer of `interface_name` with the given `id`
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.delete_peer({interface_name}, {id})")
|
app.logger.debug(f"db.delete_peer({interface_name}, {id})")
|
||||||
sql = "DELETE FROM %s WHERE id = '%s'" % (interface_name, id)
|
sql = "DELETE FROM %s WHERE id = '%s'" % (interface_name, id)
|
||||||
g.cur.execute(sql)
|
g.cur.execute(sql)
|
||||||
|
|
||||||
|
|
||||||
def insert_peer(interface_name: str, data: dict):
|
def insert_peer(interface_name: str, data: dict):
|
||||||
|
"""
|
||||||
|
Inserts a peer of `interface_name` with the given `data`
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.insert_peer({interface_name}, {data})")
|
app.logger.debug(f"db.insert_peer({interface_name}, {data})")
|
||||||
sql = f"""
|
sql = f"""
|
||||||
INSERT INTO {interface_name}
|
INSERT INTO {interface_name}
|
||||||
@ -95,10 +122,13 @@ def insert_peer(interface_name: str, data: dict):
|
|||||||
g.cur.execute(sql, data)
|
g.cur.execute(sql, data)
|
||||||
|
|
||||||
|
|
||||||
def create_table_if_missing(table_name: str):
|
def create_table_if_missing(interface_name: str):
|
||||||
app.logger.debug(f"db.create_table_if_missing({table_name})")
|
"""
|
||||||
|
Creates a table for `interface_name`, if missing.
|
||||||
|
"""
|
||||||
|
app.logger.debug(f"db.create_table_if_missing({interface_name})")
|
||||||
create_table = f"""
|
create_table = f"""
|
||||||
CREATE TABLE IF NOT EXISTS {table_name} (
|
CREATE TABLE IF NOT EXISTS {interface_name} (
|
||||||
id VARCHAR NOT NULL PRIMARY KEY, private_key VARCHAR NULL UNIQUE, DNS VARCHAR NULL,
|
id VARCHAR NOT NULL PRIMARY KEY, private_key VARCHAR NULL UNIQUE, DNS VARCHAR NULL,
|
||||||
endpoint_allowed_ips VARCHAR NULL, name VARCHAR NULL, total_receive FLOAT NULL,
|
endpoint_allowed_ips VARCHAR NULL, name VARCHAR NULL, total_receive FLOAT NULL,
|
||||||
total_sent FLOAT NULL, total_data FLOAT NULL, endpoint VARCHAR NULL,
|
total_sent FLOAT NULL, total_data FLOAT NULL, endpoint VARCHAR NULL,
|
||||||
@ -111,6 +141,9 @@ def create_table_if_missing(table_name: str):
|
|||||||
|
|
||||||
|
|
||||||
def update_peer(interface_name: str, data: dict):
|
def update_peer(interface_name: str, data: dict):
|
||||||
|
"""
|
||||||
|
Updates the peer of `interface_name` with the given `data`, if the peer record exists.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.interface_name({data})")
|
app.logger.debug(f"db.interface_name({data})")
|
||||||
id = data["id"]
|
id = data["id"]
|
||||||
db_peer = get_peer_by_id(interface_name, id)
|
db_peer = get_peer_by_id(interface_name, id)
|
||||||
@ -121,6 +154,10 @@ def update_peer(interface_name: str, data: dict):
|
|||||||
|
|
||||||
|
|
||||||
def _update_peer(interface_name: str, data: dict):
|
def _update_peer(interface_name: str, data: dict):
|
||||||
|
"""
|
||||||
|
Updates the peer of `interface_name` with the given `data`.
|
||||||
|
`data` should contain the peer's `id` (public key), plus any other field to be updated.
|
||||||
|
"""
|
||||||
app.logger.debug(f"db.update_peer({interface_name}, {data})")
|
app.logger.debug(f"db.update_peer({interface_name}, {data})")
|
||||||
sql = f"""
|
sql = f"""
|
||||||
UPDATE {interface_name} SET
|
UPDATE {interface_name} SET
|
||||||
|
@ -322,7 +322,7 @@ def add_peer(interface_name):
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
public_key = data["public_key"]
|
public_key = data["public_key"]
|
||||||
allowed_ips = data["allowed_ips"]
|
allowed_ips = data["allowed_ips"]
|
||||||
endpoint_allowed_ips = data["endpoint_allowed_ip"]
|
endpoint_allowed_ips = data["endpoint_allowed_ips"]
|
||||||
dns_addresses = data["DNS"]
|
dns_addresses = data["DNS"]
|
||||||
enable_preshared_key = data["enable_preshared_key"]
|
enable_preshared_key = data["enable_preshared_key"]
|
||||||
preshared_key = data["preshared_key"]
|
preshared_key = data["preshared_key"]
|
||||||
@ -398,7 +398,7 @@ def save_peer_setting(interface_name):
|
|||||||
private_key = data["private_key"]
|
private_key = data["private_key"]
|
||||||
dns_addresses = data["DNS"]
|
dns_addresses = data["DNS"]
|
||||||
allowed_ips = data["allowed_ips"]
|
allowed_ips = data["allowed_ips"]
|
||||||
endpoint_allowed_ips = data["endpoint_allowed_ip"]
|
endpoint_allowed_ips = data["endpoint_allowed_ips"]
|
||||||
preshared_key = data["preshared_key"]
|
preshared_key = data["preshared_key"]
|
||||||
db_peer = db.get_peer_by_id(interface_name, id)
|
db_peer = db.get_peer_by_id(interface_name, id)
|
||||||
if db_peer:
|
if db_peer:
|
||||||
@ -624,7 +624,7 @@ def add_peer_bulk(interface_name):
|
|||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
keys = data["keys"]
|
keys = data["keys"]
|
||||||
endpoint_allowed_ips = data["endpoint_allowed_ip"]
|
endpoint_allowed_ips = data["endpoint_allowed_ips"]
|
||||||
dns_addresses = data["DNS"]
|
dns_addresses = data["DNS"]
|
||||||
enable_preshared_key = data["enable_preshared_key"]
|
enable_preshared_key = data["enable_preshared_key"]
|
||||||
amount = data["amount"]
|
amount = data["amount"]
|
||||||
|
@ -102,7 +102,7 @@
|
|||||||
'</div>';
|
'</div>';
|
||||||
let peer_transfer = '<div class="col-12 peer_data_group" style="text-align: right; display: flex; margin-bottom: 0.5rem"><p class="text-primary" style="text-transform: uppercase; margin-bottom: 0; margin-right: 1rem"><small><i class="bi bi-arrow-down-right"></i> ' + roundN(peer.total_receive + total_r, 4) + ' GB</small></p> <p class="text-success" style="text-transform: uppercase; margin-bottom: 0"><small><i class="bi bi-arrow-up-right"></i> ' + roundN(peer.total_sent + total_s, 4) + ' GB</small></p> </div>';
|
let peer_transfer = '<div class="col-12 peer_data_group" style="text-align: right; display: flex; margin-bottom: 0.5rem"><p class="text-primary" style="text-transform: uppercase; margin-bottom: 0; margin-right: 1rem"><small><i class="bi bi-arrow-down-right"></i> ' + roundN(peer.total_receive + total_r, 4) + ' GB</small></p> <p class="text-success" style="text-transform: uppercase; margin-bottom: 0"><small><i class="bi bi-arrow-up-right"></i> ' + roundN(peer.total_sent + total_s, 4) + ' GB</small></p> </div>';
|
||||||
let peer_key = '<div class="col-sm"><small class="text-muted" style="display: flex"><strong>PEER</strong><strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong></small> <h6><samp class="ml-auto key">' + peer.id + '</samp></h6></div>';
|
let peer_key = '<div class="col-sm"><small class="text-muted" style="display: flex"><strong>PEER</strong><strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong></small> <h6><samp class="ml-auto key">' + peer.id + '</samp></h6></div>';
|
||||||
let peer_allowed_ip = '<div class="col-sm"><small class="text-muted"><strong>ALLOWED IP</strong></small><h6 style="text-transform: uppercase;">'+peer.allowed_ip+'</h6></div>';
|
let peer_allowed_ip = '<div class="col-sm"><small class="text-muted"><strong>ALLOWED IP</strong></small><h6 style="text-transform: uppercase;">' + peer.allowed_ips + '</h6></div>';
|
||||||
let peer_latest_handshake = '<div class="col-sm"> <small class="text-muted"><strong>LATEST HANDSHAKE</strong></small> <h6 style="text-transform: uppercase;">' + peer.latest_handshake + '</h6> </div>';
|
let peer_latest_handshake = '<div class="col-sm"> <small class="text-muted"><strong>LATEST HANDSHAKE</strong></small> <h6 style="text-transform: uppercase;">' + peer.latest_handshake + '</h6> </div>';
|
||||||
let peer_endpoint = '<div class="col-sm"><small class="text-muted"><strong>END POINT</strong></small><h6 style="text-transform: uppercase;">' + peer.endpoint + '</h6></div>';
|
let peer_endpoint = '<div class="col-sm"><small class="text-muted"><strong>END POINT</strong></small><h6 style="text-transform: uppercase;">' + peer.endpoint + '</h6></div>';
|
||||||
let peer_control = '<div class="col-sm"><hr><div class="button-group" style="display:flex"><button type="button" class="btn btn-outline-primary btn-setting-peer btn-control" id="' + peer.id + '" data-toggle="modal"><i class="bi bi-gear-fill" data-toggle="tooltip" data-placement="bottom" title="Peer Settings"></i></button> <button type="button" class="btn btn-outline-danger btn-delete-peer btn-control" id="' + peer.id + '" data-toggle="modal"><i class="bi bi-x-circle-fill" data-toggle="tooltip" data-placement="bottom" title="Delete Peer"></i></button>';
|
let peer_control = '<div class="col-sm"><hr><div class="button-group" style="display:flex"><button type="button" class="btn btn-outline-primary btn-setting-peer btn-control" id="' + peer.id + '" data-toggle="modal"><i class="bi bi-gear-fill" data-toggle="tooltip" data-placement="bottom" title="Peer Settings"></i></button> <button type="button" class="btn btn-outline-danger btn-delete-peer btn-control" id="' + peer.id + '" data-toggle="modal"><i class="bi bi-x-circle-fill" data-toggle="tooltip" data-placement="bottom" title="Delete Peer"></i></button>';
|
||||||
@ -169,7 +169,7 @@
|
|||||||
},
|
},
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
"DNS": $new_add_DNS.val(),
|
"DNS": $new_add_DNS.val(),
|
||||||
"endpoint_allowed_ip": $new_add_endpoint_allowed_ip.val(),
|
"endpoint_allowed_ips": $new_add_endpoint_allowed_ip.val(),
|
||||||
"MTU": $new_add_MTU.val(),
|
"MTU": $new_add_MTU.val(),
|
||||||
"keep_alive": $new_add_keep_alive.val(),
|
"keep_alive": $new_add_keep_alive.val(),
|
||||||
"enable_preshared_key": $enable_preshare_key.prop("checked"),
|
"enable_preshared_key": $enable_preshare_key.prop("checked"),
|
||||||
@ -649,7 +649,7 @@ $add_peer.addEventListener("click",function(){
|
|||||||
"allowed_ips": $allowed_ips.val(),
|
"allowed_ips": $allowed_ips.val(),
|
||||||
"name": $new_add_name.val(),
|
"name": $new_add_name.val(),
|
||||||
"DNS": $new_add_DNS.val(),
|
"DNS": $new_add_DNS.val(),
|
||||||
"endpoint_allowed_ip": $new_add_endpoint_allowed_ip.val(),
|
"endpoint_allowed_ips": $new_add_endpoint_allowed_ip.val(),
|
||||||
"MTU": $new_add_MTU.val(),
|
"MTU": $new_add_MTU.val(),
|
||||||
"keep_alive": $new_add_keep_alive.val(),
|
"keep_alive": $new_add_keep_alive.val(),
|
||||||
"enable_preshared_key": $enable_preshare_key.prop("checked"),
|
"enable_preshared_key": $enable_preshare_key.prop("checked"),
|
||||||
@ -867,10 +867,10 @@ $body.on("click", ".btn-setting-peer", function(){
|
|||||||
$("#setting_modal #peer_name_textbox").val(response.name);
|
$("#setting_modal #peer_name_textbox").val(response.name);
|
||||||
$("#setting_modal #peer_private_key_textbox").val(response.private_key);
|
$("#setting_modal #peer_private_key_textbox").val(response.private_key);
|
||||||
$("#setting_modal #peer_DNS_textbox").val(response.DNS);
|
$("#setting_modal #peer_DNS_textbox").val(response.DNS);
|
||||||
$("#setting_modal #peer_allowed_ip_textbox").val(response.allowed_ip);
|
$("#setting_modal #peer_allowed_ip_textbox").val(response.allowed_ips);
|
||||||
$("#setting_modal #peer_endpoint_allowed_ips").val(response.endpoint_allowed_ip);
|
$("#setting_modal #peer_endpoint_allowed_ips").val(response.endpoint_allowed_ips);
|
||||||
$("#setting_modal #peer_mtu").val(response.mtu);
|
$("#setting_modal #peer_mtu").val(response.mtu);
|
||||||
$("#setting_modal #peer_keep_alive").val(response.keep_alive);
|
$("#setting_modal #peer_keep_alive").val(response.keepalive);
|
||||||
$("#setting_modal #peer_preshared_key_textbox").val(response.preshared_key);
|
$("#setting_modal #peer_preshared_key_textbox").val(response.preshared_key);
|
||||||
window.configurations.settingModal().toggle();
|
window.configurations.settingModal().toggle();
|
||||||
window.configurations.endProgressBar();
|
window.configurations.endProgressBar();
|
||||||
@ -941,8 +941,8 @@ $("#save_peer_setting").on("click",function (){
|
|||||||
name: $peer_name_textbox.val(),
|
name: $peer_name_textbox.val(),
|
||||||
DNS: $peer_DNS_textbox.val(),
|
DNS: $peer_DNS_textbox.val(),
|
||||||
private_key: $peer_private_key_textbox.val(),
|
private_key: $peer_private_key_textbox.val(),
|
||||||
allowed_ip: $peer_allowed_ip_textbox.val(),
|
allowed_ips: $peer_allowed_ip_textbox.val(),
|
||||||
endpoint_allowed_ip: $peer_endpoint_allowed_ips.val(),
|
endpoint_allowed_ips: $peer_endpoint_allowed_ips.val(),
|
||||||
MTU: $peer_mtu.val(),
|
MTU: $peer_mtu.val(),
|
||||||
keep_alive: $peer_keep_alive.val(),
|
keep_alive: $peer_keep_alive.val(),
|
||||||
preshared_key: $peer_preshared_key_textbox.val()
|
preshared_key: $peer_preshared_key_textbox.val()
|
||||||
|
2
src/static/js/configuration.min.js
vendored
2
src/static/js/configuration.min.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,7 @@
|
|||||||
{% with title=title%}
|
{% with title=title%}
|
||||||
{% include "header.html"%}
|
{% include "header.html"%}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="no-response">
|
<div class="no-response">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -30,7 +31,8 @@
|
|||||||
<div class="col">
|
<div class="col">
|
||||||
<small class="text-muted"><strong>SWITCH</strong></small><br>
|
<small class="text-muted"><strong>SWITCH</strong></small><br>
|
||||||
<div id="conf_status_btn" class="info_loading"></div>
|
<div id="conf_status_btn" class="info_loading"></div>
|
||||||
<div class="spinner-border text-primary" role="status" style="display: none; margin-top: 10px">
|
<div class="spinner-border text-primary" role="status"
|
||||||
|
style="display: none; margin-top: 10px">
|
||||||
<span class="sr-only">Loading...</span>
|
<span class="sr-only">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -49,7 +51,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<small class="text-muted"><strong>TOTAL RECEIVED</strong></small>
|
<small class="text-muted"><strong>TOTAL RECEIVED</strong></small>
|
||||||
<h6 style="text-transform: uppercase;" id="conf_total_data_received" class="info_loading"></h6>
|
<h6 style="text-transform: uppercase;" id="conf_total_data_received" class="info_loading">
|
||||||
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<small class="text-muted"><strong>TOTAL SENT</strong></small>
|
<small class="text-muted"><strong>TOTAL SENT</strong></small>
|
||||||
@ -59,17 +62,20 @@
|
|||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
<strong>PUBLIC KEY</strong>
|
<strong>PUBLIC KEY</strong>
|
||||||
<strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out" class="text-primary">CLICK TO COPY</strong>
|
<strong style="margin-left: auto!important; opacity: 0; transition: 0.2s ease-in-out"
|
||||||
|
class="text-primary">CLICK TO COPY</strong>
|
||||||
</small>
|
</small>
|
||||||
<h6 class="info_loading"><samp class="key" id="conf_public_key"></samp></h6>
|
<h6 class="info_loading"><samp class="key" id="conf_public_key"></samp></h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<small class="text-muted"><strong>LISTEN PORT</strong></small>
|
<small class="text-muted"><strong>LISTEN PORT</strong></small>
|
||||||
<h6 style="text-transform: uppercase;" class="info_loading"><samp id="conf_listen_port"></samp></h6>
|
<h6 style="text-transform: uppercase;" class="info_loading"><samp
|
||||||
|
id="conf_listen_port"></samp></h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<small class="text-muted"><strong>ADDRESS</strong></small>
|
<small class="text-muted"><strong>ADDRESS</strong></small>
|
||||||
<h6 style="text-transform: uppercase;" class="info_loading"><samp id="conf_address"></samp></h6>
|
<h6 style="text-transform: uppercase;" class="info_loading"><samp id="conf_address"></samp>
|
||||||
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -90,11 +96,22 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label><small class="text-muted">Refresh Interval</small></label><br>
|
<label><small class="text-muted">Refresh Interval</small></label><br>
|
||||||
<div class="btn-group interval-btn-group" role="group" style="width: 100%">
|
<div class="btn-group interval-btn-group" role="group" style="width: 100%">
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary btn-group-label refresh" data-toggle="tooltip" data-placement="bottom" title="Refresh Peers"><i class="bi bi-arrow-repeat"></i></button>
|
<button style="width: 20%" type="button"
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="5000">5s</button>
|
class="btn btn-outline-primary btn-group-label refresh" data-toggle="tooltip"
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="10000">10s</button>
|
data-placement="bottom" title="Refresh Peers"><i
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="30000">30s</button>
|
class="bi bi-arrow-repeat"></i></button>
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary update_interval" data-refresh-interval="60000">1m</button>
|
<button style="width: 20%" type="button"
|
||||||
|
class="btn btn-outline-primary update_interval"
|
||||||
|
data-refresh-interval="5000">5s</button>
|
||||||
|
<button style="width: 20%" type="button"
|
||||||
|
class="btn btn-outline-primary update_interval"
|
||||||
|
data-refresh-interval="10000">10s</button>
|
||||||
|
<button style="width: 20%" type="button"
|
||||||
|
class="btn btn-outline-primary update_interval"
|
||||||
|
data-refresh-interval="30000">30s</button>
|
||||||
|
<button style="width: 20%" type="button"
|
||||||
|
class="btn btn-outline-primary update_interval"
|
||||||
|
data-refresh-interval="60000">1m</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -102,17 +119,26 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label><small class="text-muted">Display Mode</small></label><br>
|
<label><small class="text-muted">Display Mode</small></label><br>
|
||||||
<div class="btn-group display-btn-group" role="group" style="width: 100%">
|
<div class="btn-group display-btn-group" role="group" style="width: 100%">
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode" data-display-mode="grid"><i class="bi bi-grid-fill" style="font-size: 1.5rem;"></i></button>
|
<button style="width: 20%" type="button"
|
||||||
<button style="width: 20%" type="button" class="btn btn-outline-primary display_mode" data-display-mode="list"><i class="bi bi-list" style="font-size: 1.5rem;"></i></button>
|
class="btn btn-outline-primary display_mode" data-display-mode="grid"><i
|
||||||
|
class="bi bi-grid-fill" style="font-size: 1.5rem;"></i></button>
|
||||||
|
<button style="width: 20%" type="button"
|
||||||
|
class="btn btn-outline-primary display_mode" data-display-mode="list"><i
|
||||||
|
class="bi bi-list" style="font-size: 1.5rem;"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-manage-group">
|
<div class="btn-manage-group">
|
||||||
<button type="button" class="btn btn-primary add_btn"><i class="bi bi-plus-circle-fill" style=""></i></button>
|
<button type="button" class="btn btn-primary add_btn"><i class="bi bi-plus-circle-fill"
|
||||||
<button type="button" class="btn btn-secondary setting_btn"><i class="bi bi-three-dots"></i></button>
|
style=""></i></button>
|
||||||
|
<button type="button" class="btn btn-secondary setting_btn"><i
|
||||||
|
class="bi bi-three-dots"></i></button>
|
||||||
<div class="setting_btn_menu">
|
<div class="setting_btn_menu">
|
||||||
<a class="text-danger" id="delete_peers_by_bulk_btn"><i class="bi bi-trash-fill"></i> Delete Peers</a>
|
<a class="text-danger" id="delete_peers_by_bulk_btn"><i class="bi bi-trash-fill"></i>
|
||||||
<a class="text-info" id="download_all_peers" data-url="/download_all/{{conf_data['name']}}"><i class="bi bi-cloud-download-fill"></i> Download All Peers</a>
|
Delete Peers</a>
|
||||||
|
<a class="text-info" id="download_all_peers"
|
||||||
|
data-url="/download_all/{{conf_data['name']}}"><i
|
||||||
|
class="bi bi-cloud-download-fill"></i> Download All Peers</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -138,11 +164,15 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="custom-control custom-switch" style="margin-bottom: 1rem">
|
<div class="custom-control custom-switch" style="margin-bottom: 1rem">
|
||||||
<input class="custom-control-input" type="checkbox" id="bulk_add">
|
<input class="custom-control-input" type="checkbox" id="bulk_add">
|
||||||
<label class="custom-control-label" for="bulk_add"><strong>Add Peers by bulk</strong></label>
|
<label class="custom-control-label" for="bulk_add"><strong>Add Peers by
|
||||||
<i class="bi bi-question-circle-fill" style="cursor: pointer" data-container="body" data-toggle="popover" data-placement="right" data-trigger="click" data-content="By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP."></i>
|
bulk</strong></label>
|
||||||
|
<i class="bi bi-question-circle-fill" style="cursor: pointer" data-container="body"
|
||||||
|
data-toggle="popover" data-placement="right" data-trigger="click"
|
||||||
|
data-content="By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP."></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="margin: 0">
|
<div class="form-group" style="margin: 0">
|
||||||
<input type="number" class="form-control" id="new_add_amount" min="1" placeholder="Amount" disabled>
|
<input type="number" class="form-control" id="new_add_amount" min="1" placeholder="Amount"
|
||||||
|
disabled>
|
||||||
<div id="bulk_amount_validation" class="invalid-feedback"></div>
|
<div id="bulk_amount_validation" class="invalid-feedback"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -161,13 +191,16 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="private_key" aria-describedby="private_key">
|
<input type="text" class="form-control" id="private_key" aria-describedby="private_key">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type="button" class="btn btn-danger" id="re_generate_key" data-toggle="tooltip" data-placement="top" title="Regenerate Key"><i class="bi bi-arrow-repeat"></i></button>
|
<button type="button" class="btn btn-danger" id="re_generate_key"
|
||||||
|
data-toggle="tooltip" data-placement="top" title="Regenerate Key"><i
|
||||||
|
class="bi bi-arrow-repeat"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group non-bulk">
|
<div class="form-group non-bulk">
|
||||||
<label for="public_key">Public Key <code>(Required)</code></label>
|
<label for="public_key">Public Key <code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="public_key" aria-describedby="public_key" disabled>
|
<input type="text" class="form-control" id="public_key" aria-describedby="public_key"
|
||||||
|
disabled>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 non-bulk">
|
<div class="col-sm-6 non-bulk">
|
||||||
@ -182,12 +215,14 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="allowed_ips">
|
<input type="text" class="form-control" id="allowed_ips">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type="button" class="btn btn-primary" id="search_available_ip" data-toggle="tooltip" data-placement="top" title="Search Available IPs">
|
<button type="button" class="btn btn-primary" id="search_available_ip"
|
||||||
|
data-toggle="tooltip" data-placement="top" title="Search Available IPs">
|
||||||
<i class="bi bi-search"></i>
|
<i class="bi bi-search"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p style="position: absolute; top: 4px; right: 1rem;" class="text-success" id="allowed_ips_indicator"></p>
|
<p style="position: absolute; top: 4px; right: 1rem;" class="text-success"
|
||||||
|
id="allowed_ips_indicator"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
@ -198,8 +233,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_endpoint_allowed_ip">Endpoint Allowed IPs <code>(Required)</code></label>
|
<label for="new_add_endpoint_allowed_ip">Endpoint Allowed IPs
|
||||||
<input type="text" class="form-control" id="new_add_endpoint_allowed_ip" value="{{ endpoint_allowed_ip }}">
|
<code>(Required)</code></label>
|
||||||
|
<input type="text" class="form-control" id="new_add_endpoint_allowed_ip"
|
||||||
|
value="{{ endpoint_allowed_ips }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
@ -211,12 +248,14 @@
|
|||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_keep_alive">Persistent keepalive</label>
|
<label for="new_add_keep_alive">Persistent keepalive</label>
|
||||||
<input type="text" class="form-control" id="new_add_keep_alive" value="{{ keep_alive }}">
|
<input type="text" class="form-control" id="new_add_keep_alive"
|
||||||
|
value="{{ keep_alive }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="enable_preshare_key" name="enable_preshare_key" value="enable_psk">
|
<input class="form-check-input" type="checkbox" id="enable_preshare_key"
|
||||||
|
name="enable_preshare_key" value="enable_psk">
|
||||||
<label class="form-check-label" for="enable_preshare_key">Use Pre-shared Key</label>
|
<label class="form-check-label" for="enable_preshare_key">Use Pre-shared Key</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -225,7 +264,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-primary" id="save_peer" conf_id={{conf_data['name']}}>Add</button>
|
<button type="button" class="btn btn-primary" id="save_peer"
|
||||||
|
conf_id={{conf_data['name']}}>Add</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -241,7 +281,8 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none"
|
||||||
|
role="alert">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@ -250,7 +291,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
||||||
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}} peer_id="">Yes</button>
|
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}}
|
||||||
|
peer_id="">Yes</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -266,14 +308,17 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div id="setting_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
<div id="setting_peer_alert" class="alert alert-danger alert-dismissible fade show d-none"
|
||||||
|
role="alert">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_private_key_textbox" class="form-label">Private Key <code>(Required for QR Code and download)</code></label>
|
<label for="peer_private_key_textbox" class="form-label">Private Key
|
||||||
<input type="password" class="form-control" id="peer_private_key_textbox" style="padding-right: 40px">
|
<code>(Required for QR Code and download)</code></label>
|
||||||
|
<input type="password" class="form-control" id="peer_private_key_textbox"
|
||||||
|
style="padding-right: 40px">
|
||||||
<a class="peer_private_key_textbox_switch"><i class="bi bi-eye-fill"></i></a>
|
<a class="peer_private_key_textbox_switch"><i class="bi bi-eye-fill"></i></a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -291,7 +336,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_allowed_ip_textbox" class="form-label">Allowed IPs <code>(Required)</code></label>
|
<label for="peer_allowed_ip_textbox" class="form-label">Allowed IPs
|
||||||
|
<code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="peer_allowed_ip_textbox">
|
<input type="text" class="form-control" id="peer_allowed_ip_textbox">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -303,7 +349,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_endpoint_allowed_ips" class="form-label">Endpoint Allowed IPs <code>(Required)</code></label>
|
<label for="peer_endpoint_allowed_ips" class="form-label">Endpoint Allowed IPs
|
||||||
|
<code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="peer_endpoint_allowed_ips">
|
<input type="text" class="form-control" id="peer_endpoint_allowed_ips">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -323,7 +370,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-primary" id="save_peer_setting" conf_id={{conf_data['name']}} peer_id="">Save</button>
|
<button type="button" class="btn btn-primary" id="save_peer_setting" conf_id={{conf_data['name']}}
|
||||||
|
peer_id="">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -360,7 +408,8 @@
|
|||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="bulk_remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert" style="margin: 1rem">
|
<div id="bulk_remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none"
|
||||||
|
role="alert" style="margin: 1rem">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@ -373,8 +422,10 @@
|
|||||||
<div class="list-group"></div>
|
<div class="list-group"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="text-danger" id="select_all_delete_bulk_peers" style="cursor: pointer; margin-right: auto;"><small><strong>SELECT ALL</strong></small></a>
|
<a class="text-danger" id="select_all_delete_bulk_peers"
|
||||||
<button type="button" class="btn btn-danger" id="confirm_delete_bulk_peers" disabled data-conf="{{conf_data['name']}}">Delete</button>
|
style="cursor: pointer; margin-right: auto;"><small><strong>SELECT ALL</strong></small></a>
|
||||||
|
<button type="button" class="btn btn-danger" id="confirm_delete_bulk_peers" disabled
|
||||||
|
data-conf="{{conf_data['name']}}">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -423,4 +474,5 @@
|
|||||||
configurations.loadPeers($('#search_peer_textbox').val());
|
configurations.loadPeers($('#search_peer_textbox').val());
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -3,6 +3,7 @@
|
|||||||
{% set title="Settings" %}
|
{% set title="Settings" %}
|
||||||
{% include "header.html" %}
|
{% include "header.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% include "navbar.html" %}
|
{% include "navbar.html" %}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
@ -26,32 +27,30 @@
|
|||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label for="peer_global_DNS">DNS</label>
|
<label for="peer_global_DNS">DNS</label>
|
||||||
<input type="text" class="form-control mb-4" id="peer_global_DNS"
|
<input type="text" class="form-control mb-4" id="peer_global_DNS"
|
||||||
name="peer_global_DNS"
|
name="peer_global_DNS" value="{{ peer_global_DNS }}" required>
|
||||||
value="{{ peer_global_DNS }}" required>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label for="peer_endpoint_allowed_ip">Peer Endpoint Allowed IPs</label>
|
<label for="peer_endpoint_allowed_ips">Peer Endpoint Allowed IPs</label>
|
||||||
<input type="text" class="form-control mb-4" id="peer_endpoint_allowed_ip"
|
<input type="text" class="form-control mb-4" id="peer_endpoint_allowed_ip"
|
||||||
name="peer_endpoint_allowed_ip"
|
name="peer_endpoint_allowed_ips" value="{{ peer_endpoint_allowed_ips }}"
|
||||||
value="{{ peer_endpoint_allowed_ip }}" required>
|
required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label for="peer_mtu">MTU</label>
|
<label for="peer_mtu">MTU</label>
|
||||||
<input type="text" class="form-control mb-4" id="peer_mtu"
|
<input type="text" class="form-control mb-4" id="peer_mtu" name="peer_mtu"
|
||||||
name="peer_mtu"
|
|
||||||
value="{{ peer_mtu }}">
|
value="{{ peer_mtu }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<label for="peer_keep_alive">Persistent Keepalive</label>
|
<label for="peer_keep_alive">Persistent Keepalive</label>
|
||||||
<input type="text" class="form-control mb-4" id="peer_keep_alive"
|
<input type="text" class="form-control mb-4" id="peer_keep_alive"
|
||||||
name="peer_keep_alive"
|
name="peer_keep_alive" value="{{ peer_keepalive }}">
|
||||||
value="{{ peer_keepalive }}">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<label for="peer_remote_endpoint"><strong>Peer Remote Endpoint (This will be change globally, and will be apply to all peer's QR code and configuration file.)</strong></label>
|
<label for="peer_remote_endpoint"><strong>Peer Remote Endpoint (This will be
|
||||||
|
change globally, and will be apply to all peer's QR code and
|
||||||
|
configuration file.)</strong></label>
|
||||||
<input type="text" class="form-control mb-4" id="peer_remote_endpoint"
|
<input type="text" class="form-control mb-4" id="peer_remote_endpoint"
|
||||||
name="peer_remote_endpoint"
|
name="peer_remote_endpoint" value="{{ peer_remote_endpoint }}" required>
|
||||||
value="{{ peer_remote_endpoint }}" required>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-success" type="submit">Update Peer Default Settings</button>
|
<button class="btn btn-success" type="submit">Update Peer Default Settings</button>
|
||||||
@ -68,7 +67,8 @@
|
|||||||
<label for="wg_conf_path">Path</label>
|
<label for="wg_conf_path">Path</label>
|
||||||
<input type="text" class="form-control mb-2" id="wg_conf_path" name="wg_conf_path"
|
<input type="text" class="form-control mb-2" id="wg_conf_path" name="wg_conf_path"
|
||||||
value="{{ wg_conf_path }}">
|
value="{{ wg_conf_path }}">
|
||||||
<p class="text-muted">Remember to remove <code>/</code> at the end of your path. e.g <code>/etc/wireguard</code>
|
<p class="text-muted">Remember to remove <code>/</code> at the end of your path. e.g
|
||||||
|
<code>/etc/wireguard</code>
|
||||||
</p>
|
</p>
|
||||||
<button class="btn btn-danger change_path">Update Path & Restart Dashboard</button>
|
<button class="btn btn-danger change_path">Update Path & Restart Dashboard</button>
|
||||||
</div>
|
</div>
|
||||||
@ -115,8 +115,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<label for="app_ip">Dashboard IP</label>
|
<label for="app_ip">Dashboard IP</label>
|
||||||
<input type="text" class="form-control mb-2" id="app_ip" name="app_ip" value="{{ app_ip }}">
|
<input type="text" class="form-control mb-2" id="app_ip" name="app_ip"
|
||||||
<p><small class="text-danger mb-4">0.0.0.0 means it can be access by anyone with your server
|
value="{{ app_ip }}">
|
||||||
|
<p><small class="text-danger mb-4">0.0.0.0 means it can be access by anyone with
|
||||||
|
your server
|
||||||
IP Address.</small></p>
|
IP Address.</small></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
@ -153,8 +155,10 @@
|
|||||||
<p class="app_new_port text-bold text-danger" style="font-weight: bold"></p>
|
<p class="app_new_port text-bold text-danger" style="font-weight: bold"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary cancel_restart" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary cancel_restart"
|
||||||
<button type="button" class="btn btn-danger confirm_restart">Confirm & Restart Dashboard</button>
|
data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-danger confirm_restart">Confirm & Restart
|
||||||
|
Dashboard</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -201,4 +205,5 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
49
src/util.py
49
src/util.py
@ -14,16 +14,21 @@ Helper Functions
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def adapt_for_rest(x):
|
def get_interface_file_path(interface_name: str, base_dir: str) -> str:
|
||||||
x["allowed_ip"] = x.pop("allowed_ips")
|
return os.path.join(base_dir, f"{interface_name}.conf")
|
||||||
x["endpoint_allowed_ip"] = x.pop("endpoint_allowed_ips")
|
|
||||||
for i in ["latest_handshake", "endpoint", "allowed_ip"]:
|
|
||||||
if not x[i]:
|
|
||||||
x[i] = "N/A"
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
def connect_db(dashboard_configuration_dir):
|
def adapt_for_rest(peer_dict: dict) -> dict:
|
||||||
|
"""
|
||||||
|
Renames necessary entries and replaces falsy values. Returns the modified dict.
|
||||||
|
"""
|
||||||
|
for i in ["latest_handshake", "endpoint", "allowed_ips"]:
|
||||||
|
if not peer_dict[i]:
|
||||||
|
peer_dict[i] = "(None)"
|
||||||
|
return peer_dict
|
||||||
|
|
||||||
|
|
||||||
|
def connect_db(dashboard_configuration_dir: str):
|
||||||
"""
|
"""
|
||||||
Connect to the database
|
Connect to the database
|
||||||
@return: sqlite3.Connection
|
@return: sqlite3.Connection
|
||||||
@ -35,7 +40,7 @@ def connect_db(dashboard_configuration_dir):
|
|||||||
return con
|
return con
|
||||||
|
|
||||||
|
|
||||||
def read_dashboard_conf(dashboard_conf_file_path):
|
def read_dashboard_conf(dashboard_conf_file_path: str):
|
||||||
"""
|
"""
|
||||||
Get dashboard configuration
|
Get dashboard configuration
|
||||||
@return: configparser.ConfigParser
|
@return: configparser.ConfigParser
|
||||||
@ -45,7 +50,7 @@ def read_dashboard_conf(dashboard_conf_file_path):
|
|||||||
return r_config
|
return r_config
|
||||||
|
|
||||||
|
|
||||||
def write_dashboard_conf(config, dashboard_conf_file_path):
|
def write_dashboard_conf(config: str, dashboard_conf_file_path: str):
|
||||||
"""
|
"""
|
||||||
Write to configuration
|
Write to configuration
|
||||||
@param config: Input configuration
|
@param config: Input configuration
|
||||||
@ -54,7 +59,9 @@ def write_dashboard_conf(config, dashboard_conf_file_path):
|
|||||||
config.write(conf_object)
|
config.write(conf_object)
|
||||||
|
|
||||||
|
|
||||||
def wg_peer_data_to_db(interface_name, wg_conf_dir, dashboard_conf_file_path):
|
def wg_peer_data_to_db(
|
||||||
|
interface_name: str, wg_conf_dir: str, dashboard_conf_file_path: str
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Look for new peers from WireGuard
|
Look for new peers from WireGuard
|
||||||
@param interface_name: Configuration name
|
@param interface_name: Configuration name
|
||||||
@ -110,9 +117,7 @@ def wg_peer_data_to_db(interface_name, wg_conf_dir, dashboard_conf_file_path):
|
|||||||
handshakes = wg.get_interface_peers_latest_handshakes(interface_name)
|
handshakes = wg.get_interface_peers_latest_handshakes(interface_name)
|
||||||
transfers = wg.get_interface_peers_net_stats(interface_name)
|
transfers = wg.get_interface_peers_net_stats(interface_name)
|
||||||
endpoints = wg.get_interface_peers_endpoints(interface_name)
|
endpoints = wg.get_interface_peers_endpoints(interface_name)
|
||||||
allowed_ips = wg.get_interface_peers_allowed_ips(
|
allowed_ips = wg.get_interface_peers_allowed_ips(interface_and_peer_data)
|
||||||
interface_and_peer_data, interface_name
|
|
||||||
)
|
|
||||||
keys = set()
|
keys = set()
|
||||||
for x in [handshakes, transfers, endpoints, allowed_ips]:
|
for x in [handshakes, transfers, endpoints, allowed_ips]:
|
||||||
keys.update(x.keys())
|
keys.update(x.keys())
|
||||||
@ -127,7 +132,11 @@ def wg_peer_data_to_db(interface_name, wg_conf_dir, dashboard_conf_file_path):
|
|||||||
|
|
||||||
|
|
||||||
def update_db_and_get_peers(
|
def update_db_and_get_peers(
|
||||||
interface_name, search, sort_t, wg_conf_dir, dashboard_conf_file_path
|
interface_name: str,
|
||||||
|
search: str,
|
||||||
|
sort_t: str,
|
||||||
|
wg_conf_dir: str,
|
||||||
|
dashboard_conf_file_path: str,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Get all peers.
|
Get all peers.
|
||||||
@ -162,7 +171,7 @@ def update_db_and_get_peers(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_conf_list(wg_conf_dir):
|
def get_conf_list(wg_conf_dir: str):
|
||||||
"""Get all wireguard interfaces with status.
|
"""Get all wireguard interfaces with status.
|
||||||
@return: Return a list of dicts with interfaces and its statuses
|
@return: Return a list of dicts with interfaces and its statuses
|
||||||
@rtype: list
|
@rtype: list
|
||||||
@ -188,7 +197,7 @@ def get_conf_list(wg_conf_dir):
|
|||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
def f_check_key_match(private_key, public_key, interface_name):
|
def f_check_key_match(private_key: str, public_key: str, interface_name: str):
|
||||||
"""
|
"""
|
||||||
Check if private key and public key match
|
Check if private key and public key match
|
||||||
@param private_key: Private key
|
@param private_key: Private key
|
||||||
@ -216,7 +225,7 @@ def f_check_key_match(private_key, public_key, interface_name):
|
|||||||
return {"status": "success"}
|
return {"status": "success"}
|
||||||
|
|
||||||
|
|
||||||
def check_repeat_allowed_ips(public_key, ip, interface_name):
|
def check_repeat_allowed_ips(public_key: str, ip: str, interface_name: str):
|
||||||
"""
|
"""
|
||||||
Check if there are repeated IPs
|
Check if there are repeated IPs
|
||||||
@param public_key: Public key of the peer
|
@param public_key: Public key of the peer
|
||||||
@ -238,7 +247,7 @@ def check_repeat_allowed_ips(public_key, ip, interface_name):
|
|||||||
return {"status": "success"}
|
return {"status": "success"}
|
||||||
|
|
||||||
|
|
||||||
def f_available_ips(interface_name, wg_conf_dir):
|
def f_available_ips(interface_name: str, wg_conf_dir: str):
|
||||||
"""
|
"""
|
||||||
Get a list of available IPs
|
Get a list of available IPs
|
||||||
@param interface_name: Configuration Name
|
@param interface_name: Configuration Name
|
||||||
@ -289,7 +298,7 @@ def ensure_subnet(ipv4: str, default_subnet: str = "24") -> str:
|
|||||||
|
|
||||||
|
|
||||||
# Regex Match
|
# Regex Match
|
||||||
def regex_match(regex, text):
|
def regex_match(regex: str, text: str):
|
||||||
pattern = re.compile(regex)
|
pattern = re.compile(regex)
|
||||||
return pattern.search(text) is not None
|
return pattern.search(text) is not None
|
||||||
|
|
||||||
|
65
src/wg.py
65
src/wg.py
@ -7,15 +7,21 @@ import db
|
|||||||
import os
|
import os
|
||||||
import ifcfg
|
import ifcfg
|
||||||
import re
|
import re
|
||||||
|
import util
|
||||||
|
|
||||||
|
|
||||||
def _is_comment_line(line: str) -> bool:
|
def _is_comment_line(line: str) -> bool:
|
||||||
"""Returns true if the passed string is a comment"""
|
"""
|
||||||
|
Returns true if the passed string is a comment in an INI style file.
|
||||||
|
"""
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
return line.startswith("#") or line.startswith(";")
|
return line.startswith("#") or line.startswith(";")
|
||||||
|
|
||||||
|
|
||||||
def _parse_peer_or_interface(lines, i, limit):
|
def _parse_peer_or_interface(lines: list[str], i: int, limit: int) -> dict:
|
||||||
|
"""
|
||||||
|
Parses a [Peer] or [Interface] section of an interface config file into a `dict`.
|
||||||
|
"""
|
||||||
data = {}
|
data = {}
|
||||||
while i < limit:
|
while i < limit:
|
||||||
line = lines[i].strip()
|
line = lines[i].strip()
|
||||||
@ -30,23 +36,32 @@ def _parse_peer_or_interface(lines, i, limit):
|
|||||||
|
|
||||||
|
|
||||||
def set_peer_options(
|
def set_peer_options(
|
||||||
interface_name, public_key, allowed_ips, preshared_key_filename=None
|
interface_name: str,
|
||||||
|
public_key: str,
|
||||||
|
allowed_ips: str,
|
||||||
|
preshared_key_filename: str = None,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
Sets the given options for the specified `interface_name` and peer (`public_key`)
|
||||||
|
"""
|
||||||
if preshared_key_filename:
|
if preshared_key_filename:
|
||||||
status = subprocess.check_output(
|
subprocess.check_output(
|
||||||
f"wg set {interface_name} peer {public_key} allowed-ips {allowed_ips} preshared-key {preshared_key_filename}",
|
f"wg set {interface_name} peer {public_key} allowed-ips {allowed_ips} preshared-key {preshared_key_filename}",
|
||||||
shell=True,
|
shell=True,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
status = subprocess.check_output(
|
subprocess.check_output(
|
||||||
f"wg set {interface_name} peer {public_key} allowed-ips {allowed_ips}",
|
f"wg set {interface_name} peer {public_key} allowed-ips {allowed_ips}",
|
||||||
shell=True,
|
shell=True,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def remove_peer_from_interface(interface_name, public_key):
|
def remove_peer_from_interface(interface_name: str, public_key: str):
|
||||||
|
"""
|
||||||
|
Removes the specified peer (`public_key`) from `interface_name`
|
||||||
|
"""
|
||||||
subprocess.check_output(
|
subprocess.check_output(
|
||||||
f"wg set {interface_name} peer {public_key} remove",
|
f"wg set {interface_name} peer {public_key} remove",
|
||||||
shell=True,
|
shell=True,
|
||||||
@ -54,7 +69,7 @@ def remove_peer_from_interface(interface_name, public_key):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_interface_listen_port(interface_name, base_dir):
|
def get_interface_listen_port(interface_name: str, base_dir: str) -> str:
|
||||||
"""
|
"""
|
||||||
Get listen port number.
|
Get listen port number.
|
||||||
@param interface_name: Name of WG interface
|
@param interface_name: Name of WG interface
|
||||||
@ -80,7 +95,7 @@ def get_interface_listen_port(interface_name, base_dir):
|
|||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
def get_interface_public_key(interface_name, base_dir):
|
def get_interface_public_key(interface_name: str, base_dir: str) -> str:
|
||||||
"""
|
"""
|
||||||
Get public key for configuration.
|
Get public key for configuration.
|
||||||
@param interface_name: Name of WG interface
|
@param interface_name: Name of WG interface
|
||||||
@ -122,7 +137,7 @@ def get_interface_total_net_stats(interface_name):
|
|||||||
return [total, upload_total, download_total]
|
return [total, upload_total, download_total]
|
||||||
|
|
||||||
|
|
||||||
def get_interface_status(interface_name):
|
def get_interface_status(interface_name: str) -> str:
|
||||||
"""
|
"""
|
||||||
Check if the configuration is running or not
|
Check if the configuration is running or not
|
||||||
@param interface_name:
|
@param interface_name:
|
||||||
@ -206,7 +221,7 @@ def read_interface_config_file(interface_name: str, base_dir: str) -> dict:
|
|||||||
"""
|
"""
|
||||||
app.logger.debug(f"read_conf_file({interface_name})")
|
app.logger.debug(f"read_conf_file({interface_name})")
|
||||||
|
|
||||||
config_file = os.path.join(base_dir, f"{interface_name}.conf")
|
config_file = util.get_interface_file_path(interface_name, base_dir)
|
||||||
with open(config_file, "r", encoding="utf-8") as file_object:
|
with open(config_file, "r", encoding="utf-8") as file_object:
|
||||||
file = list(file_object.readlines())
|
file = list(file_object.readlines())
|
||||||
result = {"Interface": {}, "Peers": []}
|
result = {"Interface": {}, "Peers": []}
|
||||||
@ -229,7 +244,10 @@ def read_interface_config_file(interface_name: str, base_dir: str) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def switch_interface(interface_name: str, base_dir: str):
|
def switch_interface(interface_name: str, base_dir: str):
|
||||||
config_file = os.path.join(base_dir, f"{interface_name}.conf")
|
"""
|
||||||
|
Switches `interface_name` around (up if it is down, down if it is up)
|
||||||
|
"""
|
||||||
|
config_file = util.get_interface_file_path(interface_name, base_dir)
|
||||||
status = get_interface_status(interface_name)
|
status = get_interface_status(interface_name)
|
||||||
if status == "running":
|
if status == "running":
|
||||||
check = subprocess.check_output(
|
check = subprocess.check_output(
|
||||||
@ -242,14 +260,20 @@ def switch_interface(interface_name: str, base_dir: str):
|
|||||||
|
|
||||||
|
|
||||||
def enable_interface(interface_name: str, base_dir: str):
|
def enable_interface(interface_name: str, base_dir: str):
|
||||||
config_file = os.path.join(base_dir, f"{interface_name}.conf")
|
"""
|
||||||
|
Brings `interface_name` up (enables it)
|
||||||
|
"""
|
||||||
|
config_file = util.get_interface_file_path(interface_name, base_dir)
|
||||||
check = subprocess.check_output(
|
check = subprocess.check_output(
|
||||||
"wg-quick up " + config_file, shell=True, stderr=subprocess.STDOUT
|
"wg-quick up " + config_file, shell=True, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def disable_interface(interface_name: str, base_dir: str):
|
def disable_interface(interface_name: str, base_dir: str):
|
||||||
config_file = os.path.join(base_dir, f"{interface_name}.conf")
|
"""
|
||||||
|
Brings `interface_name` down (disables it)
|
||||||
|
"""
|
||||||
|
config_file = util.get_interface_file_path(interface_name, base_dir)
|
||||||
check = subprocess.check_output(
|
check = subprocess.check_output(
|
||||||
"wg-quick down " + config_file, shell=True, stderr=subprocess.STDOUT
|
"wg-quick down " + config_file, shell=True, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
@ -297,7 +321,7 @@ def get_interface_peers_latest_handshakes(interface_name) -> dict:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_interface_peers_net_stats(interface_name) -> dict:
|
def get_interface_peers_net_stats(interface_name: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Get transfer from all peers of a configuration
|
Get transfer from all peers of a configuration
|
||||||
@param interface_name: Configuration name
|
@param interface_name: Configuration name
|
||||||
@ -354,14 +378,17 @@ def get_interface_peers_net_stats(interface_name) -> dict:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def quick_save_interface_config(interface_name, base_dir):
|
def quick_save_interface_config(interface_name: str, base_dir: str):
|
||||||
config_file = os.path.join(base_dir, f"{interface_name}.conf")
|
"""
|
||||||
|
Executes `wg-quick save` for `interface_name`
|
||||||
|
"""
|
||||||
|
config_file = util.get_interface_file_path(interface_name, base_dir)
|
||||||
status = subprocess.check_output(
|
status = subprocess.check_output(
|
||||||
"wg-quick save " + config_file, shell=True, stderr=subprocess.STDOUT
|
"wg-quick save " + config_file, shell=True, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def gen_public_key(private_key):
|
def gen_public_key(private_key: str):
|
||||||
"""Generate the public key.
|
"""Generate the public key.
|
||||||
|
|
||||||
@param private_key: Private key
|
@param private_key: Private key
|
||||||
@ -390,7 +417,7 @@ def gen_public_key(private_key):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_interface_peers_endpoints(interface_name) -> dict:
|
def get_interface_peers_endpoints(interface_name: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Get endpoint from all peers of a configuration
|
Get endpoint from all peers of a configuration
|
||||||
@param interface_name: Configuration name
|
@param interface_name: Configuration name
|
||||||
@ -414,7 +441,7 @@ def get_interface_peers_endpoints(interface_name) -> dict:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_interface_peers_allowed_ips(conf_peer_data, interface_name) -> dict:
|
def get_interface_peers_allowed_ips(conf_peer_data: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Get allowed ips from all peers of a configuration
|
Get allowed ips from all peers of a configuration
|
||||||
@param conf_peer_data: Configuration peer data
|
@param conf_peer_data: Configuration peer data
|
||||||
|
Loading…
Reference in New Issue
Block a user