use error_support::{ErrorHandling, GetErrorHandling};
use rc_crypto::hawk;
use std::string;
#[derive(Debug, thiserror::Error)]
pub enum FxaError {
#[error("authentication error")]
Authentication,
#[error("network error")]
Network,
#[error("no authentication flow was active")]
NoExistingAuthFlow,
#[error("the requested authentication flow was not active")]
WrongAuthFlow,
#[error("Origin mismatch")]
OriginMismatch,
#[error("The sync scoped key was missing")]
SyncScopedKeyMissingInServerResponse,
#[error("panic in native code")]
Panic,
#[error("other error: {0}")]
Other(String),
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Server asked the client to back off, please wait {0} seconds to try again")]
BackoffError(u64),
#[error("Unknown OAuth State")]
UnknownOAuthState,
#[error("Multiple OAuth scopes requested")]
MultipleScopesRequested,
#[error("No cached token for scope {0}")]
NoCachedToken(String),
#[error("No cached scoped keys for scope {0}")]
NoScopedKey(String),
#[error("No stored refresh token")]
NoRefreshToken,
#[error("No stored session token")]
NoSessionToken,
#[error("No stored migration data")]
NoMigrationData,
#[error("No stored current device id")]
NoCurrentDeviceId,
#[error("Device target is unknown (Device ID: {0})")]
UnknownTargetDevice(String),
#[error("Api client error {0}")]
ApiClientError(&'static str),
#[error("Illegal state: {0}")]
IllegalState(&'static str),
#[error("Unknown command: {0}")]
UnknownCommand(String),
#[error("Send Tab diagnosis error: {0}")]
SendTabDiagnosisError(&'static str),
#[error("Cannot xor arrays with different lengths: {0} and {1}")]
XorLengthMismatch(usize, usize),
#[error("Origin mismatch: {0}")]
OriginMismatch(String),
#[error("Remote key and local key mismatch")]
MismatchedKeys,
#[error("The sync scoped key was missing in the server response")]
SyncScopedKeyMissingInServerResponse,
#[error("Client: {0} is not allowed to request scope: {1}")]
ScopeNotAllowed(String, String),
#[error("Unsupported command: {0}")]
UnsupportedCommand(&'static str),
#[error("Missing URL parameter: {0}")]
MissingUrlParameter(&'static str),
#[error("Null pointer passed to FFI")]
NullPointer,
#[error("Invalid buffer length: {0}")]
InvalidBufferLength(i32),
#[error("Too many calls to auth introspection endpoint")]
AuthCircuitBreakerError,
#[error("Remote server error: '{code}' '{errno}' '{error}' '{message}' '{info}'")]
RemoteError {
code: u64,
errno: u64,
error: String,
message: String,
info: String,
},
#[error("Crypto/NSS error: {0}")]
CryptoError(#[from] rc_crypto::Error),
#[error("http-ece encryption error: {0}")]
EceError(#[from] rc_crypto::ece::Error),
#[error("Hex decode error: {0}")]
HexDecodeError(#[from] hex::FromHexError),
#[error("Base64 decode error: {0}")]
Base64Decode(#[from] base64::DecodeError),
#[error("JSON error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("JWCrypto error: {0}")]
JwCryptoError(#[from] jwcrypto::JwCryptoError),
#[error("UTF8 decode error: {0}")]
UTF8DecodeError(#[from] string::FromUtf8Error),
#[error("Network error: {0}")]
RequestError(#[from] viaduct::Error),
#[error("Malformed URL error: {0}")]
MalformedUrl(#[from] url::ParseError),
#[error("Unexpected HTTP status: {0}")]
UnexpectedStatus(#[from] viaduct::UnexpectedStatus),
#[error("Sync15 error: {0}")]
SyncError(#[from] sync15::Error),
#[error("HAWK error: {0}")]
HawkError(#[from] hawk::Error),
#[error("Integer conversion error: {0}")]
IntegerConversionError(#[from] std::num::TryFromIntError),
#[error("Command not found by fxa")]
CommandNotFound,
#[error("Invalid Push Event")]
InvalidPushEvent,
#[error("Invalid state transition: {0}")]
InvalidStateTransition(String),
#[error("Internal error in the state machine: {0}")]
StateMachineLogicError(String),
}
impl GetErrorHandling for Error {
type ExternalError = FxaError;
fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
match self {
Error::RemoteError { code: 401, .. }
| Error::NoRefreshToken
| Error::NoScopedKey(_)
| Error::NoCachedToken(_) => {
ErrorHandling::convert(FxaError::Authentication).log_warning()
}
Error::RequestError(_) => ErrorHandling::convert(FxaError::Network).log_warning(),
Error::SyncScopedKeyMissingInServerResponse => {
ErrorHandling::convert(FxaError::SyncScopedKeyMissingInServerResponse)
.report_error("fxa-client-scoped-key-missing")
}
Error::UnknownOAuthState => {
ErrorHandling::convert(FxaError::NoExistingAuthFlow).log_warning()
}
Error::BackoffError(_) => ErrorHandling::convert(FxaError::Other(self.to_string()))
.report_error("fxa-client-backoff"),
Error::InvalidStateTransition(_) | Error::StateMachineLogicError(_) => {
ErrorHandling::convert(FxaError::Other(self.to_string()))
.report_error("fxa-state-machine-error")
}
Error::OriginMismatch(_) => ErrorHandling::convert(FxaError::OriginMismatch),
_ => ErrorHandling::convert(FxaError::Other(self.to_string()))
.report_error("fxa-client-other-error"),
}
}
}