Refactored some files
244
src/api.py
@ -1,244 +0,0 @@
|
|||||||
import ipaddress, subprocess, datetime, os, util
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from flask import jsonify
|
|
||||||
from util import *
|
|
||||||
import configparser
|
|
||||||
|
|
||||||
notEnoughParameter = {"status": False, "reason": "Please provide all required parameters."}
|
|
||||||
good = {"status": True, "reason": ""}
|
|
||||||
|
|
||||||
def ret(status=True, reason="", data=""):
|
|
||||||
return {"status": status, "reason": reason, "data": data}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def togglePeerAccess(data, g):
|
|
||||||
checkUnlock = g.cur.execute(f"SELECT * FROM {data['config']} WHERE id='{data['peerID']}'").fetchone()
|
|
||||||
if checkUnlock:
|
|
||||||
moveUnlockToLock = g.cur.execute(
|
|
||||||
f"INSERT INTO {data['config']}_restrict_access SELECT * FROM {data['config']} WHERE id = '{data['peerID']}'")
|
|
||||||
if g.cur.rowcount == 1:
|
|
||||||
print(g.cur.rowcount)
|
|
||||||
print(util.deletePeers(data['config'], [data['peerID']], g.cur, g.db))
|
|
||||||
else:
|
|
||||||
moveLockToUnlock = g.cur.execute(
|
|
||||||
f"SELECT * FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'").fetchone()
|
|
||||||
try:
|
|
||||||
if len(moveLockToUnlock[-1]) == 0:
|
|
||||||
status = subprocess.check_output(
|
|
||||||
f"wg set {data['config']} peer {moveLockToUnlock[0]} allowed-ips {moveLockToUnlock[11]}",
|
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
|
||||||
else:
|
|
||||||
now = str(datetime.datetime.now().strftime("%m%d%Y%H%M%S"))
|
|
||||||
f_name = now + "_tmp_psk.txt"
|
|
||||||
f = open(f_name, "w+")
|
|
||||||
f.write(moveLockToUnlock[-1])
|
|
||||||
f.close()
|
|
||||||
subprocess.check_output(
|
|
||||||
f"wg set {data['config']} peer {moveLockToUnlock[0]} allowed-ips {moveLockToUnlock[11]} preshared-key {f_name}",
|
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
|
||||||
os.remove(f_name)
|
|
||||||
status = subprocess.check_output(f"wg-quick save {data['config']}", shell=True, stderr=subprocess.STDOUT)
|
|
||||||
g.cur.execute(
|
|
||||||
f"INSERT INTO {data['config']} SELECT * FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'")
|
|
||||||
if g.cur.rowcount == 1:
|
|
||||||
g.cur.execute(f"DELETE FROM {data['config']}_restrict_access WHERE id = '{data['peerID']}'")
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as exc:
|
|
||||||
return {"status": False, "reason": str(exc.output.strip())}
|
|
||||||
return good
|
|
||||||
|
|
||||||
class managePeer:
|
|
||||||
def getPeerDataUsage(self, data, cur):
|
|
||||||
now = datetime.now()
|
|
||||||
now_string = now.strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
interval = {
|
|
||||||
"30min": now - timedelta(hours=0, minutes=30),
|
|
||||||
"1h": now - timedelta(hours=1, minutes=0),
|
|
||||||
"6h": now - timedelta(hours=6, minutes=0),
|
|
||||||
"24h": now - timedelta(hours=24, minutes=0),
|
|
||||||
"all": ""
|
|
||||||
}
|
|
||||||
if data['interval'] not in interval.keys():
|
|
||||||
return {"status": False, "reason": "Invalid interval."}
|
|
||||||
intv = ""
|
|
||||||
if data['interval'] != "all":
|
|
||||||
t = interval[data['interval']].strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
intv = f" AND time >= '{t}'"
|
|
||||||
timeData = cur.execute(f"SELECT total_receive, total_sent, time FROM wg0_transfer WHERE id='{data['peerID']}' {intv} ORDER BY time DESC;")
|
|
||||||
chartData = []
|
|
||||||
for i in timeData:
|
|
||||||
chartData.append({
|
|
||||||
"total_receive": i[0],
|
|
||||||
"total_sent": i[1],
|
|
||||||
"time": i[2]
|
|
||||||
})
|
|
||||||
return {"status": True, "reason": "", "data": chartData}
|
|
||||||
|
|
||||||
class manageConfiguration:
|
|
||||||
def AddressCheck(self, data):
|
|
||||||
address = data['address']
|
|
||||||
address = address.replace(" ", "")
|
|
||||||
address = address.split(',')
|
|
||||||
amount = 0
|
|
||||||
for i in address:
|
|
||||||
try:
|
|
||||||
ips = ipaddress.ip_network(i, False)
|
|
||||||
amount += ips.num_addresses
|
|
||||||
except ValueError as e:
|
|
||||||
return {"status": False, "reason": str(e)}
|
|
||||||
if amount >= 1:
|
|
||||||
return {"status": True, "reason": "", "data": f"Total of {amount} IPs"}
|
|
||||||
else:
|
|
||||||
return {"status": True, "reason": "", "data": f"0 available IPs"}
|
|
||||||
|
|
||||||
def PortCheck(self, data, configs):
|
|
||||||
port = data['port']
|
|
||||||
if (not port.isdigit()) or int(port) < 1 or int(port) > 65535:
|
|
||||||
return {"status": False, "reason": f"Invalid port."}
|
|
||||||
for i in configs:
|
|
||||||
if i['port'] == port:
|
|
||||||
return {"status": False, "reason": f"{port} used by {i['conf']}."}
|
|
||||||
checkSystem = subprocess.run(f'ss -tulpn | grep :{port} > /dev/null', shell=True)
|
|
||||||
if checkSystem.returncode != 1:
|
|
||||||
return {"status": False, "reason": f"Port {port} used by other process in your system."}
|
|
||||||
return good
|
|
||||||
|
|
||||||
def NameCheck(self, data, configs):
|
|
||||||
name = data['name']
|
|
||||||
name = name.replace(" ", "")
|
|
||||||
for i in configs:
|
|
||||||
if name == i['conf']:
|
|
||||||
return {"status": False, "reason": f"{name} already existed."}
|
|
||||||
illegal_filename = ["(Space)", " ", ".", ",", "/", "?", "<", ">", "\\", ":", "*", '|' '\"', "com1", "com2",
|
|
||||||
"com3",
|
|
||||||
"com4", "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4",
|
|
||||||
"lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "con", "nul", "prn"]
|
|
||||||
for i in illegal_filename:
|
|
||||||
name = name.replace(i, "")
|
|
||||||
if len(name) == 0:
|
|
||||||
return {"status": False, "reason": "Invalid name."}
|
|
||||||
return good
|
|
||||||
|
|
||||||
def addConfiguration(self, data, configs, WG_CONF_PATH):
|
|
||||||
output = ["[Interface]", "SaveConfig = true"]
|
|
||||||
required = ['addConfigurationPrivateKey', 'addConfigurationListenPort',
|
|
||||||
'addConfigurationAddress', 'addConfigurationPreUp', 'addConfigurationPreDown',
|
|
||||||
'addConfigurationPostUp', 'addConfigurationPostDown']
|
|
||||||
for i in required:
|
|
||||||
e = data[i]
|
|
||||||
if len(e) != 0:
|
|
||||||
key = i.replace("addConfiguration", "")
|
|
||||||
o = f"{key} = {e}"
|
|
||||||
output.append(o)
|
|
||||||
name = data['addConfigurationName']
|
|
||||||
illegal_filename = ["(Space)", " ", ".", ",", "/", "?", "<", ">", "\\", ":", "*", '|' '\"', "com1", "com2",
|
|
||||||
"com3",
|
|
||||||
"com4", "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4",
|
|
||||||
"lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "con", "nul", "prn"]
|
|
||||||
for i in illegal_filename:
|
|
||||||
name = name.replace(i, "")
|
|
||||||
|
|
||||||
try:
|
|
||||||
newFile = open(f"{WG_CONF_PATH}/{name}.conf", "w+")
|
|
||||||
newFile.write("\n".join(output))
|
|
||||||
except Exception as e:
|
|
||||||
return {"status": False, "reason": str(e)}
|
|
||||||
return {"status": True, "reason": "", "data": name}
|
|
||||||
|
|
||||||
def deleteConfiguration(self, data, config, g, WG_CONF_PATH):
|
|
||||||
confs = []
|
|
||||||
for i in config:
|
|
||||||
confs.append(i['conf'])
|
|
||||||
print(confs)
|
|
||||||
if data['name'] not in confs:
|
|
||||||
return {"status": False, "reason": "Configuration does not exist", "data": ""}
|
|
||||||
for i in config:
|
|
||||||
if i['conf'] == data['name']:
|
|
||||||
if i['status'] == "running":
|
|
||||||
try:
|
|
||||||
subprocess.check_output("wg-quick down " + data['name'], shell=True, stderr=subprocess.STDOUT)
|
|
||||||
except subprocess.CalledProcessError as exc:
|
|
||||||
return {"status": False, "reason": "Can't stop peer", "data": str(exc.output.strip().decode("utf-8"))}
|
|
||||||
|
|
||||||
g.cur.execute(f'DROP TABLE {data["name"]}')
|
|
||||||
g.cur.execute(f'DROP TABLE {data["name"]}_restrict_access')
|
|
||||||
g.db.commit()
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.remove(f'{WG_CONF_PATH}/{data["name"]}.conf')
|
|
||||||
except Exception as e:
|
|
||||||
return {"status": False, "reason": "Can't delete peer", "data": str(e)}
|
|
||||||
|
|
||||||
return good
|
|
||||||
|
|
||||||
def getConfigurationInfo(self, configName, WG_CONF_PATH):
|
|
||||||
conf = configparser.RawConfigParser(strict=False)
|
|
||||||
conf.optionxform = str
|
|
||||||
try:
|
|
||||||
with open(f'{WG_CONF_PATH}/{configName}.conf', 'r'):
|
|
||||||
conf.read(f'{WG_CONF_PATH}/{configName}.conf')
|
|
||||||
if not conf.has_section("Interface"):
|
|
||||||
return ret(status=False, reason="No [Interface] in configuration file")
|
|
||||||
return ret(data=dict(conf['Interface']))
|
|
||||||
except FileNotFoundError as err:
|
|
||||||
return ret(status=False, reason=str(err))
|
|
||||||
|
|
||||||
def saveConfiguration(self, data, WG_CONF_PATH, configs):
|
|
||||||
conf = configparser.RawConfigParser(strict=False)
|
|
||||||
conf.optionxform = str
|
|
||||||
configName = data['configurationName']
|
|
||||||
pc = manageConfiguration.PortCheck(self, {'port': data['ListenPort']}, configs)
|
|
||||||
if pc['status']:
|
|
||||||
try:
|
|
||||||
newData = []
|
|
||||||
with open(f'{WG_CONF_PATH}/{configName}.conf', 'r') as f:
|
|
||||||
conf.read(f'{WG_CONF_PATH}/{configName}.conf')
|
|
||||||
if not conf.has_section("Interface"):
|
|
||||||
return ret(status=False, reason="No [Interface] in configuration file")
|
|
||||||
l = ['ListenPort', 'PostUp', 'PostDown', 'PreUp', 'PreDown']
|
|
||||||
for i in l:
|
|
||||||
conf.set("Interface", i, data[i])
|
|
||||||
conf.remove_section("Peer")
|
|
||||||
newData = list(map(lambda x : f"{x[0]} = {x[1]}\n", list(conf.items("Interface"))))
|
|
||||||
originalData = f.readlines()
|
|
||||||
for i in range(len(originalData)):
|
|
||||||
if originalData[i] == "[Peer]\n":
|
|
||||||
originalData = originalData[i:]
|
|
||||||
break
|
|
||||||
newData.insert(0, "[Interface]\n")
|
|
||||||
newData.append("\n")
|
|
||||||
newData = newData + originalData
|
|
||||||
conf.clear()
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
check = subprocess.check_output("wg-quick down " + configName,
|
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
|
||||||
except subprocess.CalledProcessError as exc:
|
|
||||||
pass
|
|
||||||
with open(f'{WG_CONF_PATH}/{configName}.conf', 'w') as f:
|
|
||||||
for i in newData:
|
|
||||||
f.write(i)
|
|
||||||
try:
|
|
||||||
check = subprocess.check_output("wg-quick up " + configName,
|
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
|
||||||
except subprocess.CalledProcessError as exc:
|
|
||||||
pass
|
|
||||||
return ret()
|
|
||||||
except FileNotFoundError as err:
|
|
||||||
return ret(status=False, reason=str(err))
|
|
||||||
else:
|
|
||||||
return pc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class settings:
|
|
||||||
def setTheme(self, theme, config, setConfig):
|
|
||||||
themes = ['light', 'dark']
|
|
||||||
if theme not in themes:
|
|
||||||
return ret(status=False, reason="Theme does not exist")
|
|
||||||
config['Server']['dashboard_theme'] = theme
|
|
||||||
setConfig(config)
|
|
||||||
return ret()
|
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
8
src/static/app/dist/json/manifest.json
vendored
@ -21,22 +21,22 @@
|
|||||||
],
|
],
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-192x192.png",
|
"src": "../img/icon-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-256x256.png",
|
"src": "../img/icon-256x256.png",
|
||||||
"sizes": "256x256",
|
"sizes": "256x256",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-384x384.png",
|
"src": "../img/icon-384x384.png",
|
||||||
"sizes": "384x384",
|
"sizes": "384x384",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-512x512.png",
|
"src": "../img/icon-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
BIN
src/static/app/public/img/192x192ios.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
src/static/app/public/img/icon-192x192.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/static/app/public/img/icon-256x256.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/static/app/public/img/icon-384x384.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
src/static/app/public/img/icon-512x512.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
src/static/app/public/img/logo.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
src/static/app/public/img/wireguard_logo.png
Normal file
After Width: | Height: | Size: 80 KiB |
@ -21,22 +21,22 @@
|
|||||||
],
|
],
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-192x192.png",
|
"src": "../img/icon-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-256x256.png",
|
"src": "../img/icon-256x256.png",
|
||||||
"sizes": "256x256",
|
"sizes": "256x256",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-384x384.png",
|
"src": "../img/icon-384x384.png",
|
||||||
"sizes": "384x384",
|
"sizes": "384x384",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/static/img/icon-512x512.png",
|
"src": "../img/icon-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|