bitwarden_sm/
error.rs

1use bitwarden_api_api::apis::Error as ApiApisError;
2use log::debug;
3use thiserror::Error;
4use validator::ValidationErrors;
5
6#[derive(Debug, thiserror::Error)]
7pub enum SecretsManagerError {
8    #[error(transparent)]
9    Validation(ValidationError),
10    #[error(transparent)]
11    Crypto(#[from] bitwarden_crypto::CryptoError),
12    #[error(transparent)]
13    Chrono(#[from] chrono::ParseError),
14
15    #[error(transparent)]
16    Api(#[from] bitwarden_core::ApiError),
17    #[error(transparent)]
18    MissingField(#[from] bitwarden_core::MissingFieldError),
19}
20
21// Validation
22#[derive(Debug, Error)]
23pub enum ValidationError {
24    #[error("{0} must not be empty")]
25    Required(String),
26    #[error("{0} must not exceed {1} characters in length")]
27    ExceedsCharacterLength(String, u64),
28    #[error("{0} must not contain only whitespaces")]
29    OnlyWhitespaces(String),
30    #[error("Unknown validation error: {0}")]
31    Unknown(String),
32}
33
34const VALIDATION_LENGTH_CODE: &str = "length";
35const VALIDATION_ONLY_WHITESPACES_CODE: &str = "only_whitespaces";
36
37pub fn validate_only_whitespaces(value: &str) -> Result<(), validator::ValidationError> {
38    if !value.is_empty() && value.trim().is_empty() {
39        return Err(validator::ValidationError::new(
40            VALIDATION_ONLY_WHITESPACES_CODE,
41        ));
42    }
43    Ok(())
44}
45
46impl From<ValidationErrors> for ValidationError {
47    fn from(e: ValidationErrors) -> Self {
48        debug!("Validation errors: {e:#?}");
49        for (field_name, errors) in e.field_errors() {
50            for error in errors {
51                match error.code.as_ref() {
52                    VALIDATION_LENGTH_CODE => {
53                        if error.params.contains_key("min")
54                            && error.params["min"].as_u64().expect("Min provided") == 1
55                            && error.params["value"]
56                                .as_str()
57                                .expect("Value provided")
58                                .is_empty()
59                        {
60                            return ValidationError::Required(field_name.to_string());
61                        } else if error.params.contains_key("max") {
62                            return ValidationError::ExceedsCharacterLength(
63                                field_name.to_string(),
64                                error.params["max"].as_u64().expect("Max provided"),
65                            );
66                        }
67                    }
68                    VALIDATION_ONLY_WHITESPACES_CODE => {
69                        return ValidationError::OnlyWhitespaces(field_name.to_string());
70                    }
71                    _ => {}
72                }
73            }
74        }
75        ValidationError::Unknown(format!("{e:#?}"))
76    }
77}
78
79impl From<ValidationErrors> for SecretsManagerError {
80    fn from(e: ValidationErrors) -> Self {
81        SecretsManagerError::Validation(e.into())
82    }
83}
84
85impl<T> From<ApiApisError<T>> for SecretsManagerError {
86    fn from(e: bitwarden_api_api::apis::Error<T>) -> Self {
87        SecretsManagerError::Api(e.into())
88    }
89}