mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-10-04 00:06:18 +00:00
Compare commits
36 Commits
v3.0-beta.
...
v3.0.6
Author | SHA1 | Date | |
---|---|---|---|
|
d52cd2b17c | ||
|
cefa80f317 | ||
|
191ff1abec | ||
|
3bb86493cc | ||
|
d1d3151e1e | ||
|
f9dc9ebdb3 | ||
|
3b478bcc2d | ||
|
77bb78c381 | ||
|
cafa97f502 | ||
|
0d858493d5 | ||
|
99fb07c6b3 | ||
|
eaad971c0a | ||
|
377abd87fd | ||
|
af71176296 | ||
|
69737177ef | ||
|
efae1222c1 | ||
|
3caea1a903 | ||
|
a43478d627 | ||
|
ed2c3f43c7 | ||
|
fcfd816cec | ||
|
2e3977e59c | ||
|
3c68430336 | ||
|
43afb86fa8 | ||
|
194ccbdbb4 | ||
|
7139e230cf | ||
|
120d3b9f54 | ||
|
712460a040 | ||
|
be5594f1c9 | ||
|
0a885117db | ||
|
5b73654544 | ||
|
1485b78b7b | ||
|
bfec57172a | ||
|
9f8559c12d | ||
|
83dde12ca9 | ||
|
d17888db4e | ||
|
096529af96 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,4 @@
|
|||||||
.vscode/sftp.json
|
.vscode
|
||||||
src/.vscode/sftp.json
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
src/db
|
src/db
|
||||||
|
62
README.md
62
README.md
@@ -10,6 +10,7 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard"></a>
|
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard"></a>
|
||||||
<a href="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6"><img src="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6.svg" alt="wakatime"></a>
|
<a href="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6"><img src="https://wakatime.com/badge/user/45f53c7c-9da9-4cb0-85d6-17bd38cc748b/project/5334ae20-e9a6-4c55-9fea-52d4eb9dfba6.svg" alt="wakatime"></a>
|
||||||
|
<a href="https://hits.seeyoufarm.com"><img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fdonaldzou%2FWGDashboard&count_bg=%2379C83D&title_bg=%23555555&icon=github.svg&icon_color=%23E7E7E7&title=Visitor&edge_flat=false"/></a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">Monitoring WireGuard is not convinient, need to login into server and type <code>wg show</code>. That's why this platform is being created, to view all configurations and manage them in a easier way.</p>
|
<p align="center">Monitoring WireGuard is not convinient, need to login into server and type <code>wg show</code>. That's why this platform is being created, to view all configurations and manage them in a easier way.</p>
|
||||||
<p align="center"><small>Note: This project is not affiliate to the official WireGuard Project ;)</small></p>
|
<p align="center"><small>Note: This project is not affiliate to the official WireGuard Project ;)</small></p>
|
||||||
@@ -18,17 +19,18 @@
|
|||||||
|
|
||||||
- 🎉 **New Features**
|
- 🎉 **New Features**
|
||||||
- **Moved from TinyDB to SQLite**: SQLite provide a better performance and loading speed when getting peers! Also avoided crashing the database due to **race condition**.
|
- **Moved from TinyDB to SQLite**: SQLite provide a better performance and loading speed when getting peers! Also avoided crashing the database due to **race condition**.
|
||||||
- **Added Gunicorn WSGI Server**: This could provide more stable on handling HTTP request, and more flexibility in the future (such as HTTPS support). **BIG THANKS to @pgalonza :heart: **
|
- **Added Gunicorn WSGI Server**: This could provide more stable on handling HTTP request, and more flexibility in the future (such as HTTPS support). **BIG THANKS to @pgalonza :heart:**
|
||||||
- **Add Peers by Bulk: ** User can add peers by bulk, just simply set the amount and click add.
|
- **Add Peers by Bulk:** User can add peers by bulk, just simply set the amount and click add.
|
||||||
- **Delete Peers by Bulk**: User can delete peers by bulk, without deleting peers one by one.
|
- **Delete Peers by Bulk**: User can delete peers by bulk, without deleting peers one by one.
|
||||||
- **Download Peers in Zip**: User can download all *downloadable* peers in a zip.
|
- **Download Peers in Zip**: User can download all *downloadable* peers in a zip.
|
||||||
- **Added Pre-shared Key to peers:** Now each peer can add with a pre-shared key to enhance security. Previously added peers can add the pre-shared key through the peer setting button.
|
- **Added Pre-shared Key to peers:** Now each peer can add with a pre-shared key to enhance security. Previously added peers can add the pre-shared key through the peer setting button.
|
||||||
- **Redirect Back to Previous Page:** The dashboard will now redirect you back to your previous page if the current session got timed out and you need to sign in again.
|
- **Redirect Back to Previous Page:** The dashboard will now redirect you back to your previous page if the current session got timed out and you need to sign in again.
|
||||||
|
- **Added Some [🥘 Experimental Functions](#-experimental-functions)**
|
||||||
|
|
||||||
- 🪚 **Bug Fixed**
|
- 🪚 **Bug Fixed**
|
||||||
- [IP Sorting range issues #99](https://github.com/donaldzou/WGDashboard/issues/99) [❤️ @barryboom]
|
- [IP Sorting range issues #99](https://github.com/donaldzou/WGDashboard/issues/99) [❤️ @barryboom]
|
||||||
- [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ ikidd]
|
- [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ikidd]
|
||||||
- [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @ pgalonza]
|
- [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @pgalonza]
|
||||||
- [Added MTU and PersistentKeepalive to QR code and download files #112](https://github.com/donaldzou/WGDashboard/pull/112) [:heart: @reafian]
|
- [Added MTU and PersistentKeepalive to QR code and download files #112](https://github.com/donaldzou/WGDashboard/pull/112) [:heart: @reafian]
|
||||||
- **And many other bugs provided by our beloved users** :heart:
|
- **And many other bugs provided by our beloved users** :heart:
|
||||||
- **🧐 Other Changes**
|
- **🧐 Other Changes**
|
||||||
@@ -40,7 +42,9 @@
|
|||||||
|
|
||||||
*And many other small changes for performance and bug fixes! :laughing:*
|
*And many other small changes for performance and bug fixes! :laughing:*
|
||||||
|
|
||||||
> If you have any other brilliant ideas for this project, please shout it in here [#129](https://github.com/donaldzou/WGDashboard/issues/129) :heart:
|
> If you have any other brilliant ideas for this project, please shout it in here [#129](https://github.com/donaldzou/WGDashboard/issues/129) :heart:
|
||||||
|
|
||||||
|
**For users who is using `v2.x.x` please be sure to read [this](#please-note-for-user-who-is-using-v231-or-below) before updating WGDashboard ;)**
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
@@ -57,6 +61,7 @@
|
|||||||
- [Dashboard Configuration file](#dashboard-configuration-file)
|
- [Dashboard Configuration file](#dashboard-configuration-file)
|
||||||
- [Generating QR code and peer configuration file (.conf)](#generating-qr-code-and-peer-configuration-file-conf)
|
- [Generating QR code and peer configuration file (.conf)](#generating-qr-code-and-peer-configuration-file-conf)
|
||||||
- [❓ How to update the dashboard?](#-how-to-update-the-dashboard)
|
- [❓ How to update the dashboard?](#-how-to-update-the-dashboard)
|
||||||
|
- [🥘 Experimental Functions](#-experimental-functions)
|
||||||
- [🔍 Screenshot](#-screenshot)
|
- [🔍 Screenshot](#-screenshot)
|
||||||
- [⏰ Changelog](#--changelog)
|
- [⏰ Changelog](#--changelog)
|
||||||
- [🛒 Dependencies](#-dependencies)
|
- [🛒 Dependencies](#-dependencies)
|
||||||
@@ -111,7 +116,7 @@
|
|||||||
1. Download WGDashboard
|
1. Download WGDashboard
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone -b v3.0 https://github.com/donaldzou/WGDashboard.git wgdashboard
|
git clone -b v3.0.6 https://github.com/donaldzou/WGDashboard.git wgdashboard
|
||||||
|
|
||||||
2. Open the WGDashboard folder
|
2. Open the WGDashboard folder
|
||||||
|
|
||||||
@@ -297,7 +302,7 @@ Since version 2.0, WGDashboard will be using a configuration file called `wg-das
|
|||||||
| `app_ip` | IP address the dashboard will run with | `0.0.0.0` | Yes |
|
| `app_ip` | IP address the dashboard will run with | `0.0.0.0` | Yes |
|
||||||
| `app_port` | Port the the dashboard will run with | `10086` | Yes |
|
| `app_port` | Port the the dashboard will run with | `10086` | Yes |
|
||||||
| `auth_req` | Does the dashboard need authentication to access, if `auth_req = false` , user will not be access the **Setting** tab due to security consideration. **User can only edit the file directly in system**. | `true` | **No** |
|
| `auth_req` | Does the dashboard need authentication to access, if `auth_req = false` , user will not be access the **Setting** tab due to security consideration. **User can only edit the file directly in system**. | `true` | **No** |
|
||||||
| `version` | Dashboard Version | `v3.0` | **No** |
|
| `version` | Dashboard Version | `v3.0.6` | **No** |
|
||||||
| `dashboard_refresh_interval` | How frequent the dashboard will refresh on the configuration page | `60000ms` | Yes |
|
| `dashboard_refresh_interval` | How frequent the dashboard will refresh on the configuration page | `60000ms` | Yes |
|
||||||
| `dashboard_sort` | How configuration is sorting | `status` | Yes |
|
| `dashboard_sort` | How configuration is sorting | `status` | Yes |
|
||||||
| | | | |
|
| | | | |
|
||||||
@@ -344,19 +349,56 @@ Endpoint = 0.0.0.0:51820
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
#### Update Method 1 (For `v3.0` or above)
|
||||||
|
|
||||||
|
1. Change your directory to `wgdashboard/src`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd wgdashboard/src
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Update the dashboard with the following
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./wgd.sh update
|
||||||
|
```
|
||||||
|
|
||||||
|
> If this doesn't work, please use the method below. Sorry about that :(
|
||||||
|
|
||||||
|
#### Update Method 2
|
||||||
|
|
||||||
|
|
||||||
1. Change your directory to `wgdashboard`
|
1. Change your directory to `wgdashboard`
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd wgdashboard
|
cd wgdashboard/src
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Update the dashboard
|
2. Update the dashboard
|
||||||
```shell
|
```shell
|
||||||
git pull https://github.com/donaldzou/WGDashboard.git v3.0 --force
|
git pull https://github.com/donaldzou/WGDashboard.git v3.0.6 --force
|
||||||
```
|
```
|
||||||
|
|
||||||
|
3. Install
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./wgd.sh install
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Starting with `v3.0`, you can simply do `./wgd.sh update` !! (I hope, lol)
|
Starting with `v3.0`, you can simply do `./wgd.sh update` !! (I hope, lol)
|
||||||
|
|
||||||
|
## 🥘 Experimental Functions
|
||||||
|
|
||||||
|
#### Progressive Web App (PWA) for WGDashboard
|
||||||
|
|
||||||
|
- With `v3.0`, I've added a `manifest.json` into the dashboard, so user could add their dashboard as a PWA to their browser or mobile device.
|
||||||
|
|
||||||
|
<img src="img/PWA.gif"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 🔍 Screenshot
|
## 🔍 Screenshot
|
||||||
|
|
||||||

|

|
||||||
|
BIN
img/PWA.gif
Normal file
BIN
img/PWA.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 MiB |
@@ -4,7 +4,6 @@ Under Apache-2.0 License
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from flask import g
|
|
||||||
import configparser
|
import configparser
|
||||||
import hashlib
|
import hashlib
|
||||||
import ipaddress
|
import ipaddress
|
||||||
@@ -22,7 +21,7 @@ from datetime import datetime, timedelta
|
|||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
# PIP installed library
|
# PIP installed library
|
||||||
import ifcfg
|
import ifcfg
|
||||||
from flask import Flask, request, render_template, redirect, url_for, session, jsonify
|
from flask import Flask, request, render_template, redirect, url_for, session, jsonify, g
|
||||||
from flask_qrcode import QRcode
|
from flask_qrcode import QRcode
|
||||||
from icmplib import ping, traceroute
|
from icmplib import ping, traceroute
|
||||||
|
|
||||||
@@ -31,22 +30,27 @@ from util import regex_match, check_DNS, check_Allowed_IPs, check_remote_endpoin
|
|||||||
check_IP_with_range, clean_IP_with_range
|
check_IP_with_range, clean_IP_with_range
|
||||||
|
|
||||||
# Dashboard Version
|
# Dashboard Version
|
||||||
DASHBOARD_VERSION = 'v3.0'
|
DASHBOARD_VERSION = 'v3.0.6'
|
||||||
|
|
||||||
# WireGuard's configuration path
|
# WireGuard's configuration path
|
||||||
WG_CONF_PATH = None
|
WG_CONF_PATH = None
|
||||||
|
|
||||||
# Dashboard Config Name
|
# Dashboard Config Name
|
||||||
configuration_path = os.getenv('CONFIGURATION_PATH', '.')
|
configuration_path = os.getenv('CONFIGURATION_PATH', '.')
|
||||||
DB_PATH = os.path.join(configuration_path, 'db')
|
DB_PATH = os.path.join(configuration_path, 'db')
|
||||||
if not os.path.isdir(DB_PATH):
|
if not os.path.isdir(DB_PATH):
|
||||||
os.mkdir(DB_PATH)
|
os.mkdir(DB_PATH)
|
||||||
DASHBOARD_CONF = os.path.join(configuration_path, 'wg-dashboard.ini')
|
DASHBOARD_CONF = os.path.join(configuration_path, 'wg-dashboard.ini')
|
||||||
|
|
||||||
# Upgrade Required
|
# Upgrade Required
|
||||||
UPDATE = None
|
UPDATE = None
|
||||||
|
|
||||||
# Flask App Configuration
|
# Flask App Configuration
|
||||||
app = Flask("WGDashboard")
|
app = Flask("WGDashboard")
|
||||||
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 5206928
|
||||||
app.secret_key = secrets.token_urlsafe(16)
|
app.secret_key = secrets.token_urlsafe(16)
|
||||||
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||||
|
|
||||||
# Enable QR Code Generator
|
# Enable QR Code Generator
|
||||||
QRcode(app)
|
QRcode(app)
|
||||||
|
|
||||||
@@ -66,9 +70,9 @@ def get_dashboard_conf():
|
|||||||
Get dashboard configuration
|
Get dashboard configuration
|
||||||
@return: configparser.ConfigParser
|
@return: configparser.ConfigParser
|
||||||
"""
|
"""
|
||||||
config = configparser.ConfigParser(strict=False)
|
r_config = configparser.ConfigParser(strict=False)
|
||||||
config.read(DASHBOARD_CONF)
|
r_config.read(DASHBOARD_CONF)
|
||||||
return config
|
return r_config
|
||||||
|
|
||||||
|
|
||||||
def set_dashboard_conf(config):
|
def set_dashboard_conf(config):
|
||||||
@@ -99,7 +103,6 @@ def get_conf_peer_key(config_name):
|
|||||||
return config_name + " is not running."
|
return config_name + " is not running."
|
||||||
|
|
||||||
|
|
||||||
# Get numbers of connected peer of a configuration
|
|
||||||
def get_conf_running_peer_number(config_name):
|
def get_conf_running_peer_number(config_name):
|
||||||
"""
|
"""
|
||||||
Get number of running peers on wireguard interface.
|
Get number of running peers on wireguard interface.
|
||||||
@@ -128,7 +131,6 @@ def get_conf_running_peer_number(config_name):
|
|||||||
return running
|
return running
|
||||||
|
|
||||||
|
|
||||||
# Read [Interface] section from configuration file
|
|
||||||
def read_conf_file_interface(config_name):
|
def read_conf_file_interface(config_name):
|
||||||
"""
|
"""
|
||||||
Get interface settings.
|
Get interface settings.
|
||||||
@@ -161,7 +163,6 @@ def read_conf_file(config_name):
|
|||||||
@rtype: dict
|
@rtype: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Read Configuration File Start
|
|
||||||
conf_location = WG_CONF_PATH + "/" + config_name + ".conf"
|
conf_location = WG_CONF_PATH + "/" + config_name + ".conf"
|
||||||
f = open(conf_location, 'r')
|
f = open(conf_location, 'r')
|
||||||
file = f.read().split("\n")
|
file = f.read().split("\n")
|
||||||
@@ -190,7 +191,7 @@ def read_conf_file(config_name):
|
|||||||
conf_peer_data["Peers"].append({})
|
conf_peer_data["Peers"].append({})
|
||||||
elif peer > -1:
|
elif peer > -1:
|
||||||
if len(i) > 0:
|
if len(i) > 0:
|
||||||
tmp = re.split('\s*=\s*', i, 1)
|
tmp = re.split(r'\s*=\s*', i, 1)
|
||||||
if len(tmp) == 2:
|
if len(tmp) == 2:
|
||||||
conf_peer_data["Peers"][peer][tmp[0]] = tmp[1]
|
conf_peer_data["Peers"][peer][tmp[0]] = tmp[1]
|
||||||
|
|
||||||
@@ -224,10 +225,10 @@ def get_latest_handshake(config_name):
|
|||||||
status = "stopped"
|
status = "stopped"
|
||||||
if int(data_usage[count + 1]) > 0:
|
if int(data_usage[count + 1]) > 0:
|
||||||
g.cur.execute("UPDATE %s SET latest_handshake = '%s', status = '%s' WHERE id='%s'"
|
g.cur.execute("UPDATE %s SET latest_handshake = '%s', status = '%s' WHERE id='%s'"
|
||||||
% (config_name, str(minus).split(".", maxsplit=1)[0], status, data_usage[count]))
|
% (config_name, str(minus).split(".", maxsplit=1)[0], status, data_usage[count]))
|
||||||
else:
|
else:
|
||||||
g.cur.execute("UPDATE %s SET latest_handshake = '(None)', status = '%s' WHERE id='%s'"
|
g.cur.execute("UPDATE %s SET latest_handshake = '(None)', status = '%s' WHERE id='%s'"
|
||||||
% (config_name, status, data_usage[count]))
|
% (config_name, status, data_usage[count]))
|
||||||
count += 2
|
count += 2
|
||||||
|
|
||||||
|
|
||||||
@@ -294,6 +295,7 @@ def get_endpoint(config_name):
|
|||||||
count += 2
|
count += 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_allowed_ip(conf_peer_data, config_name):
|
def get_allowed_ip(conf_peer_data, config_name):
|
||||||
"""
|
"""
|
||||||
Get allowed ips from all peers of a configuration
|
Get allowed ips from all peers of a configuration
|
||||||
@@ -626,7 +628,6 @@ def close_DB(exception):
|
|||||||
g.db.close()
|
g.db.close()
|
||||||
|
|
||||||
|
|
||||||
# Before request
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def auth_req():
|
def auth_req():
|
||||||
"""
|
"""
|
||||||
@@ -652,7 +653,10 @@ def auth_req():
|
|||||||
else:
|
else:
|
||||||
session['message'] = ""
|
session['message'] = ""
|
||||||
conf.clear()
|
conf.clear()
|
||||||
return redirect("/signin?redirect=" + str(request.url))
|
redirectURL = str(request.url)
|
||||||
|
redirectURL = redirectURL.replace("http://", "")
|
||||||
|
redirectURL = redirectURL.replace("https://", "")
|
||||||
|
return redirect("/signin?redirect=" + redirectURL)
|
||||||
else:
|
else:
|
||||||
if request.endpoint in ['signin', 'signout', 'auth', 'settings', 'update_acct', 'update_pwd',
|
if request.endpoint in ['signin', 'signout', 'auth', 'settings', 'update_acct', 'update_pwd',
|
||||||
'update_app_ip_port', 'update_wg_conf_path']:
|
'update_app_ip_port', 'update_wg_conf_path']:
|
||||||
@@ -678,7 +682,7 @@ def signin():
|
|||||||
if "message" in session:
|
if "message" in session:
|
||||||
message = session['message']
|
message = session['message']
|
||||||
session.pop("message")
|
session.pop("message")
|
||||||
return render_template('signin.html', message=message)
|
return render_template('signin.html', message=message, version=DASHBOARD_VERSION)
|
||||||
|
|
||||||
|
|
||||||
# Sign Out
|
# Sign Out
|
||||||
@@ -901,7 +905,8 @@ def update_app_ip_port():
|
|||||||
config.set("Server", "app_port", request.form['app_port'])
|
config.set("Server", "app_port", request.form['app_port'])
|
||||||
set_dashboard_conf(config)
|
set_dashboard_conf(config)
|
||||||
config.clear()
|
config.clear()
|
||||||
os.system('./wgd.sh restart')
|
subprocess.Popen('bash wgd.sh restart', shell=True)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
# Update WireGuard configuration file path
|
# Update WireGuard configuration file path
|
||||||
@@ -918,7 +923,7 @@ def update_wg_conf_path():
|
|||||||
config.clear()
|
config.clear()
|
||||||
session['message'] = "WireGuard Configuration Path Update Successfully!"
|
session['message'] = "WireGuard Configuration Path Update Successfully!"
|
||||||
session['message_status'] = "success"
|
session['message_status'] = "success"
|
||||||
os.system('./wgd.sh restart')
|
subprocess.Popen('bash wgd.sh restart', shell=True)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/update_dashboard_sort', methods=['POST'])
|
@app.route('/update_dashboard_sort', methods=['POST'])
|
||||||
@@ -1699,11 +1704,11 @@ def get_host_bind():
|
|||||||
config.read('wg-dashboard.ini')
|
config.read('wg-dashboard.ini')
|
||||||
app_ip = config.get("Server", "app_ip")
|
app_ip = config.get("Server", "app_ip")
|
||||||
app_port = config.get("Server", "app_port")
|
app_port = config.get("Server", "app_port")
|
||||||
|
|
||||||
return app_ip, app_port
|
return app_ip, app_port
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
init_dashboard()
|
||||||
UPDATE = check_update()
|
UPDATE = check_update()
|
||||||
config = configparser.ConfigParser(strict=False)
|
config = configparser.ConfigParser(strict=False)
|
||||||
config.read('wg-dashboard.ini')
|
config.read('wg-dashboard.ini')
|
||||||
|
BIN
src/static/.DS_Store
vendored
BIN
src/static/.DS_Store
vendored
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
body {
|
body {
|
||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
|
/*font-family: 'Poppins', sans-serif;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.feather {
|
.feather {
|
||||||
@@ -407,8 +408,26 @@ main{
|
|||||||
|
|
||||||
.btn{
|
.btn{
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
/*padding: 0.6rem 0.9em;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#username, #password{
|
||||||
|
padding: 0.6rem calc( 0.9rem + 32px );
|
||||||
|
height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
label[for="username"], label[for="password"]{
|
||||||
|
font-size: 1rem;
|
||||||
|
margin: 0 !important;
|
||||||
|
transform: translateY(30px) translateX(16px);
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*label[for="password"]{*/
|
||||||
|
/* transform: translateY(32px) translateX(16px);*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
|
||||||
.modal-content{
|
.modal-content{
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
2
src/static/css/dashboard.min.css
vendored
2
src/static/css/dashboard.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -338,8 +338,12 @@
|
|||||||
* Load Peers from server to configuration page
|
* Load Peers from server to configuration page
|
||||||
* @param searchString
|
* @param searchString
|
||||||
*/
|
*/
|
||||||
|
let d1 = new Date();
|
||||||
|
let time = 0;
|
||||||
|
let count = 0;
|
||||||
function loadPeers(searchString){
|
function loadPeers(searchString){
|
||||||
startProgressBar();
|
startProgressBar();
|
||||||
|
d1 = new Date();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `/get_config/${conf_name}?search=${encodeURIComponent(searchString)}`,
|
url: `/get_config/${conf_name}?search=${encodeURIComponent(searchString)}`,
|
||||||
@@ -354,6 +358,12 @@
|
|||||||
$(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
|
$(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
|
||||||
$("i[data-toggle='tooltip']").tooltip();
|
$("i[data-toggle='tooltip']").tooltip();
|
||||||
endProgressBar();
|
endProgressBar();
|
||||||
|
let d2 = new Date();
|
||||||
|
let seconds = (d2 - d1);
|
||||||
|
time += seconds;
|
||||||
|
count += 1;
|
||||||
|
console.log(`Average ${time/count}ms`);
|
||||||
|
$("#peer_loading_time").html(`Peer Loading Time: ${seconds}ms`);
|
||||||
}).fail(function(){
|
}).fail(function(){
|
||||||
noResponding();
|
noResponding();
|
||||||
});
|
});
|
||||||
|
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
@@ -171,6 +171,17 @@
|
|||||||
return String.fromCharCode.apply(null, base64);
|
return String.fromCharCode.apply(null, base64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function base64ToKey(base64) {
|
||||||
|
let binary_string = window.atob(base64);
|
||||||
|
let len = binary_string.length;
|
||||||
|
let bytes = new Uint8Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
bytes[i] = binary_string.charCodeAt(i);
|
||||||
|
}
|
||||||
|
let uint8 = new Uint8Array(bytes.buffer);
|
||||||
|
return uint8;
|
||||||
|
}
|
||||||
|
|
||||||
function putU32(b, n)
|
function putU32(b, n)
|
||||||
{
|
{
|
||||||
b.push(n & 0xff, (n >>> 8) & 0xff, (n >>> 16) & 0xff, (n >>> 24) & 0xff);
|
b.push(n & 0xff, (n >>> 8) & 0xff, (n >>> 16) & 0xff, (n >>> 24) & 0xff);
|
||||||
@@ -282,7 +293,8 @@
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
generatePublicKey: function (privateKey){
|
generatePublicKey: function (privateKey){
|
||||||
return keyToBase64(generatePublicKey(privateKey))
|
privateKey = base64ToKey(privateKey);
|
||||||
|
return keyToBase64(generatePublicKey(privateKey));
|
||||||
},
|
},
|
||||||
|
|
||||||
generateZipFiles: function(res){
|
generateZipFiles: function(res){
|
||||||
|
2
src/static/js/wireguard.min.js
vendored
2
src/static/js/wireguard.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -11,7 +11,6 @@
|
|||||||
</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">
|
||||||
@@ -120,6 +119,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row peer_list"></div>
|
<div class="row peer_list"></div>
|
||||||
|
<small id="peer_loading_time" class="text-muted"></small>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -14,41 +14,46 @@
|
|||||||
<div class="container-fluid login-container-fluid">
|
<div class="container-fluid login-container-fluid">
|
||||||
<main role="main" class="container login-container">
|
<main role="main" class="container login-container">
|
||||||
<div class="login-box" style="margin: auto !important;">
|
<div class="login-box" style="margin: auto !important;">
|
||||||
<h1 class="text-center">Sign In</h1>
|
<h1 class="text-center">Sign in</h1>
|
||||||
|
<h5 class="text-center">to WGDashboard</h5>
|
||||||
<form style="margin-left: auto !important; margin-right: auto !important; max-width: 500px;" action="/auth" method="post">
|
<form style="margin-left: auto !important; margin-right: auto !important; max-width: 500px;" action="/auth" method="post">
|
||||||
{% if message != "" %}
|
{% if message != "" %}
|
||||||
<div class="alert alert-warning" role="alert">You need to sign in first</div>
|
<div class="alert alert-warning" role="alert">You need to sign in first</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="alert alert-danger d-none" role="alert"></div>
|
<div class="alert alert-danger d-none" role="alert" style="margin-top: 1rem; margin-bottom: 0rem;"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username" class="text-left" style="font-size: 1rem"><i class="bi bi-person-circle"></i> Username</label>
|
<label for="username" class="text-left" style="font-size: 1rem"><i class="bi bi-person-circle"></i></label>
|
||||||
<input type="text" class="form-control" id="username" name="username" required>
|
<input type="text" class="form-control" id="username" name="username" placeholder="Your username" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i> Password</label>
|
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i></label>
|
||||||
<input type="password" class="form-control" id="password" name="password" required>
|
<input type="password" class="form-control" id="password" name="password" placeholder="Your password" required>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-dark" style="width: 100%;">Sign In</button>
|
<button type="submit" class="btn btn-dark" style="width: 100%">Sign In</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
<small class="text-muted" style="position: fixed; bottom: 0; width: 100%; text-align: center; margin-bottom: 2rem">Version: {{ version }}</small>
|
||||||
</body>
|
</body>
|
||||||
{% include "footer.html" %}
|
{% include "footer.html" %}
|
||||||
<script>
|
<script>
|
||||||
$("button").on("click", function(e){
|
let loginButton = $('button[type="submit"]');
|
||||||
let req = $("input[required]");
|
loginButton.on("click", function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
let $password = $("#password");
|
||||||
|
let $username = $("#username");
|
||||||
|
let req = [$password, $username];
|
||||||
let check = true
|
let check = true
|
||||||
for (let i = 0; i < req.length; i++){
|
for (let i = 0; i < req.length; i++){
|
||||||
if ($(req[i]).val().length === 0){
|
if ($(req[i]).val().length === 0){
|
||||||
$("button").html("Sign In");
|
loginButton.html("Sign In");
|
||||||
check = false;
|
check = false;
|
||||||
$("input[required]").addClass("is-invalid");
|
$(req[i]).addClass("is-invalid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (check){
|
if (check){
|
||||||
e.preventDefault();
|
|
||||||
$(this).html("Signing In...").attr("disabled", "disabled");
|
$(this).html("Signing In...").attr("disabled", "disabled");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/auth",
|
url: "/auth",
|
||||||
@@ -62,13 +67,17 @@
|
|||||||
if (res.status === true){
|
if (res.status === true){
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
if (urlParams.get("redirect")){
|
if (urlParams.get("redirect")){
|
||||||
window.location.replace(urlParams.get("redirect"))
|
if (document.URL.substring(0, 5) == "http:"){
|
||||||
|
window.location.replace(`http://${urlParams.get("redirect")}`)
|
||||||
|
}else if (document.URL.substring(0, 5) == "https"){
|
||||||
|
window.location.replace(`https://${urlParams.get("redirect")}`)
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
window.location.replace("/");
|
window.location.replace("/");
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
$(".alert").html(res.msg).removeClass("d-none");
|
$(".alert").html(res.msg).removeClass("d-none").fadeIn();
|
||||||
$("button").html("Sign In").removeAttr("disabled");
|
loginButton.html("Sign In").removeAttr("disabled");
|
||||||
$("input[required]").addClass("is-invalid");
|
$("input[required]").addClass("is-invalid");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
3
src/wgd.sh
Executable file → Normal file
3
src/wgd.sh
Executable file → Normal file
@@ -33,6 +33,7 @@ help () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_check_and_set_venv(){
|
_check_and_set_venv(){
|
||||||
|
# This function will not be using in v3.0
|
||||||
# deb/ubuntu users: might need a 'apt install python3.8-venv'
|
# deb/ubuntu users: might need a 'apt install python3.8-venv'
|
||||||
# set up the local environment
|
# set up the local environment
|
||||||
APP_ROOT=`pwd`
|
APP_ROOT=`pwd`
|
||||||
@@ -192,7 +193,7 @@ if [ "$#" != 1 ];
|
|||||||
printf "%s\n" "$dashes"
|
printf "%s\n" "$dashes"
|
||||||
stop_wgd
|
stop_wgd
|
||||||
printf "| WGDashboard is stopped. |\n"
|
printf "| WGDashboard is stopped. |\n"
|
||||||
sleep 2
|
sleep 4
|
||||||
start_wgd
|
start_wgd
|
||||||
else
|
else
|
||||||
start_wgd
|
start_wgd
|
||||||
|
Reference in New Issue
Block a user