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 related error
|
||||||
Database(mongodb::error::Error),
|
Database(mongodb::error::Error),
|
||||||
/// Validation failed
|
/// Validation failed
|
||||||
Validation,
|
Validation(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Model:
|
pub trait Model:
|
||||||
|
@ -203,18 +203,18 @@ pub trait Model:
|
||||||
self.update_values(obj, &mut update).await;
|
self.update_values(obj, &mut update).await;
|
||||||
|
|
||||||
// validate and update
|
// validate and update
|
||||||
if self.validate().await {
|
if let Err(msg) = self.validate().await {
|
||||||
collection
|
return Err(UpdateError::Validation(msg));
|
||||||
.update_one(
|
|
||||||
id_of!(self.id()),
|
|
||||||
mongodb::bson::doc! {"$set": update },
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(UpdateError::Database)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
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)
|
Err(UpdateError::NoObject)
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl Reference {
|
||||||
/// Create a new reference from String
|
/// Create a new reference from String
|
||||||
pub async fn new_raw(reference: &str) -> Option<Self> {
|
pub async fn new_raw(reference: &str) -> Option<Self> {
|
||||||
let r = Self(reference.to_string());
|
let r = Self(reference.to_string());
|
||||||
if r.validate().await {
|
if r.validate().await.is_ok() {
|
||||||
Some(r)
|
Some(r)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -63,12 +63,20 @@ impl Reference {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Reference {
|
impl Validate for Reference {
|
||||||
async fn validate(&self) -> bool {
|
async fn validate(&self) -> Result<(), String> {
|
||||||
// cheap
|
// cheap
|
||||||
//self.0.split_once("::").is_some()
|
//self.0.split_once("::").is_some()
|
||||||
|
|
||||||
// right
|
// 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.
|
/// This trait allows a `Model` to be validated.
|
||||||
pub trait Validate {
|
pub trait Validate {
|
||||||
/// Validate the `Model`
|
/// 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_export]
|
||||||
macro_rules! validate {
|
macro_rules! validate {
|
||||||
($val:expr) => {
|
($val:expr) => {
|
||||||
if !$val.validate().await {
|
if let Err(err) = $val.validate().await {
|
||||||
return false;
|
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.
|
/// 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.
|
/// 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 {
|
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