From a8e6c2449bee00c7052067df43943642fbf00ee0 Mon Sep 17 00:00:00 2001 From: Pauline Date: Sat, 23 Mar 2024 05:11:54 +0100 Subject: [PATCH] error handling part 1.5 --- Cargo.toml | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/auth/microsoft_auth.rs | 4 ++-- src-tauri/src/auth/mod.rs | 12 ++++++------ src-tauri/src/lib.rs | 6 ++++++ src-tauri/src/utils/file.rs | 23 ++++++++++++++--------- src-tauri/src/utils/http.rs | 12 ++++++------ 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ba73c1f1..28117038 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ tar = { version = "0.4" } zip = { version = "0.6" } async-trait = { version = "0.1" } thiserror = { version = "1" } +anyhow = { version = "1" } [profile.dev] # Make compilation faster on macOS diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d976302f..db25f308 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -28,6 +28,7 @@ uuid = { workspace = true } async-trait = { workspace = true } prisma-client-rust = { workspace = true } thiserror = { workspace = true } +anyhow = { workspace = true } [features] # This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!! diff --git a/src-tauri/src/auth/microsoft_auth.rs b/src-tauri/src/auth/microsoft_auth.rs index 0a6cad9b..6d0ff701 100644 --- a/src-tauri/src/auth/microsoft_auth.rs +++ b/src-tauri/src/auth/microsoft_auth.rs @@ -4,13 +4,13 @@ use serde_json::json; use tauri::{AppHandle, Runtime}; use tauri_plugin_shell::ShellExt; -use crate::{constants::CLIENT_ID, utils::http::create_client}; +use crate::{constants::CLIENT_ID, utils::http::create_client, PolyResult}; use super::{Account, AuthenticationMethod}; pub(super) struct MicrosoftAuthenticationMethod; impl AuthenticationMethod for MicrosoftAuthenticationMethod { - async fn auth(handle: &AppHandle, stage: F) -> > + async fn auth(handle: &AppHandle, stage: F) -> PolyResult where F: Fn(String, u8, bool) -> () { stage("Authenticating with Microsoft".into(), 0, false); diff --git a/src-tauri/src/auth/mod.rs b/src-tauri/src/auth/mod.rs index 3390b35f..df79bb40 100644 --- a/src-tauri/src/auth/mod.rs +++ b/src-tauri/src/auth/mod.rs @@ -1,9 +1,9 @@ -use std::error::Error; - use serde::{Deserialize, Serialize}; use tauri::{plugin::TauriPlugin, AppHandle, Manager, Runtime}; use tauri_plugin_http::reqwest::Client; +use crate::{PolyError, PolyResult}; + use self::microsoft_auth::MicrosoftAuthenticationMethod; mod microsoft_auth; @@ -27,10 +27,10 @@ pub struct AccountSkin { pub trait AuthenticationMethod { /// Authenticate with a given method. Stage is a function that takes a string and a u8. /// The string is the message to display to the user, and the u8 is the progress of the authentication. - async fn auth(handle: &AppHandle, stage: F) -> Result> + async fn auth(handle: &AppHandle, stage: F) -> PolyResult where F: Fn(String, u8, bool) -> (); - async fn get_profile(access_token: String) -> Result> { + async fn get_profile(access_token: String) -> PolyResult { let response = Client::new() .get("https://api.minecraftservices.com/minecraft/profile") .header("Authorization", format!("Bearer {}", access_token)) @@ -39,7 +39,7 @@ pub trait AuthenticationMethod { let response = response.json::().await?; if let Some(error) = response.get("error") { - return Err(error.to_string().into()); + return Err(PolyError(error.to_string())); } let account = serde_json::from_value::(response)?; @@ -64,4 +64,4 @@ async fn login_msa(app: tauri::AppHandle) -> Result Ok(account), Err(err) => Err(err.to_string()) } -} \ No newline at end of file +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a5c1250e..1834c085 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -36,9 +36,15 @@ pub enum PolyError { #[error("failed to establish a connection to the database: {0}")] /// Wrapper around [`prisma_client_rust::NewClientError`] to handle errors occuring while programmatically connecting to Prisma. DBConnectionError(#[from] prisma_client_rust::NewClientError), + #[error("failed to establish a HTTP connection: {0}")] + /// Wrapper around [`reqwest::Error`] to handle HTTP errors. + HTTPError(#[from] tauri_plugin_http::reqwest::Error), #[error("failed to download java: {0}")] /// Wrapper around [`game::client::JavaDownloadError`] to handle Java executable downloading. JavaError(#[from] game::client::JavaDownloadError), + #[error("file management failed: {0}")] + /// Wrapper around [`utils::file::FileError`] to handle file management errors. + FileError(#[from] utils::file::FileError), } /// Alias for a [`Result`] with the error type [`PolyError`]. diff --git a/src-tauri/src/utils/file.rs b/src-tauri/src/utils/file.rs index 194e6d1e..5f04a196 100644 --- a/src-tauri/src/utils/file.rs +++ b/src-tauri/src/utils/file.rs @@ -1,27 +1,32 @@ -use std::{error::Error, fs::File, path::Path}; +use std::{fs::File, path::Path}; +use anyhow::anyhow; +use thiserror::Error; -pub fn extract_archive(archive: &Path, dest: &Path) -> Result<(), Box> { +use crate::{PolyError, PolyResult}; + +pub fn extract_archive(archive: &Path, dest: &Path) -> PolyResult<()> { let ext = match archive.extension() { Some(ext) => ext.to_str().unwrap(), - None => return Err("Archive has no extension".into()) + None => return Err(anyhow!("unsupported archive type")) }; match ext { "zip" => extract_zip(archive, dest), "gz" => extract_tar_gz(archive, dest), - _ => Err("Unsupported archive type".into()) + _ => Err(PolyError::FileError(FileError::UnsupportedArch)) } } -pub fn extract_zip(archive: &Path, dest: &Path) -> Result<(), Box> { - let mut archive = zip::ZipArchive::new(File::open(archive)?)?; - archive.extract(dest)?; +pub fn extract_zip(archive: &Path, dest: &Path) -> PolyResult<()> { + let mut archive = zip::ZipArchive::new(File::open(archive)?) + .map_err(|err| PolyError::FileError(FileError::ZipError(err))); + archive?.extract(dest).map_err(|err| PolyError::FileError(FileError::ZipError(err))); Ok(()) } -pub fn extract_tar_gz(archive: &Path, dest: &Path) -> Result<(), Box> { +pub fn extract_tar_gz(archive: &Path, dest: &Path) -> PolyResult<()> { let tar_gz = flate2::read::GzDecoder::new(File::open(archive)?); let mut archive = tar::Archive::new(tar_gz); archive.unpack(dest)?; Ok(()) -} \ No newline at end of file +} diff --git a/src-tauri/src/utils/http.rs b/src-tauri/src/utils/http.rs index bd89defc..6d3da8b6 100644 --- a/src-tauri/src/utils/http.rs +++ b/src-tauri/src/utils/http.rs @@ -1,17 +1,17 @@ -use std::{error::Error, fs::File, io::{self, Cursor}, path::Path}; +use std::{fs::File, io::{self, Cursor}, path::Path}; use tauri_plugin_http::reqwest::{Client, ClientBuilder}; -use crate::constants::USER_AGENT; +use crate::{constants::USER_AGENT, PolyError, PolyResult}; -pub fn create_client() -> Client { +pub fn create_client() -> PolyResult { ClientBuilder::new() .user_agent(USER_AGENT) - .build().expect("Failed to create HTTP client. Please report this issue on GitHub.") + .build().map_err(|err| PolyError::HTTPError(err)) } -pub async fn download_file(url: &str, path: &Path) -> Result<(), Box> { - let response = create_client().get(url).send().await?; +pub async fn download_file(url: &str, path: &Path) -> PolyResult<()> { + let response = create_client()?.get(url).send().await?; let mut file = File::create(path)?; let mut content = Cursor::new(response.bytes().await?); io::copy(&mut content, &mut file)?;