diff --git a/crates/service/web/storyteller_web/src/api_doc_cli.rs b/crates/service/web/storyteller_web/src/api_doc_cli.rs index fc62536c7c..3d6aebd27e 100644 --- a/crates/service/web/storyteller_web/src/api_doc_cli.rs +++ b/crates/service/web/storyteller_web/src/api_doc_cli.rs @@ -27,6 +27,7 @@ use errors::AnyhowResult; pub mod billing; pub mod configs; +pub mod error; pub mod http_server; pub mod state; pub mod threads; diff --git a/crates/service/web/storyteller_web/src/api_doc_server.rs b/crates/service/web/storyteller_web/src/api_doc_server.rs index 1924c42725..de5c546b18 100644 --- a/crates/service/web/storyteller_web/src/api_doc_server.rs +++ b/crates/service/web/storyteller_web/src/api_doc_server.rs @@ -30,6 +30,7 @@ use crate::configs::static_api_tokens::StaticApiTokenSet; pub mod billing; pub mod configs; +pub mod error; pub mod http_server; pub mod state; pub mod threads; diff --git a/crates/service/web/storyteller_web/src/error/internal_error.rs b/crates/service/web/storyteller_web/src/error/internal_error.rs new file mode 100644 index 0000000000..0c479310bd --- /dev/null +++ b/crates/service/web/storyteller_web/src/error/internal_error.rs @@ -0,0 +1,37 @@ +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; + +/// Any generic errors arising internally. +/// An error class that we do not expose via the API. +/// This should be massaged before we send it to the user. +#[derive(Debug)] +pub enum InternalError { + /// Issue with HMAC decoding + /// This is typically when using development cookies against production, + /// or vice versa. + VisitorCookieError(String), + + /// Decode error with AVT cookie missing a required field. + VisitorCookieMissingField(&'static str), + + /// Catch instances of anyhow::Error. + AnyhowError(anyhow::Error), +} + +impl Error for InternalError {} + +impl Display for InternalError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + InternalError::VisitorCookieError(reason) => write!(f, "Visitor cookie error: {:?}", reason), + InternalError::VisitorCookieMissingField(field) => write!(f, "Visitor cookie missing field: {}", field), + InternalError::AnyhowError(err) => write!(f, "Anyhow error: {}", err), + } + } +} + +impl From for InternalError { + fn from(err: anyhow::Error) -> Self { + InternalError::AnyhowError(err) + } +} diff --git a/crates/service/web/storyteller_web/src/error/mod.rs b/crates/service/web/storyteller_web/src/error/mod.rs new file mode 100644 index 0000000000..3e6d672990 --- /dev/null +++ b/crates/service/web/storyteller_web/src/error/mod.rs @@ -0,0 +1 @@ +pub mod internal_error; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_manager.rs b/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_manager.rs index c5a009796e..93b1f906a2 100644 --- a/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_manager.rs +++ b/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_manager.rs @@ -4,12 +4,12 @@ use actix_web::HttpRequest; use anyhow::anyhow; use log::warn; +use crate::error::internal_error::InternalError; +use crate::http_server::cookies::anonymous_visitor_tracking::avt_cookie_payload::AvtCookiePayload; use cookies::jwt_signer::JwtSigner; use errors::AnyhowResult; use tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken; -use crate::http_server::cookies::anonymous_visitor_tracking::avt_cookie_payload::AvtCookiePayload; - const VISITOR_COOKIE_NAME : &str = "visitor"; /// Handle "anonymous visitor tracking" cookies. @@ -70,7 +70,7 @@ impl AvtCookieManager { Ok(payload) } - pub fn decode_cookie_payload_from_request(&self, request: &HttpRequest) -> AnyhowResult> { + pub fn decode_cookie_payload_from_request(&self, request: &HttpRequest) -> Result, InternalError> { let cookie = match request.cookie(VISITOR_COOKIE_NAME) { None => return Ok(None), Some(cookie) => cookie, @@ -79,7 +79,7 @@ impl AvtCookieManager { match self.decode_cookie_payload(&cookie) { Err(e) => { warn!("Visitor cookie decode error: {:?}", e); - Err(anyhow!("Could not decode visitor cookie: {:?}", e)) + Err(InternalError::VisitorCookieError(e.to_string())) }, Ok(payload) => Ok(Some(payload)), } diff --git a/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_payload.rs b/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_payload.rs index 49d19c1f6d..0706d90590 100644 --- a/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_payload.rs +++ b/crates/service/web/storyteller_web/src/http_server/cookies/anonymous_visitor_tracking/avt_cookie_payload.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; use std::str::FromStr; -use anyhow::anyhow; - -use errors::AnyhowResult; +use crate::error::internal_error::InternalError; use tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken; /** @@ -38,18 +36,19 @@ impl AvtCookiePayload { } } - pub fn from_map(map: BTreeMap) -> AnyhowResult { + pub fn from_map(map: BTreeMap) -> Result { let avt_token = map.get("avt_token") - .ok_or(anyhow!("avt_token not present"))? - .to_string(); + .ok_or_else(|| InternalError::VisitorCookieMissingField("avt_token"))?; let cookie_version = map .get("cookie_version") - .ok_or(anyhow!("avt_token not present"))?; + .ok_or_else(|| InternalError::VisitorCookieMissingField("cookie_version"))?; - let avt_token = AnonymousVisitorTrackingToken::new_from_str(&avt_token); + let avt_token = AnonymousVisitorTrackingToken::new_from_str(avt_token); - let cookie_version = u32::from_str(cookie_version)?; + let cookie_version = u32::from_str(cookie_version) + .map_err(|e| InternalError::VisitorCookieError( + format!("invalid integer for cookie_version: {:?}, version: {}", e, cookie_version)))?; Ok(AvtCookiePayload { avt_token, diff --git a/crates/service/web/storyteller_web/src/main.rs b/crates/service/web/storyteller_web/src/main.rs index bc12ed599d..73a9a72dc6 100644 --- a/crates/service/web/storyteller_web/src/main.rs +++ b/crates/service/web/storyteller_web/src/main.rs @@ -92,6 +92,7 @@ use crate::util::troll_user_bans::troll_user_ban_list::TrollUserBanList; pub mod billing; pub mod configs; +pub mod error; pub mod http_server; pub mod state; pub mod threads;