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