use thiserror::Error as ThisError; use aws_sdk_sts::{ types::SdkError as AwsSdkError, error::GetSessionTokenError, }; use sqlx::{ error::Error as SqlxError, migrate::MigrateError, }; use serde::{Serialize, Serializer, ser::SerializeMap}; use strum_macros::IntoStaticStr; pub struct SerializeError { pub err: E } impl Serialize for SerializeError { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(None)?; map.serialize_entry("msg", &format!("{}", self.err))?; if let Some(src) = self.err.source() { let ser_src = SerializeError { err: src }; map.serialize_entry("source", &ser_src)?; } map.end() } } impl From for SerializeError { fn from(err: E) -> Self { SerializeError { err } } } // error during initial setup (primarily loading state from db) #[derive(Debug, ThisError)] pub enum SetupError { #[error("Invalid database record")] InvalidRecord, // e.g. wrong size blob for nonce or salt #[error("Error from database: {0}")] DbError(#[from] SqlxError), #[error("Error running migrations: {0}")] MigrationError(#[from] MigrateError), #[error("Error parsing configuration from database")] ConfigParseError(#[from] serde_json::Error), } // error when attempting to tell a request handler whether to release or deny credentials #[derive(Debug, ThisError, IntoStaticStr)] pub enum SendResponseError { #[error("The specified credentials request was not found")] NotFound, // no request with the given id #[error("The specified request was already closed by the client")] Abandoned, // request has already been closed by client } // errors encountered while handling an HTTP request #[derive(Debug, ThisError)] pub enum RequestError { #[error("Error writing to stream: {0}")] StreamIOError(#[from] std::io::Error), // #[error("Received invalid UTF-8 in request")] // InvalidUtf8, // MalformedHttpRequest, #[error("HTTP request too large")] RequestTooLarge, #[error("Error accessing credentials: {0}")] NoCredentials(#[from] GetCredentialsError), #[error("Error getting client details: {0}")] ClientInfo(#[from] ClientInfoError), #[error("Error from Tauri: {0}")] Tauri(#[from] tauri::Error), #[error("No main application window found")] NoMainWindow, } #[derive(Debug, ThisError)] pub enum GetCredentialsError { #[error("Credentials are currently locked")] Locked, #[error("No credentials are known")] Empty, } #[derive(Debug, ThisError)] pub enum GetSessionError { #[error("Request completed successfully but no credentials were returned")] NoCredentials, // SDK returned successfully but credentials are None #[error("Error response from AWS SDK: {0}")] SdkError(#[from] AwsSdkError), } #[derive(Debug, ThisError)] pub enum UnlockError { #[error("App is not locked")] NotLocked, #[error("No saved credentials were found")] NoCredentials, #[error("Invalid passphrase")] BadPassphrase, #[error("Data was found to be corrupt after decryption")] InvalidUtf8, // Somehow we got invalid utf-8 even though decryption succeeded #[error("Database error: {0}")] DbError(#[from] SqlxError), #[error("Failed to create AWS session: {0}")] GetSession(#[from] GetSessionError), } // Errors encountered while trying to figure out who's on the other end of a request #[derive(Debug, ThisError)] pub enum ClientInfoError { #[error("Found PID for client socket, but no corresponding process")] ProcessNotFound, #[error("Couldn't get client socket details: {0}")] NetstatError(#[from] netstat2::error::Error), }