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