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"]
|
||||||
|
File diff suppressed because it is too large
Load Diff
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
@ -1,8 +1,9 @@
|
|||||||
<!-- configuration.html - < WGDashboard > - Copyright(C) 2021 Donald Zou [https://github.com/donaldzou]-->
|
<!-- configuration.html - < WGDashboard > - Copyright(C) 2021 Donald Zou [https://github.com/donaldzou]-->
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
{% 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">
|
||||||
@ -10,15 +11,15 @@
|
|||||||
<h4 class="text-white">Oops!<br>I can't connect to the server.</h4>
|
<h4 class="text-white">Oops!<br>I can't connect to the server.</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include "navbar.html" %}
|
{% include "navbar.html" %}
|
||||||
<div class="container-fluid" id="right_body">
|
<div class="container-fluid" id="right_body">
|
||||||
{% include "sidebar.html" %}
|
{% include "sidebar.html" %}
|
||||||
<div class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
<div class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" class="form-control" id="search_peer_textbox" placeholder="Search Peer..." value="">
|
<input type="text" class="form-control" id="search_peer_textbox" placeholder="Search Peer..." value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="config_body">
|
<div id="config_body">
|
||||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4 mt-4 mb-4">
|
||||||
<div class="info mt-4">
|
<div class="info mt-4">
|
||||||
<div id="config_info_alert"></div>
|
<div id="config_info_alert"></div>
|
||||||
@ -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>
|
||||||
@ -77,7 +83,7 @@
|
|||||||
<div class="button-div mb-3">
|
<div class="button-div mb-3">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="sort_by_dropdown"><small class="text-muted">Sort Peers By</small></label>
|
<label for="sort_by_dropdown"><small class="text-muted">Sort Peers By</small></label>
|
||||||
<select class="form-control" id="sort_by_dropdown">
|
<select class="form-control" id="sort_by_dropdown">
|
||||||
<option value="status">Status</option>
|
<option value="status">Status</option>
|
||||||
@ -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>
|
||||||
|
|
||||||
@ -122,38 +148,42 @@
|
|||||||
<small id="peer_loading_time" class="text-muted"></small>
|
<small id="peer_loading_time" class="text-muted"></small>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="add_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
<div class="modal fade" id="add_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="staticBackdropLabel">Add New Peer</h5>
|
<h5 class="modal-title" id="staticBackdropLabel">Add New Peer</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<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>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div id="add_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
<div id="add_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>
|
||||||
<form id="add_peer_form">
|
<form id="add_peer_form">
|
||||||
<div class="form-group non-bulk">
|
<div class="form-group non-bulk">
|
||||||
<div>
|
<div>
|
||||||
<label for="private_key">Private Key</label>
|
<label for="private_key">Private Key</label>
|
||||||
@ -161,17 +191,20 @@
|
|||||||
<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"
|
||||||
</div>
|
disabled>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 non-bulk">
|
<div class="col-sm-6 non-bulk">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_name">Name</label>
|
<label for="new_add_name">Name</label>
|
||||||
<input type="text" class="form-control" id="new_add_name">
|
<input type="text" class="form-control" id="new_add_name">
|
||||||
</div>
|
</div>
|
||||||
@ -182,98 +215,110 @@
|
|||||||
<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">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_DNS">DNS <code>(Required)</code></label>
|
<label for="new_add_DNS">DNS <code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="new_add_DNS" value="{{ DNS }}">
|
<input type="text" class="form-control" id="new_add_DNS" value="{{ DNS }}">
|
||||||
</div>
|
</div>
|
||||||
</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">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_MTU">MTU</label>
|
<label for="new_add_MTU">MTU</label>
|
||||||
<input type="text" class="form-control" id="new_add_MTU" value="{{ mtu }}">
|
<input type="text" class="form-control" id="new_add_MTU" value="{{ mtu }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<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"
|
||||||
</div>
|
value="{{ keep_alive }}">
|
||||||
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</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"
|
||||||
</div>
|
conf_id={{conf_data['name']}}>Add</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal fade" id="delete_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
</div>
|
||||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
<div class="modal fade" id="delete_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
<div class="modal-content">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-header">
|
<div class="modal-content">
|
||||||
<h5 class="modal-title" id="staticBackdropLabel">Are you sure to delete this peer?</h5>
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<h5 class="modal-title" id="staticBackdropLabel">Are you sure to delete this peer?</h5>
|
||||||
<span aria-hidden="true">×</span>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
</button>
|
<span aria-hidden="true">×</span>
|
||||||
</div>
|
</button>
|
||||||
<div class="modal-body">
|
</div>
|
||||||
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none" role="alert">
|
<div class="modal-body">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
<div id="remove_peer_alert" class="alert alert-danger alert-dismissible fade show d-none"
|
||||||
<span aria-hidden="true">×</span>
|
role="alert">
|
||||||
</button>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
</div>
|
<span aria-hidden="true">×</span>
|
||||||
<h6 style="margin: 0">This action is not reversible.</h6>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<h6 style="margin: 0">This action is not reversible.</h6>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
</div>
|
||||||
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}} peer_id="">Yes</button>
|
<div class="modal-footer">
|
||||||
</div>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
|
||||||
</div>
|
<button type="button" class="btn btn-danger" id="delete_peer" conf_id={{conf_data['name']}}
|
||||||
</div>
|
peer_id="">Yes</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="modal fade" id="setting_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
<div class="modal fade" id="setting_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||||
aria-labelledby="staticBackdropLabel" aria-hidden="true" conf_id={{conf_data['name']}} peer_id="">
|
aria-labelledby="staticBackdropLabel" aria-hidden="true" conf_id={{conf_data['name']}} peer_id="">
|
||||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title peer_name"></h5>
|
<h5 class="modal-title peer_name"></h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</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"
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
role="alert">
|
||||||
<span aria-hidden="true">×</span>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
</button>
|
<span aria-hidden="true">×</span>
|
||||||
</div>
|
</button>
|
||||||
|
</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>
|
||||||
@ -285,69 +330,72 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_name_textbox" class="form-label">Name</label>
|
<label for="peer_name_textbox" class="form-label">Name</label>
|
||||||
<input type="text" class="form-control" id="peer_name_textbox" placeholder="">
|
<input type="text" class="form-control" id="peer_name_textbox" placeholder="">
|
||||||
</div>
|
</div>
|
||||||
</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
|
||||||
<input type="text" class="form-control" id="peer_allowed_ip_textbox">
|
<code>(Required)</code></label>
|
||||||
|
<input type="text" class="form-control" id="peer_allowed_ip_textbox">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_DNS_textbox" class="form-label">DNS <code>(Required)</code></label>
|
<label for="peer_DNS_textbox" class="form-label">DNS <code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="peer_DNS_textbox">
|
<input type="text" class="form-control" id="peer_DNS_textbox">
|
||||||
</div>
|
</div>
|
||||||
</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
|
||||||
<input type="text" class="form-control" id="peer_endpoint_allowed_ips">
|
<code>(Required)</code></label>
|
||||||
|
<input type="text" class="form-control" id="peer_endpoint_allowed_ips">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_mtu" class="form-label">MTU</label>
|
<label for="peer_mtu" class="form-label">MTU</label>
|
||||||
<input type="text" class="form-control" id="peer_mtu">
|
<input type="text" class="form-control" id="peer_mtu">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="peer_keep_alive" class="form-label">Persistent Keepalive</label>
|
<label for="peer_keep_alive" class="form-label">Persistent Keepalive</label>
|
||||||
<input type="text" class="form-control" id="peer_keep_alive">
|
<input type="text" class="form-control" id="peer_keep_alive">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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']}}
|
||||||
</div>
|
peer_id="">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="modal fade" id="available_ip_modal" data-backdrop="static" data-keyboard="false">
|
<div class="modal fade" id="available_ip_modal" data-backdrop="static" data-keyboard="false">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="staticBackdropLabel">Select available IP</h5>
|
<h5 class="modal-title" id="staticBackdropLabel">Select available IP</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="selected_ip" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
<div class="selected_ip" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
||||||
<small class="text-muted"><strong>SELECTED IP (CLICK TO REMOVE)</strong></small>
|
<small class="text-muted"><strong>SELECTED IP (CLICK TO REMOVE)</strong></small>
|
||||||
<div id="selected_ip_list"></div>
|
<div id="selected_ip_list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
||||||
<div class="list-group"></div>
|
<div class="list-group"></div>
|
||||||
</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="confirm_ip">Confirm</button>
|
<button type="button" class="btn btn-primary" id="confirm_ip">Confirm</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -355,57 +403,60 @@
|
|||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="staticBackdropLabel">Select Peers to Delete</h5>
|
<h5 class="modal-title" id="staticBackdropLabel">Select Peers to Delete</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
<div class="selected_peers" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
<div class="selected_peers" style="padding: 1rem; border-bottom: 1px solid #dee2e6;">
|
||||||
<small class="text-muted"><strong>SELECTED PEERS (CLICK TO REMOVE)</strong></small>
|
<small class="text-muted"><strong>SELECTED PEERS (CLICK TO REMOVE)</strong></small>
|
||||||
<div id="selected_peer_list"></div>
|
<div id="selected_peer_list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
<div class="modal-body" style="max-height: 400px; overflow-y: scroll;">
|
||||||
<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>
|
||||||
</div>
|
<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>
|
</div>
|
||||||
<div class="modal fade" id="qrcode_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
<div class="modal fade" id="qrcode_modal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">QR Code</h5>
|
<h5 class="modal-title">QR Code</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<img id="qrcode_img" style="width: 100%">
|
<img id="qrcode_img" style="width: 100%">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="position-fixed top-0 right-0 p-3" style="z-index: 5; right: 0; top: 50px;">
|
<div class="position-fixed top-0 right-0 p-3" style="z-index: 5; right: 0; top: 50px;">
|
||||||
<div id="alertToast" class="toast hide" role="alert" aria-live="assertive" aria-atomic="true" data-delay="5000">
|
<div id="alertToast" class="toast hide" role="alert" aria-live="assertive" aria-atomic="true" data-delay="5000">
|
||||||
<div class="toast-header">
|
<div class="toast-header">
|
||||||
<strong class="mr-auto">WGDashboard</strong>
|
<strong class="mr-auto">WGDashboard</strong>
|
||||||
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
|
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include "tools.html" %}
|
{% include "tools.html" %}
|
||||||
</body>
|
</body>
|
||||||
@ -418,9 +469,10 @@
|
|||||||
let load_interval = 0;
|
let load_interval = 0;
|
||||||
let conf_name = "{{ conf_data['name'] }}"
|
let conf_name = "{{ conf_data['name'] }}"
|
||||||
let peers = [];
|
let peers = [];
|
||||||
$(".sb-"+conf_name+"-url").addClass("active");
|
$(".sb-" + conf_name + "-url").addClass("active");
|
||||||
$(function(){
|
$(function () {
|
||||||
configurations.loadPeers($('#search_peer_textbox').val());
|
configurations.loadPeers($('#search_peer_textbox').val());
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</html>
|
|
||||||
|
</html>
|
@ -1,22 +1,23 @@
|
|||||||
<html>
|
<html>
|
||||||
{% with %}
|
{% with %}
|
||||||
{% 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">
|
||||||
{% include "sidebar.html" %}
|
{% include "sidebar.html" %}
|
||||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||||
<div class="setting-container mt-4">
|
<div class="setting-container mt-4">
|
||||||
{% if message != "" %}
|
{% if message != "" %}
|
||||||
<div class="alert alert-{{ status }}" role="alert">
|
<div class="alert alert-{{ status }}" role="alert">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<h1 class="">Settings</h1>
|
<h1 class="">Settings</h1>
|
||||||
<hr>
|
<hr>
|
||||||
{% if required_auth == "true" %}
|
{% if required_auth == "true" %}
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<h6 class="card-header">Peer Default Settings</h6>
|
<h6 class="card-header">Peer Default Settings</h6>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -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>
|
||||||
@ -67,8 +66,9 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<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>
|
||||||
@ -83,7 +83,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input type="text" class="form-control mb-4" id="username" name="username"
|
<input type="text" class="form-control mb-4" id="username" name="username"
|
||||||
value="{{ session['username'] }}" required>
|
value="{{ session['username'] }}" required>
|
||||||
<button type="submit" class="btn btn-danger">Update Account</button>
|
<button type="submit" class="btn btn-danger">Update Account</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -106,61 +106,65 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h6 class="card-header">Dashboard Configuration</h6>
|
<h6 class="card-header">Dashboard Configuration</h6>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="/update_app_ip_port" method="post" class="update_app_ip_port">
|
<form action="/update_app_ip_port" method="post" class="update_app_ip_port">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<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 }}">
|
||||||
IP Address.</small></p>
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<label for="app_port">Dashboard Port</label>
|
||||||
|
<input type="text" class="form-control mb-4" id="app_port" name="app_port"
|
||||||
|
value="{{ app_port }}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<button type="button" class="btn btn-danger confirm_modal" data-toggle="modal"
|
||||||
<label for="app_port">Dashboard Port</label>
|
|
||||||
<input type="text" class="form-control mb-4" id="app_port" name="app_port"
|
|
||||||
value="{{ app_port }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-danger confirm_modal" data-toggle="modal"
|
|
||||||
data-target="#confirmModal">Update Configuration & Restart Dashboard
|
data-target="#confirmModal">Update Configuration & Restart Dashboard
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<!-- Modal -->
|
||||||
<!-- Modal -->
|
<div class="modal fade" id="confirmModal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
||||||
<div class="modal fade" id="confirmModal" data-backdrop="static" data-keyboard="false" tabindex="-1"
|
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
<div class="modal-dialog">
|
||||||
<div class="modal-dialog">
|
<div class="modal-content">
|
||||||
<div class="modal-content">
|
<div class="modal-header">
|
||||||
<div class="modal-header">
|
<h5 class="modal-title" id="staticBackdropLabel">Confirm Dashboard Configuration</h5>
|
||||||
<h5 class="modal-title" id="staticBackdropLabel">Confirm Dashboard Configuration</h5>
|
</div>
|
||||||
</div>
|
<div class="modal-body">
|
||||||
<div class="modal-body">
|
<small>Dashboard Original IP</small>
|
||||||
<small>Dashboard Original IP</small>
|
<p>{{ app_ip }}</p>
|
||||||
<p>{{ app_ip }}</p>
|
<small style="font-weight: bold" class="text-bold">Dashboard New IP</small>
|
||||||
<small style="font-weight: bold" class="text-bold">Dashboard New IP</small>
|
<p class="app_new_ip text-bold text-danger" style="font-weight: bold"></p>
|
||||||
<p class="app_new_ip text-bold text-danger" style="font-weight: bold"></p>
|
<small>Dashboard Original Port</small>
|
||||||
<small>Dashboard Original Port</small>
|
<p>{{ app_port }}</p>
|
||||||
<p>{{ app_port }}</p>
|
<small style="font-weight: bold" class="text-bold">Dashboard New Port</small>
|
||||||
<small style="font-weight: bold" class="text-bold">Dashboard New Port</small>
|
<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"
|
||||||
<button type="button" class="btn btn-secondary cancel_restart" data-dismiss="modal">Cancel</button>
|
data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-danger confirm_restart">Confirm & Restart Dashboard</button>
|
<button type="button" class="btn btn-danger confirm_restart">Confirm & Restart
|
||||||
|
Dashboard</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% include "tools.html" %}
|
||||||
{% include "tools.html" %}
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
{% include "footer.html" %}
|
{% include "footer.html" %}
|
||||||
@ -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