better validation
This commit is contained in:
parent
d473a32820
commit
3f251a224f
3 changed files with 41 additions and 20 deletions
|
@ -24,7 +24,7 @@ pub enum UpdateError {
|
|||
/// Database related error
|
||||
Database(mongodb::error::Error),
|
||||
/// Validation failed
|
||||
Validation,
|
||||
Validation(String),
|
||||
}
|
||||
|
||||
pub trait Model:
|
||||
|
@ -203,18 +203,18 @@ pub trait Model:
|
|||
self.update_values(obj, &mut update).await;
|
||||
|
||||
// validate and update
|
||||
if self.validate().await {
|
||||
collection
|
||||
.update_one(
|
||||
id_of!(self.id()),
|
||||
mongodb::bson::doc! {"$set": update },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(UpdateError::Database)?;
|
||||
return Ok(());
|
||||
if let Err(msg) = self.validate().await {
|
||||
return Err(UpdateError::Validation(msg));
|
||||
}
|
||||
return Err(UpdateError::Validation);
|
||||
collection
|
||||
.update_one(
|
||||
id_of!(self.id()),
|
||||
mongodb::bson::doc! {"$set": update },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(UpdateError::Database)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(UpdateError::NoObject)
|
||||
|
|
|
@ -13,7 +13,7 @@ impl Reference {
|
|||
/// Create a new reference from String
|
||||
pub async fn new_raw(reference: &str) -> Option<Self> {
|
||||
let r = Self(reference.to_string());
|
||||
if r.validate().await {
|
||||
if r.validate().await.is_ok() {
|
||||
Some(r)
|
||||
} else {
|
||||
None
|
||||
|
@ -63,12 +63,20 @@ impl Reference {
|
|||
}
|
||||
|
||||
impl Validate for Reference {
|
||||
async fn validate(&self) -> bool {
|
||||
async fn validate(&self) -> Result<(), String> {
|
||||
// cheap
|
||||
//self.0.split_once("::").is_some()
|
||||
|
||||
// right
|
||||
self.exists().await.unwrap_or(false)
|
||||
if let Some(res) = self.exists().await {
|
||||
if res {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Reference '{}' does not exist", self.0))
|
||||
}
|
||||
} else {
|
||||
Err("Database error".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
/// This trait allows a `Model` to be validated.
|
||||
pub trait Validate {
|
||||
/// Validate the `Model`
|
||||
fn validate(&self) -> impl std::future::Future<Output = bool> + Send;
|
||||
fn validate(&self) -> impl std::future::Future<Output = Result<(), String>> + Send;
|
||||
}
|
||||
|
||||
/// Validate a value and return `false` if validation fails.
|
||||
/// Validate a value and return an Error if validation fails.
|
||||
#[macro_export]
|
||||
macro_rules! validate {
|
||||
($val:expr) => {
|
||||
if !$val.validate().await {
|
||||
return false;
|
||||
if let Err(err) = $val.validate().await {
|
||||
return Err(format!("{}: {}", stringify!($val), err));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! count_items {
|
||||
// Base case: single item
|
||||
($single:ident) => { 1 };
|
||||
// Recursive case: count each item
|
||||
($head:ident, $($tail:ident),*) => {
|
||||
1 + mongod::count_items!($($tail),*)
|
||||
};
|
||||
}
|
||||
|
||||
/// This macro checks for the type of a reference and is useful for validation.
|
||||
/// It will check all supplied types and return `false` if none are matching.
|
||||
///
|
||||
|
@ -34,7 +44,10 @@ macro_rules! assert_reference_of {
|
|||
}
|
||||
)*
|
||||
if !match_found {
|
||||
return false;
|
||||
let possible_types: [&str; mongod::count_items!($($struct_name),*)] = [
|
||||
$(stringify!($struct_name)),*
|
||||
];
|
||||
return Err(format!("{} is not of any type: {:?}", stringify!($var), possible_types));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue