diff options
author | Himbeer <himbeer@disroot.org> | 2024-08-07 13:18:49 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-08-07 13:18:49 +0200 |
commit | f9c1a759c7ada21cdf41644edfd2cd27c9448688 (patch) | |
tree | 255db3c9aa96919bc45281785701fd41da90498c | |
parent | 1752873ef2a673b792acb96f91c271add00baa19 (diff) |
Add system maintenance (admin password, reboot, shutdown)
-rw-r--r-- | src-tauri/src/main.rs | 141 | ||||
-rw-r--r-- | src/sys.html | 111 | ||||
-rw-r--r-- | src/sys.js | 115 | ||||
-rw-r--r-- | src/wan.js | 1 |
4 files changed, 366 insertions, 2 deletions
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c10f666..ed6ba2a 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1089,6 +1089,142 @@ fn handle_delete_response(response: Response) -> String { } } +#[tauri::command] +async fn change_sys_password( + old: String, + to: String, + repeat: String, + state: State<'_, Mutex<Session>>, +) -> Result<String, ()> { + let (client, instance) = { + let state = state.lock().unwrap(); + (state.client.clone(), state.instance.clone()) + }; + let instance = match instance { + Some(instance) => instance, + None => { + return Ok(String::from( + "Keine Instanz ausgewählt, bitte melden Sie sich neu an!", + )) + } + }; + + if to != repeat { + return Ok(String::from( + "Das neue Passwort und seine Wiederholung stimmen nicht überein", + )); + } + + let response = client + .post(instance.url.join("/data/write").unwrap()) + .query(&[("path", "/data/admind.passwd")]) + .basic_auth("rustkrazy", Some(&old)) + .body(to) + .send(); + + Ok(match response.await { + Ok(response) => handle_change_sys_password_response(response), + Err(e) => format!("Änderung fehlgeschlagen: {}", e), + }) +} + +fn handle_change_sys_password_response(response: Response) -> String { + let status = response.status(); + if status.is_success() { + String::from("Änderung erfolgreich") + } else if status == StatusCode::UNAUTHORIZED { + String::from("Das alte Passwort ist ungültig") + } else if status.is_client_error() { + format!("Clientseitiger Fehler: {}", status) + } else if status.is_server_error() { + format!("Serverseitiger Fehler: {}", status) + } else { + format!("Unerwarteter Statuscode: {}", status) + } +} + +#[tauri::command] +async fn reboot(state: State<'_, Mutex<Session>>) -> Result<String, ()> { + let (client, instance) = { + let state = state.lock().unwrap(); + (state.client.clone(), state.instance.clone()) + }; + let instance = match instance { + Some(instance) => instance, + None => { + return Ok(String::from( + "Keine Instanz ausgewählt, bitte melden Sie sich neu an!", + )) + } + }; + + let response = client + .post(instance.url.join("/reboot").unwrap()) + .basic_auth("rustkrazy", Some(&instance.password)) + .send(); + + Ok(match response.await { + Ok(response) => handle_reboot_response(response), + Err(e) => format!("Befehl fehlgeschlagen: {}", e), + }) +} + +fn handle_reboot_response(response: Response) -> String { + let status = response.status(); + if status.is_success() { + String::new() + } else if status == StatusCode::UNAUTHORIZED { + String::from("Ungültiges Verwaltungspasswort, bitte melden Sie sich neu an!") + } else if status.is_client_error() { + format!("Clientseitiger Fehler: {}", status) + } else if status.is_server_error() { + format!("Serverseitiger Fehler: {}", status) + } else { + format!("Unerwarteter Statuscode: {}", status) + } +} + +#[tauri::command] +async fn shutdown(state: State<'_, Mutex<Session>>) -> Result<String, ()> { + let (client, instance) = { + let state = state.lock().unwrap(); + (state.client.clone(), state.instance.clone()) + }; + let instance = match instance { + Some(instance) => instance, + None => { + return Ok(String::from( + "Keine Instanz ausgewählt, bitte melden Sie sich neu an!", + )) + } + }; + + let response = client + .post(instance.url.join("/shutdown").unwrap()) + .basic_auth("rustkrazy", Some(&instance.password)) + .send(); + + Ok(match response.await { + Ok(response) => handle_shutdown_response(response), + Err(e) => format!("Befehl fehlgeschlagen: {}", e), + }) +} + +fn handle_shutdown_response(response: Response) -> String { + let status = response.status(); + if status.is_success() { + String::new() + } else if status == StatusCode::UNAUTHORIZED { + String::from("Ungültiges Verwaltungspasswort, bitte melden Sie sich neu an!") + } else if status.is_client_error() { + format!("Clientseitiger Fehler: {}", status) + } else if status.is_server_error() { + format!("Serverseitiger Fehler: {}", status) + } else { + format!("Unerwarteter Statuscode: {}", status) + } +} + fn main() { tauri::Builder::default() .manage(Mutex::new(Session { @@ -1111,7 +1247,10 @@ fn main() { leases, load_domain, change_domain, - delete + delete, + change_sys_password, + reboot, + shutdown ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/sys.html b/src/sys.html new file mode 100644 index 0000000..c79d9e8 --- /dev/null +++ b/src/sys.html @@ -0,0 +1,111 @@ +<!doctype html> +<html lang="de"> + <head> + <meta charset="UTF-8" /> + <link rel="stylesheet" href="styles.css" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>System - RSDSL Verwaltungswerkzeug</title> + <script type="module" src="/dashboard.js" defer></script> + <script type="module" src="/sys.js" defer></script> + </head> + + <body> + <div class="container"> + <h1>System</h1> + + <div class="row"> + <form id="dashboard-form"> + <button id="dashboard-submit" type="submit">↩ Zurück zur Übersicht</button> + </form> + + <form id="wan-open-form"> + <button id="wan-open-submit" type="submit">Einwahl und Zugansdaten</button> + </form> + + <form id="lan-open-form"> + <button id="lan-open-submit" type="submit">LAN</button> + </form> + + <form id="ddns-open-form"> + <button id="ddns-open-submit" type="submit">Dynamisches DNS (INWX)</button> + </form> + + <form id="log-open-form"> + <button id="log-open-submit" type="submit">Diagnoseprotokolle</button> + </form> + + <form id="sys-open-form"> + <button id="sys-open-submit" type="submit">System</button> + </form> + + <form id="disconnect-form"> + <button id="disconnect-submit" type="submit">🚪 Abmelden</button> + </form> + </div> + + <br /> + + <form id="power-form"> + <fieldset> + <legend>Neustart und Herunterfahren</legend> + + <div class="row"> + <button id="power-reboot">🔄 Neustart</button> + <button id="power-shutdown">🔌 Herunterfahren</button> + </div> + + <p>Information: Ein Neustart dauert ca. 30 Sekunden bis 1 Minute. + In der Regel wird die Internetverbindung innerhalb von 1 Minute + wieder aufgebaut, sofern keine anderen Geräte neu gestartet wurden. + Bei anschließenden Verbindungsproblemen kann es ratsam sein, die + betroffenen Geräte neu mit dem Netzwerk zu verbinden oder für + mehrere Stunden verbunden zu lassen. Achtung: Insbesondere + Smartphones trennen die WLAN-Verbindung oft erst nach mindestens 5 + Sekunden Abschaltzeit. Daher die WLAN-Funktion für mindestens 5 + Sekunden deaktivieren und erst dann wieder einschalten.</p> + + <p>Nach erfolgreichem Herunterfahren muss das Stromkabel abgezogen + werden, um die Hardware tatsächlich auszuschalten. Erst beim + Wiederanschließen fährt das System wieder hoch.</p> + </fieldset> + </form> + + <br /> + + <form id="password-form"> + <fieldset> + <legend>Verwaltungspasswort</legend> + + <label for="password-old" form="password-form">Altes Passwort:</label> + <div class="row"> + <input id="password-old" type="password" /> + </div> + + <label for="password-new" form="password-form">Neues Passwort:</label> + <div class="row"> + <input id="password-new" type="password" /> + </div> + + <label for="password-repeat" form="password-form">Neues Passwort wiederholen:</label> + <div class="row"> + <input id="password-repeat" type="password" /> + </div> + + <br /> + + <div class="row"> + <button id="password-show">🔒 Neues Passwort ein-/ausblenden</button> + </div> + + <br /> + + <div class="row"> + <button id="password-submit" type="submit">Passwort ändern</button> + </div> + + <p id="password-status"></p> + </fieldset> + </form> + </div> + </body> +</html> diff --git a/src/sys.js b/src/sys.js new file mode 100644 index 0000000..8b19f22 --- /dev/null +++ b/src/sys.js @@ -0,0 +1,115 @@ +const { invoke } = window.__TAURI__.tauri; +const { message } = window.__TAURI__.dialog; + +let passwordOldEl; +let passwordNewEl; +let passwordRepeatEl; +let passwordSubmitEl; +let passwordStatusEl; + +async function reboot() { + const error = await invoke("reboot", {}); + + if (error !== "") { + await message("Befehl konnte nicht erteilt werden: " + error, { + kind: "error", + title: "Neustart nicht erfolgt" + }); + } + + const successTime = Date.now(); + + while ((Date.now() - successTime) < 60) { + await message("Neustart läuft. Bitte ca. 1 Minute warten.", { + kind: "info", + title: "Neustart im Gange" + }); + } +} + +async function shutdown() { + const error = await invoke("shutdown", {}); + + if (error !== "") { + await message("Befehl konnte nicht erteilt werden: " + error, { + kind: "error", + title: "Herunterfahren nicht erfolgt" + }); + } + + await message("Router erfolgreich heruntergefahren. Bitte Stromkabel abziehen.", { + kind: "info", + title: "Herunterfahren erfolgreich" + }); + + window.location = "index.html"; +} + +function showPassword() { + switch (passwordNewEl.type) { + case "password": + passwordNewEl.type = "text"; + passwordRepeatEl.type = "text"; + break; + case "text": + passwordNewEl.type = "password"; + passwordRepeatEl.type = "password"; + break; + } +} + +async function changePassword() { + passwordOldEl.disabled = true; + passwordNewEl.disabled = true; + passwordRepeatEl.disabled = true; + passwordSubmitEl.disabled = true; + passwordStatusEl.innerText = "Änderungsanfrage..."; + document.body.style.cursor = "progress"; + + passwordStatusEl.innerText = await invoke("change_sys_password", { + old: passwordOldEl.value, + to: passwordNewEl.value, + repeat: passwordRepeatEl.value, + }); + + passwordOldEl.disabled = false; + passwordNewEl.disabled = false; + passwordRepeatEl.disabled = false; + passwordSubmitEl.disabled = false; + document.body.style.cursor = "default"; + + if (passwordStatusEl.innerText === "Änderung erfolgreich") { + await message("Passwort erfolgreich geändert. Melden Sie sich neu an, um das Verwaltungswerkzeug weiter benutzen zu können.", { + kind: "info", + title: "Neuanmeldung erforderlich", + }); + + window.location = "index.html"; + } +} + +window.addEventListener("DOMContentLoaded", () => { + document.querySelector("#power-reboot").addEventListener("click", (e) => { + e.preventDefault(); + reboot(); + }); + document.querySelector("#power-shutdown").addEventListener("click", (e) => { + e.preventDefault(); + shutdown(); + }); + + passwordOldEl = document.querySelector("#password-old"); + passwordNewEl = document.querySelector("#password-new"); + passwordRepeatEl = document.querySelector("#password-repeat"); + passwordSubmitEl = document.querySelector("#password-submit"); + passwordStatusEl = document.querySelector("#password-status"); + + document.querySelector("#password-show").addEventListener("click", (e) => { + e.preventDefault(); + showPassword(); + }); + document.querySelector("#password-form").addEventListener("submit", (e) => { + e.preventDefault(); + changePassword(); + }); +}); @@ -214,7 +214,6 @@ window.addEventListener("DOMContentLoaded", () => { e.preventDefault(); showCredentials(); }); - document.querySelector("#credentials-form").addEventListener("submit", (e) => { e.preventDefault(); changeCredentials(); |