chore: Remove unwraps from auth.rs

Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
quexeky
2025-09-09 16:13:16 +10:00
parent ddde547c08
commit 83dc773b10
7 changed files with 67 additions and 57 deletions

View File

@ -12,7 +12,10 @@ use crate::{
app_emit, database::{ app_emit, database::{
db::{borrow_db_checked, borrow_db_mut_checked}, db::{borrow_db_checked, borrow_db_mut_checked},
models::data::DatabaseAuth, models::data::DatabaseAuth,
}, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, remote::{requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}, AppState, AppStatus, User }, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, remote::{
requests::make_authenticated_get,
utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC},
}, state_lock, AppState, AppStatus, User
}; };
use super::{ use super::{
@ -51,12 +54,13 @@ struct HandshakeResponse {
pub fn generate_authorization_header() -> String { pub fn generate_authorization_header() -> String {
let certs = { let certs = {
let db = borrow_db_checked(); let db = borrow_db_checked();
db.auth.clone().unwrap() db.auth.clone().expect("Authorisation not initialised")
}; };
let nonce = Utc::now().timestamp_millis().to_string(); let nonce = Utc::now().timestamp_millis().to_string();
let signature = sign_nonce(certs.private, nonce.clone()).unwrap(); let signature =
sign_nonce(certs.private, nonce.clone()).expect("Failed to generate authorisation header");
format!("Nonce {} {} {}", certs.client_id, nonce, signature) format!("Nonce {} {} {}", certs.client_id, nonce, signature)
} }
@ -94,11 +98,15 @@ async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), Re
Url::parse(handle.base_url.as_str())? Url::parse(handle.base_url.as_str())?
}; };
let client_id = path_chunks.get(1).unwrap(); let client_id = path_chunks
let token = path_chunks.get(2).unwrap(); .get(1)
.expect("Failed to get client id from path chunks");
let token = path_chunks
.get(2)
.expect("Failed to get token from path chunks");
let body = HandshakeRequestBody { let body = HandshakeRequestBody {
client_id: (*client_id).to_string(), client_id: (client_id).to_string(),
token: (*token).to_string(), token: (token).to_string(),
}; };
let endpoint = base_url.join("/api/v1/client/auth/handshake")?; let endpoint = base_url.join("/api/v1/client/auth/handshake")?;
@ -110,31 +118,24 @@ async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), Re
} }
let response_struct: HandshakeResponse = response.json().await?; 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 web_token = {
let header = generate_authorization_header(); let header = generate_authorization_header();
let token = client let token = client
.post(base_url.join("/api/v1/client/user/webtoken").unwrap()) .post(base_url.join("/api/v1/client/user/webtoken")?)
.header("Authorization", header) .header("Authorization", header)
.send() .send()
.await .await?;
.unwrap();
token.text().await.unwrap() token.text().await?
}; };
let mut handle = borrow_db_mut_checked(); let mut handle = borrow_db_mut_checked();
let mut_auth = handle.auth.as_mut().unwrap(); handle.auth = Some(DatabaseAuth {
mut_auth.web_token = Some(web_token); private: response_struct.private,
cert: response_struct.certificate,
client_id: response_struct.id,
web_token: Some(web_token), // gets created later
});
Ok(()) Ok(())
} }
@ -154,7 +155,7 @@ pub async fn recieve_handshake(app: AppHandle, path: String) {
let (app_status, user) = setup().await; let (app_status, user) = setup().await;
let mut state_lock = app_state.lock().unwrap(); let mut state_lock = state_lock!(app_state);
state_lock.status = app_status; state_lock.status = app_status;
state_lock.user = user; state_lock.user = user;
@ -174,7 +175,7 @@ pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> {
let endpoint = base_url.join("/api/v1/client/auth/initiate")?; let endpoint = base_url.join("/api/v1/client/auth/initiate")?;
let body = InitiateRequestBody { let body = InitiateRequestBody {
name: format!("{} (Desktop)", hostname.into_string().unwrap()), name: format!("{} (Desktop)", hostname.display()),
platform: env::consts::OS.to_string(), platform: env::consts::OS.to_string(),
capabilities: HashMap::from([ capabilities: HashMap::from([
("peerAPI".to_owned(), CapabilityConfiguration {}), ("peerAPI".to_owned(), CapabilityConfiguration {}),
@ -208,12 +209,14 @@ pub async fn setup() -> (AppStatus, Option<User>) {
let user_result = match fetch_user().await { let user_result = match fetch_user().await {
Ok(data) => data, Ok(data) => data,
Err(RemoteAccessError::FetchError(_)) => { Err(RemoteAccessError::FetchError(_)) => {
let user = get_cached_object::<User>("user").unwrap(); let user = get_cached_object::<User>("user").ok();
return (AppStatus::Offline, Some(user)); return (AppStatus::Offline, user);
} }
Err(_) => return (AppStatus::SignedInNeedsReauth, None), Err(_) => return (AppStatus::SignedInNeedsReauth, None),
}; };
cache_object("user", &user_result).unwrap(); if let Err(e) = cache_object("user", &user_result) {
warn!("Could not cache user object with error {e}");
}
return (AppStatus::SignedIn, Some(user_result)); return (AppStatus::SignedIn, Some(user_result));
} }

View File

@ -12,7 +12,7 @@ use crate::{
auth::generate_authorization_header, auth::generate_authorization_header,
requests::generate_url, requests::generate_url,
utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT}, utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT},
}, AppState, AppStatus }, state_lock, utils::webbrowser_open::webbrowser_open, AppState, AppStatus
}; };
use super::{ use super::{
@ -37,7 +37,7 @@ pub fn gen_drop_url(path: String) -> Result<String, RemoteAccessError> {
Url::parse(&handle.base_url).map_err(RemoteAccessError::ParsingError)? Url::parse(&handle.base_url).map_err(RemoteAccessError::ParsingError)?
}; };
let url = base_url.join(&path).unwrap(); let url = base_url.join(&path)?;
Ok(url.to_string()) Ok(url.to_string())
} }
@ -74,7 +74,7 @@ pub fn sign_out(app: AppHandle) {
// Update app state // Update app state
{ {
let app_state = app.state::<Mutex<AppState>>(); let app_state = app.state::<Mutex<AppState>>();
let mut app_state_handle = app_state.lock().unwrap(); let mut app_state_handle = state_lock!(app_state);
app_state_handle.status = AppStatus::SignedOut; app_state_handle.status = AppStatus::SignedOut;
app_state_handle.user = None; app_state_handle.user = None;
} }
@ -87,7 +87,7 @@ pub fn sign_out(app: AppHandle) {
pub async fn retry_connect(state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> { pub async fn retry_connect(state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> {
let (app_status, user) = setup().await; let (app_status, user) = setup().await;
let mut guard = state.lock().unwrap(); let mut guard = state_lock!(state);
guard.status = app_status; guard.status = app_status;
guard.user = user; guard.user = user;
drop(guard); drop(guard);
@ -106,7 +106,7 @@ pub fn auth_initiate() -> Result<(), RemoteAccessError> {
let complete_redir_url = base_url.join(&redir_url)?; let complete_redir_url = base_url.join(&redir_url)?;
debug!("opening web browser to continue authentication"); debug!("opening web browser to continue authentication");
webbrowser::open(complete_redir_url.as_ref()).unwrap(); webbrowser_open(complete_redir_url.as_ref());
Ok(()) Ok(())
} }
@ -123,6 +123,7 @@ pub fn auth_initiate_code(app: AppHandle) -> Result<String, RemoteAccessError> {
let db_lock = borrow_db_checked(); let db_lock = borrow_db_checked();
Url::parse(&db_lock.base_url.clone())? Url::parse(&db_lock.base_url.clone())?
}; };
let code = auth_initiate_logic("code".to_string())?; let code = auth_initiate_logic("code".to_string())?;
let header_code = code.clone(); let header_code = code.clone();

View File

@ -36,7 +36,7 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>) -> Result<Response<Ve
let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url()); let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url());
let response = client.get(url).header("Authorization", header).send().await; let response = client.get(url).header("Authorization", header).send().await;
return match response { match response {
Ok(r) => { Ok(r) => {
let resp_builder = ResponseBuilder::new().header( let resp_builder = ResponseBuilder::new().header(
CONTENT_TYPE, CONTENT_TYPE,
@ -59,10 +59,10 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>) -> Result<Response<Ve
.expect("Failed to create cached object"); .expect("Failed to create cached object");
} }
Ok(resp.into()) Ok(resp)
} }
Err(e) => { Err(e) => {
debug!("Object fetch failed with error {}. Attempting to download from cache", e); debug!("Object fetch failed with error {e}. Attempting to download from cache");
match cache_result { match cache_result {
Ok(cache_result) => Ok(cache_result.into()), Ok(cache_result) => Ok(cache_result.into()),
Err(e) => { Err(e) => {

View File

@ -1,15 +1,15 @@
use std::str::FromStr; use std::str::FromStr;
use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri}; use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri};
use log::warn; use log::{error, warn};
use tauri::UriSchemeResponder; use tauri::UriSchemeResponder;
use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC}; use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC, utils::webbrowser_open::webbrowser_open};
pub async fn handle_server_proto_offline_wrapper(request: Request<Vec<u8>>, responder: UriSchemeResponder) { pub async fn handle_server_proto_offline_wrapper(request: Request<Vec<u8>>, responder: UriSchemeResponder) {
responder.respond(match handle_server_proto_offline(request).await { responder.respond(match handle_server_proto_offline(request).await {
Ok(res) => res, Ok(res) => res,
Err(e) => unreachable!() Err(_) => unreachable!()
}); });
} }
@ -33,9 +33,16 @@ pub async fn handle_server_proto_wrapper(request: Request<Vec<u8>>, responder: U
async fn handle_server_proto(request: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, StatusCode> { async fn handle_server_proto(request: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, StatusCode> {
let db_handle = borrow_db_checked(); let db_handle = borrow_db_checked();
let web_token = match &db_handle.auth.as_ref().unwrap().web_token { let auth = match db_handle.auth.as_ref() {
Some(e) => e, Some(auth) => auth,
None => return Err(StatusCode::BAD_REQUEST), None => {
error!("Could not find auth in database");
return Err(StatusCode::UNAUTHORIZED)
}
};
let web_token = match &auth.web_token {
Some(token) => token,
None => return Err(StatusCode::UNAUTHORIZED),
}; };
let remote_uri = db_handle.base_url.parse::<Uri>().expect("Failed to parse base url"); let remote_uri = db_handle.base_url.parse::<Uri>().expect("Failed to parse base url");
@ -46,18 +53,14 @@ async fn handle_server_proto(request: Request<Vec<u8>>) -> Result<Response<Vec<u
Some(PathAndQuery::from_str(&format!("{path}?noWrapper=true")).expect("Failed to parse request path in proto")); Some(PathAndQuery::from_str(&format!("{path}?noWrapper=true")).expect("Failed to parse request path in proto"));
new_uri.authority = remote_uri.authority().cloned(); new_uri.authority = remote_uri.authority().cloned();
new_uri.scheme = remote_uri.scheme().cloned(); new_uri.scheme = remote_uri.scheme().cloned();
let new_uri = Uri::from_parts(new_uri).expect(&format!("Failed to build new uri from parts")); let err_msg = &format!("Failed to build new uri from parts {new_uri:?}");
let new_uri = Uri::from_parts(new_uri).expect(err_msg);
let whitelist_prefix = ["/store", "/api", "/_", "/fonts"]; let whitelist_prefix = ["/store", "/api", "/_", "/fonts"];
if whitelist_prefix.iter().all(|f| !path.starts_with(f)) { if whitelist_prefix.iter().all(|f| !path.starts_with(f)) {
return match webbrowser::open(&new_uri.to_string()) { webbrowser_open(new_uri.to_string());
Ok(_) => Ok(Response::new(Vec::new())), return Ok(Response::new(Vec::new()))
Err(e) => {
warn!("Could not open web browser to link {new_uri} with error {e}");
Ok(Response::new(Vec::new()))
}
}
} }
let client = DROP_CLIENT_SYNC.clone(); let client = DROP_CLIENT_SYNC.clone();

View File

@ -1,11 +1,6 @@
#[macro_export] #[macro_export]
macro_rules! app_emit { macro_rules! app_emit {
($app:expr, $event:expr, $p:expr) => { ($app:expr, $event:expr, $p:expr) => {
match $app.emit($event, $p) { $app.emit($event, $p).expect(&format!("Failed to emit event {}", $event));
Ok(_) => (),
Err(e) => {
log::error!("Failed to emit event {} with error {}", $event, e);
}
};
}; };
} }

View File

@ -1,2 +1,3 @@
mod app_emit; mod app_emit;
mod state_lock; mod state_lock;
pub mod webbrowser_open;

View File

@ -0,0 +1,7 @@
use log::warn;
pub fn webbrowser_open<T: AsRef<str>>(url: T) {
if let Err(e) = webbrowser::open(url.as_ref()) {
warn!("Could not open web browser to url {} with error {}", url.as_ref(), e);
};
}