Server tools to backfill, tail, mirror, and verify PLC logs
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

mirror: rudimentary did reconstruction, match path patterns as plc.directory

geesawra ee7a33cc 4b57ed4e

+74 -10
+74 -10
src/mirror.rs
··· 13 13 web::{Data, Json, Path}, 14 14 }; 15 15 use reqwest::{Client, Url}; 16 - use serde::Serialize; 16 + use serde::{Deserialize, Serialize}; 17 17 use std::{net::SocketAddr, path::PathBuf, time::Duration}; 18 - use tokio_util::sync; 19 18 20 19 #[derive(Clone)] 21 20 struct State { ··· 295 294 Response::from_parts(parts, poem::Body::from_bytes_stream(body)) 296 295 } 297 296 298 - #[derive(Serialize)] 299 - struct OpsResponse { 300 - operations: Vec<Op>, 297 + #[derive(Serialize, Deserialize)] 298 + #[serde(rename_all = "camelCase")] 299 + struct DidResponse { 300 + #[serde(rename = "@context")] 301 + context: Vec<String>, 302 + id: String, 303 + #[serde(flatten)] 304 + op: serde_json::Value, 305 + } 306 + 307 + impl Default for DidResponse { 308 + fn default() -> Self { 309 + Self { 310 + context: vec![ 311 + "https://www.w3.org/ns/did/v1".to_string(), 312 + "https://w3id.org/security/multikey/v1".to_string(), 313 + "https://w3id.org/security/suites/secp256k1-2019/v1".to_string(), 314 + ], 315 + id: Default::default(), 316 + op: serde_json::json!({}), 317 + } 318 + } 301 319 } 302 320 303 321 #[handler] 304 - async fn ops(req: &Request, Data(state): Data<&State>) -> Result<Response> { 305 - let did = req.uri().path().strip_prefix("/").unwrap_or_default(); 322 + async fn get_did(Path(did): Path<String>, Data(state): Data<&State>) -> Result<Response> { 323 + let ds = match state.ds.as_ref() { 324 + Some(ds) => ds, 325 + None => { 326 + return Ok("no data store configured :(" 327 + .with_status(reqwest::StatusCode::BAD_REQUEST) 328 + .into_response()); 329 + } 330 + }; 306 331 332 + let oplist = match ds.query_ops(did.to_string()).await { 333 + Ok(res) => res, 334 + Err(e) => { 335 + return Ok(e 336 + .to_string() 337 + .with_status(reqwest::StatusCode::BAD_REQUEST) 338 + .into_response()); 339 + } 340 + }; 341 + 342 + let op = oplist.last().unwrap(); 343 + 344 + let mut op_value: serde_json::Value = serde_json::from_str(op.operation.get()).unwrap(); 345 + 346 + // Remove unwanted fields 347 + if let Some(obj) = op_value.as_object_mut() { 348 + obj.remove("sig"); 349 + obj.remove("prev"); 350 + // Add more fields to remove as needed 351 + } 352 + 353 + let dr = DidResponse { 354 + id: did.to_string(), 355 + op: op_value, 356 + ..Default::default() 357 + }; 358 + 359 + Ok(Json(dr).into_response()) 360 + } 361 + 362 + #[handler] 363 + async fn ops(Path(did): Path<String>, Data(state): Data<&State>) -> Result<Response> { 307 364 let ds = match state.ds.as_ref() { 308 365 Some(ds) => ds, 309 366 None => { ··· 313 370 } 314 371 }; 315 372 316 - match ds.query_ops(did.to_string()).await { 317 - Ok(res) => Ok(Json(OpsResponse { operations: res }).into_response()), 373 + match ds.query_ops(did).await { 374 + Ok(res) => Ok(Json(res).into_response()), 318 375 Err(e) => Ok(e 319 376 .to_string() 320 377 .with_status(reqwest::StatusCode::BAD_REQUEST) ··· 505 562 app = app.at("/did:plc:*", get(proxy).post(upstream_proxier)); 506 563 } else { 507 564 match has_db { 508 - true => app = app.at("/did:plc:*", get(ops).post(nope)), 565 + true => { 566 + app = app 567 + .at( 568 + "/:did<did\\:plc\\:[a-z0-9]+>/log/audit", 569 + get(ops).post(nope), 570 + ) 571 + .at("/:did<did\\:plc\\:[a-z0-9]+>", get(get_did).post(nope)) 572 + } 509 573 false => app = app.at("/did:plc:*", get(proxy).post(nope)), 510 574 }; 511 575 }