relay_actions/actions/
messages.rs1use serde::{Deserialize, Serialize};
2
3use crate::{
4 actions::Action, cache::CacheManager, sign::sign_request, sinks::progress::ProgressSink,
5 storage::Storage,
6};
7use relay_lib::prelude::{Address, InboxId, MetaEnvelope, PrivateEnvelope, e2e};
8
9#[derive(Serialize)]
10struct InboxMessagesReq {
11 pub inbox: Option<InboxId>,
12 pub start: Option<u32>,
13 pub amount: Option<u32>,
14}
15
16#[derive(Deserialize)]
17struct InboxMessagesResp {
18 pub messages: Vec<MetaEnvelope>,
19}
20
21pub struct Messages {
22 pub address: Address,
23 pub contents: bool,
24}
25
26impl Action for Messages {
27 type Output = Vec<(MetaEnvelope, PrivateEnvelope)>;
28
29 fn execute(
30 &self,
31 storage: &mut Storage,
32 cache: &mut CacheManager,
33 progress: &mut dyn ProgressSink,
34 ) -> Self::Output {
35 let identity = storage
36 .root
37 .get_identity(&self.address)
38 .unwrap_or_else(|| {
39 progress.abort(&format!("No identity found for address `{}`", self.address));
40 })
41 .clone();
42
43 progress.step("Fetching records", "Fetched records");
44 let agent_record = cache
45 .records
46 .agent(&mut cache.agents, self.address.agent())
47 .unwrap_or_else(|e| {
48 progress.error(&format!("{:?}", e));
49 progress.abort("Failed to fetch agent record");
50 });
51
52 progress.step("Fetching messages", "Fetched messages");
53 let request = sign_request(
54 &self.address.canonical(),
55 InboxMessagesReq {
56 inbox: self.address.inbox().cloned(),
57 start: None,
58 amount: None,
59 },
60 &agent_record,
61 &identity.signing_key(),
62 )
63 .unwrap_or_else(|e| {
64 progress.error(&format!("{:?}", e));
65 progress.abort("Failed to sign messages request");
66 });
67
68 let resp = reqwest::blocking::Client::new()
69 .get(
70 cache
71 .agents
72 .url(self.address.agent())
73 .unwrap_or_else(|e| {
74 progress.error(&format!("{:?}", e));
75 progress.abort("Failed to fetch Agent information");
76 })
77 .join("/inbox/messages")
78 .unwrap_or_else(|e| {
79 progress.error(&format!("{:?}", e));
80 progress.abort("Failed to construct inbox messages URL");
81 }),
82 )
83 .json(&request)
84 .send()
85 .unwrap_or_else(|e| {
86 progress.error(&format!("{:?}", e));
87 progress.abort("Failed to send messages request");
88 });
89
90 if resp.status().as_u16() == 404 {
91 progress.abort("Inbox not found on the Agent");
92 }
93
94 if !resp.status().is_success() {
95 progress.abort(&format!(
96 "Failed to list messages. HTTP {}",
97 resp.status().as_u16()
98 ));
99 }
100
101 progress.step("Processing response", "Processed response");
102 let mut response = resp.json::<InboxMessagesResp>().unwrap_or_else(|e| {
103 progress.error(&format!("{:?}", e));
104 progress.abort("Failed to parse messages response");
105 });
106
107 progress.step("Decrypting messages", "Decrypted messages");
108 response.messages.sort_by_key(|m| m.timestamp);
109 let messages = response
110 .messages
111 .iter()
112 .map(|meta| {
113 let payload = e2e::decrypt(
114 &identity.static_secret(),
115 &meta.crypto,
116 &meta.payload.payload,
117 &[],
118 )
119 .unwrap_or_else(|e| {
120 progress.error(&format!("{:?}", e));
121 progress.abort(&format!("Failed to decrypt message with GID {}", meta.gid));
122 });
123
124 let private =
125 serde_json::from_slice::<PrivateEnvelope>(&payload).unwrap_or_else(|e| {
126 progress.error(&format!("{:?}", e));
127 progress.abort(&format!(
128 "Failed to parse private envelope for message with GID {}",
129 meta.gid
130 ));
131 });
132
133 (meta.clone(), private)
134 })
135 .collect::<Vec<_>>();
136
137 progress.done();
138 messages
139 }
140}