add basic integrity check on startup

This commit is contained in:
JMARyA 2024-09-19 11:42:59 +02:00
parent 1271387131
commit 416c1f06c1
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
2 changed files with 88 additions and 6 deletions

84
src/integrity.rs Normal file
View file

@ -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<FlowInfo>,
locations: &JSONStore<Location>,
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<bool> {
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;
}

View file

@ -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<Location> = JSONStore::new("./locations");
let mut flows: JSONStore<FlowInfo> = 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<FlowInfo> = 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(
"/",