diff --git a/desktop/app.vue b/desktop/app.vue index bab7fad8..4b927289 100644 --- a/desktop/app.vue +++ b/desktop/app.vue @@ -3,6 +3,8 @@ {{ state }} + + Go diff --git a/desktop/components/WindowControl.vue b/desktop/components/WindowControl.vue index 818229f0..3610162f 100644 --- a/desktop/components/WindowControl.vue +++ b/desktop/components/WindowControl.vue @@ -1,5 +1,6 @@ diff --git a/desktop/pages/auth/connecting.vue b/desktop/pages/auth/processing.vue similarity index 100% rename from desktop/pages/auth/connecting.vue rename to desktop/pages/auth/processing.vue diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 3de262f7..2083da55 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -931,13 +931,14 @@ version = "0.1.0" dependencies = [ "ciborium", "directories", - "futures", + "log", "os_info", "rayon", "reqwest", "rustbreak", "serde", "serde_json", + "structured-logger", "tauri", "tauri-build", "tauri-plugin-deep-link", @@ -1195,21 +1196,6 @@ dependencies = [ "new_debug_unreachable", ] -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -1285,7 +1271,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -2116,6 +2101,10 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "serde", + "value-bag", +] [[package]] name = "mac" @@ -3108,6 +3097,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", @@ -3401,6 +3391,15 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "serde_fmt" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_json" version = "1.0.128" @@ -3689,12 +3688,103 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "structured-logger" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16524b1ef57fd2e253216ab20ec44f0dc32b29155a4b3e6bef0a857d8c9f5f08" +dependencies = [ + "log", + "parking_lot", + "serde", + "serde_json", + "tokio", +] + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "sval" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf38d1fa2ce984086ea42fb856a9f374d94680a4f796831a7fc868d7f2af1b9" + +[[package]] +name = "sval_buffer" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81682ff859964ca1d7cf3d3d0f9ec7204ea04c2c32acb8cc2cf68ecbd3127354" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a213b93bb4c6f4c9f9b17f2e740e077fd18746bbf7c80c72bbadcac68fa7ee4" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6902c6d3fb52c89206fe0dc93546c0123f7d48b5997fd14e61c9e64ff0b63275" +dependencies = [ + "itoa 1.0.11", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a28041ea78cdc394b930ae6b897d36246dc240a29a6edf82d76562487fb0b4" +dependencies = [ + "itoa 1.0.11", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850346e4b0742a7f2fd2697d703ff80084d0b658f0f2e336d71b8a06abf9b68e" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824afd97a8919f28a35b0fdea979845cc2ae461a8a3aaa129455cb89c88bb77a" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ada7520dd719ed672c786c7db7de4f5230f4d504b0821bd8305cd30ca442315" +dependencies = [ + "serde", + "sval", + "sval_nested", +] + [[package]] name = "swift-rs" version = "1.0.7" @@ -4220,6 +4310,7 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", "socket2", "windows-sys 0.52.0", @@ -4525,6 +4616,42 @@ dependencies = [ "serde", ] +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccacf50c5cb077a9abb723c5bcb5e0754c1a433f1e1de89edc328e2760b6328b" +dependencies = [ + "erased-serde", + "serde", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1785bae486022dfb9703915d42287dcb284c1ee37bd1080eeba78cc04721285b" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 34b4f9ec..a26e11aa 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -33,7 +33,8 @@ webbrowser = "1.0.2" url = "2.5.2" os_info = "3.8.2" tauri-plugin-deep-link = "2" -futures = "0.3.31" +log = "0.4.22" +structured-logger = "1.0.3" [dependencies.rustbreak] version = "2" @@ -41,5 +42,5 @@ features = ["bin_enc"] # You can also use "yaml_enc" or "bin_enc" [dependencies.reqwest] version = "0.12" -features = ["json"] +features = ["json", "blocking"] diff --git a/desktop/src-tauri/src/auth.rs b/desktop/src-tauri/src/auth.rs index a48a4b16..1512bebc 100644 --- a/desktop/src-tauri/src/auth.rs +++ b/desktop/src-tauri/src/auth.rs @@ -3,11 +3,12 @@ use std::{ sync::Mutex, }; +use log::info; use serde::{Deserialize, Serialize}; -use tauri::{App, AppHandle, Emitter, Error, EventLoopMessage, Wry}; +use tauri::{App, AppHandle, Emitter, Error, EventLoopMessage, Manager, Wry}; use url::Url; -use crate::{AppStatus, User, DB}; +use crate::{data::DatabaseCerts, AppState, AppStatus, User, DB}; #[derive(Serialize)] struct InitiateRequestBody { @@ -15,11 +16,78 @@ struct InitiateRequestBody { platform: String, } -pub async fn recieve_handshake(app: AppHandle, path: String) { - // Tell the app we're connecting - app.emit("auth/connecting", ()).unwrap(); +#[derive(Serialize)] +struct HandshakeRequestBody { + clientId: String, + token: String, +} - // TODO +#[derive(Deserialize)] +struct HandshakeResponse { + private: String, + public: String, + certificate: String, + id: String, +} + +macro_rules! unwrap_or_return { + ( $e:expr, $app:expr ) => { + match $e { + Ok(x) => x, + Err(_) => { + $app.emit("auth/failed", ()).unwrap(); + return; + } + } + }; +} + +pub fn recieve_handshake(app: AppHandle, path: String) { + // Tell the app we're processing + app.emit("auth/processing", ()).unwrap(); + + let path_chunks: Vec<&str> = path.split("/").collect(); + if path_chunks.len() != 3 { + app.emit("auth/failed", ()).unwrap(); + return; + } + + let base_url = { + let handle = DB.borrow_data().unwrap(); + Url::parse(handle.base_url.as_str()).unwrap() + }; + + let client_id = path_chunks.get(1).unwrap(); + let token = path_chunks.get(2).unwrap(); + let body = HandshakeRequestBody { + clientId: client_id.to_string(), + token: token.to_string(), + }; + + let endpoint = unwrap_or_return!(base_url.join("/api/v1/client/handshake"), app); + let client = reqwest::blocking::Client::new(); + let response = unwrap_or_return!(client.post(endpoint).json(&body).send(), app); + info!("server responded with {}", response.status()); + let response_struct = unwrap_or_return!(response.json::(), app); + + { + let mut handle = DB.borrow_data_mut().unwrap(); + handle.certs = Some(DatabaseCerts { + private: response_struct.private, + public: response_struct.public, + cert: response_struct.certificate, + }); + drop(handle); + DB.save().unwrap(); + } + + { + let app_state = app.state::>(); + let mut app_state_handle = app_state.lock().unwrap(); + app_state_handle.status = AppStatus::SignedIn; + } + + app.emit("auth/finished", ()).unwrap(); } #[tauri::command] @@ -48,6 +116,7 @@ pub async fn auth_initiate<'a>() -> Result<(), String> { let redir_url = response.text().await.unwrap(); let complete_redir_url = base_url.join(&redir_url).unwrap(); + info!("opening web browser to continue authentication"); webbrowser::open(&complete_redir_url.to_string()).unwrap(); return Ok(()); @@ -59,12 +128,11 @@ pub fn setup() -> Result<(AppStatus, Option), Error> { // If we have certs, exit for now if data.certs.is_some() { // TODO: check if it's still valid, and fetch user information + info!("have existing certs, assuming logged in..."); return Ok((AppStatus::SignedInNeedsReauth, None)); } drop(data); - auth_initiate(); - return Ok((AppStatus::SignedOut, None)); } diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 2b87d31a..4f7d6448 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -4,15 +4,17 @@ mod remote; mod unpacker; use std::{ + io, sync::{LazyLock, Mutex}, task, thread, }; use auth::{auth_initiate, recieve_handshake}; use data::DatabaseInterface; -use futures::executor; +use log::info; use remote::use_remote; use serde::Serialize; +use structured_logger::{json::new_writer, Builder}; use tauri_plugin_deep_link::DeepLinkExt; #[derive(Clone, Copy, Serialize)] @@ -40,6 +42,10 @@ fn fetch_state<'a>(state: tauri::State<'_, Mutex>) -> Result() -> AppState { + Builder::with_level("info") + .with_target_writer("*", new_writer(io::stdout())) + .init(); + let is_set_up = data::is_set_up(); if !is_set_up { return AppState { @@ -60,14 +66,14 @@ pub static DB: LazyLock = LazyLock::new(|| data::setup()); #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let state = setup(); + info!("Initialized drop client"); let mut builder = tauri::Builder::default(); #[cfg(desktop)] { builder = builder.plugin(tauri_plugin_single_instance::init(|_app, argv, _cwd| { - println!("a new app instance was opened with {argv:?} and the deep link event was already triggered"); - // when defining deep link schemes at runtime, you must also check `argv` here + // when defining deep link schemes at runtime, you must also check `argv` here })); } @@ -85,20 +91,17 @@ pub fn run() { { use tauri_plugin_deep_link::DeepLinkExt; app.deep_link().register_all()?; + info!("registered all pre-defined deep links"); } let handle = app.handle().clone(); app.deep_link().on_open_url(move |event| { + info!("handling drop:// url"); let binding = event.urls(); let url = binding.get(0).unwrap(); match url.host_str().unwrap() { - "handshake" => { - executor::block_on(recieve_handshake( - handle.clone(), - url.path().to_string(), - )); - } + "handshake" => recieve_handshake(handle.clone(), url.path().to_string()), _ => (), } }); diff --git a/desktop/src-tauri/src/remote.rs b/desktop/src-tauri/src/remote.rs index 91926913..d02770bc 100644 --- a/desktop/src-tauri/src/remote.rs +++ b/desktop/src-tauri/src/remote.rs @@ -3,6 +3,7 @@ use std::{ sync::Mutex, }; +use log::{info, warn}; use serde::Deserialize; use url::Url; @@ -32,7 +33,7 @@ pub async fn use_remote<'a>( url: String, state: tauri::State<'_, Mutex>, ) -> Result<(), String> { - println!("connecting to url {}", url); + info!("connecting to url {}", url); let base_url = unwrap_or_return!(Url::parse(&url)); // Test Drop url @@ -42,6 +43,7 @@ pub async fn use_remote<'a>( let result = response.json::().await.unwrap(); if result.appName != "Drop" { + warn!("user entered drop endpoint that connected, but wasn't identified as Drop"); return Err("Not a valid Drop endpoint".to_string()); }