steel implementation, validation check only on post request
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
// src/steel/handlers.rs
|
// src/steel/handlers.rs
|
||||||
pub mod evaluator;
|
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;
|
||||||
|
|||||||
34
server/src/steel/handlers/engine.rs
Normal file
34
server/src/steel/handlers/engine.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
// src/steel/handlers/evaluator.rs
|
// src/steel/handlers/evaluator.rs
|
||||||
|
use crate::validation::script::validate_script;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
const SYSTEM_COLUMNS: &[&str] = &["id", "deleted", "firma", "created_at"];
|
const SYSTEM_COLUMNS: &[&str] = &["id", "deleted", "firma", "created_at"];
|
||||||
|
|
||||||
// Column validation
|
|
||||||
pub fn validate_target_column(
|
pub fn validate_target_column(
|
||||||
table_name: &str,
|
table_name: &str,
|
||||||
target: &str,
|
target: &str,
|
||||||
@@ -22,11 +22,3 @@ pub fn validate_target_column(
|
|||||||
|
|
||||||
Ok(())
|
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(())
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
// src/steel/mod.rs
|
// src/steel/mod.rs
|
||||||
|
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
|
pub mod validation;
|
||||||
|
|||||||
30
server/src/steel/validation/script.rs
Normal file
30
server/src/steel/validation/script.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
use tonic::Status;
|
use tonic::Status;
|
||||||
use sqlx::{PgPool, Error as SqlxError};
|
use sqlx::{PgPool, Error as SqlxError};
|
||||||
use common::proto::multieko2::table_script::{PostTableScriptRequest, TableScriptResponse};
|
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(
|
pub async fn post_table_script(
|
||||||
db_pool: &PgPool,
|
db_pool: &PgPool,
|
||||||
@@ -20,8 +21,8 @@ pub async fn post_table_script(
|
|||||||
.ok_or_else(|| Status::not_found("Table definition not found"))?;
|
.ok_or_else(|| Status::not_found("Table definition not found"))?;
|
||||||
|
|
||||||
// Call validation functions
|
// Call validation functions
|
||||||
validate_script(&request.script) // Changed from validate_syntax to validate_script
|
validate_script(&request.script)
|
||||||
.map_err(|e| Status::invalid_argument(e))?;
|
.map_err(|e| Status::invalid_argument(e.to_string()))?;
|
||||||
|
|
||||||
validate_target_column(&table_def.table_name, &request.target_column, &table_def.columns)
|
validate_target_column(&table_def.table_name, &request.target_column, &table_def.columns)
|
||||||
.map_err(|e| Status::invalid_argument(e))?;
|
.map_err(|e| Status::invalid_argument(e))?;
|
||||||
|
|||||||
Reference in New Issue
Block a user