mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2026-07-26 09:44:47 +10:00
feat: more refactoring (broken)
This commit is contained in:
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
bitcode = "0.6.7"
|
||||
chrono = "0.4.42"
|
||||
drop-database = { path = "../drop-database" }
|
||||
drop-consts = { path = "../drop-consts" }
|
||||
drop-errors = { path = "../drop-errors" }
|
||||
droplet-rs = "0.7.3"
|
||||
gethostname = "1.0.2"
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use std::{collections::HashMap, env, sync::Mutex};
|
||||
|
||||
use chrono::Utc;
|
||||
use drop_database::{borrow_db_checked, borrow_db_mut_checked, models::data::DatabaseAuth, runtime_models::User};
|
||||
use drop_errors::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError};
|
||||
use drop_errors::{drop_server_error::ServerError, remote_access_error::RemoteAccessError};
|
||||
use droplet_rs::ssl::sign_nonce;
|
||||
use gethostname::gethostname;
|
||||
use log::{debug, error, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use crate::{requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}};
|
||||
use crate::{
|
||||
requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}, DropRemoteAuth, DropRemoteContext
|
||||
};
|
||||
|
||||
use super::requests::generate_url;
|
||||
|
||||
@@ -41,23 +42,24 @@ struct HandshakeResponse {
|
||||
id: String,
|
||||
}
|
||||
|
||||
pub fn generate_authorization_header() -> String {
|
||||
let certs = {
|
||||
let db = borrow_db_checked();
|
||||
db.auth.clone().unwrap()
|
||||
pub fn generate_authorization_header(context: &DropRemoteContext) -> String {
|
||||
let auth = if let Some(auth) = &context.auth {
|
||||
auth
|
||||
} else {
|
||||
return "".to_owned();
|
||||
};
|
||||
|
||||
let nonce = Utc::now().timestamp_millis().to_string();
|
||||
|
||||
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
|
||||
let signature = sign_nonce(auth.private.clone(), nonce.clone()).unwrap();
|
||||
|
||||
format!("Nonce {} {} {}", certs.client_id, nonce, signature)
|
||||
format!("Nonce {} {} {}", auth.client_id, nonce, signature)
|
||||
}
|
||||
|
||||
pub async fn fetch_user() -> Result<User, RemoteAccessError> {
|
||||
let response = make_authenticated_get(generate_url(&["/api/v1/client/user"], &[])?).await?;
|
||||
pub async fn fetch_user(context: &DropRemoteContext) -> Result<Vec<u8>, RemoteAccessError> {
|
||||
let response =
|
||||
make_authenticated_get(context, generate_url(context, &["/api/v1/client/user"], &[])?).await?;
|
||||
if response.status() != 200 {
|
||||
let err: DropServerError = response.json().await?;
|
||||
let err: ServerError = response.json().await?;
|
||||
warn!("{err:?}");
|
||||
|
||||
if err.status_message == "Nonce expired" {
|
||||
@@ -68,25 +70,24 @@ pub async fn fetch_user() -> Result<User, RemoteAccessError> {
|
||||
}
|
||||
|
||||
response
|
||||
.json::<User>()
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(std::convert::Into::into)
|
||||
.map(|v| v.to_vec())
|
||||
}
|
||||
|
||||
pub async fn recieve_handshake_logic(path: String) -> Result<(), RemoteAccessError> {
|
||||
pub async fn recieve_handshake_logic(
|
||||
context: &mut DropRemoteContext,
|
||||
path: String,
|
||||
) -> Result<(), RemoteAccessError> {
|
||||
let path_chunks: Vec<&str> = path.split('/').collect();
|
||||
if path_chunks.len() != 3 {
|
||||
// app.emit("auth/failed", ()).unwrap();
|
||||
// app.emit("auth/failed", ()).unwrap();
|
||||
return Err(RemoteAccessError::HandshakeFailed(
|
||||
"failed to parse token".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let base_url = {
|
||||
let handle = borrow_db_checked();
|
||||
Url::parse(handle.base_url.as_str())?
|
||||
};
|
||||
|
||||
let client_id = path_chunks.get(1).unwrap();
|
||||
let token = path_chunks.get(2).unwrap();
|
||||
let body = HandshakeRequestBody {
|
||||
@@ -94,7 +95,7 @@ pub async fn recieve_handshake_logic(path: String) -> Result<(), RemoteAccessErr
|
||||
token: (*token).to_string(),
|
||||
};
|
||||
|
||||
let endpoint = base_url.join("/api/v1/client/auth/handshake")?;
|
||||
let endpoint = generate_url(context, &["/api/v1/client/auth/handshake"], &[])?;
|
||||
let client = DROP_CLIENT_ASYNC.clone();
|
||||
let response = client.post(endpoint).json(&body).send().await?;
|
||||
debug!("handshake responsded with {}", response.status().as_u16());
|
||||
@@ -103,20 +104,10 @@ pub async fn recieve_handshake_logic(path: String) -> Result<(), RemoteAccessErr
|
||||
}
|
||||
let response_struct: HandshakeResponse = response.json().await?;
|
||||
|
||||
{
|
||||
let mut handle = borrow_db_mut_checked();
|
||||
handle.auth = Some(DatabaseAuth {
|
||||
private: response_struct.private,
|
||||
cert: response_struct.certificate,
|
||||
client_id: response_struct.id,
|
||||
web_token: None, // gets created later
|
||||
});
|
||||
}
|
||||
|
||||
let web_token = {
|
||||
let header = generate_authorization_header();
|
||||
let header = generate_authorization_header(context);
|
||||
let token = client
|
||||
.post(base_url.join("/api/v1/client/user/webtoken").unwrap())
|
||||
.post(generate_url(context, &["/api/v1/client/user/webtoken"], &[])?)
|
||||
.header("Authorization", header)
|
||||
.send()
|
||||
.await
|
||||
@@ -125,22 +116,20 @@ pub async fn recieve_handshake_logic(path: String) -> Result<(), RemoteAccessErr
|
||||
token.text().await.unwrap()
|
||||
};
|
||||
|
||||
let mut handle = borrow_db_mut_checked();
|
||||
let mut_auth = handle.auth.as_mut().unwrap();
|
||||
mut_auth.web_token = Some(web_token);
|
||||
context.auth = Some(DropRemoteAuth {
|
||||
private: response_struct.private,
|
||||
cert: response_struct.certificate,
|
||||
client_id: response_struct.id,
|
||||
web_token: web_token,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> {
|
||||
let base_url = {
|
||||
let db_lock = borrow_db_checked();
|
||||
Url::parse(&db_lock.base_url.clone())?
|
||||
};
|
||||
|
||||
pub fn auth_initiate_logic(context: &DropRemoteContext, mode: String) -> Result<String, RemoteAccessError> {
|
||||
let hostname = gethostname();
|
||||
|
||||
let endpoint = base_url.join("/api/v1/client/auth/initiate")?;
|
||||
let endpoint = generate_url(context, &["/api/v1/client/auth/initiate"], &[])?;
|
||||
let body = InitiateRequestBody {
|
||||
name: format!("{} (Desktop)", hostname.into_string().unwrap()),
|
||||
platform: env::consts::OS.to_string(),
|
||||
@@ -155,7 +144,7 @@ pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> {
|
||||
let response = client.post(endpoint.to_string()).json(&body).send()?;
|
||||
|
||||
if response.status() != 200 {
|
||||
let data: DropServerError = response.json()?;
|
||||
let data: ServerError = response.json()?;
|
||||
error!("could not start handshake: {}", data.status_message);
|
||||
|
||||
return Err(RemoteAccessError::HandshakeFailed(data.status_message));
|
||||
@@ -164,4 +153,4 @@ pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> {
|
||||
let response = response.text()?;
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
};
|
||||
|
||||
use bitcode::{Decode, DecodeOwned, Encode};
|
||||
use drop_database::{borrow_db_checked, models::data::Database};
|
||||
use drop_consts::CACHE_DIR;
|
||||
use drop_errors::remote_access_error::RemoteAccessError;
|
||||
use http::{Response, header::CONTENT_TYPE, response::Builder as ResponseBuilder};
|
||||
|
||||
@@ -57,36 +57,33 @@ fn delete_sync(base: &Path, key: &str) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn cache_object<D: Encode>(key: &str, data: &D) -> Result<(), RemoteAccessError> {
|
||||
cache_object_db(key, data, &borrow_db_checked())
|
||||
cache_object_db(key, data)
|
||||
}
|
||||
pub fn cache_object_db<D: Encode>(
|
||||
key: &str,
|
||||
data: &D,
|
||||
database: &Database,
|
||||
) -> Result<(), RemoteAccessError> {
|
||||
let bytes = bitcode::encode(data);
|
||||
write_sync(&database.cache_dir, key, bytes).map_err(RemoteAccessError::Cache)
|
||||
write_sync(&CACHE_DIR, key, bytes).map_err(RemoteAccessError::Cache)
|
||||
}
|
||||
pub fn get_cached_object<D: Encode + DecodeOwned>(key: &str) -> Result<D, RemoteAccessError> {
|
||||
get_cached_object_db::<D>(key, &borrow_db_checked())
|
||||
get_cached_object_db::<D>(key)
|
||||
}
|
||||
pub fn get_cached_object_db<D: DecodeOwned>(
|
||||
key: &str,
|
||||
db: &Database,
|
||||
) -> Result<D, RemoteAccessError> {
|
||||
let bytes = read_sync(&db.cache_dir, key).map_err(RemoteAccessError::Cache)?;
|
||||
let bytes = read_sync(&CACHE_DIR, key).map_err(RemoteAccessError::Cache)?;
|
||||
let data =
|
||||
bitcode::decode::<D>(&bytes).map_err(|e| RemoteAccessError::Cache(io::Error::other(e)))?;
|
||||
Ok(data)
|
||||
}
|
||||
pub fn clear_cached_object(key: &str) -> Result<(), RemoteAccessError> {
|
||||
clear_cached_object_db(key, &borrow_db_checked())
|
||||
clear_cached_object_db(key)
|
||||
}
|
||||
pub fn clear_cached_object_db(
|
||||
key: &str,
|
||||
db: &Database,
|
||||
) -> Result<(), RemoteAccessError> {
|
||||
delete_sync(&db.cache_dir, key).map_err(RemoteAccessError::Cache)?;
|
||||
delete_sync(&CACHE_DIR, key).map_err(RemoteAccessError::Cache)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
use drop_database::{db::DatabaseImpls as _, DB};
|
||||
use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder};
|
||||
use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder, Request};
|
||||
use log::warn;
|
||||
use tauri::UriSchemeResponder;
|
||||
|
||||
|
||||
use crate::utils::DROP_CLIENT_ASYNC;
|
||||
use crate::{requests::generate_url, utils::DROP_CLIENT_ASYNC, DropRemoteContext};
|
||||
|
||||
use super::{
|
||||
auth::generate_authorization_header,
|
||||
cache::{ObjectCache, cache_object, get_cached_object},
|
||||
};
|
||||
|
||||
pub async fn fetch_object(request: http::Request<Vec<u8>>, responder: UriSchemeResponder) {
|
||||
pub async fn fetch_object(context: &DropRemoteContext, request: Request<Vec<u8>>, responder: UriSchemeResponder) {
|
||||
// Drop leading /
|
||||
let object_id = &request.uri().path()[1..];
|
||||
|
||||
@@ -23,9 +22,9 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>, responder: UriSchemeR
|
||||
return;
|
||||
}
|
||||
|
||||
let header = generate_authorization_header();
|
||||
let header = generate_authorization_header(context);
|
||||
let client = DROP_CLIENT_ASYNC.clone();
|
||||
let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url());
|
||||
let url = generate_url(context, &["/api/v1/client/object", object_id], &[]).expect("failed to generated object url");
|
||||
let response = client.get(url).header("Authorization", header).send().await;
|
||||
|
||||
if response.is_err() {
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
pub mod auth;
|
||||
pub mod cache;
|
||||
pub mod fetch_object;
|
||||
pub mod requests;
|
||||
pub mod utils;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
struct DropRemoteAuth {
|
||||
private: String,
|
||||
cert: String,
|
||||
client_id: String,
|
||||
web_token: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct DropRemoteContext {
|
||||
base_url: Url,
|
||||
auth: Option<DropRemoteAuth>,
|
||||
}
|
||||
|
||||
|
||||
impl DropRemoteContext {
|
||||
pub fn new(base_url: Url) -> Self {
|
||||
DropRemoteContext { base_url, auth: None }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
use drop_database::{db::DatabaseImpls as _, DB};
|
||||
use drop_errors::remote_access_error::RemoteAccessError;
|
||||
use url::Url;
|
||||
|
||||
use crate::{auth::generate_authorization_header, utils::DROP_CLIENT_ASYNC};
|
||||
use crate::{auth::generate_authorization_header, utils::DROP_CLIENT_ASYNC, DropRemoteContext};
|
||||
|
||||
pub fn generate_url<T: AsRef<str>>(
|
||||
context: &DropRemoteContext,
|
||||
path_components: &[T],
|
||||
query: &[(T, T)],
|
||||
) -> Result<Url, RemoteAccessError> {
|
||||
let mut base_url = DB.fetch_base_url();
|
||||
let mut base_url = context.base_url.clone();
|
||||
for endpoint in path_components {
|
||||
base_url = base_url.join(endpoint.as_ref())?;
|
||||
}
|
||||
@@ -21,10 +21,10 @@ pub fn generate_url<T: AsRef<str>>(
|
||||
Ok(base_url)
|
||||
}
|
||||
|
||||
pub async fn make_authenticated_get(url: Url) -> Result<reqwest::Response, reqwest::Error> {
|
||||
pub async fn make_authenticated_get(context: &DropRemoteContext, url: Url) -> Result<reqwest::Response, reqwest::Error> {
|
||||
DROP_CLIENT_ASYNC
|
||||
.get(url)
|
||||
.header("Authorization", generate_authorization_header())
|
||||
.header("Authorization", generate_authorization_header(context))
|
||||
.send()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@ use std::{
|
||||
sync::LazyLock,
|
||||
};
|
||||
|
||||
use drop_database::db::DATA_ROOT_DIR;
|
||||
use drop_consts::DATA_ROOT_DIR;
|
||||
use log::{debug, info};
|
||||
use reqwest::Certificate;
|
||||
use serde::Deserialize;
|
||||
|
||||
static DROP_CERT_BUNDLE: LazyLock<Vec<Certificate>> = LazyLock::new(fetch_certificates);
|
||||
pub static DROP_CLIENT_SYNC: LazyLock<reqwest::blocking::Client> = LazyLock::new(get_client_sync);
|
||||
|
||||
Reference in New Issue
Block a user