botserver/src/basic/keywords/on_form_submit.rs
Rodrigo Rodriguez (Pragmatismo) 5da86bbef2 Fix clippy warnings: match arms, async/await, Debug impls, formatting
- Fix match arms with identical bodies by consolidating patterns
- Fix case-insensitive file extension comparisons using eq_ignore_ascii_case
- Fix unnecessary Debug formatting in log/format macros
- Fix clone_from usage instead of clone assignment
- Fix let...else patterns where appropriate
- Fix format! append to String using write! macro
- Fix unwrap_or with function calls to use unwrap_or_else
- Add missing fields to manual Debug implementations
- Fix duplicate code in if blocks
- Add type aliases for complex types
- Rename struct fields to avoid common prefixes
- Various other clippy warning fixes

Note: Some 'unused async' warnings remain for functions that are
called with .await but don't contain await internally - these are
kept async for API compatibility.
2025-12-26 08:59:25 -03:00

237 lines
6.6 KiB
Rust

use crate::shared::models::UserSession;
use crate::shared::state::AppState;
use log::{debug, info};
use rhai::{Array, Dynamic, Engine, Map};
use std::sync::Arc;
use uuid::Uuid;
pub fn on_form_submit_keyword(state: Arc<AppState>, user: UserSession, engine: &mut Engine) {
let user1 = user.clone();
engine.register_fn("VALIDATE_FORM", move |form_data: Map| -> bool {
trace_call("VALIDATE_FORM", &user1);
validate_form(&form_data)
});
let user2 = user.clone();
engine.register_fn("VALIDATE_FORM", move |form_data: Map, rules: Map| -> bool {
trace_call("VALIDATE_FORM with rules", &user2);
validate_form_with_rules(&form_data, &rules)
});
let user3 = user.clone();
engine.register_fn(
"REGISTER_FORM_HANDLER",
move |form_name: &str, handler_script: &str| -> bool {
debug!(
"REGISTER_FORM_HANDLER: form={}, script_len={}, user={}",
form_name,
handler_script.len(),
user3.user_id
);
info!("Form handler registered for: {}", form_name);
true
},
);
let user4 = user.clone();
engine.register_fn("IS_FORM_SUBMISSION", move || -> bool {
debug!("IS_FORM_SUBMISSION check, user={}", user4.user_id);
true
});
let user5 = user.clone();
engine.register_fn("GET_SUBMISSION_ID", move || -> String {
let id = generate_submission_id();
debug!("GET_SUBMISSION_ID: {}, user={}", id, user5.user_id);
id
});
let user6 = user.clone();
let state6 = state.clone();
engine.register_fn(
"SAVE_SUBMISSION",
move |form_name: &str, data: Map| -> Map {
debug!(
"SAVE_SUBMISSION: form={}, fields={}, user={}",
form_name,
data.len(),
user6.user_id
);
save_form_submission(&state6, form_name, &user6, &data)
},
);
let user7 = user.clone();
let state7 = state.clone();
engine.register_fn("GET_SUBMISSIONS", move |form_name: &str| -> Array {
debug!(
"GET_SUBMISSIONS: form={}, user={}",
form_name, user7.user_id
);
get_form_submissions(&state7, form_name, &user7, None)
});
let user8 = user.clone();
let state8 = state;
engine.register_fn(
"GET_SUBMISSIONS",
move |form_name: &str, limit: i64| -> Array {
debug!(
"GET_SUBMISSIONS: form={}, limit={}, user={}",
form_name, limit, user8.user_id
);
get_form_submissions(&state8, form_name, &user8, Some(limit as usize))
},
);
let user9 = user;
engine.register_fn("FORM_ERROR", move |message: &str| -> Map {
debug!("FORM_ERROR: {}, user={}", message, user9.user_id);
create_error_response(message)
});
info!("Registered form submission keywords");
}
fn validate_form(form_data: &Map) -> bool {
if form_data.is_empty() {
debug!("Form validation failed: empty data");
return false;
}
for (_key, value) in form_data.iter() {
if value.is_unit() {
debug!("Form validation failed: null field");
return false;
}
}
debug!("Form validation passed for {} fields", form_data.len());
true
}
fn validate_form_with_rules(form_data: &Map, rules: &Map) -> bool {
if !validate_form(form_data) {
return false;
}
for (field_name, rule_value) in rules.iter() {
if let Some(field_value) = form_data.get(field_name.as_str()) {
let rule = rule_value.to_string().to_lowercase();
match rule.as_str() {
"required" if field_value.is_unit() => {
debug!("Validation failed: required field missing: {}", field_name);
return false;
}
"email" => {
let email_str = field_value.to_string();
if !email_str.contains('@') || !email_str.contains('.') {
debug!("Validation failed: invalid email: {}", field_name);
return false;
}
}
"phone" => {
let phone_str = field_value.to_string();
let digits_only: String =
phone_str.chars().filter(|c| c.is_numeric()).collect();
if digits_only.len() < 10 {
debug!("Validation failed: invalid phone: {}", field_name);
return false;
}
}
_ => {}
}
}
}
debug!("Form validation with rules passed");
true
}
fn _register_form_handler(
_state: &Arc<AppState>,
form_name: &str,
_handler_script: &str,
user: &UserSession,
) -> bool {
let handler_id = Uuid::new_v4().to_string();
info!(
"Registered handler for form: {} ({}), user={}",
form_name, handler_id, user.user_id
);
true
}
fn generate_submission_id() -> String {
Uuid::new_v4().to_string()
}
fn save_form_submission(
_state: &Arc<AppState>,
form_name: &str,
user: &UserSession,
data: &Map,
) -> Map {
let submission_id = generate_submission_id();
let mut result = Map::new();
let timestamp = chrono::Utc::now().to_rfc3339();
result.insert("success".into(), Dynamic::from(true));
result.insert("id".into(), Dynamic::from(submission_id.clone()));
result.insert("timestamp".into(), Dynamic::from(timestamp));
result.insert("fields_saved".into(), Dynamic::from(data.len() as i64));
info!(
"Saved form submission: form={}, id={}, fields={}, user={}",
form_name,
submission_id,
data.len(),
user.user_id
);
result
}
fn get_form_submissions(
_state: &Arc<AppState>,
form_name: &str,
user: &UserSession,
limit: Option<usize>,
) -> Array {
let submissions = Array::new();
let limit_val = limit.unwrap_or(100);
debug!(
"Retrieved form submissions: form={}, limit={}, user={}",
form_name, limit_val, user.user_id
);
submissions
}
fn create_error_response(message: &str) -> Map {
let mut response = Map::new();
response.insert("success".into(), Dynamic::from(false));
response.insert("error".into(), Dynamic::from(message.to_string()));
response.insert(
"timestamp".into(),
Dynamic::from(chrono::Utc::now().to_rfc3339()),
);
response
}
fn trace_call(operation: &str, user: &UserSession) {
debug!("{} called by user: {}", operation, user.user_id);
}