From 30505f8285b018e7f17b1686e7a88793d743bbfc Mon Sep 17 00:00:00 2001 From: William Brown Date: Tue, 12 Mar 2019 15:40:19 +1000 Subject: [PATCH] Added state machine verification of modifylists --- src/lib/modify.rs | 57 ++++++++++++++++++++++++++++++++++++++++++----- src/lib/server.rs | 28 ++--------------------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/lib/modify.rs b/src/lib/modify.rs index 940eaed32..d60b07bcc 100644 --- a/src/lib/modify.rs +++ b/src/lib/modify.rs @@ -82,15 +82,62 @@ impl ModifyList { pub fn validate(&self, schema: &SchemaReadTransaction, ) -> Result, SchemaError> { - // Check that all attributes exist in the schema - // Normalise them + let schema_attributes = schema.get_attributes(); + let schema_name = schema_attributes + .get("name") + .expect("Critical: Core schema corrupt or missing. To initiate a core transfer, please deposit substitute core in receptacle."); - // Validate them + let res: Result, _> = (&self.mods).into_iter() + .map(|m| { + match m { + Modify::Present(attr, value) => { + let attr_norm = schema_name.normalise_value(&attr); + match schema_attributes.get(&attr_norm) { + Some(schema_a) => { + let value_norm = schema_a.normalise_value(&value); + schema_a + .validate_value(&value_norm) + .map(|_| Modify::Present(attr_norm, value_norm)) + } + None => Err(SchemaError::InvalidAttribute), + } + } + Modify::Removed(attr, value) => { + let attr_norm = schema_name.normalise_value(&attr); + match schema_attributes.get(&attr_norm) { + Some(schema_a) => { + let value_norm = schema_a.normalise_value(&value); + schema_a + .validate_value(&value_norm) + .map(|_| Modify::Removed(attr_norm, value_norm)) + } + None => Err(SchemaError::InvalidAttribute), + } + } + Modify::Purged(attr) => { + let attr_norm = schema_name.normalise_value(&attr); + match schema_attributes.get(&attr_norm) { + Some(_attr_name) => { + Ok(Modify::Purged(attr_norm)) + } + None => Err(SchemaError::InvalidAttribute), + } + } + } + }) + .collect(); + + let valid_mods = match res { + Ok(v) => v, + Err(e) => return Err(e), + }; // Return new ModifyList! - - unimplemented!() + Ok(ModifyList { + valid: ModifyValid, + mods: valid_mods, + }) } } diff --git a/src/lib/server.rs b/src/lib/server.rs index af52348b7..a8dbfccbb 100644 --- a/src/lib/server.rs +++ b/src/lib/server.rs @@ -357,32 +357,8 @@ impl<'a> QueryServerWriteTransaction<'a> { return plug_pre_res; } - // TODO: Rework this to be better. - /* - let (norm_cand, invalid_cand): ( - Vec, _>>, - Vec>, - ) = candidates - .into_iter() - .map(|e| e.validate(&self.schema)) - .partition(|e| e.is_ok()); - - for err in invalid_cand.iter() { - audit_log!(au, "Schema Violation: {:?}", err); - } - - for err in invalid_cand.iter() { - return Err(OperationError::SchemaViolation(err.unwrap_err())); - } - - let norm_cand: Vec> = norm_cand - .into_iter() - .map(|e| match e { - Ok(v) => v, - Err(_) => panic!("Invalid data set state!!!"), - }) - .collect(); - */ + // NOTE: This is how you map from Vec> to Result> + // remember, that you only get the first error and the iter terminates. let res: Result>, SchemaError> = candidates .into_iter()