From 468f745c77e88ae86796ce7cc1961988ab31bdc1 Mon Sep 17 00:00:00 2001 From: Martin Raiber Date: Sun, 18 Jul 2021 20:20:41 +0200 Subject: [PATCH] Preconfigured internet server via connection settings --- urbackupclient/client_restore_http.cpp | 16 +++++++ urbackupclient/client_restore_http.h | 1 + urbackupclient/dllmain.cpp | 1 + urbackupclient/restorewww/package.json | 2 +- urbackupclient/restorewww/src/App.tsx | 43 ++++++++++++++++++- urbackupclient/restorewww/src/Restoring.tsx | 4 +- .../restorewww/src/ServerSearch.tsx | 33 +++++++++++++- urbackupclient/restorewww/src/WizardState.tsx | 3 +- urbackupclient/restorewww/src/logo.svg | 1 - 9 files changed, 96 insertions(+), 8 deletions(-) delete mode 100644 urbackupclient/restorewww/src/logo.svg diff --git a/urbackupclient/client_restore_http.cpp b/urbackupclient/client_restore_http.cpp index 6d98cc0f..17bb49ab 100644 --- a/urbackupclient/client_restore_http.cpp +++ b/urbackupclient/client_restore_http.cpp @@ -533,4 +533,20 @@ ACTION_IMPL(set_keyboard_layout) JSON::Object ret; ret.set("ok", true); restore::writeJsonResponse(tid, ret); +} + +ACTION_IMPL(get_connection_settings) +{ + std::string settingsfn = "/run/live/medium/connection_settings.json"; + if(!FileExists(settingsfn)) + { + JSON::Object ret; + ret.set("ok", true); + ret.set("no_config", true); + restore::writeJsonResponse(tid, ret); + return; + } + + Server->setContentType(tid, "application/json"); + Server->Write(tid, getFile(settingsfn)); } \ No newline at end of file diff --git a/urbackupclient/client_restore_http.h b/urbackupclient/client_restore_http.h index da669d6e..8059d9ce 100644 --- a/urbackupclient/client_restore_http.h +++ b/urbackupclient/client_restore_http.h @@ -29,6 +29,7 @@ namespace Actions ACTION(restart); ACTION(get_keyboard_layouts); ACTION(set_keyboard_layout); + ACTION(get_connection_settings); } namespace restore diff --git a/urbackupclient/dllmain.cpp b/urbackupclient/dllmain.cpp index e7c29770..ef8e94c2 100644 --- a/urbackupclient/dllmain.cpp +++ b/urbackupclient/dllmain.cpp @@ -383,6 +383,7 @@ DLLEXPORT void LoadActions(IServer* pServer) ADD_ACTION(restart); ADD_ACTION(get_keyboard_layouts); ADD_ACTION(set_keyboard_layout); + ADD_ACTION(get_connection_settings); Server->Log("Started UrBackup Restore HTTP backend...", LL_INFO); return; } diff --git a/urbackupclient/restorewww/package.json b/urbackupclient/restorewww/package.json index f64197ed..bb95e4ce 100644 --- a/urbackupclient/restorewww/package.json +++ b/urbackupclient/restorewww/package.json @@ -1,5 +1,5 @@ { - "name": "antd-demo-ts", + "name": "urbackup-image-restore-ui", "version": "0.1.0", "private": true, "dependencies": { diff --git a/urbackupclient/restorewww/src/App.tsx b/urbackupclient/restorewww/src/App.tsx index 24721179..707c792d 100644 --- a/urbackupclient/restorewww/src/App.tsx +++ b/urbackupclient/restorewww/src/App.tsx @@ -34,6 +34,8 @@ export const toIsoDateTime = (d: Date) => { function CurrentContent(args: WizardComponent) { switch(args.props.state) { + case WizardState.Init: + return
Initializing...
case WizardState.SelectKeyboard: return ; case WizardState.WaitForNetwork: @@ -59,8 +61,8 @@ function CurrentContent(args: WizardComponent) { function App() { const [wizard_state, setWizardState] = useState({ - state: WizardState.SelectKeyboard, - max_state: WizardState.WaitForNetwork, + state: WizardState.Init, + max_state: WizardState.Init, serverFound: false, internetServer: false, serverUrl: "", @@ -110,6 +112,43 @@ function App() { return false; } + useMountEffect( () => { + (async () => { + let jdata; + try { + const resp = await fetch("x?a=get_connection_settings", + {method: "POST"}) + jdata = await resp.json(); + } catch(error) { + jdata = {"no_config": true}; + } + + if(jdata["no_config"]) { + setWizardState(produce(draft => { + draft.state = WizardState.SelectKeyboard; + draft.max_state = WizardState.WaitForNetwork; + })); + return; + } + + if(jdata["serverUrl"]) { + let serverUrl: string = jdata["serverUrl"]; + let serverAuthkey: string = jdata["serverAuthkey"]; + let serverProxy: string = ""; + if(jdata["serverProxy"]) + serverProxy = jdata["serverProxy"]; + setWizardState(produce(draft => { + draft.serverUrl = serverUrl; + draft.serverAuthkey = serverAuthkey; + draft.serverProxy = serverProxy; + draft.internetServer = true; + draft.state = WizardState.ServerSearch; + draft.max_state = draft.state; + })); + } + })(); + }); + return (
diff --git a/urbackupclient/restorewww/src/Restoring.tsx b/urbackupclient/restorewww/src/Restoring.tsx index 84636334..81997cf0 100644 --- a/urbackupclient/restorewww/src/Restoring.tsx +++ b/urbackupclient/restorewww/src/Restoring.tsx @@ -176,7 +176,7 @@ function Restoring(props: WizardComponent) { return; } - setRestoreAction(props.props.restoreImage.letter +" - "+(new Date(props.props.restoreImage.time_s)).toLocaleString() + " client "+props.props.restoreImage.clientname); + setRestoreAction(props.props.restoreImage.letter +" - "+toIsoDateTime(new Date(props.props.restoreImage.time_s*1000)) + " client "+props.props.restoreImage.clientname); addLog("Getting partition to restore to...") try { @@ -347,7 +347,7 @@ function Restoring(props: WizardComponent) { loading={restartLoading}>Restart machine } -
+
diff --git a/urbackupclient/restorewww/src/ServerSearch.tsx b/urbackupclient/restorewww/src/ServerSearch.tsx index 9e2b8398..04f63dc0 100644 --- a/urbackupclient/restorewww/src/ServerSearch.tsx +++ b/urbackupclient/restorewww/src/ServerSearch.tsx @@ -21,6 +21,7 @@ function ServerSearch(props: WizardComponent) { const [serviceError, setServiceError] = useState(""); const [noLocalServer, setNoLocalServer] = useState(false); + const [isLoading, setIsLoading] = useState(true); const checkConnected = async () : Promise => { try { @@ -54,7 +55,37 @@ function ServerSearch(props: WizardComponent) { useMountEffect(() => { (async () => { + if(props.props.internetServer) { + console.log("Skip local server search because internet server is configured"); + + let jdata; + try { + const resp = await fetch("x?a=configure_server", + {method: "POST", + body: new URLSearchParams({ + "active": "1", + "url": props.props.serverUrl, + "authkey": props.props.serverAuthkey, + "proxy": props.props.serverProxy + }) }); + jdata = await resp.json(); + } catch(error) { + setServiceError("Error retrieving data from HTTP server"); + } + + if(!jdata["ok"]) { + setServiceError("Error configuring client to connect to server"); + } else { + props.update(produce(props.props, draft => { + draft.state = WizardState.WaitForConnection; + draft.max_state = draft.state; + })); + } + return; + } + console.log("Server search started"); + setIsLoading(false); var cnt = 0; while(props.props.state===WizardState.ServerSearch) { @@ -96,7 +127,7 @@ function ServerSearch(props: WizardComponent) { draft.state = WizardState.ConfigureServerConnectionDetails; draft.max_state = draft.state; })); - } }>Configure Internet server + } } loading={isLoading}>Configure Internet server {noLocalServer && <>
\ No newline at end of file