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