mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-13 16:22:43 +10:00
handshakes
This commit is contained in:
16
app.vue
16
app.vue
@ -3,6 +3,8 @@
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
{{ state }}
|
||||
<input type="text" v-model="debugLocation" />
|
||||
<NuxtLink :to="debugLocation">Go</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -23,7 +25,17 @@ switch (state.status) {
|
||||
break;
|
||||
}
|
||||
|
||||
listen("auth/connecting", (event) => {
|
||||
router.push("/auth/connecting");
|
||||
listen("auth/processing", () => {
|
||||
router.push("/auth/processing");
|
||||
});
|
||||
|
||||
listen("auth/failed", () => {
|
||||
router.push("/auth/failed");
|
||||
});
|
||||
|
||||
listen("auth/finished", () => {
|
||||
router.push("/");
|
||||
});
|
||||
|
||||
const debugLocation = ref("");
|
||||
</script>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="inline-flex items-center gap-x-2">
|
||||
<!--
|
||||
<HeaderButton @click="() => window.minimize()">
|
||||
<MinusIcon />
|
||||
</HeaderButton>
|
||||
@ -17,6 +18,7 @@
|
||||
/>
|
||||
</svg>
|
||||
</HeaderButton>
|
||||
-->
|
||||
<HeaderButton @click="() => window.close()">
|
||||
<XMarkIcon />
|
||||
</HeaderButton>
|
||||
@ -24,10 +26,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
MinusIcon,
|
||||
XMarkIcon,
|
||||
} from "@heroicons/vue/16/solid";
|
||||
import { MinusIcon, XMarkIcon } from "@heroicons/vue/16/solid";
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
|
||||
const window = getCurrentWindow();
|
||||
|
||||
30
pages/auth/failed.vue
Normal file
30
pages/auth/failed.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="min-h-full w-full flex items-center justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<XCircleIcon class="h-12 w-12 text-red-600" aria-hidden="true" />
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<h1 class="text-3xl font-semibold font-display leading-6 text-zinc-100">
|
||||
Connection failed
|
||||
</h1>
|
||||
<div class="mt-4">
|
||||
<p class="text-sm text-zinc-400 max-w-sm">
|
||||
Drop encountered an error while connecting to your instance.
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||
<NuxtLink href="/auth" class="text-sm font-semibold text-zinc-100"
|
||||
><span aria-hidden="true">←</span> Back to authentication
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { XCircleIcon } from "@heroicons/vue/16/solid";
|
||||
|
||||
definePageMeta({
|
||||
layout: "mini",
|
||||
});
|
||||
</script>
|
||||
161
src-tauri/Cargo.lock
generated
161
src-tauri/Cargo.lock
generated
@ -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"
|
||||
|
||||
@ -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"]
|
||||
|
||||
|
||||
@ -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::<HandshakeResponse>(), 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::<Mutex<AppState>>();
|
||||
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<User>), 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));
|
||||
}
|
||||
|
||||
@ -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<AppState>>) -> Result<AppState,
|
||||
}
|
||||
|
||||
fn setup<'a>() -> 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,13 +66,13 @@ pub static DB: LazyLock<DatabaseInterface> = 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
|
||||
}));
|
||||
}
|
||||
@ -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()),
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
|
||||
@ -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<AppState>>,
|
||||
) -> 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::<DropHealthcheck>().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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user