commit
a47c4a0398
96 files changed
+25721
No files matched your search
@@ -0,0 +1,90 @@
|
||||
//! Read-only audit presentation; persisted event payloads are never rewritten.
|
||||
use crate::domain::WorkspaceDocument;
|
||||
use serde_json::{Value, json};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub type Names = BTreeMap<String, String>;
|
||||
|
||||
pub fn remember(names: &mut Names, doc: &WorkspaceDocument) {
|
||||
for person in &doc.people {
|
||||
names.insert(person.id.to_string(), person.display_name.clone());
|
||||
if let Some(id) = person.user_id {
|
||||
names.insert(id.to_string(), person.display_name.clone());
|
||||
}
|
||||
}
|
||||
for (id, name) in doc
|
||||
.schedules
|
||||
.iter()
|
||||
.map(|s| (s.id, &s.name))
|
||||
.chain(doc.escalations.iter().map(|s| (s.id, &s.name)))
|
||||
.chain(doc.routes.iter().map(|s| (s.id, &s.name)))
|
||||
.chain(doc.generation.rules.iter().map(|s| (s.id, &s.name)))
|
||||
.chain(doc.generation.variables.iter().map(|s| (s.id, &s.name)))
|
||||
{
|
||||
names.insert(id.to_string(), name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve(value: &Value, names: &Names) -> Value {
|
||||
match value {
|
||||
Value::String(id) => names
|
||||
.get(id)
|
||||
.map(|name| json!({"name":name,"id":id}))
|
||||
.unwrap_or_else(|| value.clone()),
|
||||
Value::Array(items) => Value::Array(items.iter().map(|v| resolve(v, names)).collect()),
|
||||
Value::Object(fields) => Value::Object(
|
||||
fields
|
||||
.iter()
|
||||
.map(|(key, value)| {
|
||||
// Free text must remain verbatim, even if a comment happens to equal a UUID.
|
||||
let reference = key == "id"
|
||||
|| key.ends_with("_id")
|
||||
|| matches!(
|
||||
key.as_str(),
|
||||
"from_user"
|
||||
| "to_user"
|
||||
| "requested_by"
|
||||
| "forced_by"
|
||||
| "approvals"
|
||||
| "required_approvers"
|
||||
| "participants"
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "fallback"
|
||||
| "user"
|
||||
| "redirect_to"
|
||||
| "escalation"
|
||||
| "variable"
|
||||
| "iteration"
|
||||
| "output"
|
||||
);
|
||||
let resolved = if reference || value.is_object() || value.is_array() {
|
||||
resolve(value, names)
|
||||
} else {
|
||||
value.clone()
|
||||
};
|
||||
(key.clone(), resolved)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
_ => value.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn references_expand_without_changing_comments_unknown_ids_or_raw_details() {
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let names = Names::from([(id.clone(), "Alice".into())]);
|
||||
let raw = json!({"from_user":id,"approvals":[id],"reason":id,"unknown_id":"missing","legs":[{"to_user":id}]});
|
||||
let resolved = resolve(&raw, &names);
|
||||
assert_eq!(resolved["from_user"]["name"], "Alice");
|
||||
assert_eq!(resolved["approvals"][0]["id"], id);
|
||||
assert_eq!(resolved["legs"][0]["to_user"]["name"], "Alice");
|
||||
assert_eq!(resolved["reason"], id);
|
||||
assert_eq!(resolved["unknown_id"], "missing");
|
||||
assert_eq!(raw["from_user"], id);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user