steel implementation, validation check only on post request

This commit is contained in:
filipriec
2025-03-07 23:21:00 +01:00
parent 9b8e49e65f
commit 66c29d8d65
6 changed files with 73 additions and 13 deletions

View File

@@ -1,4 +1,6 @@
// src/steel/handlers.rs
pub mod evaluator;
pub mod engine;
pub use evaluator::{validate_script, validate_target_column};
pub use engine::validate_steel_script;
pub use evaluator::validate_target_column;

View File

@@ -0,0 +1,34 @@
// src/steel/handlers/engine.rs
use steel_core::{steel_vm::engine::Engine, rvals::SteelVal};
use tonic::Status;
pub fn validate_steel_script(script: &str) -> Result<(), Status> {
let mut engine = Engine::new();
// Basic syntax check
let parsed = engine.compile(script).map_err(|e| {
Status::invalid_argument(format!("Syntax error: {}", e))
})?;
// Validate required function signature
let has_transform = parsed.iter().any(|expr| match expr {
SteelVal::Func(f) => f.name() == Some("transform"),
_ => false,
});
if !has_transform {
return Err(Status::invalid_argument(
"Script must contain a 'transform' function"
));
}
// Simple sandboxed execution test
let test_input = SteelVal::StringV("test_data".into());
engine.call_function("transform", vec![test_input])
.map_err(|e| {
Status::invalid_argument(format!("Runtime validation failed: {}", e))
})?;
Ok(())
}

View File

@@ -1,9 +1,9 @@
// src/steel/handlers/evaluator.rs
use crate::validation::script::validate_script;
use serde_json::Value;
const SYSTEM_COLUMNS: &[&str] = &["id", "deleted", "firma", "created_at"];
// Column validation
pub fn validate_target_column(
table_name: &str,
target: &str,
@@ -22,11 +22,3 @@ pub fn validate_target_column(
Ok(())
}
// Basic script validation
pub fn validate_script(script: &str) -> Result<(), String> {
if script.trim().is_empty() {
return Err("Script cannot be empty".to_string());
}
Ok(())
}

View File

@@ -1,3 +1,4 @@
// src/steel/mod.rs
pub mod handlers;
pub mod validation;

View File

@@ -0,0 +1,30 @@
// src/steel/validation/script.rs
use std::fmt;
use super::handlers::engine::validate_steel_script;
use tonic::Status;
#[derive(Debug)]
pub enum ScriptValidationError {
EmptyScript,
SteelValidation(String),
}
impl fmt::Display for ScriptValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ScriptValidationError::EmptyScript => write!(f, "Script cannot be empty"),
ScriptValidationError::SteelValidation(msg) => write!(f, "Steel validation error: {}", msg),
}
}
}
pub fn validate_script(script: &str) -> Result<(), ScriptValidationError> {
if script.trim().is_empty() {
return Err(ScriptValidationError::EmptyScript);
}
validate_steel_script(script)
.map_err(|e| ScriptValidationError::SteelValidation(e.message().to_string()))?;
Ok(())
}

View File

@@ -2,7 +2,8 @@
use tonic::Status;
use sqlx::{PgPool, Error as SqlxError};
use common::proto::multieko2::table_script::{PostTableScriptRequest, TableScriptResponse};
use crate::steel::handlers::evaluator::{validate_script, validate_target_column};
use crate::steel::handlers::evaluator::validate_target_column;
use crate::steel::validation::script::validate_script;
pub async fn post_table_script(
db_pool: &PgPool,
@@ -20,8 +21,8 @@ pub async fn post_table_script(
.ok_or_else(|| Status::not_found("Table definition not found"))?;
// Call validation functions
validate_script(&request.script) // Changed from validate_syntax to validate_script
.map_err(|e| Status::invalid_argument(e))?;
validate_script(&request.script)
.map_err(|e| Status::invalid_argument(e.to_string()))?;
validate_target_column(&table_def.table_name, &request.target_column, &table_def.columns)
.map_err(|e| Status::invalid_argument(e))?;