1use std::any::Any;
52use std::collections::HashMap;
53use async_trait::async_trait;
54use mongodb::bson::{to_bson, Document};
55use mongodb::{bson, Database};
56use serde_json::Value;
57use crate::error::ValidationError;
58use crate::traits::{ValidationResult, Validator};
59
60pub mod rules;
61pub mod traits;
62pub mod error;
63
64pub struct Rules {
79 validators: Vec<Box<dyn Validator+ Send + Sync>>,
80 default_value: Option<Value>,
81}
82
83impl Rules {
84 pub fn new() -> Self {
86 Self {
87 validators: Vec::new(),
88 default_value: None,
89 }
90 }
91
92 pub fn add<V: Validator + 'static>(mut self, validator: V) -> Self {
94 self.validators.push(Box::new(validator));
95 self
96 }
97
98 pub fn default(mut self, default: Value) -> Self {
100 self.default_value = Some(default);
101 self
102 }
103 pub fn len(&self) -> usize {
104 self.validators.len()
105 }
106}
107
108#[async_trait]
109impl Validator for Rules {
110 fn validate(&self, value: &Value) -> ValidationResult {
111 let value = if value.is_null() && self.default_value.is_some() {
112 self.default_value.as_ref().unwrap()
113 } else {
114 value
115 };
116 for validator in &self.validators {
117 validator.validate(value)?;
118 }
119 Ok(())
120 }
121
122 async fn validate_async(&self, _db: &Database, value: &Value) -> ValidationResult {
123 let value = if value.is_null() && self.default_value.is_some() {
124 self.default_value.as_ref().unwrap()
125 } else {
126 value
127 };
128 for validator in &self.validators {
129 validator.validate_async(_db,value).await?;
130 }
131 Ok(())
132 }
133
134 fn as_any(&self) -> &dyn Any {
135 self
136 }
137}
138
139
140pub struct FormValidator {
158 break_on_error:bool,
159 field_validators: HashMap<String, Box<dyn Validator+ Send + Sync>>,
160}
161
162impl FormValidator {
163 pub fn new() -> Self {
165 Self {
166 break_on_error:false,
167 field_validators: HashMap::new(),
168 }
169 }
170
171 pub fn add(
178 mut self,
179 field_name: &str,
180 validator: impl Validator + 'static,
181 ) -> Self {
182 self.field_validators
183 .insert(field_name.to_string(), Box::new(validator));
184 self
185 }
186
187 pub fn validate(
193 &self,
194 form_data: &Value,
195 ) -> Result<Document, HashMap<String,Vec<ValidationError>>> {
196 let mut errors = HashMap::new();
197 let mut valid_data = HashMap::new();
198
199 for (field_name, validator) in &self.field_validators {
200 let value = if field_name.contains('.') {
201 let mut current = form_data;
202 for part in field_name.split('.') {
203 current = current.get(part).unwrap_or(&Value::Null);
204 }
205 current
206 } else {
207 form_data.get(field_name).unwrap_or(&Value::Null)
208 };
209 let processed_value = if let Some(rules) = validator.as_any().downcast_ref::<Rules>() {
210 if value.is_null() && rules.default_value.is_some() {
211 rules.default_value.as_ref().unwrap()
212 } else {
213 value
214 }
215 } else {
216 value
217 };
218 if let Err(err) = validator.validate(processed_value) {
219 match errors.get_mut(field_name){
220 None => {
221 errors.insert(field_name.clone(),vec![err]);
222 }
223 Some(a) => {
224 a.push(err);
225 }
226 }
227
228 if self.break_on_error {
229 break;
230 }
231 } else {
232 valid_data.insert(field_name.clone(), processed_value.clone());
233 }
234 }
235
236 if errors.is_empty() {
237 match hashmap_to_document(valid_data){
238 Ok(a) => {
239 Ok(a)
240 }
241 Err(e) => {
242 errors.insert("data".to_string(),vec![ValidationError::Custom(e.to_string())]);
243 Err(errors)
244 }
245 }
246 } else {
247 Err(errors)
248 }
249 }
250
251 pub async fn validate_async(
258 &self,
259 db:&Database,
260 form_data: &Value,
261 ) -> Result<Document, HashMap<String,Vec<ValidationError>>> {
262 let mut errors = HashMap::new();
263 let mut valid_data = HashMap::new();
264
265 for (field_name, validator) in &self.field_validators {
266 let value = if field_name.contains('.') {
267 let mut current = form_data;
268 for part in field_name.split('.') {
269 current = current.get(part).unwrap_or(&Value::Null);
270 }
271 current
272 } else {
273 form_data.get(field_name).unwrap_or(&Value::Null)
274 };
275 let processed_value = if let Some(rules) = validator.as_any().downcast_ref::<Rules>() {
276 if value.is_null() && rules.default_value.is_some() {
277 rules.default_value.as_ref().unwrap()
278 } else {
279 value
280 }
281 } else {
282 value
283 };
284
285 if let Err(err) = validator.validate_async(db,processed_value).await {
286 match errors.get_mut(field_name){
287 None => {
288 errors.insert(field_name.clone(),vec![err]);
289 }
290 Some(a) => {
291 a.push(err);
292 }
293 }
294 if self.break_on_error {
295 break;
296 }
297 } else {
298 valid_data.insert(field_name.clone(), processed_value.clone());
299 }
300 }
301
302 if errors.is_empty() {
303 match hashmap_to_document(valid_data){
304 Ok(a) => {
305 Ok(a)
306 }
307 Err(e) => {
308 errors.insert("data".to_string(),vec![ValidationError::Custom(e.to_string())]);
309 Err(errors)
310 }
311 }
312 } else {
313 Err(errors)
314 }
315 }
316
317 pub fn break_on_error(mut self) -> FormValidator {
318 self.break_on_error = true;
319 self
320 }
321}
322fn hashmap_to_document(input: HashMap<String, Value>) -> Result<Document, bson::ser::Error> {
323 let mut doc = Document::new();
324
325 for (key, value) in input {
326 let bson_value = to_bson(&value)?;
327
328 doc.insert(key, bson_value);
329 }
330
331 Ok(doc)
332}
333
334#[macro_export]
335macro_rules! rules {
336 ($($rule:expr),+ $(,)?) => {
337 {
338 let mut r = Rules::new();
339 $(r = r.add($rule);)+
340 r
341 }
342 };
343}