chore: rework api endpoints

This commit is contained in:
DaanSelen
2026-04-02 14:36:04 +02:00
parent 9315fe9c0e
commit 7bb3bf45c7
17 changed files with 127 additions and 74 deletions
+13 -14
View File
@@ -19,19 +19,19 @@ wgdashboard_refresh_interval = 60000
wgdashboard_peer_list_display = grid wgdashboard_peer_list_display = grid
wgdashboard_sort = status wgdashboard_sort = status
wgdashboard_theme = dark wgdashboard_theme = dark
wgdashboard_apikey = True wgdashboard_apikey = true
wgdashboard_language = en-US wgdashboard_language = en-US
log_level = DEBUG log_level = DEBUG
[account] [account]
username = dselen username = admin
password = $2b$12$0dvZY7mNbEcjfJI09AqxbeKYhBwoNwBrD4OQNhlJ3HqXoAbZmhNFq password = $2b$12$1VN62Q7CS/BJcAahHAWsA.3CD6zPqWTmE/HN/AJqwP0zds2l25Fqe
enable_totp = False enable_totp = false
totp_verified = False totp_verified = false
totp_key = ON75CRNI7MGTA33PTHTQEZVXB5JKCEYK totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ
[other] [other]
welcome_session = False welcome_session = false
[database] [database]
type = sqlite type = sqlite
@@ -46,19 +46,18 @@ port =
encryption = encryption =
username = username =
email_password = email_password =
authentication_required = True authentication_required = true
send_from = send_from =
email_template = email_template =
[oidc] [oidc]
admin_enable = False admin_enable = false
client_enable = False client_enable = false
[clients] [clients]
enable = True enable = true
sign_up = True sign_up = true
[wireguardconfiguration] [wireguardconfiguration]
autostart = autostart =
peer_tracking = False peer_tracking = false
+3 -2
View File
@@ -16,7 +16,8 @@
| Endpoint | Method | File | | 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/version` | `GET` | `routes.py` |
| `/api/dashboard/theme` | `GET` | `routes.py` | | `/api/dashboard/theme` | `GET` | `routes.py` |
| `/api/dashboard/update` | `GET` | `routes.py` | | `/api/dashboard/update` | `GET` | `routes.py` |
@@ -30,6 +31,6 @@
| Endpoint | Method | File | | Endpoint | Method | File |
| ------------------------------------------- | ----------------------------- | ---------------------------- | | ------------------------------------------- | ----------------------------- | ---------------------------- |
| `/api/dashboard/Wireguard/Interface` | `GET` | `routes.py` | | `/api/dashboard/wireguard/interfaces` | `GET` | `routes.py` |
## Uninplemented routes: ## Uninplemented routes:
+23 -8
View File
@@ -40,11 +40,26 @@ class localeman:
return json.load(lang_file) return json.load(lang_file)
return None return None
# def update_language(self, lang_id): def get_available_languages():
# path = os.path.join(self.locale_path, f"{lang_id}.json") available_languages_path = "./static/locales/supported_locales.json"
#
# if not os.path.isfile(path): with open(os.path.join(available_languages_path), "r") as f:
# lang_id = "en" language_data = json.load(f)
#
# util.set_config(self.wgd_config, "Server", "dashboard_language", lang_id) available_languages = sorted(language_data, key=lambda x: x['lang_name'])
# return self.get_language()
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()
+42 -13
View File
@@ -23,10 +23,18 @@ from ..utilities.statistics import statistics
routes = flask.Blueprint("routes", __name__) routes = flask.Blueprint("routes", __name__)
white_list = [ white_list = [
"/", "/client", "/static/", "/fileDownload", "/",
"/api/authenticate", "/api/locale", "getDashboardConfiguration", "/favicon.ico",
"getDashboardTheme", "getDashboardVersion", "sharePeer/get", "/client",
"isTotpEnabled", "validateAuthentication", "favicon.ico", "/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 @routes.before_request
@@ -185,14 +193,35 @@ def api_validate_auth():
return make_resp_obj() return make_resp_obj()
@routes.route('/api/dashboard/locale', methods=["GET"]) @routes.route('/api/dashboard/locale', methods=["GET"])
def api_locale_handler(): def api_retrieve_locale():
locale_manager = localeman() locale_manager = localeman()
locale_data = locale_manager.get_language() locale_data = locale_manager.get_language()
return make_resp_obj(True, "", locale_data, 200) 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"]) @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') ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER')
if not ok: if not ok:
log.error("failed to filter the config in-memory") 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")) return make_resp_obj(True, "", config_server.get("version"))
@routes.route('/api/dashboard/theme', methods=["GET"]) @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') ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER')
if not ok: if not ok:
log.error("failed to filter the config in-memory") 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) return make_resp_obj(True, "", config_server.get("wgdashboard_theme"), 200)
@routes.route('/api/dashboard/update', methods=["GET"]) @routes.route('/api/dashboard/updatestatus', methods=["GET"])
def api_retrieve_dashboard_update(): def api_retrieve_update_status():
utilities.update_available() utilities.update_available()
return make_resp_obj() return make_resp_obj()
@routes.route('/api/dashboard/configuration', methods=["GET"]) @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) 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(): def api_totp_status():
ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT') ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT')
if not ok: if not ok:
@@ -229,7 +258,7 @@ def api_totp_status():
return make_resp_obj(True, "", data, 200) return make_resp_obj(True, "", data, 200)
@routes.route('/api/getWireguardConfigurations') @routes.route('/api/dashboard/wireguard/interfaces', methods=["GET"])
def api_retrieve_wireguard_configurations(): def api_retrieve_wireguard_configurations():
ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER') ok, config_server = config.filter(flask.current_app.wgd_config, 'SERVER')
if not ok: if not ok:
@@ -248,7 +277,7 @@ def api_retrieve_wireguard_configurations():
return make_resp_obj(True, 'Wireguard', {}, 200) return make_resp_obj(True, 'Wireguard', {}, 200)
@routes.route('/api/dashboard/statistics') @routes.route('/api/dashboard/statistics', methods=["GET"])
def api_system_status(): def api_system_status():
status = statistics() status = statistics()
return make_resp_obj(True, "", status.to_json(), 200) return make_resp_obj(True, "", status.to_json(), 200)
+1 -1
View File
@@ -57,7 +57,7 @@ def api_welcome_finish():
return make_resp_obj() return make_resp_obj()
@routes_welcome.route('/api/welcome/totplink') @routes_welcome.route('/api/welcome/totplink', methods=["GET"])
def api_welcome_get_totp(): def api_welcome_get_totp():
ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT') ok, config_account = config.filter(flask.current_app.wgd_config, 'ACCOUNT')
if not ok: if not ok:
+5
View File
@@ -0,0 +1,5 @@
#!/bin/env python3
class wireguard():
def __init__():
print("triggered init")
-2
View File
@@ -1,2 +0,0 @@
#!/bin/env python3
+2 -2
View File
@@ -10,12 +10,12 @@ if (window.IS_WGDASHBOARD_DESKTOP){
store.IsElectronApp = true; store.IsElectronApp = true;
store.CrossServerConfiguration.Enable = true; store.CrossServerConfiguration.Enable = true;
if (store.ActiveServerConfiguration){ if (store.ActiveServerConfiguration){
fetchGet("/api/locale", {}, (res) => { fetchGet("/api/dashboard/locale", {}, (res) => {
store.Locale = res.data store.Locale = res.data
}) })
} }
}else{ }else{
fetchGet("/api/locale", {}, (res) => { fetchGet("/api/dashboard/locale", {}, (res) => {
store.Locale = res.data store.Locale = res.data
}) })
} }
@@ -16,22 +16,28 @@ export default {
} }
}, },
mounted() { mounted() {
fetchGet("/api/locale/available", {}, (res) => { fetchGet("/api/dashboard/locale/available", {}, (res) => {
this.languages = res.data; this.languages = res.data;
}) })
}, },
methods: { methods: {
changeLanguage(lang_id){ changeLanguage(lang_id){
fetchPost("/api/locale/update", { fetch("/api/dashboard/locale", {
lang_id: lang_id method: "PATCH",
}, (res) => { headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ lang_id: lang_id }),
})
.then(res => res.json())
.then(res => {
if (res.status){ if (res.status){
this.store.Configuration.server.wgdashboard_language = lang_id; this.store.Configuration.server.wgdashboard_language = lang_id;
this.store.Locale = res.data this.store.Locale = res.data;
}else{ } else {
this.store.newMessage("Server", "WGDashboard language update failed", "danger") this.store.newMessage("Server", "WGDashboard failed to update the language", "danger")
} }
}) });
} }
}, },
computed:{ computed:{
@@ -56,7 +56,7 @@ export default {
} }
}, },
async connect(){ async connect(){
await fetch(`${this.server.host}/api/authenticate`, { await fetch(`${this.server.host}/api/auth`, {
headers: this.getHeaders, headers: this.getHeaders,
body: JSON.stringify({ body: JSON.stringify({
host: window.location.hostname host: window.location.hostname
@@ -11,7 +11,7 @@ export class WireguardConfigurations{
async getConfigurations(){ async getConfigurations(){
await fetchGet("/api/getWireguardConfigurations", {}, (res) => { await fetchGet("/api/dashboard/wireguard/interfaces", {}, (res) => {
if (res.status) this.Configurations = res.data if (res.status) this.Configurations = res.data
}); });
} }
+1 -1
View File
@@ -5,7 +5,7 @@ import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.
const checkAuth = async () => { const checkAuth = async () => {
let result = false let result = false
await fetchGet("/api/validateAuthentication", {}, (res) => { await fetchGet("/api/auth/validate", {}, (res) => {
result = res.status result = res.status
}); });
return result; return result;
@@ -60,7 +60,7 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
async setActiveCrossServer(key){ async setActiveCrossServer(key){
this.ActiveServerConfiguration = key; this.ActiveServerConfiguration = key;
localStorage.setItem('ActiveCrossServerConfiguration', key) localStorage.setItem('ActiveCrossServerConfiguration', key)
await fetchGet("/api/locale", {}, (res) => { await fetchGet("/api/dashboard/locale", {}, (res) => {
this.Locale = res.data this.Locale = res.data
}) })
}, },
@@ -101,7 +101,7 @@ export const WireguardConfigurationsStore = defineStore('WireguardConfigurations
}, },
actions: { actions: {
async getConfigurations(){ async getConfigurations(){
await fetchGet("/api/getWireguardConfigurations", {}, (res) => { await fetchGet("/api/dashboard/wireguard/interfaces", {}, (res) => {
if (res.status) { if (res.status) {
this.Configurations = res.data this.Configurations = res.data
} }
+1 -1
View File
@@ -16,7 +16,7 @@ export default {
const theme = ref(""); const theme = ref("");
const peerConfiguration = ref(undefined); const peerConfiguration = ref(undefined);
const blob = ref(new Blob()) const blob = ref(new Blob())
await fetchGet("/api/getDashboardTheme", {}, (res) => { await fetchGet("/api/dashboard/theme", {}, (res) => {
theme.value = res.data theme.value = res.data
}); });
+4 -4
View File
@@ -18,13 +18,13 @@ export default {
let version = undefined; let version = undefined;
if (!store.IsElectronApp){ if (!store.IsElectronApp){
await Promise.all([ await Promise.all([
fetchGet("/api/getDashboardTheme", {}, (res) => { fetchGet("/api/dashboard/theme", {}, (res) => {
theme = res.data theme = res.data
}), }),
fetchGet("/api/isTotpEnabled", {}, (res) => { fetchGet("/api/dashboard/totp", {}, (res) => {
totpEnabled = res.data totpEnabled = res.data
}), }),
fetchGet("/api/getDashboardVersion", {}, (res) => { fetchGet("/api/dashboard/version", {}, (res) => {
version = res.data version = res.data
}) })
]); ]);
@@ -60,7 +60,7 @@ export default {
async auth(){ async auth(){
if (this.formValid){ if (this.formValid){
this.loading = true this.loading = true
await fetchPost("/api/authenticate", this.data, (response) => { await fetchPost("/api/auth", this.data, (response) => {
if (response.status){ if (response.status){
this.loginError = false; this.loginError = false;
this.$refs["signInBtn"].classList.add("signedIn") this.$refs["signInBtn"].classList.add("signedIn")
+1 -1
View File
@@ -64,7 +64,7 @@ router.beforeEach(async (to, from, next) => {
store.newNotification("Sign in session ended, please sign in again", "warning") store.newNotification("Sign in session ended, please sign in again", "warning")
}else{ }else{
if (to.meta.auth){ if (to.meta.auth){
const status = await axiosGet('/api/validateAuthentication') const status = await axiosGet('/api/auth/validate')
if (status){ if (status){
next() next()
}else{ }else{