mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 07:10:09 +01:00
Finalizing everything.
This commit is contained in:
parent
e2e8222005
commit
258564208b
19
README.md
19
README.md
@ -18,16 +18,19 @@
|
|||||||
|
|
||||||
- 🎉 **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: **
|
||||||
- **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.
|
||||||
|
|
||||||
- 🪚 **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:
|
||||||
- **🧐 Other Changes**
|
- **🧐 Other Changes**
|
||||||
- **Key generating moved to front-end**: No longer need to use the server's WireGuard to generate keys, thanks to the `wireguard.js` from the [official repository](https://git.zx2c4.com/wireguard-tools/tree/contrib/keygen-html/wireguard.js)!
|
- **Key generating moved to front-end**: No longer need to use the server's WireGuard to generate keys, thanks to the `wireguard.js` from the [official repository](https://git.zx2c4.com/wireguard-tools/tree/contrib/keygen-html/wireguard.js)!
|
||||||
- **Peer transfer calculation**: each peer will now show all transfer amount (previously was only showing transfer amount from the last configuration start-up).
|
- **Peer transfer calculation**: each peer will now show all transfer amount (previously was only showing transfer amount from the last configuration start-up).
|
||||||
@ -35,12 +38,15 @@
|
|||||||
- **`wgd.sh` finally can update itself**: So now user could update the whole dashboard from `wgd.sh`, with the `update` command.
|
- **`wgd.sh` finally can update itself**: So now user could update the whole dashboard from `wgd.sh`, with the `update` command.
|
||||||
- **Minified JS and CSS files**: Although only a small changes on the file size, but I think is still a good practice to save a bit of bandwidth ;)
|
- **Minified JS and CSS files**: Although only a small changes on the file size, but I think is still a good practice to save a bit of bandwidth ;)
|
||||||
|
|
||||||
|
|
||||||
*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:
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
## Table of Content
|
## Table of Content
|
||||||
|
|
||||||
|
|
||||||
- [💡 Features](#-features)
|
- [💡 Features](#-features)
|
||||||
- [📝 Requirement](#-requirement)
|
- [📝 Requirement](#-requirement)
|
||||||
- [🛠 Install](#-install)
|
- [🛠 Install](#-install)
|
||||||
@ -332,11 +338,18 @@ Endpoint = 0.0.0.0:51820
|
|||||||
|
|
||||||
## ❓ How to update the dashboard?
|
## ❓ How to update the dashboard?
|
||||||
|
|
||||||
|
#### **Please note for user who is using `v2.3.1` or below**
|
||||||
|
|
||||||
|
- For user who is using `v2.3.1` or below, please notice that all data that stored in the current database will **not** transfer to the new database. This is hard decision to move from TinyDB to SQLite. But SQLite does provide a thread-safe access and TinyDB doesn't. I couldn't find a safe way to transfer the data, so you need to do them manually... Sorry about that :pensive: . But I guess this would be a great start for future development :sunglasses:.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
1. Change your directory to `wgdashboard`
|
1. Change your directory to `wgdashboard`
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd wgdashboard
|
cd wgdashboard
|
||||||
```
|
```
|
||||||
|
|
||||||
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 --force
|
||||||
|
388
src/dashboard.py
388
src/dashboard.py
@ -17,6 +17,7 @@ import time
|
|||||||
import re
|
import re
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
# PIP installed library
|
# PIP installed library
|
||||||
@ -65,7 +66,6 @@ def get_dashboard_conf():
|
|||||||
Get dashboard configuration
|
Get dashboard configuration
|
||||||
@return: configparser.ConfigParser
|
@return: configparser.ConfigParser
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = configparser.ConfigParser(strict=False)
|
config = configparser.ConfigParser(strict=False)
|
||||||
config.read(DASHBOARD_CONF)
|
config.read(DASHBOARD_CONF)
|
||||||
return config
|
return config
|
||||||
@ -76,7 +76,6 @@ def set_dashboard_conf(config):
|
|||||||
Write to configuration
|
Write to configuration
|
||||||
@param config: Input configuration
|
@param config: Input configuration
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open(DASHBOARD_CONF, "w", encoding='utf-8') as conf_object:
|
with open(DASHBOARD_CONF, "w", encoding='utf-8') as conf_object:
|
||||||
config.write(conf_object)
|
config.write(conf_object)
|
||||||
|
|
||||||
@ -129,7 +128,6 @@ def get_conf_running_peer_number(config_name):
|
|||||||
return running
|
return running
|
||||||
|
|
||||||
|
|
||||||
# TODO use modules for working with ini(configparser or wireguard)
|
|
||||||
# Read [Interface] section from configuration file
|
# Read [Interface] section from configuration file
|
||||||
def read_conf_file_interface(config_name):
|
def read_conf_file_interface(config_name):
|
||||||
"""
|
"""
|
||||||
@ -154,10 +152,6 @@ def read_conf_file_interface(config_name):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
# TODO use modules for working with ini(configparser or wireguard)
|
|
||||||
# Tried to use configparser but it does not support sections with the same name
|
|
||||||
|
|
||||||
|
|
||||||
def read_conf_file(config_name):
|
def read_conf_file(config_name):
|
||||||
"""
|
"""
|
||||||
Get configurations from file of wireguard interface.
|
Get configurations from file of wireguard interface.
|
||||||
@ -375,7 +369,6 @@ def get_all_peers_data(config_name):
|
|||||||
get_allowed_ip(conf_peer_data, config_name)
|
get_allowed_ip(conf_peer_data, config_name)
|
||||||
|
|
||||||
|
|
||||||
# Search for peers
|
|
||||||
def get_peers(config_name, search, sort_t):
|
def get_peers(config_name, search, sort_t):
|
||||||
"""
|
"""
|
||||||
Get all peers.
|
Get all peers.
|
||||||
@ -428,7 +421,6 @@ def get_conf_pub_key(config_name):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
# Get configuration listen port
|
|
||||||
def get_conf_listen_port(config_name):
|
def get_conf_listen_port(config_name):
|
||||||
"""
|
"""
|
||||||
Get listen port number.
|
Get listen port number.
|
||||||
@ -452,8 +444,12 @@ def get_conf_listen_port(config_name):
|
|||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
# Get configuration total data
|
|
||||||
def get_conf_total_data(config_name):
|
def get_conf_total_data(config_name):
|
||||||
|
"""
|
||||||
|
Get configuration's total amount of data
|
||||||
|
@param config_name: Configuration name
|
||||||
|
@return: list
|
||||||
|
"""
|
||||||
data = g.cur.execute("SELECT total_sent, total_receive, cumu_sent, cumu_receive FROM " + config_name)
|
data = g.cur.execute("SELECT total_sent, total_receive, cumu_sent, cumu_receive FROM " + config_name)
|
||||||
upload_total = 0
|
upload_total = 0
|
||||||
download_total = 0
|
download_total = 0
|
||||||
@ -468,19 +464,21 @@ def get_conf_total_data(config_name):
|
|||||||
return [total, upload_total, download_total]
|
return [total, upload_total, download_total]
|
||||||
|
|
||||||
|
|
||||||
# Get configuration status
|
|
||||||
def get_conf_status(config_name):
|
def get_conf_status(config_name):
|
||||||
|
"""
|
||||||
|
Check if the configuration is running or not
|
||||||
|
@param config_name:
|
||||||
|
@return: Return a string indicate the running status
|
||||||
|
"""
|
||||||
ifconfig = dict(ifcfg.interfaces().items())
|
ifconfig = dict(ifcfg.interfaces().items())
|
||||||
|
|
||||||
return "running" if config_name in ifconfig.keys() else "stopped"
|
return "running" if config_name in ifconfig.keys() else "stopped"
|
||||||
|
|
||||||
|
|
||||||
# Get all configuration as a list
|
|
||||||
def get_conf_list():
|
def get_conf_list():
|
||||||
"""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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
conf = []
|
conf = []
|
||||||
@ -510,25 +508,13 @@ def get_conf_list():
|
|||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
# Generate private key
|
|
||||||
def gen_private_key():
|
|
||||||
subprocess.run('wg genkey > private_key.txt && wg pubkey < private_key.txt > public_key.txt', shell=True)
|
|
||||||
with open('private_key.txt', encoding='utf-8') as file_object:
|
|
||||||
private_key = file_object.readline().strip()
|
|
||||||
with open('public_key.txt', encoding='utf-8') as file_object:
|
|
||||||
public_key = file_object.readline().strip()
|
|
||||||
data = {"private_key": private_key, "public_key": public_key}
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
# Generate public key
|
|
||||||
def gen_public_key(private_key):
|
def gen_public_key(private_key):
|
||||||
"""Generate the public key.
|
"""Generate the public key.
|
||||||
|
|
||||||
:param private_key: Pricate key
|
@param private_key: Private key
|
||||||
:type private_key: str
|
@type private_key: str
|
||||||
:return: Return dict with public key or error message
|
@return: Return dict with public key or error message
|
||||||
:rtype: dict
|
@rtype: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open('private_key.txt', 'w', encoding='utf-8') as file_object:
|
with open('private_key.txt', 'w', encoding='utf-8') as file_object:
|
||||||
@ -570,8 +556,14 @@ def f_check_key_match(private_key, public_key, config_name):
|
|||||||
return {'status': 'success'}
|
return {'status': 'success'}
|
||||||
|
|
||||||
|
|
||||||
# Check if there is repeated allowed IP
|
|
||||||
def check_repeat_allowed_ip(public_key, ip, config_name):
|
def check_repeat_allowed_ip(public_key, ip, config_name):
|
||||||
|
"""
|
||||||
|
Check if there are repeated IPs
|
||||||
|
@param public_key: Public key of the peer
|
||||||
|
@param ip: IP of the peer
|
||||||
|
@param config_name: configuration name
|
||||||
|
@return: a JSON object
|
||||||
|
"""
|
||||||
peer = g.cur.execute("SELECT COUNT(*) FROM " + config_name + " WHERE id = ?", (public_key,)).fetchone()
|
peer = g.cur.execute("SELECT COUNT(*) FROM " + config_name + " WHERE id = ?", (public_key,)).fetchone()
|
||||||
if peer[0] != 1:
|
if peer[0] != 1:
|
||||||
return {'status': 'failed', 'msg': 'Peer does not exist'}
|
return {'status': 'failed', 'msg': 'Peer does not exist'}
|
||||||
@ -586,6 +578,11 @@ def check_repeat_allowed_ip(public_key, ip, config_name):
|
|||||||
|
|
||||||
|
|
||||||
def f_available_ips(config_name):
|
def f_available_ips(config_name):
|
||||||
|
"""
|
||||||
|
Get a list of available IPs
|
||||||
|
@param config_name: Configuration Name
|
||||||
|
@return: list
|
||||||
|
"""
|
||||||
config_interface = read_conf_file_interface(config_name)
|
config_interface = read_conf_file_interface(config_name)
|
||||||
if "Address" in config_interface:
|
if "Address" in config_interface:
|
||||||
existed = []
|
existed = []
|
||||||
@ -596,7 +593,6 @@ def f_available_ips(config_name):
|
|||||||
existed.append(ipaddress.ip_address(add))
|
existed.append(ipaddress.ip_address(add))
|
||||||
peers = g.cur.execute("SELECT allowed_ip FROM " + config_name).fetchall()
|
peers = g.cur.execute("SELECT allowed_ip FROM " + config_name).fetchall()
|
||||||
for i in peers:
|
for i in peers:
|
||||||
print(i[0])
|
|
||||||
add = i[0].split(",")
|
add = i[0].split(",")
|
||||||
for k in add:
|
for k in add:
|
||||||
a, s = k.split("/")
|
a, s = k.split("/")
|
||||||
@ -620,6 +616,11 @@ Flask Functions
|
|||||||
|
|
||||||
@app.teardown_request
|
@app.teardown_request
|
||||||
def close_DB(exception):
|
def close_DB(exception):
|
||||||
|
"""
|
||||||
|
Commit to the database for every request
|
||||||
|
@param exception: Exception
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
if hasattr(g, 'db'):
|
if hasattr(g, 'db'):
|
||||||
g.db.commit()
|
g.db.commit()
|
||||||
g.db.close()
|
g.db.close()
|
||||||
@ -628,6 +629,10 @@ def close_DB(exception):
|
|||||||
# Before request
|
# Before request
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def auth_req():
|
def auth_req():
|
||||||
|
"""
|
||||||
|
Action before every request
|
||||||
|
@return: Redirect
|
||||||
|
"""
|
||||||
if getattr(g, 'db', None) is None:
|
if getattr(g, 'db', None) is None:
|
||||||
g.db = connect_db()
|
g.db = connect_db()
|
||||||
g.cur = g.db.cursor()
|
g.cur = g.db.cursor()
|
||||||
@ -647,7 +652,7 @@ def auth_req():
|
|||||||
else:
|
else:
|
||||||
session['message'] = ""
|
session['message'] = ""
|
||||||
conf.clear()
|
conf.clear()
|
||||||
return redirect(url_for("signin"))
|
return redirect("/signin?redirect=" + str(request.url))
|
||||||
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']:
|
||||||
@ -662,13 +667,11 @@ Sign In / Sign Out
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# Sign In
|
|
||||||
@app.route('/signin', methods=['GET'])
|
@app.route('/signin', methods=['GET'])
|
||||||
def signin():
|
def signin():
|
||||||
"""Sign in request.
|
"""
|
||||||
|
Sign in request
|
||||||
:return: TODO
|
@return: template
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = ""
|
message = ""
|
||||||
@ -681,46 +684,43 @@ def signin():
|
|||||||
# Sign Out
|
# Sign Out
|
||||||
@app.route('/signout', methods=['GET'])
|
@app.route('/signout', methods=['GET'])
|
||||||
def signout():
|
def signout():
|
||||||
"""Sign out request.
|
|
||||||
|
|
||||||
:return: TODO
|
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
Sign out request
|
||||||
|
@return: redirect back to sign in
|
||||||
|
"""
|
||||||
if "username" in session:
|
if "username" in session:
|
||||||
session.pop("username")
|
session.pop("username")
|
||||||
message = "Sign out successfully!"
|
return redirect(url_for('signin'))
|
||||||
return render_template('signin.html', message=message)
|
|
||||||
|
|
||||||
|
|
||||||
# Authentication
|
|
||||||
@app.route('/auth', methods=['POST'])
|
@app.route('/auth', methods=['POST'])
|
||||||
def auth():
|
def auth():
|
||||||
"""Authentication request.
|
|
||||||
|
|
||||||
:return: TODO
|
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
Authentication request
|
||||||
|
@return: json object indicating verifying
|
||||||
|
"""
|
||||||
|
data = request.get_json()
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
password = hashlib.sha256(request.form['password'].encode())
|
password = hashlib.sha256(data['password'].encode())
|
||||||
if password.hexdigest() == config["Account"]["password"] \
|
if password.hexdigest() == config["Account"]["password"] \
|
||||||
and request.form['username'] == config["Account"]["username"]:
|
and data['username'] == config["Account"]["username"]:
|
||||||
session['username'] = request.form['username']
|
session['username'] = data['username']
|
||||||
config.clear()
|
config.clear()
|
||||||
return redirect(url_for("index"))
|
return jsonify({"status": True, "msg": ""})
|
||||||
|
|
||||||
session['message'] = "Username or Password is incorrect."
|
|
||||||
config.clear()
|
config.clear()
|
||||||
return redirect(url_for("signin"))
|
return jsonify({"status": False, "msg": "Username or Password is incorrect."})
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Index Page
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', methods=['GET'])
|
@app.route('/', methods=['GET'])
|
||||||
def index():
|
def index():
|
||||||
"""Index Page Related.
|
"""
|
||||||
|
Index page related
|
||||||
:return: TODO
|
@return: Template
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
msg = ""
|
msg = ""
|
||||||
if "switch_msg" in session:
|
if "switch_msg" in session:
|
||||||
@ -733,10 +733,9 @@ def index():
|
|||||||
# Setting Page
|
# Setting Page
|
||||||
@app.route('/settings', methods=['GET'])
|
@app.route('/settings', methods=['GET'])
|
||||||
def settings():
|
def settings():
|
||||||
"""Setting Page Related.
|
"""
|
||||||
|
Settings page related
|
||||||
:return: TODO
|
@return: Template
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
message = ""
|
message = ""
|
||||||
status = ""
|
status = ""
|
||||||
@ -757,13 +756,11 @@ def settings():
|
|||||||
peer_remote_endpoint=config.get("Peers", "remote_endpoint"))
|
peer_remote_endpoint=config.get("Peers", "remote_endpoint"))
|
||||||
|
|
||||||
|
|
||||||
# Update account username
|
|
||||||
@app.route('/update_acct', methods=['POST'])
|
@app.route('/update_acct', methods=['POST'])
|
||||||
def update_acct():
|
def update_acct():
|
||||||
"""Change account user name.
|
"""
|
||||||
|
Change dashboard username
|
||||||
:return: TODO
|
@return: Redirect
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if len(request.form['username']) == 0:
|
if len(request.form['username']) == 0:
|
||||||
@ -786,13 +783,12 @@ def update_acct():
|
|||||||
return redirect(url_for("settings"))
|
return redirect(url_for("settings"))
|
||||||
|
|
||||||
|
|
||||||
# Update peer default settting
|
# Update peer default setting
|
||||||
@app.route('/update_peer_default_config', methods=['POST'])
|
@app.route('/update_peer_default_config', methods=['POST'])
|
||||||
def update_peer_default_config():
|
def update_peer_default_config():
|
||||||
"""Change default configurations for peers.
|
"""
|
||||||
|
Update new peers default setting
|
||||||
:return: TODO
|
@return: None
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -860,10 +856,9 @@ def update_peer_default_config():
|
|||||||
# Update dashboard password
|
# Update dashboard password
|
||||||
@app.route('/update_pwd', methods=['POST'])
|
@app.route('/update_pwd', methods=['POST'])
|
||||||
def update_pwd():
|
def update_pwd():
|
||||||
"""Change account password.
|
"""
|
||||||
|
Update dashboard password
|
||||||
:return: TODO
|
@return: Redirect
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -894,10 +889,11 @@ def update_pwd():
|
|||||||
return redirect(url_for("settings"))
|
return redirect(url_for("settings"))
|
||||||
|
|
||||||
|
|
||||||
# Update dashboard IP and port
|
|
||||||
@app.route('/update_app_ip_port', methods=['POST'])
|
@app.route('/update_app_ip_port', methods=['POST'])
|
||||||
def update_app_ip_port():
|
def update_app_ip_port():
|
||||||
"""Change port number of dashboard.
|
"""
|
||||||
|
Update dashboard ip and port
|
||||||
|
@return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -905,13 +901,15 @@ 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('bash wgd.sh restart')
|
os.system('./wgd.sh restart')
|
||||||
|
|
||||||
|
|
||||||
# Update WireGuard configuration file path
|
# Update WireGuard configuration file path
|
||||||
@app.route('/update_wg_conf_path', methods=['POST'])
|
@app.route('/update_wg_conf_path', methods=['POST'])
|
||||||
def update_wg_conf_path():
|
def update_wg_conf_path():
|
||||||
"""Change path to dashboard configuration.
|
"""
|
||||||
|
Update configuration path
|
||||||
|
@return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -920,13 +918,14 @@ 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('bash wgd.sh restart')
|
os.system('./wgd.sh restart')
|
||||||
|
|
||||||
|
|
||||||
# Update configuration sorting
|
|
||||||
@app.route('/update_dashboard_sort', methods=['POST'])
|
@app.route('/update_dashboard_sort', methods=['POST'])
|
||||||
def update_dashbaord_sort():
|
def update_dashbaord_sort():
|
||||||
"""Configuration Page Related
|
"""
|
||||||
|
Update configuration sorting
|
||||||
|
@return: Boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -944,10 +943,10 @@ def update_dashbaord_sort():
|
|||||||
# Update configuration refresh interval
|
# Update configuration refresh interval
|
||||||
@app.route('/update_dashboard_refresh_interval', methods=['POST'])
|
@app.route('/update_dashboard_refresh_interval', methods=['POST'])
|
||||||
def update_dashboard_refresh_interval():
|
def update_dashboard_refresh_interval():
|
||||||
"""Change the refresh time.
|
"""
|
||||||
|
Change the refresh time.
|
||||||
:return: Return text with result
|
@return: Return text with result
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
preset_interval = ["5000", "10000", "30000", "60000"]
|
preset_interval = ["5000", "10000", "30000", "60000"]
|
||||||
@ -964,12 +963,11 @@ def update_dashboard_refresh_interval():
|
|||||||
# Configuration Page
|
# Configuration Page
|
||||||
@app.route('/configuration/<config_name>', methods=['GET'])
|
@app.route('/configuration/<config_name>', methods=['GET'])
|
||||||
def configuration(config_name):
|
def configuration(config_name):
|
||||||
"""Show wireguard interface view.
|
"""
|
||||||
|
Show wireguard interface view.
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: TODO
|
@return: Template
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
@ -1004,12 +1002,11 @@ def configuration(config_name):
|
|||||||
# Get configuration details
|
# Get configuration details
|
||||||
@app.route('/get_config/<config_name>', methods=['GET'])
|
@app.route('/get_config/<config_name>', methods=['GET'])
|
||||||
def get_conf(config_name):
|
def get_conf(config_name):
|
||||||
"""Get configuration setting of wireguard interface.
|
"""
|
||||||
|
Get configuration setting of wireguard interface.
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: TODO
|
@return: TODO
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config_interface = read_conf_file_interface(config_name)
|
config_interface = read_conf_file_interface(config_name)
|
||||||
@ -1050,12 +1047,11 @@ def get_conf(config_name):
|
|||||||
# Turn on / off a configuration
|
# Turn on / off a configuration
|
||||||
@app.route('/switch/<config_name>', methods=['GET'])
|
@app.route('/switch/<config_name>', methods=['GET'])
|
||||||
def switch(config_name):
|
def switch(config_name):
|
||||||
"""On/off the wireguard interface.
|
"""
|
||||||
|
On/off the wireguard interface.
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: TODO
|
@return: redirects
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
status = get_conf_status(config_name)
|
status = get_conf_status(config_name)
|
||||||
@ -1078,6 +1074,11 @@ def switch(config_name):
|
|||||||
|
|
||||||
@app.route('/add_peer_bulk/<config_name>', methods=['POST'])
|
@app.route('/add_peer_bulk/<config_name>', methods=['POST'])
|
||||||
def add_peer_bulk(config_name):
|
def add_peer_bulk(config_name):
|
||||||
|
"""
|
||||||
|
Add peers by bulk
|
||||||
|
@param config_name: Configuration Name
|
||||||
|
@return: String
|
||||||
|
"""
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
keys = data['keys']
|
keys = data['keys']
|
||||||
endpoint_allowed_ip = data['endpoint_allowed_ip']
|
endpoint_allowed_ip = data['endpoint_allowed_ip']
|
||||||
@ -1138,9 +1139,13 @@ def add_peer_bulk(config_name):
|
|||||||
return exc.output.strip()
|
return exc.output.strip()
|
||||||
|
|
||||||
|
|
||||||
# Add peer
|
|
||||||
@app.route('/add_peer/<config_name>', methods=['POST'])
|
@app.route('/add_peer/<config_name>', methods=['POST'])
|
||||||
def add_peer(config_name):
|
def add_peer(config_name):
|
||||||
|
"""
|
||||||
|
Add Peers
|
||||||
|
@param config_name: configuration name
|
||||||
|
@return: string
|
||||||
|
"""
|
||||||
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']
|
||||||
@ -1172,7 +1177,6 @@ def add_peer(config_name):
|
|||||||
if enable_preshared_key:
|
if enable_preshared_key:
|
||||||
now = str(datetime.now().strftime("%m%d%Y%H%M%S"))
|
now = str(datetime.now().strftime("%m%d%Y%H%M%S"))
|
||||||
f_name = now + "_tmp_psk.txt"
|
f_name = now + "_tmp_psk.txt"
|
||||||
print(f_name)
|
|
||||||
f = open(f_name, "w+")
|
f = open(f_name, "w+")
|
||||||
f.write(preshared_key)
|
f.write(preshared_key)
|
||||||
f.close()
|
f.close()
|
||||||
@ -1192,15 +1196,14 @@ def add_peer(config_name):
|
|||||||
return exc.output.strip()
|
return exc.output.strip()
|
||||||
|
|
||||||
|
|
||||||
# Remove peer
|
|
||||||
@app.route('/remove_peer/<config_name>', methods=['POST'])
|
@app.route('/remove_peer/<config_name>', methods=['POST'])
|
||||||
def remove_peer(config_name):
|
def remove_peer(config_name):
|
||||||
"""Remove peer.
|
"""
|
||||||
|
Remove peer.
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: Return result of action or recommendations
|
@return: Return result of action or recommendations
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if get_conf_status(config_name) == "stopped":
|
if get_conf_status(config_name) == "stopped":
|
||||||
@ -1231,15 +1234,14 @@ def remove_peer(config_name):
|
|||||||
return "true"
|
return "true"
|
||||||
|
|
||||||
|
|
||||||
# Save peer settings
|
|
||||||
@app.route('/save_peer_setting/<config_name>', methods=['POST'])
|
@app.route('/save_peer_setting/<config_name>', methods=['POST'])
|
||||||
def save_peer_setting(config_name):
|
def save_peer_setting(config_name):
|
||||||
"""Save peer configuration.
|
"""
|
||||||
|
Save peer configuration.
|
||||||
|
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: Return status of action and text with recommendations
|
@return: Return status of action and text with recommendations
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -1296,12 +1298,12 @@ def save_peer_setting(config_name):
|
|||||||
# Get peer settings
|
# Get peer settings
|
||||||
@app.route('/get_peer_data/<config_name>', methods=['POST'])
|
@app.route('/get_peer_data/<config_name>', methods=['POST'])
|
||||||
def get_peer_name(config_name):
|
def get_peer_name(config_name):
|
||||||
"""Get peer settings.
|
"""
|
||||||
|
Get peer settings.
|
||||||
|
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: Return settings of peer
|
@return: Return settings of peer
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -1321,41 +1323,14 @@ def available_ips(config_name):
|
|||||||
return jsonify(f_available_ips(config_name))
|
return jsonify(f_available_ips(config_name))
|
||||||
|
|
||||||
|
|
||||||
# Generate a private key
|
|
||||||
@app.route('/generate_peer', methods=['GET'])
|
|
||||||
def generate_peer():
|
|
||||||
"""Generate the private key for peer.
|
|
||||||
|
|
||||||
:return: Return dict with private, public and preshared keys
|
|
||||||
:rtype: TODO
|
|
||||||
"""
|
|
||||||
|
|
||||||
return jsonify(gen_private_key())
|
|
||||||
|
|
||||||
|
|
||||||
# Generate a public key from a private key
|
|
||||||
@app.route('/generate_public_key', methods=['POST'])
|
|
||||||
def generate_public_key():
|
|
||||||
"""Generate the public key.
|
|
||||||
|
|
||||||
:return: Return dict with public key or error message
|
|
||||||
:rtype: TODO
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
private_key = data['private_key']
|
|
||||||
return jsonify(gen_public_key(private_key))
|
|
||||||
|
|
||||||
|
|
||||||
# Check if both key match
|
# Check if both key match
|
||||||
@app.route('/check_key_match/<config_name>', methods=['POST'])
|
@app.route('/check_key_match/<config_name>', methods=['POST'])
|
||||||
def check_key_match(config_name):
|
def check_key_match(config_name):
|
||||||
"""TODO
|
"""
|
||||||
|
Check key matches
|
||||||
:param config_name: Name of WG interface
|
@param config_name: Name of WG interface
|
||||||
:type config_name: str
|
@type config_name: str
|
||||||
:return: Return dictionary with status
|
@return: Return dictionary with status
|
||||||
:rtype: TODO
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -1366,6 +1341,11 @@ def check_key_match(config_name):
|
|||||||
|
|
||||||
@app.route("/qrcode/<config_name>", methods=['GET'])
|
@app.route("/qrcode/<config_name>", methods=['GET'])
|
||||||
def generate_qrcode(config_name):
|
def generate_qrcode(config_name):
|
||||||
|
"""
|
||||||
|
Generate QRCode
|
||||||
|
@param config_name: Configuration Name
|
||||||
|
@return: Template containing QRcode img
|
||||||
|
"""
|
||||||
peer_id = request.args.get('id')
|
peer_id = request.args.get('id')
|
||||||
get_peer = g.cur.execute(
|
get_peer = g.cur.execute(
|
||||||
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key FROM "
|
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key FROM "
|
||||||
@ -1396,9 +1376,13 @@ def generate_qrcode(config_name):
|
|||||||
return redirect("/configuration/" + config_name)
|
return redirect("/configuration/" + config_name)
|
||||||
|
|
||||||
|
|
||||||
# Download all configuration file
|
|
||||||
@app.route('/download_all/<config_name>', methods=['GET'])
|
@app.route('/download_all/<config_name>', methods=['GET'])
|
||||||
def download_all(config_name):
|
def download_all(config_name):
|
||||||
|
"""
|
||||||
|
Download all configuration
|
||||||
|
@param config_name: Configuration Name
|
||||||
|
@return: JSON Object
|
||||||
|
"""
|
||||||
get_peer = g.cur.execute(
|
get_peer = g.cur.execute(
|
||||||
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key, name FROM "
|
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key, name FROM "
|
||||||
+ config_name + " WHERE private_key != ''").fetchall()
|
+ config_name + " WHERE private_key != ''").fetchall()
|
||||||
@ -1445,6 +1429,11 @@ def download_all(config_name):
|
|||||||
# Download configuration file
|
# Download configuration file
|
||||||
@app.route('/download/<config_name>', methods=['GET'])
|
@app.route('/download/<config_name>', methods=['GET'])
|
||||||
def download(config_name):
|
def download(config_name):
|
||||||
|
"""
|
||||||
|
Download one configuration
|
||||||
|
@param config_name: Configuration name
|
||||||
|
@return: JSON object
|
||||||
|
"""
|
||||||
peer_id = request.args.get('id')
|
peer_id = request.args.get('id')
|
||||||
get_peer = g.cur.execute(
|
get_peer = g.cur.execute(
|
||||||
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key, name FROM "
|
"SELECT private_key, allowed_ip, DNS, mtu, endpoint_allowed_ip, keepalive, preshared_key, name FROM "
|
||||||
@ -1491,15 +1480,15 @@ def download(config_name):
|
|||||||
return jsonify({"status": False, "filename": "", "content": ""})
|
return jsonify({"status": False, "filename": "", "content": ""})
|
||||||
|
|
||||||
|
|
||||||
# Switch peer display mode
|
|
||||||
@app.route('/switch_display_mode/<mode>', methods=['GET'])
|
@app.route('/switch_display_mode/<mode>', methods=['GET'])
|
||||||
def switch_display_mode(mode):
|
def switch_display_mode(mode):
|
||||||
"""Change display view style.
|
"""
|
||||||
|
Change display view style.
|
||||||
|
|
||||||
:param mode: Mode name
|
@param mode: Mode name
|
||||||
:type mode: str
|
@type mode: str
|
||||||
:return: Return text with result
|
@return: Return text with result
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if mode in ['list', 'grid']:
|
if mode in ['list', 'grid']:
|
||||||
@ -1519,10 +1508,11 @@ Dashboard Tools Related
|
|||||||
# Get all IP for ping
|
# Get all IP for ping
|
||||||
@app.route('/get_ping_ip', methods=['POST'])
|
@app.route('/get_ping_ip', methods=['POST'])
|
||||||
def get_ping_ip():
|
def get_ping_ip():
|
||||||
"""Get ips for network testing.
|
# TODO: convert return to json object
|
||||||
|
|
||||||
:return: TODO
|
"""
|
||||||
:rtype: TODO
|
Get ips for network testing.
|
||||||
|
@return: HTML containing a list of IPs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = request.form['config']
|
config = request.form['config']
|
||||||
@ -1545,10 +1535,10 @@ def get_ping_ip():
|
|||||||
# Ping IP
|
# Ping IP
|
||||||
@app.route('/ping_ip', methods=['POST'])
|
@app.route('/ping_ip', methods=['POST'])
|
||||||
def ping_ip():
|
def ping_ip():
|
||||||
"""Execute ping command.
|
"""
|
||||||
|
Execute ping command.
|
||||||
:return: Return text with result
|
@return: Return text with result
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1573,10 +1563,11 @@ def ping_ip():
|
|||||||
# Traceroute IP
|
# Traceroute IP
|
||||||
@app.route('/traceroute_ip', methods=['POST'])
|
@app.route('/traceroute_ip', methods=['POST'])
|
||||||
def traceroute_ip():
|
def traceroute_ip():
|
||||||
"""Execute ping traceroute command.
|
"""
|
||||||
|
Execute ping traceroute command.
|
||||||
|
|
||||||
:return: Return text with result
|
@return: Return text with result
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1600,21 +1591,22 @@ Dashboard Initialization
|
|||||||
|
|
||||||
|
|
||||||
def init_dashboard():
|
def init_dashboard():
|
||||||
"""Create dashboard default configuration.
|
"""
|
||||||
|
Create dashboard default configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Set Default INI File
|
# Set Default INI File
|
||||||
if not os.path.isfile(DASHBOARD_CONF):
|
if not os.path.isfile(DASHBOARD_CONF):
|
||||||
open(DASHBOARD_CONF, "w+").close()
|
open(DASHBOARD_CONF, "w+").close()
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
# Defualt dashboard account setting
|
# Default dashboard account setting
|
||||||
if "Account" not in config:
|
if "Account" not in config:
|
||||||
config['Account'] = {}
|
config['Account'] = {}
|
||||||
if "username" not in config['Account']:
|
if "username" not in config['Account']:
|
||||||
config['Account']['username'] = 'admin'
|
config['Account']['username'] = 'admin'
|
||||||
if "password" not in config['Account']:
|
if "password" not in config['Account']:
|
||||||
config['Account']['password'] = '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918'
|
config['Account']['password'] = '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918'
|
||||||
# Defualt dashboard server setting
|
# Default dashboard server setting
|
||||||
if "Server" not in config:
|
if "Server" not in config:
|
||||||
config['Server'] = {}
|
config['Server'] = {}
|
||||||
if 'wg_conf_path' not in config['Server']:
|
if 'wg_conf_path' not in config['Server']:
|
||||||
@ -1651,24 +1643,28 @@ def init_dashboard():
|
|||||||
|
|
||||||
|
|
||||||
def check_update():
|
def check_update():
|
||||||
"""Dashboard check update
|
"""
|
||||||
|
Dashboard check update
|
||||||
|
|
||||||
:return: Retunt text with result
|
@return: Retunt text with result
|
||||||
:rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
data = urllib.request.urlopen("https://api.github.com/repos/donaldzou/WGDashboard/releases").read()
|
try:
|
||||||
output = json.loads(data)
|
data = urllib.request.urlopen("https://api.github.com/repos/donaldzou/WGDashboard/releases").read()
|
||||||
release = []
|
output = json.loads(data)
|
||||||
for i in output:
|
release = []
|
||||||
if not i["prerelease"]:
|
for i in output:
|
||||||
release.append(i)
|
if not i["prerelease"]:
|
||||||
if config.get("Server", "version") == release[0]["tag_name"]:
|
release.append(i)
|
||||||
result = "false"
|
if config.get("Server", "version") == release[0]["tag_name"]:
|
||||||
else:
|
result = "false"
|
||||||
result = "true"
|
else:
|
||||||
|
result = "true"
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
except urllib.error.HTTPError:
|
||||||
|
return "false"
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
Flask
|
Flask
|
||||||
tinydb==4.5.2
|
|
||||||
ifcfg
|
ifcfg
|
||||||
icmplib
|
icmplib
|
||||||
flask-qrcode
|
flask-qrcode
|
||||||
|
@ -16,11 +16,10 @@
|
|||||||
<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>
|
||||||
<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-danger" role="alert">
|
<div class="alert alert-warning" role="alert">You need to sign in first</div>
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="alert alert-danger d-none" role="alert"></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> Username</label>
|
||||||
<input type="text" class="form-control" id="username" name="username" required>
|
<input type="text" class="form-control" id="username" name="username" required>
|
||||||
@ -37,20 +36,43 @@
|
|||||||
</body>
|
</body>
|
||||||
{% include "footer.html" %}
|
{% include "footer.html" %}
|
||||||
<script>
|
<script>
|
||||||
$("button").on("click", function(){
|
$("button").on("click", function(e){
|
||||||
let req = $("input[required]");
|
let req = $("input[required]");
|
||||||
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");
|
$("button").html("Sign In");
|
||||||
check = false;
|
check = false;
|
||||||
|
$("input[required]").addClass("is-invalid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (check){
|
if (check){
|
||||||
$(this).html("Signing In...");
|
e.preventDefault();
|
||||||
|
$(this).html("Signing In...").attr("disabled", "disabled");
|
||||||
|
$.ajax({
|
||||||
|
url: "/auth",
|
||||||
|
method: "POST",
|
||||||
|
headers:{"Content-Type": "application/json"},
|
||||||
|
data: JSON.stringify({
|
||||||
|
"username": $("#username").val(),
|
||||||
|
"password": $("#password").val()
|
||||||
|
})
|
||||||
|
}).done(function(res){
|
||||||
|
if (res.status === true){
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
if (urlParams.get("redirect")){
|
||||||
|
window.location.replace(urlParams.get("redirect"))
|
||||||
|
}else{
|
||||||
|
window.location.replace("/");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$(".alert").html(res.msg).removeClass("d-none");
|
||||||
|
$("button").html("Sign In").removeAttr("disabled");
|
||||||
|
$("input[required]").addClass("is-invalid");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
45
src/wgd.sh
45
src/wgd.sh
@ -4,6 +4,7 @@
|
|||||||
# Under Apache-2.0 License
|
# Under Apache-2.0 License
|
||||||
app_name="dashboard.py"
|
app_name="dashboard.py"
|
||||||
app_official_name="WGDashboard"
|
app_official_name="WGDashboard"
|
||||||
|
PID_FILE=./gunicorn.pid
|
||||||
environment=$(if [[ $ENVIRONMENT ]]; then echo $ENVIRONMENT; else echo 'develop'; fi)
|
environment=$(if [[ $ENVIRONMENT ]]; then echo $ENVIRONMENT; else echo 'develop'; fi)
|
||||||
if [[ $CONFIGURATION_PATH ]]; then
|
if [[ $CONFIGURATION_PATH ]]; then
|
||||||
cb_work_dir=$CONFIGURATION_PATH/letsencrypt/work-dir
|
cb_work_dir=$CONFIGURATION_PATH/letsencrypt/work-dir
|
||||||
@ -66,18 +67,12 @@ install_wgd(){
|
|||||||
|
|
||||||
|
|
||||||
check_wgd_status(){
|
check_wgd_status(){
|
||||||
if [[ $environment == 'production' ]]; then
|
if test -f "$PID_FILE"; then
|
||||||
PID_FILE=./gunicorn.pid
|
if ps aux | grep -v grep | grep $(cat ./gunicorn.pid) > /dev/null; then
|
||||||
if test -f "$PID_FILE"; then
|
return 0
|
||||||
if ps aux | grep -v grep | grep $(cat ./gunicorn.pid) > /dev/null; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
if ps aux | grep -v grep | grep '[p]ython3 '$app_name > /dev/null; then
|
if ps aux | grep -v grep | grep '[p]ython3 '$app_name > /dev/null; then
|
||||||
return 0
|
return 0
|
||||||
@ -96,15 +91,8 @@ certbot_renew_ssl () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gunicorn_start () {
|
gunicorn_start () {
|
||||||
# if [[ $SSL ]]; then
|
|
||||||
# if [ ! -d $cb_config_dir ]; then
|
|
||||||
# certbot_create_ssl
|
|
||||||
# else
|
|
||||||
# certbot_renew_ssl
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
printf "%s\n" "$dashes"
|
printf "%s\n" "$dashes"
|
||||||
printf "| Starting WGDashboard in the background. |\n"
|
printf "| Starting WGDashboard with Gunicorn in the background. |\n"
|
||||||
if [ ! -d "log" ]; then
|
if [ ! -d "log" ]; then
|
||||||
mkdir "log"
|
mkdir "log"
|
||||||
fi
|
fi
|
||||||
@ -112,15 +100,8 @@ gunicorn_start () {
|
|||||||
if [[ $USER == root ]]; then
|
if [[ $USER == root ]]; then
|
||||||
export PATH=$PATH:/usr/local/bin:$HOME/.local/bin
|
export PATH=$PATH:/usr/local/bin:$HOME/.local/bin
|
||||||
fi
|
fi
|
||||||
# if [[ $SSL ]]; then
|
|
||||||
# gunicorn --certfile $cb_config_dir/live/"$SERVERURL"/cert.pem \
|
|
||||||
# --keyfile $cb_config_dir/live/"$SERVERURL"/privkey.pem \
|
|
||||||
# --access-logfile log/access_"$d".log \
|
|
||||||
# --error-logfile log/error_"$d".log 'dashboard:run_dashboard()'
|
|
||||||
# else
|
|
||||||
gunicorn --access-logfile log/access_"$d".log \
|
gunicorn --access-logfile log/access_"$d".log \
|
||||||
--error-logfile log/error_"$d".log 'dashboard:run_dashboard()'
|
--error-logfile log/error_"$d".log 'dashboard:run_dashboard()'
|
||||||
# fi
|
|
||||||
printf "| Log files is under log/ |\n"
|
printf "| Log files is under log/ |\n"
|
||||||
printf "%s\n" "$dashes"
|
printf "%s\n" "$dashes"
|
||||||
}
|
}
|
||||||
@ -130,23 +111,11 @@ gunicorn_stop () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start_wgd () {
|
start_wgd () {
|
||||||
if [[ $environment == 'production' ]]; then
|
gunicorn_start
|
||||||
gunicorn_start
|
|
||||||
else
|
|
||||||
printf "%s\n" "$dashes"
|
|
||||||
printf "| Starting WGDashboard in the background. |\n"
|
|
||||||
if [ ! -d "log" ]
|
|
||||||
then mkdir "log"
|
|
||||||
fi
|
|
||||||
d=$(date '+%Y%m%d%H%M%S')
|
|
||||||
python3 "$app_name" > log/"$d".txt 2>&1 &
|
|
||||||
printf "| Log files is under log/ |\n"
|
|
||||||
printf "%s\n" "$dashes"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_wgd() {
|
stop_wgd() {
|
||||||
if [[ $environment == 'production' ]]; then
|
if test -f "$PID_FILE"; then
|
||||||
gunicorn_stop
|
gunicorn_stop
|
||||||
else
|
else
|
||||||
kill "$(ps aux | grep "[p]ython3 $app_name" | awk '{print $2}')"
|
kill "$(ps aux | grep "[p]ython3 $app_name" | awk '{print $2}')"
|
||||||
|
Loading…
Reference in New Issue
Block a user