bitwarden_sm/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use bitwarden_api_api::apis::Error as ApiApisError;
use log::debug;
use thiserror::Error;
use validator::ValidationErrors;

#[derive(Debug, thiserror::Error)]
pub enum SecretsManagerError {
    #[error(transparent)]
    ValidationError(ValidationError),
    #[error(transparent)]
    VaultLocked(#[from] bitwarden_core::VaultLocked),
    #[error(transparent)]
    CryptoError(#[from] bitwarden_crypto::CryptoError),
    #[error(transparent)]
    Chrono(#[from] chrono::ParseError),

    #[error(transparent)]
    ApiError(#[from] bitwarden_core::ApiError),
    #[error(transparent)]
    MissingFieldError(#[from] bitwarden_core::MissingFieldError),
}

// Validation
#[derive(Debug, Error)]
pub enum ValidationError {
    #[error("{0} must not be empty")]
    Required(String),
    #[error("{0} must not exceed {1} characters in length")]
    ExceedsCharacterLength(String, u64),
    #[error("{0} must not contain only whitespaces")]
    OnlyWhitespaces(String),
    #[error("Unknown validation error: {0}")]
    Unknown(String),
}

const VALIDATION_LENGTH_CODE: &str = "length";
const VALIDATION_ONLY_WHITESPACES_CODE: &str = "only_whitespaces";

pub fn validate_only_whitespaces(value: &str) -> Result<(), validator::ValidationError> {
    if !value.is_empty() && value.trim().is_empty() {
        return Err(validator::ValidationError::new(
            VALIDATION_ONLY_WHITESPACES_CODE,
        ));
    }
    Ok(())
}

impl From<ValidationErrors> for ValidationError {
    fn from(e: ValidationErrors) -> Self {
        debug!("Validation errors: {:#?}", e);
        for (field_name, errors) in e.field_errors() {
            for error in errors {
                match error.code.as_ref() {
                    VALIDATION_LENGTH_CODE => {
                        if error.params.contains_key("min")
                            && error.params["min"].as_u64().expect("Min provided") == 1
                            && error.params["value"]
                                .as_str()
                                .expect("Value provided")
                                .is_empty()
                        {
                            return ValidationError::Required(field_name.to_string());
                        } else if error.params.contains_key("max") {
                            return ValidationError::ExceedsCharacterLength(
                                field_name.to_string(),
                                error.params["max"].as_u64().expect("Max provided"),
                            );
                        }
                    }
                    VALIDATION_ONLY_WHITESPACES_CODE => {
                        return ValidationError::OnlyWhitespaces(field_name.to_string());
                    }
                    _ => {}
                }
            }
        }
        ValidationError::Unknown(format!("{:#?}", e))
    }
}

impl From<ValidationErrors> for SecretsManagerError {
    fn from(e: ValidationErrors) -> Self {
        SecretsManagerError::ValidationError(e.into())
    }
}

impl<T> From<ApiApisError<T>> for SecretsManagerError {
    fn from(e: bitwarden_api_api::apis::Error<T>) -> Self {
        SecretsManagerError::ApiError(e.into())
    }
}