diff --git a/src/dashboard.py b/src/dashboard.py index 60b5de4..ffaf45b 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -33,7 +33,7 @@ import threading from flask.json.provider import DefaultJSONProvider -DASHBOARD_VERSION = 'v4.0' +DASHBOARD_VERSION = 'v4.0.1.1' CONFIGURATION_PATH = os.getenv('CONFIGURATION_PATH', '.') DB_PATH = os.path.join(CONFIGURATION_PATH, 'db') if not os.path.isdir(DB_PATH): @@ -490,6 +490,7 @@ class WireguardConfiguration: # Create tables in database self.__createDatabase() self.getPeersList() + self.getRestrictedPeersList() def __createDatabase(self): existingTables = sqldb.cursor().execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall() @@ -697,6 +698,7 @@ class WireguardConfiguration: sqldb.cursor().execute("UPDATE '%s_restrict_access' SET status = 'stopped' WHERE id = ?" % (self.Name,), (pf.id,)) sqldb.cursor().execute("DELETE FROM '%s' WHERE id = ?" % self.Name, (pf.id,)) + sqldb.commit() numOfRestrictedPeers += 1 except Exception as e: numOfFailedToRestrictPeers += 1 @@ -1115,6 +1117,8 @@ class DashboardConfig: self.__createAPIKeyTable() self.DashboardAPIKeys = self.__getAPIKeys() self.APIAccessed = False + self.SetConfig("Server", "version", DASHBOARD_VERSION) + def __createAPIKeyTable(self): existingTable = sqldb.cursor().execute("SELECT name FROM sqlite_master WHERE type='table' AND name = 'DashboardAPIKeys'").fetchall() @@ -1344,6 +1348,14 @@ def _getWireguardConfigurationAvailableIP(configName: str) -> tuple[bool, list[s for i in add: a, c = i.split('/') existedAddress.append(ipaddress.ip_address(a.replace(" ", ""))) + + for p in configuration.getRestrictedPeersList(): + if len(p.allowed_ip) > 0: + add = p.allowed_ip.split(',') + for i in add: + a, c = i.split('/') + existedAddress.append(ipaddress.ip_address(a.replace(" ", ""))) + for i in address: addressSplit, cidr = i.split('/') existedAddress.append(ipaddress.ip_address(addressSplit.replace(" ", ""))) @@ -1419,6 +1431,7 @@ def auth_req(): and f"{(APP_PREFIX if len(APP_PREFIX) > 0 else '')}" != request.path) and "validateAuthentication" not in request.path and "authenticate" not in request.path and "getDashboardConfiguration" not in request.path and "getDashboardTheme" not in request.path + and "getDashboardVersion" not in request.path and "sharePeer/get" not in request.path and "isTotpEnabled" not in request.path ): @@ -1751,10 +1764,13 @@ def API_addPeers(configName): return ResponseObject(False, "Please fill in all required box.") if not config.getStatus(): config.toggleConfiguration() + + availableIps = _getWireguardConfigurationAvailableIP(configName) + if bulkAdd: if bulkAddAmount < 1: return ResponseObject(False, "Please specify amount of peers you want to add") - availableIps = _getWireguardConfigurationAvailableIP(configName) + if not availableIps[0]: return ResponseObject(False, "No more available IP can assign") if bulkAddAmount > len(availableIps[1]): @@ -1788,6 +1804,11 @@ def API_addPeers(configName): return ResponseObject(False, f"This peer already exist.") name = data['name'] private_key = data['private_key'] + + for i in allowed_ips: + if i not in availableIps[1]: + return ResponseObject(False, f"This IP is not available: {i}") + config.addPeers([{"id": public_key, "allowed_ip": ''.join(allowed_ips)}]) # subprocess.check_output( # f"wg set {config.Name} peer {public_key} allowed-ips {''.join(allowed_ips)}", @@ -1857,6 +1878,10 @@ def API_getConfigurationInfo(): def API_getDashboardTheme(): return ResponseObject(data=DashboardConfig.GetConfig("Server", "dashboard_theme")[1]) +@app.route(f'{APP_PREFIX}/api/getDashboardVersion') +def API_getDashboardVersion(): + return ResponseObject(data=DashboardConfig.GetConfig("Server", "version")[1]) + @app.route(f'{APP_PREFIX}/api/savePeerScheduleJob/', methods=["POST"]) def API_savePeerScheduleJob(): @@ -2102,6 +2127,7 @@ def backGroundThread(): c.getPeersLatestHandshake() c.getPeersEndpoint() c.getPeersList() + c.getRestrictedPeersList() except Exception as e: print(f"[WGDashboard] Background Thread #1 Error: {str(e)}", flush=True) time.sleep(10) diff --git a/src/static/app/src/components/configurationComponents/newPeersComponents/allowedIPsInput.vue b/src/static/app/src/components/configurationComponents/newPeersComponents/allowedIPsInput.vue index a075414..e1ac51e 100644 --- a/src/static/app/src/components/configurationComponents/newPeersComponents/allowedIPsInput.vue +++ b/src/static/app/src/components/configurationComponents/newPeersComponents/allowedIPsInput.vue @@ -36,8 +36,11 @@ export default { addAllowedIp(ip){ if(this.store.checkCIDR(ip)){ this.data.allowed_ips.push(ip); + this.customAvailableIp = '' return true; } + this.allowedIpFormatError = true; + this.dashboardStore.newMessage('WGDashboard', 'Allowed IP is invalid', 'danger') return false; } }, @@ -80,10 +83,7 @@ export default { :disabled="bulk"> diff --git a/src/static/app/src/components/configurationComponents/peerList.vue b/src/static/app/src/components/configurationComponents/peerList.vue index 388a267..dd15058 100644 --- a/src/static/app/src/components/configurationComponents/peerList.vue +++ b/src/static/app/src/components/configurationComponents/peerList.vue @@ -200,7 +200,8 @@ export default { }) this.loading = false; if (this.configurationPeers.length > 0){ - const sent = this.configurationPeers.map(x => x.total_sent + x.cumu_sent).reduce((x,y) => x + y).toFixed(4); + const sent = this.configurationPeers.map(x => x.total_sent + x.cumu_sent) + .reduce((x,y) => x + y).toFixed(4); const receive = this.configurationPeers.map(x => x.total_receive + x.cumu_receive).reduce((x,y) => x + y).toFixed(4); if ( this.historyDataSentDifference[this.historyDataSentDifference.length - 1] !== sent @@ -259,13 +260,13 @@ export default { connectedPeers: this.configurationPeers.filter(x => x.status === "running").length, totalUsage: this.configurationPeers.length > 0 ? this.configurationPeers.filter(x => !x.restricted) - .map(x => x.total_data + x.cumu_data).reduce((a, b) => a + b).toFixed(4) : 0, + .map(x => x.total_data + x.cumu_data).reduce((a, b) => a + b, 0).toFixed(4) : 0, totalReceive: this.configurationPeers.length > 0 ? this.configurationPeers.filter(x => !x.restricted) - .map(x => x.total_receive + x.cumu_receive).reduce((a, b) => a + b).toFixed(4) : 0, + .map(x => x.total_receive + x.cumu_receive).reduce((a, b) => a + b, 0).toFixed(4) : 0, totalSent: this.configurationPeers.length > 0 ? this.configurationPeers.filter(x => !x.restricted) - .map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b).toFixed(4) : 0 + .map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b, 0).toFixed(4) : 0 } return k diff --git a/src/static/app/src/views/signin.vue b/src/static/app/src/views/signin.vue index 2fd5c30..7ded9bb 100644 --- a/src/static/app/src/views/signin.vue +++ b/src/static/app/src/views/signin.vue @@ -11,16 +11,22 @@ export default { const store = DashboardConfigurationStore() let theme = "dark" let totpEnabled = false; + let version = undefined; if (!store.IsElectronApp){ - await fetchGet("/api/getDashboardTheme", {}, (res) => { - theme = res.data - }); - await fetchGet("/api/isTotpEnabled", {}, (res) => { - totpEnabled = res.data - }); + await Promise.all([ + fetchGet("/api/getDashboardTheme", {}, (res) => { + theme = res.data + }), + fetchGet("/api/isTotpEnabled", {}, (res) => { + totpEnabled = res.data + }), + fetchGet("/api/getDashboardVersion", {}, (res) => { + version = res.data + }) + ]); } store.removeActiveCrossServer(); - return {store, theme, totpEnabled} + return {store, theme, totpEnabled, version} }, data(){ return { @@ -146,7 +152,7 @@ export default { - WGDashboard v4.0 | Developed with ❤️ by + WGDashboard {{ this.version }} | Developed with ❤️ by Donald Zou