diff --git a/src/integrity.rs b/src/integrity.rs new file mode 100644 index 0000000..e7f8e80 --- /dev/null +++ b/src/integrity.rs @@ -0,0 +1,84 @@ +use crate::{ + config::Config, db::ItemDB, flow::FlowInfo, json_store::JSONStore, location::Location, +}; + +/// Verify the base configuration files and check if they are sound before starting +pub async fn verify_integrity( + config: &Config, + flows: &JSONStore, + locations: &JSONStore, + itemdb: &ItemDB, +) { + let mut tainted = false; + + if config.allowed_tokens.is_empty() { + log::error!("No login tokens in the config file. No user will be able to access."); + tainted = true; + } + + for flow in &**flows { + // check valid depends + produces + for dep in &flow.1.depends { + if let Some(valid) = verify_item_variant_exists(dep, flow.0, itemdb) { + tainted = valid; + } + } + + for prod in flow.1.produces.as_ref().unwrap_or(&Vec::new()) { + if let Some(valid) = verify_item_variant_exists(prod, flow.0, itemdb) { + tainted = valid; + } + } + + if flow + .1 + .next + .as_ref() + .map(|x| flows.get(x).is_none()) + .unwrap_or(false) + { + log::error!( + "Flow '{}' is referencing unknown flow '{}' as next step.", + flow.0, + flow.1.next.as_ref().unwrap() + ); + tainted = true; + } + } + + for location in &**locations { + if location + .1 + .parent + .as_ref() + .map(|x| flows.get(x).is_none()) + .unwrap_or(false) + { + log::error!( + "Location '{}' is referencing an unknown location '{}' as parent.", + location.0, + location.1.parent.as_ref().unwrap() + ); + tainted = true; + } + } + + if tainted { + std::process::exit(1); + } +} + +pub fn verify_item_variant_exists(item_variant: &str, id: &str, itemdb: &ItemDB) -> Option { + if let Some((item, variant)) = item_variant.split_once("::") { + let item_var = itemdb.get_item(item).map(|x| x.variant(variant).is_none()); + if item_var.unwrap_or(true) { + log::error!("Unknown item variant '{}' on flow '{}'.", item_variant, id); + return Some(true); + } + } else { + log::error!("Malformed item variant on flow '{}': {}", id, item_variant); + return Some(true); + } + + return None; +} diff --git a/src/main.rs b/src/main.rs index 2ec7839..8acec75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use rocket::{http::Method, launch}; mod config; mod db; mod flow; +mod integrity; mod item; mod json_store; mod location; @@ -47,23 +48,20 @@ async fn rocket() -> _ { .to_cors() .expect("error creating CORS options"); + let config = config::get_config(); let itemdb = db::ItemDB::new("./itemdb").await; let mut locations: JSONStore = JSONStore::new("./locations"); + let mut flows: JSONStore = JSONStore::new("./flows"); + integrity::verify_integrity(&config, &flows, &locations, &itemdb).await; for location in &mut *locations { location.1.add(location.0).await; } - let mut flows: JSONStore = JSONStore::new("./flows"); - for flow in &mut *flows { flow.1.add(flow.0).await; } - let config = config::get_config(); - - // todo : log warnings on misconfiguration - rocket::build() .mount( "/",