forked from mirror/grapevine
Compare commits
3 commits
custom
...
benjamin/d
Author | SHA1 | Date | |
---|---|---|---|
|
9b38bd5940 | ||
|
ba4c5edc7f | ||
|
276d73f471 |
2 changed files with 112 additions and 6 deletions
|
@ -1,4 +1,9 @@
|
|||
use std::{collections::BTreeMap, fmt::Write, sync::Arc, time::Instant};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashSet},
|
||||
fmt::Write,
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use regex::Regex;
|
||||
|
@ -121,6 +126,23 @@ enum AdminCommand {
|
|||
event_id: Box<EventId>,
|
||||
},
|
||||
|
||||
/// Dump auth chain events stored in the db in graphviz DOT format
|
||||
///
|
||||
/// Does not validate anything. Events that are missing or generate an
|
||||
/// error when we try to load them from the db are marked in red.
|
||||
GetAuthChainGraph {
|
||||
/// An event ID (the $ character followed by the base64 reference hash)
|
||||
event_ids: Vec<Box<EventId>>,
|
||||
},
|
||||
|
||||
/// Dump all events in a given events auth chain in jsonl format
|
||||
///
|
||||
/// Does not validate anything.
|
||||
GetAuthChainEvents {
|
||||
/// An event ID (the $ character followed by the base64 reference hash)
|
||||
event_ids: Vec<Box<EventId>>,
|
||||
},
|
||||
|
||||
#[command(verbatim_doc_comment)]
|
||||
/// Parse and print a PDU from a JSON
|
||||
///
|
||||
|
@ -536,6 +558,92 @@ impl Service {
|
|||
RoomMessageEventContent::text_plain("Event not found.")
|
||||
}
|
||||
}
|
||||
AdminCommand::GetAuthChainGraph {
|
||||
event_ids,
|
||||
} => {
|
||||
let mut dot = String::new();
|
||||
writeln!(&mut dot, "digraph G {{").unwrap();
|
||||
let mut todo = event_ids
|
||||
.into_iter()
|
||||
.map(Arc::<EventId>::from)
|
||||
.collect::<Vec<_>>();
|
||||
let mut done = HashSet::new();
|
||||
let mut edges = HashSet::new();
|
||||
while let Some(event_id) = todo.pop() {
|
||||
done.insert(event_id.clone());
|
||||
if let Ok(Some(pdu)) =
|
||||
services().rooms.timeline.get_pdu(&event_id)
|
||||
{
|
||||
writeln!(&mut dot, " {event_id:?};").unwrap();
|
||||
for auth_event in &pdu.auth_events {
|
||||
let edge = (
|
||||
Arc::clone(auth_event),
|
||||
Arc::clone(&event_id),
|
||||
);
|
||||
if !edges.contains(&edge) {
|
||||
writeln!(
|
||||
&mut dot,
|
||||
" {auth_event:?} -> {event_id:?};"
|
||||
)
|
||||
.unwrap();
|
||||
edges.insert(edge);
|
||||
}
|
||||
if !done.contains(&**auth_event) {
|
||||
todo.push(Arc::clone(auth_event));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeln!(&mut dot, " {event_id:?}[color=\"red\"];")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
write!(&mut dot, "}}").unwrap();
|
||||
RoomMessageEventContent::text_html(
|
||||
format!("\n```dot\n{dot}\n```"),
|
||||
format!(
|
||||
"<pre><code class=\"language-dot\">{}\n</code></pre>\n",
|
||||
html_escape::encode_safe(&dot)
|
||||
),
|
||||
)
|
||||
}
|
||||
AdminCommand::GetAuthChainEvents {
|
||||
event_ids,
|
||||
} => {
|
||||
let mut jsonl = String::new();
|
||||
let mut todo = event_ids
|
||||
.into_iter()
|
||||
.map(Arc::<EventId>::from)
|
||||
.collect::<Vec<_>>();
|
||||
let mut done = HashSet::new();
|
||||
while let Some(event_id) = todo.pop() {
|
||||
done.insert(event_id.clone());
|
||||
if let Ok(Some(pdu_json)) =
|
||||
services().rooms.timeline.get_pdu_json(&event_id)
|
||||
{
|
||||
jsonl.push_str(
|
||||
&serde_json::to_string(&pdu_json).unwrap(),
|
||||
);
|
||||
jsonl.push('\n');
|
||||
}
|
||||
if let Ok(Some(pdu)) =
|
||||
services().rooms.timeline.get_pdu(&event_id)
|
||||
{
|
||||
for auth_event in &pdu.auth_events {
|
||||
if !done.contains(&**auth_event) {
|
||||
todo.push(Arc::clone(auth_event));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RoomMessageEventContent::text_html(
|
||||
format!("\n```json\n{jsonl}\n```"),
|
||||
format!(
|
||||
"<pre><code \
|
||||
class=\"language-json\">{}\n</code></pre>\n",
|
||||
html_escape::encode_safe(&jsonl)
|
||||
),
|
||||
)
|
||||
}
|
||||
AdminCommand::ParsePdu => {
|
||||
if body.len() > 2
|
||||
&& body[0].trim() == "```"
|
||||
|
|
|
@ -31,10 +31,7 @@ impl Service {
|
|||
self.db.cache_auth_chain(key, auth_chain)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
skip(self, starting_events),
|
||||
fields(starting_events = debug_slice_truncated(&starting_events, 5)),
|
||||
)]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(crate) async fn get_auth_chain<'a>(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
|
@ -154,9 +151,10 @@ impl Service {
|
|||
match services().rooms.timeline.get_pdu(&event_id) {
|
||||
Ok(Some(pdu)) => {
|
||||
if pdu.room_id != room_id {
|
||||
warn!(bad_room_id = %pdu.room_id, "Event referenced in auth chain has incorrect room id");
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::forbidden(),
|
||||
"Evil event in db",
|
||||
"Event has incorrect room id",
|
||||
));
|
||||
}
|
||||
for auth_event in &pdu.auth_events {
|
||||
|
|
Loading…
Reference in a new issue