From 7bb3bf45c754bc69d62df9c1b331d70571459fba Mon Sep 17 00:00:00 2001 From: DaanSelen Date: Thu, 2 Apr 2026 14:36:04 +0200 Subject: [PATCH] chore: rework api endpoints --- src/config.ini | 53 +++++++++--------- src/modules/routes/README.md | 5 +- src/modules/routes/locale.py | 31 ++++++++--- src/modules/routes/routes.py | 55 ++++++++++++++----- src/modules/routes/routes_welcome.py | 2 +- src/modules/wireguard/wireguard.py | 5 ++ src/modules/wireguard/wireguard_utils.py | 2 - src/static/admin/src/App.vue | 4 +- .../settingsComponent/dashboardLanguage.vue | 22 +++++--- .../signInComponents/RemoteServer.vue | 2 +- .../src/models/WireguardConfigurations.js | 2 +- src/static/admin/src/router/router.js | 2 +- .../src/stores/DashboardConfigurationStore.js | 2 +- .../stores/WireguardConfigurationsStore.js | 2 +- src/static/admin/src/views/share.vue | 2 +- src/static/admin/src/views/signin.vue | 8 +-- src/static/client/src/router/router.js | 2 +- 17 files changed, 127 insertions(+), 74 deletions(-) create mode 100644 src/modules/wireguard/wireguard.py delete mode 100644 src/modules/wireguard/wireguard_utils.py diff --git a/src/config.ini b/src/config.ini index a656ebd..f44b45b 100644 --- a/src/config.ini +++ b/src/config.ini @@ -12,53 +12,52 @@ port = 10086 debug_enabled = True wg_conf_path = /etc/wireguard awg_conf_path = /etc/amnezia/amneziawg -app_prefix = +app_prefix = authentication_required = True version = v5.0.0 wgdashboard_refresh_interval = 60000 wgdashboard_peer_list_display = grid wgdashboard_sort = status wgdashboard_theme = dark -wgdashboard_apikey = True +wgdashboard_apikey = true wgdashboard_language = en-US log_level = DEBUG [account] -username = dselen -password = $2b$12$0dvZY7mNbEcjfJI09AqxbeKYhBwoNwBrD4OQNhlJ3HqXoAbZmhNFq -enable_totp = False -totp_verified = False -totp_key = ON75CRNI7MGTA33PTHTQEZVXB5JKCEYK +username = admin +password = $2b$12$1VN62Q7CS/BJcAahHAWsA.3CD6zPqWTmE/HN/AJqwP0zds2l25Fqe +enable_totp = false +totp_verified = false +totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ [other] -welcome_session = False +welcome_session = false [database] type = sqlite -host = -port = -username = -password = +host = +port = +username = +password = [email] -server = -port = -encryption = -username = -email_password = -authentication_required = True -send_from = -email_template = +server = +port = +encryption = +username = +email_password = +authentication_required = true +send_from = +email_template = [oidc] -admin_enable = False -client_enable = False +admin_enable = false +client_enable = false [clients] -enable = True -sign_up = True +enable = true +sign_up = true [wireguardconfiguration] -autostart = -peer_tracking = False - +autostart = +peer_tracking = false \ No newline at end of file diff --git a/src/modules/routes/README.md b/src/modules/routes/README.md index 462fd48..439a673 100644 --- a/src/modules/routes/README.md +++ b/src/modules/routes/README.md @@ -16,7 +16,8 @@ | Endpoint | Method | File | | ------------------------------------------- | ----------------------------- | ---------------------------- | -| `/api/dashboard/locale` | `GET` | `routes.py` | +| `/api/dashboard/locale` | `GET` & `PATCH` | `routes.py` | +| `/api/dashboard/locale/available` | `GET` | `routes.py` | | `/api/dashboard/version` | `GET` | `routes.py` | | `/api/dashboard/theme` | `GET` | `routes.py` | | `/api/dashboard/update` | `GET` | `routes.py` | @@ -30,6 +31,6 @@ | Endpoint | Method | File | | ------------------------------------------- | ----------------------------- | ---------------------------- | -| `/api/dashboard/Wireguard/Interface` | `GET` | `routes.py` | +| `/api/dashboard/wireguard/interfaces` | `GET` | `routes.py` | ## Uninplemented routes: \ No newline at end of file diff --git a/src/modules/routes/locale.py b/src/modules/routes/locale.py index f227efc..db68d8a 100644 --- a/src/modules/routes/locale.py +++ b/src/modules/routes/locale.py @@ -40,11 +40,26 @@ class localeman: return json.load(lang_file) return None -# def update_language(self, lang_id): -# path = os.path.join(self.locale_path, f"{lang_id}.json") -# -# if not os.path.isfile(path): -# lang_id = "en" -# -# util.set_config(self.wgd_config, "Server", "dashboard_language", lang_id) -# return self.get_language() \ No newline at end of file + def get_available_languages(): + available_languages_path = "./static/locales/supported_locales.json" + + with open(os.path.join(available_languages_path), "r") as f: + language_data = json.load(f) + + available_languages = sorted(language_data, key=lambda x: x['lang_name']) + + return available_languages + + def update_language(self, lang_id) -> bool: + path = os.path.join(self.locale_path, f"{lang_id}.json") + + if not os.path.isfile(path): + lang_id = "en" + + config.update("SERVER", "wgdashboard_language", lang_id) + # Very important to also refresh the config in-memory + ok, flask.current_app.wgd_config = config.read() + if not ok: + log.error("failed to refresh the in-memory configuration") + return make_resp_obj(False, 'Internal error', {}, 500) + return self.get_language() \ No newline at end of file diff --git a/src/modules/routes/routes.py b/src/modules/routes/routes.py index 3f54ee7..5668ce4 100644 --- a/src/modules/routes/routes.py +++ b/src/modules/routes/routes.py @@ -23,10 +23,18 @@ from ..utilities.statistics import statistics routes = flask.Blueprint("routes", __name__) white_list = [ - "/", "/client", "/static/", "/fileDownload", - "/api/authenticate", "/api/locale", "getDashboardConfiguration", - "getDashboardTheme", "getDashboardVersion", "sharePeer/get", - "isTotpEnabled", "validateAuthentication", "favicon.ico", + "/", + "/favicon.ico", + "/client", + "/static/", + "/api/auth", + "/api/auth/validate", + "/api/dashboard/locale", + "/api/dashboard/configuration", + "/api/dashboard/theme", + "/api/dashboard/version", + "/api/dashboard/totp", + "sharePeer/get", ] @routes.before_request @@ -185,14 +193,35 @@ def api_validate_auth(): return make_resp_obj() @routes.route('/api/dashboard/locale', methods=["GET"]) -def api_locale_handler(): +def api_retrieve_locale(): locale_manager = localeman() locale_data = locale_manager.get_language() return make_resp_obj(True, "", locale_data, 200) +@routes.route('/api/dashboard/locale', methods=["PATCH"]) +def api_locale_update(): + req_data = flask.request.get_json() + if "lang_id" not in req_data.keys(): + return make_resp_obj(False, "Please specify a language id: lang_id") + + language_id = req_data.get("lang_id") + + locale_manager = localeman + ok = locale_manager.update_language(language_id) + if not ok: + return make_resp_obj(False, "Failed to update the language id") + + locale_data = locale_manager.get_language() + return make_resp_obj(True, "", locale_data) + +@routes.route('/api/dashboard/locale/available', methods=["GET"]) +def api_retrieve_available_locales(): + locale_manager = localeman() + + @routes.route('/api/dashboard/version', methods=["GET"]) -def api_retrieve_dashboard_version(): +def api_retrieve_version(): ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER') if not ok: log.error("failed to filter the config in-memory") @@ -201,7 +230,7 @@ def api_retrieve_dashboard_version(): return make_resp_obj(True, "", config_server.get("version")) @routes.route('/api/dashboard/theme', methods=["GET"]) -def api_retrieve_dashboard_theme(): +def api_retrieve_theme(): ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER') if not ok: log.error("failed to filter the config in-memory") @@ -209,16 +238,16 @@ def api_retrieve_dashboard_theme(): return make_resp_obj(True, "", config_server.get("wgdashboard_theme"), 200) -@routes.route('/api/dashboard/update', methods=["GET"]) -def api_retrieve_dashboard_update(): +@routes.route('/api/dashboard/updatestatus', methods=["GET"]) +def api_retrieve_update_status(): utilities.update_available() return make_resp_obj() @routes.route('/api/dashboard/configuration', methods=["GET"]) -def api_retrieve_dashboard_config(): +def api_retrieve_config(): return make_resp_obj(data=flask.current_app.wgd_config) -@routes.route('/api/dashboard/totpenabled') +@routes.route('/api/dashboard/totp', methods=["GET"]) def api_totp_status(): ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT') if not ok: @@ -229,7 +258,7 @@ def api_totp_status(): return make_resp_obj(True, "", data, 200) -@routes.route('/api/getWireguardConfigurations') +@routes.route('/api/dashboard/wireguard/interfaces', methods=["GET"]) def api_retrieve_wireguard_configurations(): ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER') if not ok: @@ -248,7 +277,7 @@ def api_retrieve_wireguard_configurations(): return make_resp_obj(True, 'Wireguard', {}, 200) -@routes.route('/api/dashboard/statistics') +@routes.route('/api/dashboard/statistics', methods=["GET"]) def api_system_status(): status = statistics() return make_resp_obj(True, "", status.to_json(), 200) diff --git a/src/modules/routes/routes_welcome.py b/src/modules/routes/routes_welcome.py index 9a48584..7c72daa 100644 --- a/src/modules/routes/routes_welcome.py +++ b/src/modules/routes/routes_welcome.py @@ -57,7 +57,7 @@ def api_welcome_finish(): return make_resp_obj() -@routes_welcome.route('/api/welcome/totplink') +@routes_welcome.route('/api/welcome/totplink', methods=["GET"]) def api_welcome_get_totp(): ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT') if not ok: diff --git a/src/modules/wireguard/wireguard.py b/src/modules/wireguard/wireguard.py new file mode 100644 index 0000000..6a7c320 --- /dev/null +++ b/src/modules/wireguard/wireguard.py @@ -0,0 +1,5 @@ +#!/bin/env python3 + +class wireguard(): + def __init__(): + print("triggered init") \ No newline at end of file diff --git a/src/modules/wireguard/wireguard_utils.py b/src/modules/wireguard/wireguard_utils.py deleted file mode 100644 index 92bc4e7..0000000 --- a/src/modules/wireguard/wireguard_utils.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/env python3 - diff --git a/src/static/admin/src/App.vue b/src/static/admin/src/App.vue index ad06f24..c61a69e 100644 --- a/src/static/admin/src/App.vue +++ b/src/static/admin/src/App.vue @@ -10,12 +10,12 @@ if (window.IS_WGDASHBOARD_DESKTOP){ store.IsElectronApp = true; store.CrossServerConfiguration.Enable = true; if (store.ActiveServerConfiguration){ - fetchGet("/api/locale", {}, (res) => { + fetchGet("/api/dashboard/locale", {}, (res) => { store.Locale = res.data }) } }else{ - fetchGet("/api/locale", {}, (res) => { + fetchGet("/api/dashboard/locale", {}, (res) => { store.Locale = res.data }) } diff --git a/src/static/admin/src/components/settingsComponent/dashboardLanguage.vue b/src/static/admin/src/components/settingsComponent/dashboardLanguage.vue index 775c06f..3c654f6 100644 --- a/src/static/admin/src/components/settingsComponent/dashboardLanguage.vue +++ b/src/static/admin/src/components/settingsComponent/dashboardLanguage.vue @@ -16,22 +16,28 @@ export default { } }, mounted() { - fetchGet("/api/locale/available", {}, (res) => { + fetchGet("/api/dashboard/locale/available", {}, (res) => { this.languages = res.data; }) }, methods: { changeLanguage(lang_id){ - fetchPost("/api/locale/update", { - lang_id: lang_id - }, (res) => { + fetch("/api/dashboard/locale", { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ lang_id: lang_id }), + }) + .then(res => res.json()) + .then(res => { if (res.status){ this.store.Configuration.server.wgdashboard_language = lang_id; - this.store.Locale = res.data - }else{ - this.store.newMessage("Server", "WGDashboard language update failed", "danger") + this.store.Locale = res.data; + } else { + this.store.newMessage("Server", "WGDashboard failed to update the language", "danger") } - }) + }); } }, computed:{ diff --git a/src/static/admin/src/components/signInComponents/RemoteServer.vue b/src/static/admin/src/components/signInComponents/RemoteServer.vue index 178195d..d95d52b 100644 --- a/src/static/admin/src/components/signInComponents/RemoteServer.vue +++ b/src/static/admin/src/components/signInComponents/RemoteServer.vue @@ -56,7 +56,7 @@ export default { } }, async connect(){ - await fetch(`${this.server.host}/api/authenticate`, { + await fetch(`${this.server.host}/api/auth`, { headers: this.getHeaders, body: JSON.stringify({ host: window.location.hostname diff --git a/src/static/admin/src/models/WireguardConfigurations.js b/src/static/admin/src/models/WireguardConfigurations.js index 43d0fa5..1c7c972 100644 --- a/src/static/admin/src/models/WireguardConfigurations.js +++ b/src/static/admin/src/models/WireguardConfigurations.js @@ -11,7 +11,7 @@ export class WireguardConfigurations{ async getConfigurations(){ - await fetchGet("/api/getWireguardConfigurations", {}, (res) => { + await fetchGet("/api/dashboard/wireguard/interfaces", {}, (res) => { if (res.status) this.Configurations = res.data }); } diff --git a/src/static/admin/src/router/router.js b/src/static/admin/src/router/router.js index ce272b3..ead551b 100644 --- a/src/static/admin/src/router/router.js +++ b/src/static/admin/src/router/router.js @@ -5,7 +5,7 @@ import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore. const checkAuth = async () => { let result = false - await fetchGet("/api/validateAuthentication", {}, (res) => { + await fetchGet("/api/auth/validate", {}, (res) => { result = res.status }); return result; diff --git a/src/static/admin/src/stores/DashboardConfigurationStore.js b/src/static/admin/src/stores/DashboardConfigurationStore.js index 7798f9e..acb0775 100644 --- a/src/static/admin/src/stores/DashboardConfigurationStore.js +++ b/src/static/admin/src/stores/DashboardConfigurationStore.js @@ -60,7 +60,7 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt async setActiveCrossServer(key){ this.ActiveServerConfiguration = key; localStorage.setItem('ActiveCrossServerConfiguration', key) - await fetchGet("/api/locale", {}, (res) => { + await fetchGet("/api/dashboard/locale", {}, (res) => { this.Locale = res.data }) }, diff --git a/src/static/admin/src/stores/WireguardConfigurationsStore.js b/src/static/admin/src/stores/WireguardConfigurationsStore.js index 77b8949..dd2de0b 100644 --- a/src/static/admin/src/stores/WireguardConfigurationsStore.js +++ b/src/static/admin/src/stores/WireguardConfigurationsStore.js @@ -101,7 +101,7 @@ export const WireguardConfigurationsStore = defineStore('WireguardConfigurations }, actions: { async getConfigurations(){ - await fetchGet("/api/getWireguardConfigurations", {}, (res) => { + await fetchGet("/api/dashboard/wireguard/interfaces", {}, (res) => { if (res.status) { this.Configurations = res.data } diff --git a/src/static/admin/src/views/share.vue b/src/static/admin/src/views/share.vue index b0087f3..4686469 100644 --- a/src/static/admin/src/views/share.vue +++ b/src/static/admin/src/views/share.vue @@ -16,7 +16,7 @@ export default { const theme = ref(""); const peerConfiguration = ref(undefined); const blob = ref(new Blob()) - await fetchGet("/api/getDashboardTheme", {}, (res) => { + await fetchGet("/api/dashboard/theme", {}, (res) => { theme.value = res.data }); diff --git a/src/static/admin/src/views/signin.vue b/src/static/admin/src/views/signin.vue index 30b7b1d..93fcb42 100644 --- a/src/static/admin/src/views/signin.vue +++ b/src/static/admin/src/views/signin.vue @@ -18,13 +18,13 @@ export default { let version = undefined; if (!store.IsElectronApp){ await Promise.all([ - fetchGet("/api/getDashboardTheme", {}, (res) => { + fetchGet("/api/dashboard/theme", {}, (res) => { theme = res.data }), - fetchGet("/api/isTotpEnabled", {}, (res) => { + fetchGet("/api/dashboard/totp", {}, (res) => { totpEnabled = res.data }), - fetchGet("/api/getDashboardVersion", {}, (res) => { + fetchGet("/api/dashboard/version", {}, (res) => { version = res.data }) ]); @@ -60,7 +60,7 @@ export default { async auth(){ if (this.formValid){ this.loading = true - await fetchPost("/api/authenticate", this.data, (response) => { + await fetchPost("/api/auth", this.data, (response) => { if (response.status){ this.loginError = false; this.$refs["signInBtn"].classList.add("signedIn") diff --git a/src/static/client/src/router/router.js b/src/static/client/src/router/router.js index 7cbf078..3811d7a 100644 --- a/src/static/client/src/router/router.js +++ b/src/static/client/src/router/router.js @@ -64,7 +64,7 @@ router.beforeEach(async (to, from, next) => { store.newNotification("Sign in session ended, please sign in again", "warning") }else{ if (to.meta.auth){ - const status = await axiosGet('/api/validateAuthentication') + const status = await axiosGet('/api/auth/validate') if (status){ next() }else{