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#[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}