pub use fraiseql_core::schema::ErrorSanitizationConfig;
use crate::error::{ErrorCode, GraphQLError};
pub struct ErrorSanitizer {
config: ErrorSanitizationConfig,
}
impl ErrorSanitizer {
#[must_use]
pub const fn new(config: ErrorSanitizationConfig) -> Self {
Self { config }
}
#[must_use]
pub fn disabled() -> Self {
Self::new(ErrorSanitizationConfig::default())
}
#[must_use]
pub fn sanitize(&self, mut error: GraphQLError) -> GraphQLError {
if !self.config.enabled {
return error;
}
if error.code.carries_database_text() && self.config.sanitize_database_errors {
error.message = self.replacement_message(error.code);
}
if self.config.hide_implementation_details {
if let Some(ext) = error.extensions.as_mut() {
ext.detail = None;
}
}
error
}
#[must_use]
pub fn sanitize_error(
&self,
error: fraiseql_core::error::FraiseQLError,
) -> fraiseql_core::error::FraiseQLError {
use fraiseql_core::error::FraiseQLError as E;
let code = GraphQLError::from_fraiseql_error(&error).code;
if !(self.should_sanitize_internal() && code.carries_database_text()) {
return error;
}
let message = self.replacement_message(code);
match error {
E::Database { sql_state, .. } => E::Database { message, sql_state },
E::ConnectionPool { .. } => E::ConnectionPool { message },
E::Internal { .. } => E::Internal {
message,
source: None,
},
other => other,
}
}
#[must_use]
pub fn sanitize_all(&self, errors: Vec<GraphQLError>) -> Vec<GraphQLError> {
errors.into_iter().map(|e| self.sanitize(e)).collect()
}
#[must_use]
pub const fn is_enabled(&self) -> bool {
self.config.enabled
}
#[must_use]
pub const fn should_sanitize_internal(&self) -> bool {
self.config.enabled && self.config.sanitize_database_errors
}
#[must_use]
pub fn replacement_message(&self, code: ErrorCode) -> String {
if let Some(custom) = self.config.custom_error_message.clone() {
return custom;
}
match code {
ErrorCode::BadUserInput => "The request contains an invalid value".to_string(),
ErrorCode::ConstraintViolation => {
"The request conflicts with the current state of the data".to_string()
},
_ => "An internal error occurred".to_string(),
}
}
}