pharos_runtime_database/
webhook.rs1use std::collections::BTreeMap;
4
5use serde_json::Value;
6
7use crate::DbBackendConfig;
8use crate::operations::{
9 AppSchema, DatabaseError, DatabaseOperations, Mutation, Transaction, WriteValue,
10};
11
12pub fn append_webhook_receipt(
15 adapter: &dyn DatabaseOperations,
16 config: &DbBackendConfig,
17 schema: &AppSchema,
18 endpoint_id: &str,
19 verified: bool,
20 payload: &str,
21) -> Result<(), DatabaseError> {
22 if endpoint_id.is_empty()
23 || endpoint_id.len() > 128
24 || !endpoint_id
25 .bytes()
26 .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_'))
27 || payload.len() > 1_048_576
28 {
29 return Err(DatabaseError::InvalidInput);
30 }
31 let document: Value = serde_json::from_str(payload).map_err(|_| DatabaseError::InvalidInput)?;
32 adapter.transact(
33 config,
34 schema,
35 &Transaction {
36 steps: vec![Mutation::Insert {
37 entity: "webhook_receipt".to_owned(),
38 values: BTreeMap::from([
39 (
40 "endpoint_id".to_owned(),
41 WriteValue::Literal(Value::String(endpoint_id.to_owned())),
42 ),
43 (
44 "verification_status".to_owned(),
45 WriteValue::Literal(Value::String(
46 if verified { "verified" } else { "rejected" }.to_owned(),
47 )),
48 ),
49 ("payload_json".to_owned(), WriteValue::Literal(document)),
50 ]),
51 }],
52 idempotency_key: None,
53 },
54 )?;
55 Ok(())
56}