mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-14 16:51:18 +10:00
commit0f48f3fb44Author: quexeky <git@quexeky.dev> Date: Sun Oct 12 19:35:04 2025 +1100 chore: Run cargo clippy && cargo fmt Signed-off-by: quexeky <git@quexeky.dev> commit974666efe2Author: quexeky <git@quexeky.dev> Date: Sun Oct 12 19:17:40 2025 +1100 refactor: Finish refactor Signed-off-by: quexeky <git@quexeky.dev> commit9e1bf9852fAuthor: quexeky <git@quexeky.dev> Date: Sun Oct 12 18:33:43 2025 +1100 refactor: Builds, but some logic still left to move back Signed-off-by: quexeky <git@quexeky.dev> commit5d22b883d5Author: quexeky <git@quexeky.dev> Date: Sun Oct 12 17:04:27 2025 +1100 refactor: Improvements to src-tauri Signed-off-by: quexeky <git@quexeky.dev> commit62a2561539Author: quexeky <git@quexeky.dev> Date: Sat Oct 11 09:51:04 2025 +1100 fix: Remote tauri dependency from process Signed-off-by: quexeky <git@quexeky.dev> commit59f040bc8bAuthor: quexeky <git@quexeky.dev> Date: Thu Oct 9 07:46:17 2025 +1100 chore: Major refactoring Still needs a massive go-over because there shouldn't be anything referencing tauri in any of the workspaces except the original one. Process manager has been refactored as an example Signed-off-by: quexeky <git@quexeky.dev> Signed-off-by: quexeky <git@quexeky.dev>
153 lines
4.1 KiB
Rust
153 lines
4.1 KiB
Rust
use std::{collections::HashMap, env};
|
|
|
|
use chrono::Utc;
|
|
use client::{app_status::AppStatus, user::User};
|
|
use database::{DatabaseAuth, interface::borrow_db_checked};
|
|
use droplet_rs::ssl::sign_nonce;
|
|
use gethostname::gethostname;
|
|
use log::{error, warn};
|
|
use serde::{Deserialize, Serialize};
|
|
use url::Url;
|
|
|
|
use crate::{
|
|
error::{DropServerError, RemoteAccessError},
|
|
requests::make_authenticated_get,
|
|
utils::DROP_CLIENT_SYNC,
|
|
};
|
|
|
|
use super::{
|
|
cache::{cache_object, get_cached_object},
|
|
requests::generate_url,
|
|
};
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct CapabilityConfiguration {}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct InitiateRequestBody {
|
|
name: String,
|
|
platform: String,
|
|
capabilities: HashMap<String, CapabilityConfiguration>,
|
|
mode: String,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct HandshakeRequestBody {
|
|
client_id: String,
|
|
token: String,
|
|
}
|
|
|
|
impl HandshakeRequestBody {
|
|
pub fn new(client_id: String, token: String) -> Self {
|
|
Self { client_id, token }
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct HandshakeResponse {
|
|
private: String,
|
|
certificate: String,
|
|
id: String,
|
|
}
|
|
|
|
impl From<HandshakeResponse> for DatabaseAuth {
|
|
fn from(value: HandshakeResponse) -> Self {
|
|
DatabaseAuth::new(value.private, value.certificate, value.id, None)
|
|
}
|
|
}
|
|
|
|
pub fn generate_authorization_header() -> String {
|
|
let certs = {
|
|
let db = borrow_db_checked();
|
|
db.auth.clone().expect("Authorisation not initialised")
|
|
};
|
|
|
|
let nonce = Utc::now().timestamp_millis().to_string();
|
|
|
|
let signature =
|
|
sign_nonce(certs.private, nonce.clone()).expect("Failed to generate authorisation header");
|
|
|
|
format!("Nonce {} {} {}", certs.client_id, nonce, signature)
|
|
}
|
|
|
|
pub async fn fetch_user() -> Result<User, RemoteAccessError> {
|
|
let response = make_authenticated_get(generate_url(&["/api/v1/client/user"], &[])?).await?;
|
|
if response.status() != 200 {
|
|
let err: DropServerError = response.json().await?;
|
|
warn!("{err:?}");
|
|
|
|
if err.status_message == "Nonce expired" {
|
|
return Err(RemoteAccessError::OutOfSync);
|
|
}
|
|
|
|
return Err(RemoteAccessError::InvalidResponse(err));
|
|
}
|
|
|
|
response
|
|
.json::<User>()
|
|
.await
|
|
.map_err(std::convert::Into::into)
|
|
}
|
|
|
|
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())?
|
|
};
|
|
|
|
let hostname = gethostname();
|
|
|
|
let endpoint = base_url.join("/api/v1/client/auth/initiate")?;
|
|
let body = InitiateRequestBody {
|
|
name: format!("{} (Desktop)", hostname.display()),
|
|
platform: env::consts::OS.to_string(),
|
|
capabilities: HashMap::from([
|
|
("peerAPI".to_owned(), CapabilityConfiguration {}),
|
|
("cloudSaves".to_owned(), CapabilityConfiguration {}),
|
|
]),
|
|
mode,
|
|
};
|
|
|
|
let client = DROP_CLIENT_SYNC.clone();
|
|
let response = client.post(endpoint.to_string()).json(&body).send()?;
|
|
|
|
if response.status() != 200 {
|
|
let data: DropServerError = response.json()?;
|
|
error!("could not start handshake: {}", data.status_message);
|
|
|
|
return Err(RemoteAccessError::HandshakeFailed(data.status_message));
|
|
}
|
|
|
|
let response = response.text()?;
|
|
|
|
Ok(response)
|
|
}
|
|
|
|
pub async fn setup() -> (AppStatus, Option<User>) {
|
|
let auth = {
|
|
let data = borrow_db_checked();
|
|
data.auth.clone()
|
|
};
|
|
|
|
if auth.is_some() {
|
|
let user_result = match fetch_user().await {
|
|
Ok(data) => data,
|
|
Err(RemoteAccessError::FetchError(_)) => {
|
|
let user = get_cached_object::<User>("user").ok();
|
|
return (AppStatus::Offline, user);
|
|
}
|
|
Err(_) => return (AppStatus::SignedInNeedsReauth, None),
|
|
};
|
|
if let Err(e) = cache_object("user", &user_result) {
|
|
warn!("Could not cache user object with error {e}");
|
|
}
|
|
return (AppStatus::SignedIn, Some(user_result));
|
|
}
|
|
|
|
(AppStatus::SignedOut, None)
|
|
}
|