compliant with new APIs

This commit is contained in:
DecDuck
2024-10-09 00:37:27 +11:00
parent a83aa62a55
commit d7ea32d175
13 changed files with 234 additions and 139 deletions
+18 -2
View File
@@ -931,7 +931,9 @@ version = "0.1.0"
dependencies = [
"ciborium",
"directories",
"hex",
"log",
"openssl",
"os_info",
"rayon",
"reqwest",
@@ -945,6 +947,7 @@ dependencies = [
"tauri-plugin-shell",
"tauri-plugin-single-instance",
"url",
"uuid",
"webbrowser",
"zstd",
]
@@ -3203,9 +3206,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.13"
version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8"
dependencies = [
"once_cell",
"rustls-pki-types",
@@ -4613,7 +4616,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
dependencies = [
"getrandom 0.2.15",
"rand 0.8.5",
"serde",
"uuid-macro-internal",
]
[[package]]
name = "uuid-macro-internal"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee1cd046f83ea2c4e920d6ee9f7c3537ef928d75dce5d84a87c2c5d6b3999a3a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.79",
]
[[package]]
+12 -1
View File
@@ -35,6 +35,18 @@ os_info = "3.8.2"
tauri-plugin-deep-link = "2"
log = "0.4.22"
structured-logger = "1.0.3"
hex = "0.4.3"
[dependencies.uuid]
version = "1.10.0"
features = [
"v4", # Lets you generate random UUIDs
"fast-rng", # Use a faster (but still sufficiently random) RNG
"macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
]
[dependencies.openssl]
version = "0.10.66"
[dependencies.rustbreak]
version = "2"
@@ -43,4 +55,3 @@ features = ["bin_enc"] # You can also use "yaml_enc" or "bin_enc"
[dependencies.reqwest]
version = "0.12"
features = ["json", "blocking"]
+68 -8
View File
@@ -1,14 +1,22 @@
use std::{
borrow::{Borrow, BorrowMut},
fmt::format,
sync::Mutex,
};
use log::info;
use openssl::{
ec::EcKey,
hash::MessageDigest,
pkey::PKey,
sign::{self, Signer},
};
use serde::{Deserialize, Serialize};
use tauri::{App, AppHandle, Emitter, Error, EventLoopMessage, Manager, Wry};
use url::Url;
use uuid::Uuid;
use crate::{data::DatabaseCerts, AppState, AppStatus, User, DB};
use crate::{data::DatabaseAuth, AppState, AppStatus, User, DB};
#[derive(Serialize)]
struct InitiateRequestBody {
@@ -41,6 +49,52 @@ macro_rules! unwrap_or_return {
};
}
pub fn sign_nonce(private_key: String, nonce: String) -> Result<String, Error> {
let client_private_key = EcKey::private_key_from_pem(private_key.as_bytes()).unwrap();
let pkey_private_key = PKey::from_ec_key(client_private_key).unwrap();
let mut signer = Signer::new(MessageDigest::sha256(), &pkey_private_key).unwrap();
signer.update(nonce.as_bytes()).unwrap();
let signature = signer.sign_to_vec().unwrap();
let hex_signature = hex::encode(signature);
return Ok(hex_signature);
}
pub fn generate_authorization_header() -> String {
let certs = {
let db = DB.borrow_data().unwrap();
db.auth.clone().unwrap()
};
let nonce = Uuid::new_v4().to_string();
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
return format!("Nonce {} {} {}", certs.clientId, nonce, signature);
}
pub fn fetch_user() -> Result<User, Error> {
let base_url = {
let handle = DB.borrow_data().unwrap();
Url::parse(&handle.base_url).unwrap()
};
let endpoint = base_url.join("/api/v1/client/user").unwrap();
let header = generate_authorization_header();
let client = reqwest::blocking::Client::new();
let response = client
.get(endpoint.to_string())
.header("Authorization", header)
.send()
.unwrap();
let user = response.json::<User>().unwrap();
return Ok(user);
}
pub fn recieve_handshake(app: AppHandle, path: String) {
// Tell the app we're processing
app.emit("auth/processing", ()).unwrap();
@@ -63,7 +117,7 @@ pub fn recieve_handshake(app: AppHandle, path: String) {
token: token.to_string(),
};
let endpoint = unwrap_or_return!(base_url.join("/api/v1/client/handshake"), app);
let endpoint = unwrap_or_return!(base_url.join("/api/v1/client/auth/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());
@@ -71,9 +125,10 @@ pub fn recieve_handshake(app: AppHandle, path: String) {
{
let mut handle = DB.borrow_data_mut().unwrap();
handle.certs = Some(DatabaseCerts {
handle.auth = Some(DatabaseAuth {
private: response_struct.private,
cert: response_struct.certificate,
clientId: response_struct.id,
});
drop(handle);
DB.save().unwrap();
@@ -86,6 +141,8 @@ pub fn recieve_handshake(app: AppHandle, path: String) {
}
app.emit("auth/finished", ()).unwrap();
fetch_user().unwrap();
}
#[tauri::command]
@@ -97,7 +154,7 @@ pub async fn auth_initiate<'a>() -> Result<(), String> {
let current_os_info = os_info::get();
let endpoint = base_url.join("/api/v1/client/initiate").unwrap();
let endpoint = base_url.join("/api/v1/client/auth/initiate").unwrap();
let body = InitiateRequestBody {
name: format!("Drop Desktop Client"),
platform: current_os_info.os_type().to_string(),
@@ -124,10 +181,13 @@ pub fn setup() -> Result<(AppStatus, Option<User>), Error> {
let data = DB.borrow_data().unwrap();
// 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));
if data.auth.is_some() {
let user_result = fetch_user();
if user_result.is_err() {
return Ok((AppStatus::SignedInNeedsReauth, None));
}
return Ok((AppStatus::SignedIn, Some(user_result.unwrap())))
}
drop(data);
+4 -3
View File
@@ -7,14 +7,15 @@ use serde::Deserialize;
use crate::DB;
#[derive(serde::Serialize, Clone, Deserialize)]
pub struct DatabaseCerts {
pub struct DatabaseAuth {
pub private: String,
pub cert: String,
pub clientId: String,
}
#[derive(serde::Serialize, Clone, Deserialize)]
pub struct Database {
pub certs: Option<DatabaseCerts>,
pub auth: Option<DatabaseAuth>,
pub base_url: String,
}
@@ -24,7 +25,7 @@ pub type DatabaseInterface =
pub fn setup() -> DatabaseInterface {
let db_path = BaseDirs::new().unwrap().data_dir().join("drop");
let default = Database {
certs: None,
auth: None,
base_url: "".to_string(),
};
let db = match fs::exists(db_path.clone()).unwrap() {
+2 -2
View File
@@ -13,7 +13,7 @@ use auth::{auth_initiate, recieve_handshake};
use data::DatabaseInterface;
use log::info;
use remote::use_remote;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use structured_logger::{json::new_writer, Builder};
use tauri_plugin_deep_link::DeepLinkExt;
@@ -24,7 +24,7 @@ pub enum AppStatus {
SignedIn,
SignedInNeedsReauth,
}
#[derive(Clone, Copy, Serialize)]
#[derive(Clone, Copy, Serialize, Deserialize)]
pub struct User {}
#[derive(Clone, Copy, Serialize)]