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