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